Hummingbird Page Speed Optimization - Version 1.5.3

Version Description

( 2017-06-21 ) = - Fix: Avada & Google Maps scripts incompatibility - Fix: Bulk update not working when selecting all items in minification screen - Fix: Minification engine sometimes forget about files and did not clean them - Fix: Minification was always showing 0% saved in some cases - Fix: Enjoy pro features notice does not go away - Fix: Performance scans were not active for some users of the free version of the plugin - Enhance: Some code optimizations in few areas - Enhance: Minified files are now processed in a background task and in a bigger batch - Enhance: Some minor styles changes - Enhance: Use CDN option is not available in sites of a multisite anymore and is controlled from network admin - Enhance: Improved activation logic for free/pro versions - Some other minor fixes and refactoring

Download this release

Release Info

Developer jdailey
Plugin Icon 128x128 Hummingbird Page Speed Optimization
Version 1.5.3
Comparing to
See all releases

Version 1.5.3

Files changed (188) hide show
  1. _src/admin/js/admin-app.js +3 -0
  2. _src/admin/js/admin-caching.js +146 -0
  3. _src/admin/js/admin-cloudflare.js +35 -0
  4. _src/admin/js/admin-dashboard-cloudflare.js +148 -0
  5. _src/admin/js/admin-dashboard.js +87 -0
  6. _src/admin/js/admin-gzip.js +60 -0
  7. _src/admin/js/admin-main.js +101 -0
  8. _src/admin/js/admin-minification.js +309 -0
  9. _src/admin/js/admin-performance.js +179 -0
  10. _src/admin/js/admin-uptime.js +99 -0
  11. _src/admin/js/index.js +10 -0
  12. _src/admin/js/minification/Row.js +113 -0
  13. _src/admin/js/minification/RowsCollection.js +87 -0
  14. _src/admin/js/utils/fetcher.js +242 -0
  15. _src/admin/js/utils/helpers.js +21 -0
  16. _src/admin/scss/app.scss +5 -0
  17. _src/admin/scss/modules/_classes.scss +24 -0
  18. _src/admin/scss/modules/_functions.scss +9 -0
  19. _src/admin/scss/modules/_mixins.scss +90 -0
  20. _src/admin/scss/modules/_variables.scss +63 -0
  21. admin/abstract-class-admin-page.php +396 -0
  22. admin/assets/css/admin.css +3669 -0
  23. admin/assets/css/app.css +2 -0
  24. admin/assets/css/app.css.map +1 -0
  25. admin/assets/css/wphb-font.css +16 -0
  26. admin/assets/fonts/hummingbird.eot +0 -0
  27. admin/assets/fonts/hummingbird.svg +25 -0
  28. admin/assets/fonts/hummingbird.ttf +0 -0
  29. admin/assets/fonts/hummingbird.woff +0 -0
  30. admin/assets/fonts/wphb.eot +0 -0
  31. admin/assets/fonts/wphb.svg +11 -0
  32. admin/assets/fonts/wphb.ttf +0 -0
  33. admin/assets/fonts/wphb.woff +0 -0
  34. admin/assets/image/dev-team.png +0 -0
  35. admin/assets/image/dev-team@2x.png +0 -0
  36. admin/assets/image/graphic-hb-minify-summary.png +0 -0
  37. admin/assets/image/graphic-hb-minify-summary@2x.png +0 -0
  38. admin/assets/image/hb-graphic-dash-top.png +0 -0
  39. admin/assets/image/hb-graphic-dash-top@2x.png +0 -0
  40. admin/assets/image/hb-graphic-reports-disabled@1x.png +0 -0
  41. admin/assets/image/hb-graphic-reports-disabled@2x.png +0 -0
  42. admin/assets/image/hb-graphic-upsell-reports.png +0 -0
  43. admin/assets/image/hb-graphic-upsell-reports@2x.png +0 -0
  44. admin/assets/image/hb-graphic-upsell-uptime.png +0 -0
  45. admin/assets/image/hb-graphic-upsell-uptime@2x.png +0 -0
  46. admin/assets/image/hb-graphic-uptime-disabled@1x.png +0 -0
  47. admin/assets/image/hb-graphic-uptime-disabled@2x.png +0 -0
  48. admin/assets/image/hb-graphic-uptime-up.png +0 -0
  49. admin/assets/image/hb-graphic-uptime-up@2x.png +0 -0
  50. admin/assets/image/hummingbird-circle.png +0 -0
  51. admin/assets/image/hummingbird-circle@1x.jpg +0 -0
  52. admin/assets/image/hummingbird-modal-quicksetup.png +0 -0
  53. admin/assets/image/hummingbird-modal-quicksetup@2x.png +0 -0
  54. admin/assets/image/hummingbird-upsell-minify.png +0 -0
  55. admin/assets/image/hummingbird-upsell-minify@2x.png +0 -0
  56. admin/assets/image/icon-uptime-small.png +0 -0
  57. admin/assets/image/icon-uptime.png +0 -0
  58. admin/assets/image/loading.gif +0 -0
  59. admin/assets/image/smush-share-widget.png +0 -0
  60. admin/assets/image/smush-share-widget@2x.png +0 -0
  61. admin/assets/image/spin.gif +0 -0
  62. admin/assets/image/uptime-average-response-time-placeholder.png +0 -0
  63. admin/assets/image/websiteup.png +0 -0
  64. admin/assets/js/admin.min.js +2 -0
  65. admin/assets/js/admin.min.js.map +1 -0
  66. admin/class-admin-ajax.php +664 -0
  67. admin/class-admin-notices.php +153 -0
  68. admin/class-admin.php +285 -0
  69. admin/class-caching-page.php +268 -0
  70. admin/class-dashboard-page.php +548 -0
  71. admin/class-gzip-page.php +188 -0
  72. admin/class-minification-page.php +500 -0
  73. admin/class-performance-page.php +214 -0
  74. admin/class-uptime-page.php +315 -0
  75. admin/views/caching/cloudflare-meta-box-header.php +6 -0
  76. admin/views/caching/cloudflare-meta-box.php +131 -0
  77. admin/views/caching/enable-meta-box-footer.php +13 -0
  78. admin/views/caching/enable-meta-box-header.php +7 -0
  79. admin/views/caching/enable-meta-box.php +131 -0
  80. admin/views/caching/summary-meta-box-header.php +4 -0
  81. admin/views/caching/summary-meta-box.php +105 -0
  82. admin/views/dashboard/caching/module-meta-box-header.php +6 -0
  83. admin/views/dashboard/caching/module-meta-box.php +84 -0
  84. admin/views/dashboard/gzip/module-meta-box-header.php +4 -0
  85. admin/views/dashboard/gzip/module-meta-box.php +47 -0
  86. admin/views/dashboard/minification/cant-execute-php-meta-box.php +15 -0
  87. admin/views/dashboard/minification/disabled-meta-box.php +11 -0
  88. admin/views/dashboard/minification/module-meta-box-header.php +1 -0
  89. admin/views/dashboard/minification/module-meta-box.php +46 -0
  90. admin/views/dashboard/minification/network-module-meta-box.php +49 -0
  91. admin/views/dashboard/performance/disabled-meta-box.php +12 -0
  92. admin/views/dashboard/performance/module-error-meta-box.php +7 -0
  93. admin/views/dashboard/performance/module-meta-box-header.php +18 -0
  94. admin/views/dashboard/performance/module-meta-box.php +60 -0
  95. admin/views/dashboard/performance/running-test-meta-box.php +26 -0
  96. admin/views/dashboard/reports/meta-box-header.php +6 -0
  97. admin/views/dashboard/reports/no-membership-meta-box.php +49 -0
  98. admin/views/dashboard/smush/meta-box-header.php +6 -0
  99. admin/views/dashboard/smush/meta-box.php +54 -0
  100. admin/views/dashboard/uptime/disabled-meta-box.php +13 -0
  101. admin/views/dashboard/uptime/error-meta-box.php +7 -0
  102. admin/views/dashboard/uptime/module-meta-box-header.php +6 -0
  103. admin/views/dashboard/uptime/module-meta-box.php +45 -0
  104. admin/views/dashboard/uptime/no-membership-meta-box.php +22 -0
  105. admin/views/dashboard/welcome/meta-box.php +82 -0
  106. admin/views/dashboard/welcome/pro-membership-meta-box.php +22 -0
  107. admin/views/gzip/code-snippet-meta-box-header.php +7 -0
  108. admin/views/gzip/enable-meta-box-footer.php +12 -0
  109. admin/views/gzip/enable-meta-box.php +100 -0
  110. admin/views/gzip/enabled-meta-box.php +5 -0
  111. admin/views/gzip/summary-meta-box-header.php +4 -0
  112. admin/views/gzip/summary-meta-box.php +38 -0
  113. admin/views/meta-box.php +43 -0
  114. admin/views/minification/advanced-settings-header.php +6 -0
  115. admin/views/minification/advanced-settings.php +81 -0
  116. admin/views/minification/enqueued-files-empty-meta-box.php +39 -0
  117. admin/views/minification/enqueued-files-meta-box-footer.php +3 -0
  118. admin/views/minification/enqueued-files-meta-box-header.php +6 -0
  119. admin/views/minification/enqueued-files-meta-box.php +105 -0
  120. admin/views/minification/enqueued-files-rows.php +104 -0
  121. admin/views/minification/export-form.php +42 -0
  122. admin/views/minification/summary-meta-box.php +61 -0
  123. admin/views/modals/bulk-update-modal.php +72 -0
  124. admin/views/modals/check-files-modal.php +33 -0
  125. admin/views/modals/check-performance-modal.php +26 -0
  126. admin/views/modals/enable-cdn-modal.php +35 -0
  127. admin/views/modals/membership-modal.php +39 -0
  128. admin/views/modals/quick-setup-modal.php +16 -0
  129. admin/views/notice.php +10 -0
  130. admin/views/performance/empty-summary-meta-box.php +28 -0
  131. admin/views/performance/module-resume-meta-box.php +68 -0
  132. admin/views/performance/running-test-meta-box.php +25 -0
  133. admin/views/performance/summary-membership-meta-box.php +21 -0
  134. admin/views/performance/summary-meta-box-header.php +19 -0
  135. admin/views/performance/summary-meta-box.php +180 -0
  136. admin/views/tabs.php +33 -0
  137. admin/views/uptime/disabled-meta-box.php +19 -0
  138. admin/views/uptime/downtime-meta-box.php +51 -0
  139. admin/views/uptime/meta-box-header.php +4 -0
  140. admin/views/uptime/meta-box.php +48 -0
  141. admin/views/uptime/no-membership-meta-box.php +24 -0
  142. admin/views/uptime/summary-meta-box.php +62 -0
  143. admin/views/wphb-caching-page.php +19 -0
  144. admin/views/wphb-gzip-page.php +13 -0
  145. admin/views/wphb-minification-page.php +54 -0
  146. admin/views/wphb-page.php +18 -0
  147. admin/views/wphb-performance-page.php +30 -0
  148. admin/views/wphb-uptime-page.php +27 -0
  149. core/api/class-api.php +44 -0
  150. core/api/exception/exception.php +16 -0
  151. core/api/request/cloudflare.php +62 -0
  152. core/api/request/minify.php +63 -0
  153. core/api/request/request.php +297 -0
  154. core/api/request/wpmudev.php +99 -0
  155. core/api/service/cloudflare.php +68 -0
  156. core/api/service/minify.php +49 -0
  157. core/api/service/performance.php +46 -0
  158. core/api/service/service.php +21 -0
  159. core/api/service/uptime.php +76 -0
  160. core/class-abstract-module-server.php +71 -0
  161. core/class-abstract-module.php +90 -0
  162. core/class-core.php +135 -0
  163. core/class-installer.php +295 -0
  164. core/integration.php +3 -0
  165. core/integration/divi.php +58 -0
  166. core/modules-hooks.php +26 -0
  167. core/modules/class-module-caching.php +196 -0
  168. core/modules/class-module-cloudflare.php +371 -0
  169. core/modules/class-module-gzip.php +139 -0
  170. core/modules/class-module-minify.php +915 -0
  171. core/modules/class-module-performance.php +143 -0
  172. core/modules/class-module-smush.php +54 -0
  173. core/modules/class-module-uptime.php +144 -0
  174. core/modules/dummy/dummy-image.png +0 -0
  175. core/modules/dummy/dummy-js.js +39 -0
  176. core/modules/dummy/dummy-media.mp3 +0 -0
  177. core/modules/dummy/dummy-style.css +162 -0
  178. core/modules/minify/class-errors-controller.php +185 -0
  179. core/modules/minify/class-minify-group.php +1412 -0
  180. core/modules/minify/class-minify-groups-list.php +330 -0
  181. core/modules/minify/class-minify-housekeeper.php +41 -0
  182. core/modules/minify/class-minify-sources-collector.php +80 -0
  183. core/modules/minify/class-uri-rewriter.php +306 -0
  184. core/settings-hooks.php +91 -0
  185. externals/shared-ui/contributors.txt +1 -0
  186. externals/shared-ui/font/WPMU DEV Dashboard.json +1396 -0
  187. externals/shared-ui/font/WPMU-DEV-App-Icons.eot +0 -0
  188. externals/shared-ui/font/WPMU-DEV-App-Icons.svg +56 -0
_src/admin/js/admin-app.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ jQuery(document).ready( function() {
2
+ WPHB_Admin.init();
3
+ });
_src/admin/js/admin-caching.js ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Fetcher from './utils/fetcher';
2
+
3
+ ( function( $ ) {
4
+ 'use strict';
5
+ WPHB_Admin.caching = {
6
+
7
+ module: 'caching',
8
+ selectedServer: '',
9
+ $serverSelector: null,
10
+ $serverInstructions: [],
11
+ $expirySelectors: [],
12
+ $snippets: [],
13
+
14
+ init: function () {
15
+ let self = this,
16
+ cachingMetabox = $('#wphb-box-caching-enable'),
17
+ cachingContent = cachingMetabox.find('.box-content'),
18
+ cachingContentSpinner = cachingContent.find('.spinner'),
19
+ cachingFooter = cachingMetabox.find('.box-footer');
20
+
21
+ if ( wphbCachingStrings )
22
+ self.strings = wphbCachingStrings;
23
+
24
+ this.$serverSelector = $( '#wphb-server-type' );
25
+ this.selectedServer = this.$serverSelector.val();
26
+ //this.$spinner = $('#wphb-box-caching-enable .spinner');
27
+
28
+ self.$snippets.apache = $('#wphb-code-snippet-apache').find('pre').first();
29
+ self.$snippets.nginx = $('#wphb-code-snippet-nginx').find('pre').first();
30
+
31
+ let instructionsList = $( '.wphb-server-instructions' );
32
+ instructionsList.each( function() {
33
+ self.$serverInstructions[ $(this).data('server') ] = $(this);
34
+ });
35
+
36
+ let expirySelectors = $( '.wphb-expiry-select' );
37
+
38
+ expirySelectors.each( function() {
39
+ const type = $(this).data('type');
40
+ if ( type ) {
41
+ $(this).change( function() {
42
+ //self.$spinner.css( 'visibility', 'visible' );
43
+ cachingContent.find('.wphb-content').hide();
44
+ cachingFooter.hide();
45
+ cachingContentSpinner.fadeIn();
46
+ $('.wphb-notice').hide();
47
+
48
+ // Expiration selector has changed
49
+ ( function( element ) {
50
+ const value = $( element ).val();
51
+ // Change the plugin settings
52
+ Fetcher.caching.setExpiration( type, value )
53
+ .then( () => {
54
+ // And reload the code snippet
55
+ self.reloadSnippets();
56
+ });
57
+ return false;
58
+ })( this );
59
+ });
60
+ }
61
+
62
+ });
63
+
64
+ this.showServerInstructions( this.selectedServer );
65
+
66
+ this.$serverSelector.change( function() {
67
+ let value = $(this).val();
68
+ self.hideCurrentInstructions();
69
+ self.showServerInstructions( value );
70
+ self.setServer(value);
71
+ self.selectedServer = value;
72
+ });
73
+
74
+ $( '#toggle-apache-instructions').click( function( e ) {
75
+ e.preventDefault();
76
+ $('.apache-instructions').slideToggle();
77
+ });
78
+
79
+ $( '#toggle-litespeed-instructions').click( function( e ) {
80
+ e.preventDefault();
81
+ $('.litespeed-instructions').slideToggle();
82
+ });
83
+
84
+
85
+ return this;
86
+ },
87
+
88
+ setServer: function( value ) {
89
+ Fetcher.caching.setServer( value );
90
+ },
91
+
92
+ hideCurrentInstructions: function() {
93
+ let selected = this.selectedServer;
94
+ if ( this.$serverInstructions[ selected ] ) {
95
+ this.$serverInstructions[ selected ].hide();
96
+ }
97
+ },
98
+
99
+ showServerInstructions: function( server ) {
100
+ if ( typeof this.$serverInstructions[ server ] !== 'undefined' ) {
101
+ this.$serverInstructions[ server ].show();
102
+ }
103
+
104
+ if ( 'apache' === server || 'LiteSpeed' === server ) {
105
+ $( '#enable-cache-wrap').show();
106
+ }
107
+ else {
108
+ $( '#enable-cache-wrap').hide();
109
+ }
110
+ },
111
+
112
+ reloadSnippets: function() {
113
+ let self = this;
114
+ let stop = false;
115
+ for ( let i in self.$snippets ) {
116
+ if ( self.$snippets.hasOwnProperty( i ) ) {
117
+ Fetcher.caching.reloadSnippets( i )
118
+ .then( ( response ) => {
119
+ if ( stop ) {
120
+ return;
121
+ }
122
+
123
+ self.$snippets[response.type].text( response.code );
124
+
125
+ // Make sure that we only do things when server displayed is the processed one
126
+ if ( response.type !== self.selectedServer ) {
127
+ return;
128
+ }
129
+
130
+ if ( 'apache' === response.type && response.updatedFile ) {
131
+ $( '#wphb-notice-code-snippet-htaccess-updated' ).show();
132
+ location.href = self.strings.recheckURL + '&caching-updated=true';
133
+ } else if ( 'apache' === response.type && self.strings.cacheEnabled && ! response.updatedFile ) {
134
+ $( '#wphb-notice-code-snippet-htaccess-error' ).show();
135
+ location.href = self.strings.htaccessErrorURL;
136
+ } else {
137
+ $( '#wphb-notice-code-snippet-updated' ).show();
138
+ location.href = self.strings.recheckURL + '&caching-updated=true';
139
+ }
140
+ //self.$spinner.css( 'visibility', 'hidden' );
141
+ });
142
+ }
143
+ }
144
+ }
145
+ };
146
+ }( jQuery ));
_src/admin/js/admin-cloudflare.js ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Fetcher from './utils/fetcher';
2
+
3
+ ( function( $ ) {
4
+ WPHB_Admin.cloudflare = {
5
+ module: 'cloudflare',
6
+ $cfSelector: false,
7
+ $spinner: false,
8
+
9
+ init: function () {
10
+ this.$spinner = $('.wphb-spinner');
11
+ this.$cfSelector = $('#wphb-caching-cloudflare-summary-set-expiry');
12
+ let self = this;
13
+ if ( wphb.cloudflare.is.connected ) {
14
+ this.$cfSelector.change( function() {
15
+ self.setExpiry.call( self, [this] );
16
+ } );
17
+ }
18
+
19
+ return this;
20
+ },
21
+
22
+ setExpiry: function( selector ) {
23
+ this.displaySpinner();
24
+ const value = $(selector).val();
25
+ Fetcher.cloudflare.setExpiration( value )
26
+ .then( () => {
27
+ window.location.reload();
28
+ });
29
+ },
30
+
31
+ displaySpinner: function() {
32
+ this.$spinner.css( 'visibility', 'visible' );
33
+ }
34
+ };
35
+ }( jQuery ) );
_src/admin/js/admin-dashboard-cloudflare.js ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Fetcher from './utils/fetcher';
2
+
3
+ ( function( $ ) {
4
+ WPHB_Admin.DashboardCloudFlare = {
5
+ init: function( settings ) {
6
+ this.currentStep = settings.currentStep;
7
+ this.data = settings;
8
+ this.email = settings.email;
9
+ this.apiKey = settings.apiKey;
10
+ this.$stepsContainer = $('#cloudflare-steps');
11
+ this.$infoBox = $('#cloudflare-info');
12
+ this.$spinner = $( '.cloudflare-spinner' );
13
+ this.$deactivateButton = $('#wphb-box-dashboard-cloudflare').find('.box-title .buttons');
14
+
15
+ this.renderStep( this.currentStep );
16
+
17
+ $('body').on( 'click', '.cloudflare-clear-cache .button', function(e ) {
18
+ e.preventDefault();
19
+ this.purgeCache.apply( $(e.target), [this] );
20
+ }.bind(this));
21
+
22
+ },
23
+
24
+ purgeCache: function( self ) {
25
+ // Show spinner
26
+ const $button = this;
27
+ $button.attr( 'disabled', true );
28
+ self.showSpinner();
29
+
30
+ Fetcher.cloudflare.purgeCache()
31
+ .then( () => {
32
+ // Show notice
33
+ const $notice = $('#wphb-notice-cloudflare-purge-cache');
34
+ window.scrollTo(0, 0);
35
+ $notice.slideDown();
36
+ setTimeout(function() {
37
+ $notice.slideUp();
38
+ }, 5e3);
39
+ // Remove spinner
40
+ $button.removeAttr( 'disabled' );
41
+ self.hideSpinner();
42
+ });
43
+ },
44
+
45
+ renderStep: function( step ) {
46
+ const template = WPHB_Admin.DashboardCloudFlare.template( '#cloudflare-step-' + step );
47
+ const content = template( this.data );
48
+ const self = this;
49
+
50
+ if ( content ) {
51
+ this.currentStep = step;
52
+ this.$stepsContainer
53
+ .hide()
54
+ .html( template( this.data ) )
55
+ .fadeIn()
56
+ .find( 'form' )
57
+ .on( 'submit', function( e ) {
58
+ e.preventDefault();
59
+ self.submitStep.call( self, $(this) );
60
+ });
61
+
62
+ this.$spinner = this.$stepsContainer.find( '.cloudflare-spinner' );
63
+ }
64
+
65
+ this.bindEvents();
66
+ },
67
+
68
+ bindEvents: function() {
69
+ const $howToInstructions = $('#cloudflare-how-to');
70
+
71
+ $howToInstructions.hide();
72
+
73
+ $('#cloudflare-how-to-title > a').click( function( e ) {
74
+ e.preventDefault();
75
+ $howToInstructions.toggle();
76
+ });
77
+
78
+ this.$stepsContainer.find( 'select' ).each( function() {
79
+ WDP.wpmuSelect( this );
80
+ });
81
+
82
+ if ( 'final' === this.currentStep ) {
83
+ this.$deactivateButton.removeClass( 'hidden' );
84
+ } else {
85
+ this.$deactivateButton.addClass( 'hidden' );
86
+ }
87
+ },
88
+
89
+ emptyInfoBox: function() {
90
+ this.$infoBox.html('');
91
+ this.$infoBox.removeClass();
92
+ },
93
+
94
+ showInfoBox: function( message ) {
95
+ this.$infoBox.addClass( 'wphb-notice' );
96
+ this.$infoBox.addClass( 'wphb-notice-error' );
97
+ this.$infoBox.text( message );
98
+ },
99
+
100
+ showSpinner: function() {
101
+ this.$spinner.css( 'visibility', 'visible' );
102
+ },
103
+
104
+ hideSpinner: function() {
105
+ this.$spinner.css( 'visibility', 'hidden' );
106
+ },
107
+
108
+ submitStep: function( $form ) {
109
+ const self = this;
110
+
111
+ $form.find( 'input[type=submit]' ).attr( 'disabled', 'true' );
112
+ this.emptyInfoBox();
113
+ this.showSpinner();
114
+
115
+ Fetcher.cloudflare.connect( this.currentStep, $form.serialize(), this.data )
116
+ .then( ( response ) => {
117
+ self.data = response.newData;
118
+ self.renderStep( response.nextStep );
119
+
120
+ if ( response.nextStep === 'final' ) {
121
+ window.location.href = response.redirect;
122
+ }
123
+ })
124
+ .catch( ( error ) => {
125
+ self.showInfoBox( error );
126
+ });
127
+
128
+ $form.find( 'input[type=submit]' ).removeAttr( 'disabled' );
129
+ self.hideSpinner();
130
+ }
131
+ };
132
+
133
+ WPHB_Admin.DashboardCloudFlare.template = _.memoize(function ( id ) {
134
+ let compiled,
135
+ options = {
136
+ evaluate: /<#([\s\S]+?)#>/g,
137
+ interpolate: /\{\{\{([\s\S]+?)\}\}\}/g,
138
+ escape: /\{\{([^\}]+?)\}\}(?!\})/g,
139
+ variable: 'data'
140
+ };
141
+
142
+ return function ( data ) {
143
+ _.templateSettings = options;
144
+ compiled = compiled || _.template( $( id ).html() );
145
+ return compiled( data );
146
+ };
147
+ });
148
+ }(jQuery));
_src/admin/js/admin-dashboard.js ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Fetcher from './utils/fetcher';
2
+
3
+ ( function( $ ) {
4
+ WPHB_Admin.dashboard = {
5
+ module: 'dashboard',
6
+
7
+ init: function() {
8
+ const self = this;
9
+
10
+ if (wphbDashboardStrings)
11
+ this.strings = wphbDashboardStrings;
12
+
13
+ $('#wphb-activate-minification').change( function() {
14
+ const value = $(this).val();
15
+ Fetcher.dashboard.toggleMinification( value )
16
+ .then( () => {
17
+ // If disabled, uncheck CDN checkbox and disable it.
18
+ const CDNcheckbox = $('input[name="use_cdn"]');
19
+ if ( 'false' === value ) {
20
+ CDNcheckbox.prop( 'checked', false );
21
+ CDNcheckbox.prop( 'disabled', true );
22
+ } else {
23
+ CDNcheckbox.prop( 'disabled', false );
24
+ }
25
+ self.showNotice();
26
+ });
27
+ });
28
+
29
+ $('#use_cdn').change( function() {
30
+ const value = $(this).is(':checked');
31
+ Fetcher.minification.toggleCDN( value )
32
+ .then( () => {
33
+ self.showNotice();
34
+ });
35
+ });
36
+
37
+ $('.wphb-performance-report-item').click( function() {
38
+ const url = $(this).data( 'performance-url' );
39
+ if ( url ) {
40
+ location.href = url;
41
+ }
42
+ });
43
+ return this;
44
+ },
45
+
46
+ /**
47
+ * Notice on settings update.
48
+ */
49
+ showNotice: function () {
50
+ const notice = $('#wphb-notice-minification-settings-updated');
51
+ notice.slideDown();
52
+ setTimeout( function() {
53
+ notice.slideUp();
54
+ }, 5000 );
55
+ },
56
+
57
+ /**
58
+ * Run quick setup.
59
+ */
60
+ startQuickSetup: function () {
61
+ // Show quick setup modal
62
+ WDP.showOverlay( '#wphb-quick-setup-modal', { class: 'wphb-modal small wphb-quick-setup-modal no-close' } );
63
+ },
64
+
65
+ /**
66
+ * Skip quick setup.
67
+ */
68
+ skipSetup: function () {
69
+ Fetcher.dashboard.skipSetup()
70
+ .then( () => {
71
+ window.location.reload(true);
72
+ });
73
+ },
74
+
75
+ /**
76
+ * Run performance test after quick setup.
77
+ */
78
+ runPerformanceTest: function() {
79
+ // Show quick setup modal
80
+ WDP.showOverlay("#run-performance-test-modal", { class: 'wphb-modal small wphb-progress-modal no-close' } );
81
+
82
+ // Run performance test
83
+ const module = WPHB_Admin.getModule('performance');
84
+ module.performanceTest( this.strings.finishedTestURLsLink );
85
+ }
86
+ };
87
+ }( jQuery ));
_src/admin/js/admin-gzip.js ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Fetcher from './utils/fetcher';
2
+
3
+ (function($) {
4
+ WPHB_Admin.gzip = {
5
+ module: "gzip",
6
+ selectedServer: "",
7
+ $serverSelector: null,
8
+ $serverInstructions: [],
9
+
10
+ init: function() {
11
+ const self = this;
12
+
13
+ this.$serverSelector = $("#wphb-server-type");
14
+ this.selectedServer = this.$serverSelector.val();
15
+ let instructionsList = $(".wphb-server-instructions");
16
+ instructionsList.each(function() {
17
+ self.$serverInstructions[$(this).data("server")] = $(this);
18
+ });
19
+ this.showServerInstructions(this.selectedServer);
20
+ this.$serverSelector.change(function() {
21
+ const value = $(this).val();
22
+ self.hideCurrentInstructions();
23
+ self.showServerInstructions(value);
24
+ self.setServer(value);
25
+ self.selectedServer = value;
26
+ });
27
+ $("#toggle-apache-instructions").click(function(e) {
28
+ e.preventDefault();
29
+ $(".apache-instructions").toggle();
30
+ });
31
+ $("#toggle-litespeed-instructions").click(function(e) {
32
+ e.preventDefault();
33
+ $(".litespeed-instructions").toggle();
34
+ });
35
+ return this;
36
+ },
37
+
38
+ hideCurrentInstructions: function() {
39
+ const selected = this.selectedServer;
40
+ if (this.$serverInstructions[selected]) {
41
+ this.$serverInstructions[selected].hide();
42
+ }
43
+ },
44
+
45
+ showServerInstructions: function(server) {
46
+ if (typeof this.$serverInstructions[server] !== "undefined") {
47
+ this.$serverInstructions[server].show();
48
+ }
49
+ if ("apache" === server || 'LiteSpeed' === server) {
50
+ $("#enable-cache-wrap").show();
51
+ } else {
52
+ $("#enable-cache-wrap").hide();
53
+ }
54
+ },
55
+
56
+ setServer: function( value ) {
57
+ Fetcher.caching.setServer( value );
58
+ },
59
+ };
60
+ })(jQuery);
_src/admin/js/admin-main.js ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ( function( $ ) {
2
+ 'use strict';
3
+
4
+ let WPHB_Admin = {
5
+ modules: [],
6
+ // Common functionality to all screens
7
+ init: function() {
8
+
9
+ function updatePerformanceGraph($wrap){
10
+ let $item = $wrap.find('.wphb-score-result-label'),
11
+ val = parseInt($item.text(), 10) || 100,
12
+ $circle = $wrap.find(".wphb-score-graph-result"),
13
+ r, c, pct
14
+ ;
15
+ r = $circle.attr('r');
16
+ c = Math.PI*(r*2);
17
+
18
+ if (val < 0) { val = 0;}
19
+ if (val > 100) { val = 100;}
20
+
21
+ pct = ((100-val)/100)*c;
22
+
23
+ $circle.css({ strokeDashoffset: pct});
24
+ }
25
+
26
+ function updatePerformanceResultsGraphs(){
27
+
28
+ // Update Overall Score
29
+ $(".wphb-performance-report-overall-score").each(function(){
30
+ updatePerformanceGraph($(this));
31
+ });
32
+
33
+ // Update Current Score
34
+ $(".wphb-performance-report-current-score").each(function(){
35
+ updatePerformanceGraph($(this));
36
+ });
37
+
38
+ // Update All Scores
39
+ $(".wphb-performance-report-item-score").each(function(){
40
+ updatePerformanceGraph($(this));
41
+ });
42
+
43
+ }
44
+ window.register_events_performance = function(){
45
+ setTimeout(updatePerformanceResultsGraphs, 500);
46
+ };
47
+ $(function(){ setTimeout(updatePerformanceResultsGraphs, 500); });
48
+
49
+ },
50
+ initModule: function( module ) {
51
+ if ( this.hasOwnProperty( module ) ) {
52
+ this.modules[ module ] = this[ module ].init();
53
+ return this.modules[ module ];
54
+ }
55
+
56
+ return {};
57
+ },
58
+ getModule: function( module ) {
59
+ if ( typeof this.modules[ module ] !== 'undefined' )
60
+ return this.modules[ module ];
61
+ else
62
+ return this.initModule( module );
63
+ }
64
+ };
65
+
66
+
67
+ WPHB_Admin.utils = {
68
+
69
+ membershipModal: {
70
+ open: function() {
71
+ $( '#wphb-upgrade-membership-modal-link').trigger( 'click' );
72
+ }
73
+ },
74
+
75
+ post: function( data, module ) {
76
+ data.action = 'wphb_ajax';
77
+ data.module = module;
78
+ return $.ajax({
79
+ url: ajaxurl,
80
+ method: 'POST',
81
+ data: data
82
+ });
83
+ }
84
+ };
85
+
86
+ WPHB_Admin.notices = {
87
+
88
+ init: function() {
89
+ $( '.wphb-notice:not(.notice) a.wphb-dismiss').click( function( e ) {
90
+ e.preventDefault();
91
+ let id = $(this).data( 'id' );
92
+ let nonce = $(this).data( 'nonce' );
93
+
94
+ $(this).parent( '.error' ).hide();
95
+ });
96
+ }
97
+ };
98
+
99
+ window.WPHB_Admin = WPHB_Admin;
100
+
101
+ }( jQuery ) );
_src/admin/js/admin-minification.js ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Fetcher from './utils/fetcher';
2
+ import { __, getLink } from './utils/helpers';
3
+ import Row from './minification/Row';
4
+ import RowsCollection from './minification/RowsCollection';
5
+
6
+ ( function( $ ) {
7
+ 'use strict';
8
+
9
+ WPHB_Admin.minification = {
10
+
11
+ $checkFilesButton: null,
12
+ $checkFilesResultsContainer : null,
13
+ module: 'minification',
14
+ checkURLSList: null,
15
+ checkedURLS: 0,
16
+ $spinner: null,
17
+
18
+ init: function() {
19
+ const self = this;
20
+
21
+ // Filter action button on Minification page
22
+ $('#wphb-minification-filter-button').on('click', function(e) {
23
+ e.preventDefault();
24
+ $('#wphb-minification-filter').toggle('slow');
25
+ });
26
+
27
+ // Check files button
28
+ this.$checkFilesButton = $( '#check-files' );
29
+ this.$disableMinification = $('#wphb-disable-minification');
30
+ this.$spinner = $('.spinner');
31
+
32
+ if ( this.$checkFilesButton.length ) {
33
+ this.$checkFilesButton.click( function( e ) {
34
+ e.preventDefault();
35
+ $(this).attr('disabled', true);
36
+ self.checkFiles( getLink( 'minification' ) );
37
+ });
38
+ }
39
+
40
+ $('.wphb-discard').click( function(e) {
41
+ e.preventDefault();
42
+
43
+ if ( confirm( __( 'discardAlert' ) ) ) {
44
+ location.reload();
45
+ }
46
+ return false;
47
+
48
+ });
49
+
50
+ $( '.wphb-enqueued-files input' ).on( 'change', function() {
51
+ $('.wphb-discard').attr( 'disabled', false );
52
+ });
53
+
54
+ $('#use_cdn').change( function() {
55
+ const cdn_value = $(this).is(':checked');
56
+ Fetcher.minification.toggleCDN( cdn_value )
57
+ .then( () => {
58
+ const notice = $('#wphb-notice-minification-advanced-settings-updated');
59
+ notice.slideDown();
60
+ setTimeout( function() {
61
+ notice.slideUp();
62
+ }, 5000 );
63
+ });
64
+ });
65
+
66
+ this.$disableMinification.change( function() {
67
+ const value = $(this).is(':checked');
68
+
69
+ self.$spinner.css( 'visibility', 'visible' );
70
+
71
+ if ( self.timer && value ) {
72
+ clearTimeout( self.timer );
73
+ self.$spinner.css( 'visibility', 'hidden' );
74
+ }
75
+
76
+ self.timer = setTimeout( function() {
77
+ Fetcher.minification.toggleMinification( value )
78
+ .then( () => {
79
+ location.reload();
80
+ });
81
+ }, 3000 );
82
+
83
+
84
+ });
85
+
86
+ this.rowsCollection = new WPHB_Admin.minification.RowsCollection();
87
+
88
+ const rows = $('.wphb-border-row');
89
+
90
+ rows.each( function( index, row ) {
91
+ let _row;
92
+ if ( $(row).data('filter-secondary') ) {
93
+ _row = new WPHB_Admin.minification.Row( $(row), $(row).data('filter'), $(row).data('filter-secondary') );
94
+ }
95
+ else {
96
+ _row = new WPHB_Admin.minification.Row( $(row), $(row).data('filter') );
97
+ }
98
+ self.rowsCollection.push( _row );
99
+ });
100
+
101
+ $('#wphb-s').keyup( function() {
102
+ self.rowsCollection.addFilter( $(this).val(), 'primary' );
103
+ self.rowsCollection.applyFilters();
104
+ });
105
+
106
+ $('#wphb-secondary-filter').change( function() {
107
+ self.rowsCollection.addFilter( $(this).val(), 'secondary' );
108
+ self.rowsCollection.applyFilters();
109
+ });
110
+
111
+ $('.filter-toggles').change( function() {
112
+ const element = $(this);
113
+ const what = element.data('toggles');
114
+ const value = element.prop( 'checked' );
115
+ const visibleItems = self.rowsCollection.getVisibleItems();
116
+
117
+ for ( let i in visibleItems ) {
118
+ visibleItems[i].change( what, value );
119
+ }
120
+ });
121
+
122
+ // Files selectors
123
+ const filesList = $('input.wphb-minification-file-selector');
124
+ filesList.click( function() {
125
+ const $this = $( this );
126
+ const element = self.rowsCollection.getItemById( $this.data( 'type' ), $this.data( 'handle' ) );
127
+ if ( ! element ) {
128
+ return;
129
+ }
130
+
131
+ if ( $this.is( ':checked' ) ) {
132
+ element.select();
133
+ }
134
+ else {
135
+ element.unSelect();
136
+ }
137
+ });
138
+
139
+ const selectAll = $('#minification-bulk-file');
140
+ selectAll.click( function() {
141
+ const $this = $( this );
142
+ let items = self.rowsCollection.getItems();
143
+ for ( let i in items ) {
144
+ if ( items.hasOwnProperty( i ) ) {
145
+ if ( $this.is( ':checked' ) ) {
146
+ items[i].select();
147
+ }
148
+ else {
149
+ items[i].unSelect();
150
+ }
151
+ }
152
+ }
153
+ });
154
+
155
+ // Include/exclude file checkbox
156
+ $('.toggle-cross').on('click', function() {
157
+ const $this = $(this);
158
+ const checkbox = $this.find( 'input.toggle-include' );
159
+ const row = self.rowsCollection.getItemById( $this.data( 'type' ), $this.data( 'handle' ) );
160
+ // Mark the item as include or not in the rows list
161
+ if ( row ) {
162
+ row.change( 'include', ! checkbox.prop( 'checked' ) );
163
+ row.getElement().find( 'input:not(.toggle-include)' ).prop('disabled', ! checkbox.prop( 'checked' ) );
164
+ }
165
+ });
166
+
167
+ // Handle two CDN checkboxes on Minification page
168
+ const checkboxes = $("input[type=checkbox][name=use_cdn]");
169
+ checkboxes.change( function() {
170
+ const checkedState = $(this).prop('checked');
171
+
172
+ checkboxes.each( function() {
173
+ this.checked = checkedState;
174
+ });
175
+ });
176
+
177
+ /* Show details of minification row on mobile devices */
178
+ $('body').on('click', '.wphb-minification-file-details', function() {
179
+ if ( window.innerWidth < 783 ) {
180
+ $(this).parent().find('.wphb-minification-row-details').toggle('slow');
181
+ }
182
+ });
183
+
184
+ /*
185
+ Catch window resize and revert styles for responsive divs
186
+ 1/4 of a second should be enough to trigger during device rotations (from portrait to landscape mode)
187
+ */
188
+ let minification_resize_rows = _.debounce(function() {
189
+
190
+ if ( window.innerWidth >= 783 ) {
191
+ $('.wphb-minification-row-details').css('display', 'flex');
192
+ } else {
193
+ $('.wphb-minification-row-details').css('display', 'none');
194
+ }
195
+
196
+ }, 250);
197
+
198
+ window.addEventListener('resize', minification_resize_rows);
199
+
200
+ return this;
201
+ },
202
+
203
+ checkFiles: function( redirect ) {
204
+ const self = this;
205
+
206
+ if ( typeof redirect === 'undefined' )
207
+ redirect = false;
208
+
209
+ if ( ! self.minificationStarted ) {
210
+ // Store the progress in session storage to persist during page reloads
211
+ // If there is no previous value, we init one with 10%
212
+ if ( sessionStorage.getItem('progress') === null ) {
213
+ sessionStorage.setItem('progress', 10);
214
+ }
215
+
216
+ // Update progress bar
217
+ const progress = sessionStorage.getItem('progress');
218
+ this.updateProgressBar( progress );
219
+
220
+ // Send an AJAX request that will flag the check files as started
221
+ Fetcher.minification.startCheck( progress )
222
+ .then( ( response ) => {
223
+ // Set the number of steps to be used in percentage count. Only if not set already.
224
+ if ( ( typeof response.steps !== 'undefined' ) && ( sessionStorage.getItem('steps') === null ) ) {
225
+ sessionStorage.setItem('steps', response.steps);
226
+ }
227
+
228
+ self.minificationStarted = true;
229
+ self.checkFiles( redirect );
230
+ });
231
+ }
232
+ else {
233
+ const progress = sessionStorage.getItem('progress');
234
+ const step = Math.round( 80 / sessionStorage.getItem('steps') );
235
+ Fetcher.minification.checkStep( progress, step )
236
+ .then( ( response ) => {
237
+ if ( typeof response.finished !== 'undefined' ) {
238
+ // Finished
239
+ if ( response.finished && redirect ) {
240
+ // Clear session storage
241
+ sessionStorage.clear();
242
+
243
+ // Update progress bar
244
+ this.updateProgressBar( 100 );
245
+
246
+ // Show enable cdn modal only for members
247
+ if ( true === response.show_cdn && $('#enable-cdn-modal').length ) {
248
+ WDP.showOverlay( '#enable-cdn-modal', { class: 'wphb-modal small wphb-progress-modal no-close' } );
249
+ } else {
250
+ window.location.href = redirect;
251
+ }
252
+ }
253
+ // Next step
254
+ else if ( ! response.finished ) {
255
+ // Store the progress in session storage to persist during page reloads
256
+ let progress = parseInt( sessionStorage.getItem('progress') ) + Math.round( 80 / sessionStorage.getItem('steps') );
257
+ sessionStorage.setItem( 'progress', progress );
258
+
259
+ // Update progress bar.
260
+ this.updateProgressBar( progress );
261
+
262
+ // Wait 3 seconds before calling again
263
+ window.setTimeout( function() {
264
+ self.checkFiles( redirect );
265
+ }, 3000);
266
+ }
267
+ } else {
268
+ // Error
269
+ window.location.href = redirect;
270
+ }
271
+ });
272
+ } // End else
273
+
274
+ }, // End checkFiles
275
+
276
+ updateProgressBar: function( progress, cancel = false ) {
277
+ if ( progress > 100 ) {
278
+ progress = 100;
279
+ }
280
+ // Update progress bar
281
+ $('.wphb-scan-progress .wphb-scan-progress-text span').text( progress + '%' );
282
+ if ( progress >= 90 ) {
283
+ $('.wphb-progress-state .wphb-progress-state-text').text('Finalizing...');
284
+ }
285
+ if ( cancel ) {
286
+ $('.wphb-progress-state .wphb-progress-state-text').text('Cancelling...');
287
+ }
288
+ $('.wphb-scan-progress .wphb-scan-progress-bar span').width( progress + '%' );
289
+ },
290
+
291
+ cancelScan: function() {
292
+ Fetcher.minification.cancelScan()
293
+ .then( () => {
294
+ // Clear session storage
295
+ sessionStorage.clear();
296
+
297
+ this.updateProgressBar( 0, true );
298
+
299
+ // Reload page
300
+ window.location.href = getLink( 'minification' );
301
+ });
302
+ }
303
+
304
+ }; // End WPHB_Admin.minification
305
+
306
+ WPHB_Admin.minification.Row = Row;
307
+ WPHB_Admin.minification.RowsCollection = RowsCollection;
308
+
309
+ }( jQuery ));
_src/admin/js/admin-performance.js ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Fetcher from './utils/fetcher';
2
+
3
+ ( function( $ ) {
4
+ 'use strict';
5
+ WPHB_Admin.performance = {
6
+
7
+ module: 'performance',
8
+ iteration: 0,
9
+ progress: 0,
10
+
11
+ init: function () {
12
+
13
+ let self = this;
14
+ let body = $('body');
15
+
16
+ if (wphbPerformanceStrings)
17
+ this.strings = wphbPerformanceStrings;
18
+
19
+ this.$runTestButton = $('#run-performance-test');
20
+
21
+ let performanceReportTable = $(".performance-report-table");
22
+
23
+ performanceReportTable.off('click', 'button');
24
+ performanceReportTable.on('click', '.wphb-performance-report-item-cta .additional-content-opener' && 'tr.wphb-performance-report-item', function (e) {
25
+ e.preventDefault();
26
+
27
+ let getParentPerformanceItem = $(this).closest(".wphb-performance-report-item"),
28
+ getNextAdditionalContentRow = getParentPerformanceItem.nextUntil(".wphb-performance-report-item");
29
+
30
+ getNextAdditionalContentRow.toggleClass("wphb-performance-report-item-additional-content-opened");
31
+
32
+ if (getNextAdditionalContentRow.hasClass("wphb-performance-report-item-additional-content-opened")) {
33
+ getParentPerformanceItem.addClass("wphb-performance-report-item-opened");
34
+ } else {
35
+ getParentPerformanceItem.removeClass("wphb-performance-report-item-opened");
36
+ }
37
+
38
+ });
39
+
40
+ if (this.$runTestButton.length) {
41
+ this.$runTestButton.click(function (e) {
42
+ e.preventDefault();
43
+ $(this).attr('disabled', true);
44
+ self.performanceTest(self.strings.finishedTestURLsLink);
45
+ });
46
+ }
47
+
48
+ // If a hash is present in URL, let's open the rule extra content
49
+ const hash = window.location.hash;
50
+ if (hash) {
51
+ const row = $(hash);
52
+ if (row.length) {
53
+ row.find('.trigger-additional-content').trigger('click');
54
+ }
55
+
56
+ }
57
+
58
+ // Schedule show/hide day of week
59
+ $('select[name="email-frequency"]').change(function () {
60
+ if ( '1' === $(this).val() ) {
61
+ $(this).closest('.schedule-box').find('div.days-container').hide();
62
+ } else {
63
+ $(this).closest('.schedule-box').find('div.days-container').show();
64
+ }
65
+ }).change();
66
+
67
+ // Remove recipient
68
+ body.on('click', '.wphb-remove-recipient', function (e) {
69
+ e.preventDefault();
70
+ $(this).closest('.recipient').remove();
71
+ $('.scan-settings').find("input[id='scan_recipient'][value=" + $(this).attr('data-id') + "]").remove();
72
+ });
73
+
74
+ // Add recipient
75
+ $('#add-receipt').click(function () {
76
+ const email = $("#wphb-username-search").val();
77
+ const name = $("#wphb-first-name").val();
78
+ Fetcher.performance.addRecipient( email, name )
79
+ .then( ( response ) => {
80
+ const user_row = $('<div class="recipient"/>');
81
+
82
+ const img = $('<img/>').attr({
83
+ 'src': response.avatar,
84
+ 'width': '30'
85
+ });
86
+ const name = $('<span/>').html(response.name);
87
+
88
+ user_row.append('<span class="name"/>');
89
+ user_row.find('.name').append( img, name);
90
+
91
+
92
+ user_row.append($('<span class="email"/>').html(email));
93
+ user_row.append($('<a/>').attr({
94
+ 'data-id': response.user_id,
95
+ 'class': 'remove float-r wphb-remove-recipient',
96
+ 'href': '#',
97
+ 'alt': self.strings.removeButtonText
98
+ }).html('<i class="dev-icon dev-icon-cross"></i>'));
99
+
100
+ $('<input>').attr({
101
+ type: 'hidden',
102
+ id: 'scan_recipient',
103
+ name: 'email-recipients[]',
104
+ value: JSON.stringify( { email: response.email, name: response.name } )
105
+ }).appendTo(user_row);
106
+
107
+ $('.receipt .recipients').append(user_row);
108
+ $("#wphb-username-search").val('');
109
+ $("#wphb-first-name").val('');
110
+ })
111
+ .catch( ( error ) => {
112
+ alert( error.message );
113
+ } );
114
+ return false;
115
+ });
116
+
117
+ // Save report settings
118
+ body.on('submit', '.scan-frm', function (e) {
119
+ e.preventDefault();
120
+ const form_data = $(this).serialize();
121
+ let that = $(this);
122
+
123
+ that.find('.button').attr('disabled', 'disabled');
124
+
125
+ Fetcher.performance.saveReportsSettings( form_data )
126
+ .then( () => {
127
+ that.find('.button').removeAttr('disabled');
128
+ self.showUpdateMessage();
129
+ });
130
+ return false;
131
+ });
132
+
133
+ return this;
134
+
135
+ },
136
+
137
+ showUpdateMessage: function () {
138
+ const notice = $('#wphb-notice-performance-report-settings-updated');
139
+ window.scrollTo(0,0);
140
+ notice.slideDown();
141
+ setTimeout( function() {
142
+ notice.slideUp();
143
+ }, 5000 );
144
+ },
145
+
146
+ performanceTest: function ( redirect ) {
147
+ const self = this;
148
+
149
+ if ( typeof redirect === 'undefined' )
150
+ redirect = false;
151
+
152
+ // Update progress bar
153
+ self.updateProgressBar();
154
+
155
+ Fetcher.performance.runTest()
156
+ .then( ( response ) => {
157
+ if ( ! response.finished ) {
158
+ // Try again 5 seconds later
159
+ window.setTimeout(function () {
160
+ self.performanceTest( redirect );
161
+ }, 5000);
162
+ } else if ( redirect ) {
163
+ window.location = redirect;
164
+ }
165
+ });
166
+ },
167
+
168
+ updateProgressBar: function() {
169
+ if ( this.progress < 90 ) {
170
+ this.progress += 35;
171
+ }
172
+ if ( this.progress > 100 ) {
173
+ this.progress = 90;
174
+ }
175
+ $('.wphb-scan-progress .wphb-scan-progress-text span').text( this.progress + '%' );
176
+ $('.wphb-scan-progress .wphb-scan-progress-bar span').attr( 'style', 'width:' + this.progress + '%' );
177
+ }
178
+ };
179
+ }( jQuery ));
_src/admin/js/admin-uptime.js ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ( function( $ ) {
2
+ WPHB_Admin.uptime = {
3
+ module: 'uptime',
4
+ $dataRangeSelector: null,
5
+ chartData: null,
6
+ timer:null,
7
+ $spinner: null,
8
+ init: function() {
9
+ this.$spinner = $('.spinner');
10
+ this.strings = wphbUptimeStrings;
11
+ this.$dataRangeSelector = $( '#wphb-uptime-data-range' );
12
+ this.chartData = $('#uptime-chart-json').val();
13
+ this.$disableUptime = $('#wphb-disable-uptime');
14
+
15
+ this.$dataRangeSelector.change( function() {
16
+ window.location.href = $(this).find( ':selected' ).data( 'url' );
17
+ });
18
+
19
+ var self = this;
20
+ this.$disableUptime.change( function() {
21
+ self.$spinner.css( 'visibility', 'visible' );
22
+ var value = $(this).is(':checked');
23
+ if ( value && self.timer ) {
24
+ clearTimeout( self.timer );
25
+ self.$spinner.css( 'visibility', 'hidden' );
26
+ }
27
+ else {
28
+ // you have 3 seconds to change your mind
29
+ self.timer = setTimeout( function() {
30
+ location.href = self.strings.disableUptimeURL;
31
+ }, 3000 );
32
+ }
33
+
34
+ return;
35
+ });
36
+
37
+ this.drawChart();
38
+
39
+ /* Re-check Uptime status */
40
+ $('#uptime-re-check-status').on( 'click', function(e){
41
+ e.preventDefault();
42
+ location.reload();
43
+ });
44
+ },
45
+
46
+ drawChart: function() {
47
+ var data = new google.visualization.DataTable();
48
+ data.addColumn('datetime', 'Day');
49
+ data.addColumn('number', 'Response Time (ms)');
50
+
51
+ var chart_array = JSON.parse( this.chartData );
52
+ for (var i = 0; i < chart_array.length; i++) {
53
+ chart_array[i][0] = new Date( chart_array[i][0] );
54
+ chart_array[i][1] = Math.round( chart_array[i][1] );
55
+
56
+ /* brings the graph below the x axis */
57
+ if ( Math.round( chart_array[i][1] ) == 0 ) {
58
+ chart_array[i][1] = -100;
59
+ }
60
+
61
+ }
62
+
63
+ data.addRows(chart_array);
64
+
65
+ var options = {
66
+ chartArea: {
67
+ left: 80,
68
+ top: 20,
69
+ width: '90%',
70
+ height: '90%'
71
+ },
72
+ colors: ['#24ADE5'],
73
+ curveType: 'function',
74
+ /*interpolateNulls: true,*/
75
+ legend: { position: 'none' },
76
+ vAxis: {
77
+ format: '#,### ms',
78
+ viewWindow: { min: 0 } /* don't display negative values */
79
+ },
80
+ tooltip: { isHtml: true },
81
+ series: {
82
+ 0: { axis: 'Resp' }
83
+ },
84
+ axes: {
85
+ y: {
86
+ Resp: { label: 'Response Time (ms)' }
87
+ }
88
+ }
89
+ };
90
+
91
+ var chart = new google.visualization.LineChart(document.getElementById('uptime-chart'));
92
+ chart.draw(data, options);
93
+
94
+ $(window).resize(function(){
95
+ chart.draw(data, options);
96
+ });
97
+ }
98
+ };
99
+ }(jQuery));
_src/admin/js/index.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ require('./admin-main.js');
2
+ require('./admin-performance.js');
3
+ require('./admin-gzip.js');
4
+ require('./admin-caching.js');
5
+ require('./admin-minification.js');
6
+ require('./admin-dashboard.js');
7
+ require('./admin-dashboard-cloudflare.js');
8
+ require('./admin-uptime.js');
9
+ require('./admin-cloudflare.js');
10
+ require('./admin-app.js');
_src/admin/js/minification/Row.js ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const Row = ( _element, _filter, _filter_sec ) => {
2
+ let $el = _element,
3
+ filter = _filter.toLowerCase(),
4
+ filterSecondary = false,
5
+ selected = false,
6
+ visible = true;
7
+
8
+ const $include = $el.find( '.toggle-include' ),
9
+ $combine = $el.find( '.toggle-combine' ),
10
+ $minify = $el.find( '.toggle-minify' ),
11
+ $posFooter = $el.find( '.toggle-position-footer' ),
12
+ $disableIcon = $el.find( '.toggle-cross > i' );
13
+
14
+ if ( _filter_sec ) {
15
+ filterSecondary = _filter_sec.toLowerCase();
16
+ }
17
+
18
+ return {
19
+ hide: function() {
20
+ $el.addClass( 'out-of-filter' );
21
+ visible = false;
22
+ },
23
+
24
+ show: function() {
25
+ $el.removeClass( 'out-of-filter' );
26
+ visible = true;
27
+ },
28
+
29
+ getElement: function() {
30
+ return $el;
31
+ },
32
+
33
+ getId: function() {
34
+ return $el.attr( 'id' );
35
+ },
36
+
37
+ getFilter: function() {
38
+ return filter;
39
+ },
40
+
41
+ matchFilter: function( text ) {
42
+ if ( text === '' ) {
43
+ return true;
44
+ }
45
+
46
+ text = text.toLowerCase();
47
+ return filter.search( text ) > - 1;
48
+ },
49
+
50
+ matchSecondaryFilter: function( text ) {
51
+ if ( text === '' ) {
52
+ return true;
53
+ }
54
+
55
+ if ( ! filterSecondary ) {
56
+ return false;
57
+ }
58
+
59
+ text = text.toLowerCase();
60
+ return filterSecondary === text;
61
+ },
62
+
63
+ isVisible: function() {
64
+ return visible;
65
+ },
66
+
67
+ isSelected: function() {
68
+ return selected;
69
+ },
70
+
71
+ select: function() {
72
+ selected = true;
73
+ },
74
+
75
+ unSelect: function() {
76
+ selected = false;
77
+ },
78
+
79
+ change: function( what, value ) {
80
+ switch ( what ) {
81
+ case 'minify': {
82
+ $minify.prop( 'checked', value );
83
+ break;
84
+ }
85
+ case 'combine': {
86
+ $combine.prop( 'checked', value );
87
+ break;
88
+ }
89
+ case 'include': {
90
+ $disableIcon.removeClass();
91
+ $include.prop( 'checked', value );
92
+ if ( value ) {
93
+ $el.removeClass( 'disabled' );
94
+ $disableIcon.addClass( 'dev-icon dev-icon-cross' );
95
+ $include.attr( 'checked', true );
96
+ } else {
97
+ $el.addClass( 'disabled' );
98
+ $disableIcon.addClass( 'wdv-icon wdv-icon-refresh' );
99
+ $include.removeAttr( 'checked' );
100
+ }
101
+ break;
102
+ }
103
+ case 'footer': {
104
+ $posFooter.prop( 'checked', value );
105
+ break;
106
+ }
107
+ }
108
+ }
109
+
110
+ };
111
+ };
112
+
113
+ export default Row;
_src/admin/js/minification/RowsCollection.js ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const RowsCollection = () => {
2
+ let items = [];
3
+ let currentFilter = '';
4
+ let currentSecondaryFilter = '';
5
+
6
+ return {
7
+ push: function( row ) {
8
+ if ( typeof row === 'object' ) {
9
+ items.push( row );
10
+ }
11
+ },
12
+
13
+ getItems: function() {
14
+ return items;
15
+ },
16
+
17
+ getItem: function( i ) {
18
+ if ( items[i] ) {
19
+ return items[i];
20
+ }
21
+ return false;
22
+ },
23
+
24
+ /**
25
+ * Get a collection item by type and ID
26
+ * @param type
27
+ * @param id
28
+ */
29
+ getItemById: function( type, id ) {
30
+ let value = false;
31
+ for ( let i in items ) {
32
+ if ( 'wphb-file-' + type + '-' + id === items[i].getId() ) {
33
+ value = items[i];
34
+ break;
35
+ }
36
+ }
37
+ return value;
38
+ },
39
+
40
+ getVisibleItems: function() {
41
+ let visible = [];
42
+ for ( let i in items ) {
43
+ if ( items[i].isVisible() ) {
44
+ visible.push( items[i] );
45
+ }
46
+ }
47
+ return visible;
48
+ },
49
+
50
+ getSelectedItems: function() {
51
+ let selected = [];
52
+
53
+ for ( let i in items ) {
54
+ if ( items[i].isVisible() && items[i].isSelected() ) {
55
+ selected.push( items[i] );
56
+ }
57
+ }
58
+
59
+ return selected;
60
+ },
61
+
62
+ addFilter: function( filter, type ) {
63
+ if ( type === 'secondary' ) {
64
+ currentSecondaryFilter = filter;
65
+ }
66
+ else {
67
+ currentFilter = filter;
68
+ }
69
+ },
70
+
71
+ applyFilters: function() {
72
+ for ( let i in items ) {
73
+ if ( items[i] ) {
74
+ if ( items[i].matchFilter( currentFilter ) && items[i].matchSecondaryFilter( currentSecondaryFilter ) ) {
75
+ items[i].show();
76
+ }
77
+ else {
78
+ items[i].hide();
79
+ }
80
+ }
81
+
82
+ }
83
+ }
84
+ };
85
+ };
86
+
87
+ export default RowsCollection;
_src/admin/js/utils/fetcher.js ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import assign from 'lodash/assign';
2
+
3
+ function Fetcher() {
4
+ let fetchUrl = ajaxurl;
5
+ let fetchNonce = wphb.nonces.HBFetchNonce;
6
+ const actionPrefix = 'wphb_';
7
+ const actionPrefixPro = 'wphb_pro_';
8
+
9
+ function request( action, data = {}, method = 'GET' ) {
10
+ data.nonce = fetchNonce;
11
+ data.action = action;
12
+ let args = { data, method };
13
+ args.url = fetchUrl;
14
+ return new Promise( ( resolve, reject ) => {
15
+ jQuery.ajax( args ).done( resolve ).fail( reject );
16
+ })
17
+ .then( ( response ) => checkStatus( response ) );
18
+
19
+ }
20
+
21
+ const methods = {
22
+ /**
23
+ * Caching module actions.
24
+ */
25
+ caching: {
26
+ /**
27
+ * Set expiration for browser caching.
28
+ *
29
+ * @param type File type.
30
+ * @param value Expiry value.
31
+ */
32
+ setExpiration: ( type, value ) => {
33
+ const action = actionPrefix + 'caching_set_expiration';
34
+ return request( action, { type, value }, 'POST' );
35
+ },
36
+
37
+ /**
38
+ * Set server type.
39
+ *
40
+ * @param value Server type.
41
+ */
42
+ setServer: ( value ) => {
43
+ const action = actionPrefix + 'caching_set_server_type';
44
+ return request( action, { value }, 'POST' );
45
+ },
46
+
47
+ /**
48
+ * Reload snippet.
49
+ *
50
+ * @param type Server type.
51
+ */
52
+ reloadSnippets: ( type ) => {
53
+ const action = actionPrefix + 'caching_reload_snippet';
54
+ return request( action, { type }, 'POST' )
55
+ .then( ( response ) => {
56
+ return response;
57
+ });
58
+ }
59
+ },
60
+
61
+ /**
62
+ * CLoudflare module actions.
63
+ */
64
+ cloudflare: {
65
+ /**
66
+ * Connect to CloudFlare.
67
+ *
68
+ * @param step
69
+ * @param formData
70
+ * @param cfData
71
+ */
72
+ connect: ( step, formData, cfData ) => {
73
+ const action = actionPrefix + 'cloudflare_connect';
74
+ return request( action, { step, formData, cfData }, 'POST' )
75
+ .then( ( response ) => {
76
+ return response;
77
+ });
78
+ },
79
+
80
+ /**
81
+ * Set expiry for CloudFlare cache.
82
+ *
83
+ * @param value Expiry value.
84
+ */
85
+ setExpiration: ( value ) => {
86
+ const action = actionPrefix + 'cloudflare_set_expiry';
87
+ return request( action, { value }, 'POST' );
88
+ },
89
+
90
+ /**
91
+ * Purge CloudFlare cache.
92
+ */
93
+ purgeCache: () => {
94
+ const action = actionPrefix + 'cloudflare_purge_cache';
95
+ return request( action, {}, 'POST' );
96
+ }
97
+ },
98
+
99
+ /**
100
+ * Dashboard module actions.
101
+ */
102
+ dashboard: {
103
+ /**
104
+ * Toggle global minification settings for network installs.
105
+ *
106
+ * @param value Accepts: 'super-admins', 'false' and 'true'. Default: 'true'.
107
+ */
108
+ toggleMinification: ( value ) => {
109
+ const action = actionPrefix + 'dash_toggle_network_minification';
110
+ return request( action, { value }, 'POST' );
111
+ },
112
+
113
+ /**
114
+ * Skip quick setup.
115
+ */
116
+ skipSetup: () => {
117
+ const action = actionPrefix + 'dash_skip_setup';
118
+ return request( action, {}, 'POST' );
119
+ }
120
+ },
121
+
122
+ /**
123
+ * Minification module actions.
124
+ */
125
+ minification: {
126
+ /**
127
+ * Toggle CDN settings.
128
+ *
129
+ * @param value CDN checkbox value.
130
+ */
131
+ toggleCDN: ( value ) => {
132
+ const action = actionPrefix + 'minification_toggle_cdn';
133
+ return request( action, { value }, 'POST' );
134
+ },
135
+
136
+ /**
137
+ * Toggle minificatiojn settings on per site basis.
138
+ *
139
+ * @param value
140
+ */
141
+ toggleMinification: ( value ) => {
142
+ const action = actionPrefix + 'minification_toggle_minification';
143
+ return request( action, { value }, 'POST' );
144
+ },
145
+
146
+ /**
147
+ * Start minification check.
148
+ *
149
+ * @param progress
150
+ */
151
+ startCheck: ( progress ) => {
152
+ const action = actionPrefix + 'minification_start_check';
153
+ return request( action, { progress }, 'POST' )
154
+ .then( ( response ) => {
155
+ return response;
156
+ });
157
+ },
158
+
159
+ /**
160
+ * Do a step in minification process.
161
+ *
162
+ * @param progress
163
+ * @param step
164
+ */
165
+ checkStep: ( progress, step ) => {
166
+ const action = actionPrefix + 'minification_check_step';
167
+ return request( action, { progress, step }, 'POST' )
168
+ .then( ( response ) => {
169
+ return response;
170
+ });
171
+ },
172
+
173
+ /**
174
+ * Cancel minification scan.
175
+ */
176
+ cancelScan: function cancelScan() {
177
+ const action = actionPrefix + 'minification_cancel_scan';
178
+ return request( action, {}, 'POST' );
179
+ }
180
+ },
181
+
182
+ /**
183
+ * Performance module actions.
184
+ */
185
+ performance: {
186
+ /**
187
+ * Run performance test.
188
+ */
189
+ runTest: () => {
190
+ const action = actionPrefix + 'performance_run_test';
191
+ return request( action, {}, 'POST' )
192
+ .then( ( response ) => {
193
+ return response;
194
+ });
195
+ },
196
+
197
+ /**
198
+ * Add a single email/name recipient to the reports list.
199
+ *
200
+ * @param email
201
+ * @param name
202
+ */
203
+ addRecipient: ( email, name ) => {
204
+ const action = actionPrefixPro + 'performance_add_recipient';
205
+ return request( action, { email, name }, 'POST' )
206
+ .then( ( response ) => {
207
+ return response;
208
+ });
209
+
210
+ },
211
+
212
+ /**
213
+ * Save reporting settings on minification page.
214
+ *
215
+ * @param data From data.
216
+ */
217
+ saveReportsSettings: ( data ) => {
218
+ const action = actionPrefixPro + 'performance_save_reports_settings';
219
+ return request( action, { data }, 'POST' );
220
+ }
221
+ }
222
+ };
223
+
224
+ assign( this, methods );
225
+ }
226
+
227
+ const HBFetcher = new Fetcher();
228
+ export default HBFetcher;
229
+
230
+ function checkStatus( response ) {
231
+ if ( typeof response !== 'object' ) {
232
+ response = JSON.parse( response );
233
+ }
234
+ if ( response.success ) {
235
+ return response.data;
236
+ }
237
+
238
+ let data = response.data || {};
239
+ const error = new Error( data.message || 'Error trying to fetch response from server' );
240
+ error.response = response;
241
+ throw error;
242
+ }
_src/admin/js/utils/helpers.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Strings internationalization
3
+ *
4
+ * @param str
5
+ *
6
+ * @returns {*|string}
7
+ */
8
+ export const __ = ( str ) => {
9
+ return wphb.strings[ str ] || '';
10
+ };
11
+
12
+ /**
13
+ * Get a link to a HB screen
14
+ *
15
+ * @param {string} screen Screen slug
16
+ * @returns {string}
17
+ */
18
+ export const getLink = ( screen ) => {
19
+ return wphb.links[ screen ] || '';
20
+ };
21
+
_src/admin/scss/app.scss ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ // Modules
2
+ @import "modules/_variables";
3
+ @import "modules/_functions";
4
+ @import "modules/_mixins";
5
+ @import "modules/_classes";
_src/admin/scss/modules/_classes.scss ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ****************************************************************************
2
+ * MODULE: CLASSES
3
+ */
4
+
5
+ // Clearfix
6
+ .cf {
7
+ &:after {
8
+ content: "";
9
+ display: table;
10
+ clear: both;
11
+ }
12
+ }
13
+
14
+ // Responsive Helpers
15
+ .hide-to-large {
16
+ @include bp(desktop-large) {
17
+ display: none;
18
+ }
19
+ }
20
+ .hide-to-desktop {
21
+ @include bp(desktop) {
22
+ display: none;
23
+ }
24
+ }
_src/admin/scss/modules/_functions.scss ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ /* ****************************************************************************
2
+ * MODULE: FUNCTIONS
3
+ */
4
+
5
+ $browser-context: 16;
6
+
7
+ @function getEm($pixels, $context: $browser-context) {
8
+ @return #{$pixels/$context}em;
9
+ }
_src/admin/scss/modules/_mixins.scss ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ****************************************************************************
2
+ * MODULE: MIXINS
3
+ */
4
+
5
+ // Base at-root
6
+ @mixin optional-at-root($sel) {
7
+ @at-root #{if(not &, $sel, selector-append(&, $sel))} {
8
+ @content;
9
+ }
10
+ }
11
+
12
+ // Form Input Placeholder
13
+ @mixin form-placeholder {
14
+ @include optional-at-root('&::-webkit-input-placeholder') {
15
+ @content;
16
+ }
17
+
18
+ @include optional-at-root('&:-moz-placeholder') {
19
+ @content;
20
+ }
21
+
22
+ @include optional-at-root('&::-moz-placeholder') {
23
+ @content;
24
+ }
25
+
26
+ @include optional-at-root('&:-ms-input-placeholder') {
27
+ @content;
28
+ }
29
+ }
30
+
31
+ // Breakpoints
32
+ @mixin bp($point) {
33
+
34
+ // Phone: < 480px
35
+ @if $point == phone {
36
+ @media only screen and (max-width: $phone) {
37
+ @content;
38
+ }
39
+ }
40
+
41
+ // Phone Large: < 600px
42
+ @if $point == phone-large {
43
+ @media only screen and (max-width: $phone--large) {
44
+ @content;
45
+ }
46
+ }
47
+
48
+ // Tablet: < 783px
49
+ @if $point == tablet {
50
+ @media only screen and (max-width: $tablet) {
51
+ @content;
52
+ }
53
+ }
54
+
55
+ // Desktop Small: < 960px
56
+ @if $point == desktop-small {
57
+ @media only screen and (max-width: $desktop--small) {
58
+ @content;
59
+ }
60
+ }
61
+
62
+ // Desktop: < 1100px
63
+ @if $point == desktop {
64
+ @media only screen and (max-width: $desktop) {
65
+ @content;
66
+ }
67
+ }
68
+
69
+ // Desktop Large: < 1200px
70
+ @if $point == desktop-large {
71
+ @media only screen and (max-width: $desktop--large) {
72
+ @content;
73
+ }
74
+ }
75
+
76
+ // Desktop Wide: < 1440px
77
+ @if $point == desktop-wide {
78
+ @media only screen and (max-width: $desktop--wide) {
79
+ @content;
80
+ }
81
+ }
82
+
83
+ // Desktop Very Large: < 1600px
84
+ @if $point == desktop-very-large {
85
+ @media only screen and (max-width: $desktop--very-large) {
86
+ @content;
87
+ }
88
+ }
89
+
90
+ }
_src/admin/scss/modules/_variables.scss ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ****************************************************************************
2
+ * MODULE: VARIABLES
3
+ */
4
+
5
+ // Colors
6
+ $color: #4E4B10;
7
+ $color--grey: #777771;
8
+ $color--grey--light: #ddd;
9
+ $color--grey--alt: #ccc;
10
+ $color--light: #f4f4f4;
11
+ $color--light--alt: #f9f9f9;
12
+ $color--dark: #595959;
13
+ $color--dark--alt: #333;
14
+ $color--cta: #4E4B10;
15
+ $color--success: #1ABC9C;
16
+ $color--error: #FF6D6D;
17
+ $color--warning: #FECF2F;
18
+
19
+ // Typo
20
+ $font: 'Roboto', Arial, sans-serif;
21
+ $font--alt: 'Roboto Condensed', 'Roboto', Arial, sans-serif;
22
+
23
+ // Space
24
+ $space: 30px;
25
+ $space--xxs: 5px;
26
+ $space--xs: 10px;
27
+ $space--s: 15px;
28
+ $space--m: 20px;
29
+ $space--l: 40px;
30
+ $space--xl: 50px;
31
+ $space--xxl: 60px;
32
+
33
+ // Brands
34
+ $color--twitter: #00aced;
35
+ $color--facebook: #3b5998;
36
+ $color--google-plus: #dd4b39;
37
+ $color--pinterest: #cb2027;
38
+ $color--linkedin: #007bb6;
39
+ $color--youtube: #bb0000;
40
+ $color--vimeo: #aad450;
41
+ $color--tumblr: #32506d;
42
+ $color--instagram: #517fa4;
43
+ $color--flickr: #ff0084;
44
+ $color--dribbble: #ea4c89;
45
+ $color--quora: #a82400;
46
+ $color--foursquare: #0072b1;
47
+ $color--forrst: #5B9A68;
48
+ $color--vk: #45668e;
49
+ $color--wordpress: #21759b;
50
+ $color--stumbleupon: #EB4823;
51
+ $color--yahoo: #7B0099;
52
+ $color--blogger: #fb8f3d;
53
+ $color--soundcloud: #ff3a00;
54
+
55
+ // Responsive Sizes:
56
+ $phone: 480px;
57
+ $phone--large: 600px;
58
+ $tablet: 783px;
59
+ $desktop--small: 960px;
60
+ $desktop: 1100px;
61
+ $desktop--large: 1200px;
62
+ $desktop--wide: 1440px;
63
+ $desktop--very-large: 1600px;
admin/abstract-class-admin-page.php ADDED
@@ -0,0 +1,396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class WP_Hummingbird_Admin_Page {
4
+
5
+ protected $slug = '';
6
+
7
+ public $page_id = null;
8
+
9
+ protected $meta_boxes = array();
10
+
11
+ protected $tabs = array();
12
+
13
+ /**
14
+ * In order to avoid duplicated notices,
15
+ * we save notices IDs here
16
+ *
17
+ * @var array
18
+ */
19
+ protected static $displayed_notices = array();
20
+
21
+ public function __construct( $slug, $page_title, $menu_title, $parent = false, $render = true ) {
22
+ $this->slug = $slug;
23
+
24
+ if ( ! $parent ) {
25
+ $this->page_id = add_menu_page(
26
+ $page_title,
27
+ $menu_title,
28
+ wphb_get_admin_capability(),
29
+ $slug,
30
+ $render ? array( $this, 'render' ) : null,
31
+ 'none'
32
+ );
33
+ }
34
+ else {
35
+ $this->page_id = add_submenu_page(
36
+ $parent,
37
+ $page_title,
38
+ $menu_title,
39
+ wphb_get_admin_capability(),
40
+ $slug,
41
+ $render ? array( $this, 'render' ) : null
42
+ );
43
+ }
44
+
45
+
46
+ add_action( 'load-' . $this->page_id, array( $this, 'register_meta_boxes' ) );
47
+ add_action( 'load-' . $this->page_id, array( $this, 'on_load' ) );
48
+ add_action( 'load-' . $this->page_id, array( $this, 'trigger_load_action' ) );
49
+ add_filter( 'load-' . $this->page_id, array( $this, 'add_screen_hooks' ) );
50
+
51
+ }
52
+
53
+ /**
54
+ * Return the admin menu slug
55
+ *
56
+ * @return string
57
+ */
58
+ public function get_slug() {
59
+ return $this->slug;
60
+ }
61
+
62
+ /**
63
+ * Trigger an action before this screen is loaded
64
+ */
65
+ public function trigger_load_action() {
66
+ do_action( 'wphb_load_admin_page_' . $this->get_slug() );
67
+ }
68
+
69
+ /**
70
+ * Load an admin view
71
+ */
72
+ public function view( $name, $args = array(), $echo = true ) {
73
+ $file = wphb_plugin_dir() . "admin/views/$name.php";
74
+ $content = '';
75
+
76
+ if ( is_file ( $file ) ) {
77
+
78
+ ob_start();
79
+
80
+ if ( class_exists( 'WDEV_Plugin_Ui' ) ) {
81
+ WDEV_Plugin_Ui::output();
82
+ }
83
+
84
+ if ( isset( $args['id'] ) ) {
85
+ $args['orig_id'] = $args['id'];
86
+ $args['id'] = str_replace( '/', '-', $args['id'] );
87
+ }
88
+ extract( $args );
89
+
90
+ include( $file );
91
+
92
+ $content = ob_get_clean();
93
+ }
94
+
95
+ if ( ! $echo )
96
+ return $content;
97
+
98
+ echo $content;
99
+
100
+ }
101
+
102
+ protected function view_exists( $name ) {
103
+ $file = wphb_plugin_dir() . "admin/views/$name.php";
104
+ return is_file ( $file );
105
+ }
106
+
107
+ /**
108
+ * Common hooks for all screens
109
+ */
110
+ public function add_screen_hooks() {
111
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
112
+ add_action( 'admin_notices', array( $this, 'notices' ) );
113
+ add_action( 'network_admin_notices', array( $this, 'notices' ) );
114
+ }
115
+
116
+ public function notices() {}
117
+
118
+
119
+ /**
120
+ * Function triggered when the page is loaded
121
+ * before render any content
122
+ */
123
+ public function on_load() {}
124
+
125
+ public function enqueue_scripts( $hook ) {
126
+ /* Enqueue Dashboard UI Shared Lib */
127
+ WDEV_Plugin_Ui::load( wphb_plugin_url() . 'externals/shared-ui' );
128
+
129
+ // Styles
130
+ wp_enqueue_style( 'wphb-admin', wphb_plugin_url() . 'admin/assets/css/admin.css', array(), WPHB_VERSION );
131
+
132
+ // Scripts
133
+ wphb_enqueue_admin_scripts( WPHB_VERSION );
134
+
135
+ }
136
+
137
+ /**
138
+ * Trigger before on_load, allows to register meta boxes for the page
139
+ */
140
+ public function register_meta_boxes() {}
141
+
142
+ /**
143
+ * @param $id
144
+ * @param $title
145
+ * @param callable|string|null $callback
146
+ * @param callable|string|null $callback_header
147
+ * @param callable|string|null $callback_footer
148
+ * @param string $context
149
+ * @param array $args
150
+ */
151
+ public function add_meta_box( $id, $title, $callback = '', $callback_header = '', $callback_footer = '', $context = 'main', $args = array() ) {
152
+ $default_args = array(
153
+ 'box_class' => 'dev-box',
154
+ 'box_header_class' => 'box-title',
155
+ 'box_content_class' => 'box-content',
156
+ 'box_footer_class' => 'box-footer'
157
+ );
158
+
159
+ $args = wp_parse_args( $args, $default_args );
160
+
161
+ if ( ! isset( $this->meta_boxes[ $this->slug ] ) )
162
+ $this->meta_boxes[ $this->slug ] = array();
163
+
164
+ if ( ! isset( $this->meta_boxes[ $this->slug ][ $context ] ) )
165
+ $this->meta_boxes[ $this->slug ][ $context ] = array();
166
+
167
+ if ( !isset($this->meta_boxes[ $this->slug ][ $context ] ) )
168
+ $this->meta_boxes[ $this->slug ][ $context ] = array();
169
+
170
+ $meta_box = array('id' => $id, 'title' => $title, 'callback' => $callback, 'callback_header' => $callback_header, 'callback_footer' => $callback_footer, 'args' => $args );
171
+ /**
172
+ * Allow to filter a WP Hummingbird Metabox
173
+ *
174
+ * @param array $meta_box Meta box attributes
175
+ * @param string $slug Admin page slug
176
+ * @param string $page_id Admin page ID
177
+ */
178
+ $meta_box = apply_filters( 'wphb_add_meta_box', $meta_box, $this->slug, $this->page_id );
179
+ $meta_box = apply_filters( 'wphb_add_meta_box_' . $meta_box['id'], $meta_box, $this->slug, $this->page_id );
180
+
181
+ if ( $meta_box ) {
182
+ $this->meta_boxes[ $this->slug ][ $context ][ $id ] = $meta_box;
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Render
188
+ * @param string $context
189
+ */
190
+ protected function do_meta_boxes( $context = 'main' ) {
191
+ if ( empty( $this->meta_boxes[ $this->slug ][ $context ] ) )
192
+ return;
193
+
194
+ do_action_ref_array( 'wphb_admin_do_meta_boxes_' . $this->slug, array( &$this ) );
195
+
196
+ foreach ( $this->meta_boxes[ $this->slug ][ $context ] as $id => $box ) {
197
+ $args = array( 'title' => $box['title'], 'id' => $id, 'callback' => $box['callback'], 'callback_header' => $box['callback_header'], 'callback_footer' => $box['callback_footer'], 'args' => $box['args'] );
198
+ $this->view( 'meta-box', $args );
199
+ }
200
+
201
+ }
202
+
203
+ /**
204
+ * Check if there is any meta box for a given context
205
+ */
206
+ protected function has_meta_boxes( $context ) {
207
+ return ! empty( $this->meta_boxes[ $this->slug ][ $context ] );
208
+ }
209
+
210
+ /**
211
+ * Renders the template header that is repeated on every page.
212
+ * From WPMU DEV Dashboard
213
+ *
214
+ */
215
+ protected function render_header() {
216
+
217
+ ?>
218
+ <section id="header">
219
+ <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
220
+ </section><!-- end header -->
221
+
222
+ <?php
223
+ }
224
+
225
+ /**
226
+ * Render the page
227
+ */
228
+ public function render() {
229
+ ?>
230
+
231
+ <div id="container" class="wrap wrap-wp-hummingbird wrap-wp-hummingbird-page <?php echo 'wrap-' . $this->slug; ?>">
232
+
233
+ <?php
234
+ if ( isset( $_GET['updated'] ) ) :
235
+ $this->show_notice( 'updated', __( 'Settings Updated', 'wphb' ), 'success' );
236
+ endif;
237
+
238
+ $this->render_header();
239
+
240
+ $this->render_inner_content();
241
+ ?>
242
+ <div class="footer-love">
243
+ <?php printf( __( 'Made with %s by WPMU DEV', 'wphb' ), '<span class="dashicons-heart dashicons"></span>' ); ?>
244
+ </div>
245
+ </div><!-- end container -->
246
+
247
+ <script>
248
+ jQuery(document).ready( function() {
249
+ WPHB_Admin.getModule( 'notices' );
250
+ });
251
+
252
+ // Avoid moving dashboard notice under h2
253
+ var wpmuDash = document.getElementById( 'wpmu-install-dashboard' );
254
+ if ( wpmuDash )
255
+ wpmuDash.className = wpmuDash.className + " inline";
256
+
257
+ jQuery( 'div.updated, div.error' ).addClass( 'inline' );
258
+ </script>
259
+ <?php
260
+ }
261
+
262
+ protected function render_inner_content() {
263
+ $this->view( $this->slug . '-page' );
264
+ }
265
+
266
+ /**
267
+ * Show an admin notice
268
+ *
269
+ * @param string $id Unique identificator for the notice
270
+ * @param string $message The notice text
271
+ * @param string $class Class for the notice wrapper
272
+ * @param bool|false $dismissable if is dissmisable or not
273
+ */
274
+ public function show_notice( $id, $message, $class = 'error', $dismissable = false ) {
275
+ // Is already dismissed ?
276
+ if ( $dismissable && get_user_meta( get_current_user_id(), 'wphb-notice-' . $id ) )
277
+ return;
278
+
279
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
280
+ return;
281
+
282
+ if ( in_array( $id, self::$displayed_notices ) )
283
+ return;
284
+
285
+ $nonce = '';
286
+ if ( $dismissable ) {
287
+ $nonce = wp_create_nonce( 'wphb-dismiss' );
288
+ }
289
+
290
+ $args = compact( 'message', 'id', 'class', 'dismissable', 'nonce' );
291
+ $this->view( 'notice', $args );
292
+
293
+ self::$displayed_notices[] = $id;
294
+ }
295
+
296
+ /**
297
+ * Return this menu page URL
298
+ *
299
+ * @return string
300
+ */
301
+ public function get_page_url() {
302
+ if ( is_multisite() && is_network_admin() ) {
303
+ global $_parent_pages;
304
+
305
+ if ( isset( $_parent_pages[$this->slug] ) ) {
306
+ $parent_slug = $_parent_pages[$this->slug];
307
+ if ( $parent_slug && ! isset( $_parent_pages[$parent_slug] ) ) {
308
+ $url = network_admin_url( add_query_arg( 'page', $this->slug, $parent_slug ) );
309
+ } else {
310
+ $url = network_admin_url( 'admin.php?page=' . $this->slug );
311
+ }
312
+ } else {
313
+ $url = '';
314
+ }
315
+
316
+ $url = esc_url($url);
317
+
318
+ return $url;
319
+ }
320
+ else {
321
+ return menu_page_url( $this->slug, false );
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Get the current screen tab
327
+ *
328
+ * @return string
329
+ */
330
+ public function get_current_tab() {
331
+ $tabs = $this->get_tabs();
332
+ if ( isset( $_GET['view'] ) && array_key_exists( $_GET['view'], $tabs ) ) {
333
+ return $_GET['view'];
334
+ }
335
+
336
+ if ( empty( $tabs ) ) {
337
+ return false;
338
+ }
339
+
340
+ reset( $tabs );
341
+ return key( $tabs );
342
+ }
343
+
344
+ /**
345
+ * Get the list of tabs for this screen
346
+ *
347
+ * @return array
348
+ */
349
+ protected function get_tabs() {
350
+ return apply_filters( 'wphb_admin_page_tabs_' . $this->slug, $this->tabs );
351
+ }
352
+
353
+ /**
354
+ * Display tabs navigation
355
+ */
356
+ public function show_tabs() {
357
+ $this->view( 'tabs', array( 'tabs' => $this->get_tabs() ) );
358
+ }
359
+
360
+ /**
361
+ * Get a tab URL
362
+ *
363
+ * @param $tab
364
+ *
365
+ * @return string
366
+ */
367
+ public function get_tab_url( $tab ) {
368
+ $tabs = $this->get_tabs();
369
+ if ( ! isset( $tabs[ $tab ] ) ) {
370
+ return '';
371
+ }
372
+
373
+ if ( is_multisite() && is_network_admin() ) {
374
+ return network_admin_url( 'admin.php?page=' . $this->slug . '&view=' . $tab );
375
+ }
376
+ else {
377
+ return admin_url( 'admin.php?page=' . $this->slug . '&view=' . $tab );
378
+ }
379
+ }
380
+
381
+ /**
382
+ * Return the name of a tab
383
+ *
384
+ * @param $tab
385
+ *
386
+ * @return mixed|string
387
+ */
388
+ public function get_tab_name( $tab ) {
389
+ $tabs = $this->get_tabs();
390
+ if ( ! isset( $tabs[ $tab ] ) ) {
391
+ return '';
392
+ }
393
+
394
+ return $tabs[ $tab ];
395
+ }
396
+ }
admin/assets/css/admin.css ADDED
@@ -0,0 +1,3669 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ *
3
+ * -----------------------------------------------------------------------------
4
+ *
5
+ * 1. Extend/Override WPMU DEV Dashboard Styles
6
+ * 2. Common/General Styles
7
+ * 3. Components/Modules
8
+ * 4. Page: Welcome/Dashboard
9
+ * 5. Page: Performance
10
+ * 6. Page: Minification
11
+ * 7. Page: Browser Caching
12
+ * 8. Page: GZIP
13
+ * 9: Page: Uptime
14
+ * 10: Responsive/MQ
15
+ *
16
+ * -----------------------------------------------------------------------------
17
+ */
18
+
19
+ /* ****************************************************************************
20
+ * 1. EXTEND/OVERRIDE WPMUDEV DASHBOARD/WP STYLES
21
+ */
22
+ /* Fix for overflowing tooltips start */
23
+ .wpmud .list-table > tbody > tr > td {
24
+ z-index: 0;
25
+ }
26
+ .wpmud [tooltip].tooltip-s.tooltip-right:after {
27
+ margin-left: -150px;
28
+ }
29
+ /* Fix for overflowing tooltips end */
30
+ .wpmud .wrap-wp-hummingbird .clear {
31
+ padding: 0;
32
+ }
33
+ .wpmud .wrap-wp-hummingbird a:not('.wdpun-button') {
34
+ color: #17A8E3;
35
+ }
36
+ .wpmud .wrap-wp-hummingbird strong {
37
+ color: #333333;
38
+ }
39
+ .wpmud .dev-overlay .back {
40
+ background-color: rgba(51,51,51,0.95);
41
+ }
42
+ .wpmud .dev-overlay .box {
43
+ padding: 40px 30px 30px;
44
+ }
45
+ .wpmud .wrap-wp-hummingbird .mline {
46
+ margin-bottom: 30px;
47
+ }
48
+ .wpmud .wrap-wp-hummingbird i.wdv-icon-chevron-down {
49
+ color: #8A8A8A;
50
+ }
51
+ .wpmud .wrap-wp-hummingbird p {
52
+ color: #666666;
53
+ }
54
+ #wpbody-content {
55
+ padding-bottom: 25px;
56
+ }
57
+ .wpmud .with-bottom-border {
58
+ border-bottom: 1px solid #E6E6E6;
59
+ }
60
+ .wpmud .toggle .toggle-checkbox:checked + .toggle-label:before,
61
+ .wpmud .toggle .toggle-checkbox:checked + .toggle-label {
62
+ background-color: #17A8E3;
63
+ }
64
+ .wpmud .toggle .toggle-label {
65
+ width: 44px;
66
+ }
67
+ .wpmud .toggle .toggle-checkbox:checked + .toggle-label:after {
68
+ margin-left: 24px;
69
+ }
70
+ .wpmud .spinner.standalone {
71
+ float: none;
72
+ margin: 0;
73
+ }
74
+ .wpmud .spinner.left {
75
+ float: left;
76
+ }
77
+ .wpmud .spinner.hide { /* Don't take/render block on layout */
78
+ display: none;
79
+ }
80
+ .wpmud .spinner.visible { /* Re-set visibility to visible */
81
+ visibility: visible;
82
+ }
83
+ .wpmud #wpmu-install-dashboard {
84
+ margin-left: 0;
85
+ }
86
+ .wpmud #wpcontent #wpmu-install-dashboard * {
87
+ -webkit-box-sizing: content-box;
88
+ box-sizing: content-box;
89
+ }
90
+ .wpmud #wpmu-install-dashboard .wpmu-message {
91
+ font-family: inherit;
92
+ font-weight: inherit;
93
+ line-height: inherit;
94
+ }
95
+ .wpmud #header {
96
+ margin-bottom: 0;
97
+ overflow: hidden;
98
+ }
99
+ .wpmud #header h1 {
100
+ color: #333333;
101
+ margin: 0;
102
+ }
103
+ .wpmud .dev-overlay .title h3 {
104
+ font-size: 16px;
105
+ color: #333333;
106
+ }
107
+ .wpmud .dev-overlay .title .title-action {
108
+ font-family: 'Roboto', sans-serif;
109
+ margin-top: 5px;
110
+ vertical-align: middle;
111
+ color: #888888;
112
+ font-size: 13px;
113
+ line-height: 30px;
114
+
115
+ margin-right: -20px;
116
+ }
117
+ .wpmud #header .actions.status {
118
+ left: 200px;
119
+ margin-top: 36px;
120
+ }
121
+ .wpmud .wrap-wphb-uptime > #header .actions.status {
122
+ left: 120px;
123
+ }
124
+ .wpmud #header .actions.status [tooltip]:after {
125
+ margin-left: 27px;
126
+ bottom: -60%;
127
+ }
128
+ .wpmud #header .actions.status [tooltip]:before {
129
+ bottom: 25%;
130
+ left: 100%;
131
+ border-right-color: #0B2F3F;
132
+ border-top: 5px solid transparent;
133
+ }
134
+ .wpmud #header .actions {
135
+ position: absolute;
136
+ top: 0;
137
+ right: 0;
138
+ margin-top: 35px;
139
+ margin-right: 20px;
140
+ display: flex;
141
+ align-items: center;
142
+ }
143
+ .wpmud #header .actions > * {
144
+ display: inline-block;
145
+ margin-left: 10px;
146
+ }
147
+ .wpmud #header .actions.label-and-button > *:first-child {
148
+ margin-left: 0;
149
+ }
150
+ .wpmud #header .actions.label-and-button .actions-label {
151
+ color: #888888;
152
+ font-size: 13px;
153
+ line-height: 30px;
154
+ margin: 0;
155
+ }
156
+
157
+ .wpmud #header ~ .sub-header {
158
+ margin-top: -15px;
159
+ margin-bottom: 30px;
160
+ }
161
+ .wpmud .row {
162
+ margin-top: 30px;
163
+ }
164
+ .wpmud .box-content .row:first-of-type {
165
+ margin-top: 0;
166
+ }
167
+ .wpmud .row-space-large {
168
+ margin-bottom: 40px;
169
+ }
170
+ .wpmud .row .col-center {
171
+ display: block;
172
+ margin-right: auto;
173
+ margin-left: auto;
174
+ }
175
+ .wpmud .row .col-quarter,
176
+ .wpmud .row .col-three-quarters,
177
+ .wpmud .row .col-fifth,
178
+ .wpmud .row .col-four-fifths {
179
+ display: table-cell;
180
+ padding: 0 15px 0 15px;
181
+ position: relative;
182
+ vertical-align: top;
183
+ }
184
+ .wpmud .row .col-quarter {
185
+ width: 25%;
186
+ }
187
+ .wpmud .row .col-three-quarters {
188
+ width: 75%;
189
+ }
190
+ .wpmud .row .col-fifth {
191
+ width: 20%;
192
+ }
193
+ .wpmud .row .col-four-fifths {
194
+ width: 80%;
195
+ }
196
+ .wpmud .row .col-four-fifths.hidden {
197
+ display: none;
198
+ }
199
+ .wpmud .row .col-quarter:first-child,
200
+ .wpmud .row .col-three-quarters:first-child,
201
+ .wpmud .row .col-fifth:first-child,
202
+ .wpmud .row .col-four-fifths:first-child {
203
+ padding-left: 0;
204
+ }
205
+ .wpmud .row .col-quarter:last-child,
206
+ .wpmud .row .col-three-quarters:last-child,
207
+ .wpmud .row .col-fifth:last-child,
208
+ .wpmud .row .col-four-fifths:last-child {
209
+ padding-right: 0;
210
+ }
211
+ .wpmud .dev-box {
212
+ padding: 0;
213
+ }
214
+ .wpmud .dev-box:last-child {
215
+ margin-bottom: 0;
216
+ }
217
+ .wpmud .dev-box .box-title {
218
+ clear: both;
219
+ height: inherit;
220
+ margin: 0;
221
+ padding: 0 30px;
222
+ }
223
+ .wpmud .dev-box .box-title h3 {
224
+ font-size: 16px;
225
+ color: #333333;
226
+ float: left;
227
+ }
228
+ .wpmud .dev-box .box-title .wphb-label-notice-inline {
229
+ margin: 2px 15px;
230
+ }
231
+ .wpmud .dev-box .box-title:after {
232
+ content: '';
233
+ display: table;
234
+ clear: both;
235
+ }
236
+ .wpmud .dev-box .box-title .button {
237
+ font-weight: inherit;
238
+ }
239
+ .wpmud .dev-box .box-title .buttons-large {
240
+ margin: 10px 0 0;
241
+ }
242
+ .wpmud .dev-box .box-title .buttons .spinner {
243
+ margin-top: 10px;
244
+ }
245
+ .wpmud .dev-box .box-title .extra {
246
+ float: right;
247
+ }
248
+ .wpmud .dev-box .box-title .extra-text {
249
+ margin: 20px 0 0;
250
+ }
251
+ .wpmud .dev-box .box-title .extra-label {
252
+ display: inline-block;
253
+ margin: 0;
254
+ line-height: 20px;
255
+ }
256
+ .wpmud .dev-box .box-title .extra-label-value {
257
+ color: #477B92;
258
+ font-weight: 400;
259
+ text-transform: uppercase;
260
+ }
261
+ .wpmud .dev-box .box-title .wphb-select-group {
262
+ margin: 8px 0 0;
263
+ }
264
+ .wpmud .dev-box .box-title .test-results {
265
+ float: right;
266
+ margin-top: 15px;
267
+ }
268
+ .wpmud .dev-box .box-title .test-results-label {
269
+ display: block;
270
+ float: left;
271
+ font-family: 'Roboto Condensed', 'Roboto', Arial, sans-serif;
272
+ font-weight: 700;
273
+ line-height: 30px;
274
+ margin-right: 10px;
275
+ text-transform: uppercase;
276
+ }
277
+ .wpmud .dev-box .box-title .test-results .wphb-score {
278
+ display: block;
279
+ float: left;
280
+ }
281
+ .wpmud .dev-box .box-title .toggle-group {
282
+ margin: 6px 15px 0 0;
283
+ }
284
+ .wpmud .dev-box .box-content {
285
+ padding: 30px;
286
+ word-wrap: break-word;
287
+ }
288
+ .wpmud .dev-box .box-content > * {
289
+ margin-bottom: 20px;
290
+ }
291
+ .wpmud .dev-box .box-content > *:last-child {
292
+ margin-bottom: 0;
293
+ }
294
+ .wpmud .dev-box .box-content .row-space-large {
295
+ margin-bottom: 40px;
296
+ }
297
+ .wpmud .box-content.no-padding {
298
+ padding: 0;
299
+ }
300
+ .wpmud .box-content.no-vertical-padding {
301
+ padding-top: 0;
302
+ padding-bottom: 0;
303
+ }
304
+ .wpmud .wphb-modal .no-side-padding,
305
+ .wpmud .box-content.no-side-padding {
306
+ padding-right: 0;
307
+ padding-left: 0;
308
+ }
309
+ .wpmud .box-content .with-padding {
310
+ padding: 30px;
311
+ }
312
+ .wpmud .box-content .add-side-padding {
313
+ padding-right: 30px;
314
+ padding-left: 30px;
315
+ }
316
+ .wpmud .box-content .buttons.buttons-on-left {
317
+ text-align: left;
318
+ }
319
+ .wpmud .box-content .buttons.buttons-on-right {
320
+ text-align: right;
321
+ }
322
+ .wpmud .box-footer {
323
+ margin-top: 0;
324
+ padding: 0 30px 30px 30px;
325
+ }
326
+ .wpmud .select-list-container {
327
+ min-width: 100px;
328
+ }
329
+ .wpmud .select-list-container .list-value {
330
+ color: #333333;
331
+ font-weight: 400;
332
+ padding: 6px 8px 6px 15px;
333
+ }
334
+ .wpmud .list-table > tbody > tr:last-child > td {
335
+ border-bottom: 1px solid #eee;
336
+ }
337
+ .wpmud .list-table > thead > tr > th {
338
+ text-transform: none;
339
+ font-size: 13px;
340
+ font-weight: bold;
341
+ }
342
+ .wpmud .wphb-border-frame .list-table > thead > tr > th {
343
+ color: #333333;
344
+ font-size: 13px;
345
+ padding: 8px 0;
346
+ }
347
+ .wpmud .wphb-border-frame .list-table > thead > tr > th:first-child {
348
+ padding: 27px 30px;
349
+ }
350
+ .wpmud .wphb-border-frame .list-table > tbody > tr > td:first-child {
351
+ padding-left: 30px;
352
+ }
353
+ .wpmud .list-table > tbody > tr > td {
354
+ padding: 12px 10px;
355
+ }
356
+ .wpmud .list-table .radio-group.with-icon {
357
+ display: inline-table;
358
+ }
359
+ .wpmud .list-table .radio-group.with-icon .dev-icon {
360
+ vertical-align: middle;
361
+ }
362
+ .wpmud .dev-list {
363
+ margin: -30px 0 20px;
364
+ }
365
+ .wpmud .dev-list .content {
366
+ padding: 30px 0;
367
+ border-bottom: 1px solid #EEEEEE;
368
+ }
369
+ .wpmud .dev-list > li.list-header {
370
+ text-transform: none;
371
+ color: #333333;
372
+ font-size: 13px;
373
+ }
374
+ .wpmud .dev-list .list-header .list-label {
375
+ font-weight: bold;
376
+ }
377
+ .wpmud .dev-list > li .list-label {
378
+ font-size: 13px;
379
+ font-weight: 500;
380
+ line-height: 30px;
381
+ padding: 15px 10px 15px 0
382
+ }
383
+ .wpmud .dev-list > li .list-data {
384
+ border-bottom: 1px solid #EEE;
385
+ cursor: default;
386
+ display: table-cell;
387
+ padding: 10px;
388
+ vertical-align: middle;
389
+ }
390
+ .wpmud .dev-list > li:last-child .list-label,
391
+ .wpmud .dev-list > li:last-child .list-detail {
392
+ border-bottom: 1px solid #eee;
393
+ }
394
+ .wpmud .box-dashboard-welcome .dev-list > li:last-child .list-label,
395
+ .wpmud .box-dashboard-welcome .dev-list > li:last-child .list-detail,
396
+ .wpmud .box-performance-welcome .dev-list > li:last-child .list-label,
397
+ .wpmud .box-performance-welcome .dev-list > li:last-child .list-detail,
398
+ .wpmud .box-minification-summary-meta-box .dev-list > li:last-child .list-label,
399
+ .wpmud .box-minification-summary-meta-box .dev-list > li:last-child .list-detail,
400
+ .wpmud .box-uptime-summary .dev-list > li:last-child .list-label,
401
+ .wpmud .box-uptime-summary .dev-list > li:last-child .list-detail {
402
+ border-bottom: 1px solid transparent;
403
+ }
404
+
405
+ .wpmud .dev-list > li:last-child .list-data {
406
+ border-bottom: 1px solid transparent;
407
+ }
408
+ .wpmud .dev-list > li .list-detail .wphb-dash-numbers {
409
+ font-family: 'Roboto Condensed', sans-serif;
410
+ font-size: 18px;
411
+ color: #666666;
412
+ line-height: 30px;
413
+ text-align: right;
414
+ font-weight: 400;
415
+ /*text-transform: uppercase;*/
416
+ }
417
+ .wpmud .dev-list-stats-border > li:first-child .list-label,
418
+ .wpmud .dev-list-stats-border > li:first-child .list-data,
419
+ .wpmud .dev-list-stats-border > li:first-child .list-detail {
420
+ border-top: 1px solid #eee;
421
+ }
422
+ .wpmud .dev-list-stats-border > li:last-child .list-label,
423
+ .wpmud .dev-list-stats-border > li:last-child .list-data,
424
+ .wpmud .dev-list-stats-border > li:last-child .list-detail {
425
+ border-bottom-color: #eee;
426
+ }
427
+ .wpmud .dev-list-stats > li .list-label-stats,
428
+ .wpmud .dev-list-stats > li .list-detail-stats-heading,
429
+ .wpmud .dev-list-stats > li .list-label-stats-filename > p {
430
+ color: #333;
431
+ font: 500 13px/30px 'Roboto', Arial, sans-serif;
432
+ }
433
+ .wpmud .dev-list-stats > li .list-label-stats-filename > p {
434
+ line-height: 25px;
435
+ margin-bottom: -10px;
436
+ }
437
+ .wpmud .dev-list-stats > li .list-detail-stats-heading {
438
+ font-weight: 400;
439
+ font-size: 18px;
440
+ color: #666;
441
+ }
442
+ .wpmud .dev-list-stats > li .list-detail-stats-heading-extra-info {
443
+ color: #BABABA;
444
+ display: block;
445
+ font: 500 12px/16px 'Roboto', Arial, sans-serif;
446
+ margin-top: 5px;
447
+ }
448
+ .wpmud .dev-list-stats.standalone {
449
+ margin: 0;
450
+ }
451
+ .wpmud .dev-list-stats.small > li .list-label-stats,
452
+ .wpmud .dev-list-stats.small > li .list-detail-stats-heading {
453
+ line-height: 26px;
454
+ }
455
+ .wpmud .dev-list-stats > li .list-detail-stats-heading.small {
456
+ font-size: 26px;
457
+ }
458
+ .wpmud .dev-list-stats .wphb-pills-group {
459
+ font-size: 0;
460
+ line-height: 1em;
461
+ }
462
+ .wpmud .dev-list-stats .wphb-filename-extension {
463
+ margin-right: 10px;
464
+ }
465
+ .wpmud .dev-list-stats > li .list-label-stats-date {
466
+ margin-right: 30px;
467
+ }
468
+ .wpmud .dev-list-stats .buttons,
469
+ .wpmud .box-content .buttons {
470
+ margin-top: 30px;
471
+ }
472
+ .wpmud .list-label-link {
473
+ color: #19B4CF;
474
+ }
475
+ .wpmud input[type="checkbox"] {
476
+ border-radius: 4px;
477
+ border: 1px solid #E6E6E6;
478
+ background-color: #F8F8F8;
479
+ }
480
+ .wpmud [tooltip]:after {
481
+ font: 500 12px/18px 'Roboto';
482
+ padding: 8px 12px;
483
+ background: #333333;
484
+ min-width: 50px;
485
+ max-width: 250px;
486
+ transition: all 0.2s ease;
487
+ text-transform: none;
488
+ }
489
+
490
+ .wpmud .tooltip-box { overflow: hidden; }
491
+ .wpmud .tooltip-box:hover { overflow: visible; }
492
+ .wpmud .radio-group input[type="radio"] + label > [tooltip] {
493
+ position: absolute;
494
+ left: 0;
495
+ top: 0;
496
+ bottom: 0;
497
+ right: 0;
498
+ z-index: 9;
499
+ }
500
+
501
+ .wpmud #enable-cache-wrap .button {
502
+ margin: 0 30px 30px;
503
+ }
504
+
505
+ .wpmud .wphb-dashboard-caching-cloudflare-box p {
506
+ margin-top:30px;
507
+ margin-bottom:20px;
508
+ }
509
+
510
+ .wpmud #wphb-box-dashboard-cloudflare .cloudflare-step form label {
511
+ text-align: left;
512
+ font-weight: 400;
513
+ padding-left:0;
514
+ padding-right:0;
515
+ }
516
+
517
+ .wpmud .cloudflare-step form label input {
518
+ margin-top: 5px;
519
+ background-color: #F8F8F8;
520
+ }
521
+
522
+ .wpmud .cloudflare-step form label input::-webkit-input-placeholder {color: #AAAAAA;}
523
+ .wpmud .cloudflare-step form label input::-moz-placeholder {color: #AAAAAA;}/* Firefox 19+ */
524
+ .wpmud .cloudflare-step form label input:-moz-placeholder {color: #AAAAAA;}/* Firefox 18- */
525
+ .wpmud .cloudflare-step form label input:-ms-input-placeholder {color: #AAAAAA;}
526
+
527
+ .wpmud .cloudflare-step > p:first-child {
528
+ text-align:left;
529
+ }
530
+
531
+ .wpmud .cloudflare-spinner {
532
+ display: inline-block;
533
+ float:none;
534
+ }
535
+ .wpmud .cloudflare-step p.cloudflare-submit,
536
+ .wpmud #cloudflare-how-to-title {
537
+ position:relative;
538
+ margin-top:11px;
539
+ }
540
+
541
+ .wpmud .cloudflare-step p.cloudflare-submit input[type="submit"] {
542
+ display: inline-block;
543
+ margin-top:0;
544
+ }
545
+
546
+ .wpmud #cloudflare-how-to {
547
+ clear: both;
548
+ margin-left: 0;
549
+ margin-bottom: 0;
550
+ list-style-position: inside;
551
+ }
552
+
553
+ .wpmud .cloudflare-step > p {
554
+ margin-bottom:30px;
555
+ }
556
+ .wpmud .cloudflare-step p.cloudflare-submit {
557
+ float:right;
558
+ }
559
+ .wpmud .cloudflare-step p.cloudflare-clear-cache {
560
+ float:left;
561
+ margin-bottom:0;
562
+ margin-top: -10px;
563
+ }
564
+ .wpmud .cloudflare-step hr {
565
+ margin-top:20px;
566
+ margin-bottom:20px;
567
+ }
568
+ .wpmud .cloudflare-step p.cloudflare-clear-cache-text {
569
+ text-align:left;
570
+ }
571
+ .wpmud #cloudflare-how-to-title {
572
+ float: left;
573
+ line-height: 15px;
574
+ padding-top: 7px;
575
+ font-size: 13px;
576
+ }
577
+
578
+ .wpmud .cloudflare-step .cloudflare-data {
579
+ text-align:left;
580
+ margin-top:30px;
581
+ margin-bottom:0;
582
+ }
583
+
584
+ .wpmud .cloudflare-data > span {
585
+ display:inline-block;
586
+ margin-right:20px;
587
+ }
588
+
589
+ .wpmud .cloudflare-clear-cache .button {
590
+ margin-top: 0 !important;
591
+ }
592
+
593
+
594
+ /* Buttons */
595
+ .wpmud .wphb-modal button:not(.wph-button):not(#collapse-button),
596
+ .wpmud .wphb-modal .button:hover:not(:focus):not(:active):not(.wph-button):not(#collapse-button):not([tooltip]) {
597
+ background: #17A8E3;
598
+ }
599
+ .wpmud .wphb-modal .button:not(.notice-dismiss),
600
+ .wpmud .wrap-wp-hummingbird button:not(.notice-dismiss),
601
+ .wpmud .wrap-wp-hummingbird .button,
602
+ .wpmud .wrap-wp-hummingbird button:not(.wph-button):not(#collapse-button):not(.notice-dismiss) {
603
+ font: 500 12px/16px 'Roboto' !important;
604
+ padding: 7px 16px;
605
+ height: 30px;
606
+ background-color: #17A8E3;
607
+ color: #FFFFFF;
608
+ border-radius: 3px;
609
+ -moz-border-radius: 3px;
610
+ transition: all .3s ease;
611
+ -webkit-transition: all .3s ease;
612
+ text-shadow: none !important;
613
+ }
614
+ .wpmud .wrap-wp-hummingbird button:hover:not(:focus):not(:active):not(.wph-button):not(#collapse-button):not([tooltip]):not(.notice-dismiss),
615
+ .wpmud .wrap-wp-hummingbird .button:hover:not(:focus):not(:active):not(.wph-button):not(#collapse-button):not([tooltip]),
616
+ .wpmud .wphb-modal .button:hover:not(:focus):not(:active):not(.wph-button):not(#collapse-button):not([tooltip]),
617
+ .wpmud .wrap-wp-hummingbird button:active,
618
+ .wpmud .wrap-wp-hummingbird button:focus,
619
+ .wpmud .wrap-wp-hummingbird .button:active,
620
+ .wpmud .wrap-wp-hummingbird .button:focus,
621
+ .wpmud .wphb-modal .button:focus,
622
+ .wpmud .wphb-modal .button:active {
623
+ background: #0A9BD6;
624
+ }
625
+ .wpmud .wrap-wp-hummingbird .button-disabled {
626
+ border-radius: 15px;
627
+ background-color: #F8F8F8;
628
+ color: #C0C0C0;
629
+ }
630
+ .wpmud .wphb-modal .button.button-large,
631
+ .wpmud .wrap-wp-hummingbird button.button-large:not(.wph-button):not(#collapse-button),
632
+ .wpmud .wrap-wp-hummingbird button.button-large,
633
+ .wpmud .wrap-wp-hummingbird .button.button-large {
634
+ font: 500 15px/20px 'Roboto' !important;
635
+ height: 40px !important;
636
+ padding: 11px 20px 9px;
637
+ }
638
+
639
+ .wpmud .wrap-wp-hummingbird button.button-ghost:not(.wph-button):not(#collapse-button),
640
+ .wpmud .wrap-wp-hummingbird .button-ghost,
641
+ .wpmud .wphb-modal .button-ghost {
642
+ padding: 5px 16px 7px !important;
643
+ background-color: transparent !important;
644
+ border: 2px solid #888888;
645
+ color: #666666 !important;
646
+ }
647
+ .wpmud .wrap-wp-hummingbird button.button-ghost:hover:not(.wph-button):not(#collapse-button),
648
+ .wpmud .wrap-wp-hummingbird .button-ghost:hover:not(:focus):not(:active),
649
+ .wpmud .wphb-modal .button-ghost:hover:not(:focus):not(:active),
650
+ .wpmud .wrap-wp-hummingbird .button-ghost:active,
651
+ .wpmud .wrap-wp-hummingbird .button-ghost:hover:enabled,
652
+ .wpmud .wrap-wp-hummingbird .button-ghost:focus,
653
+ .wpmud .wphb-modal .button-ghost:active,
654
+ .wpmud .wphb-modal .button-ghost:hover:enabled,
655
+ .wpmud .wphb-modal .button-ghost:focus,
656
+ .wpmud .wrap-wp-hummingbird .button-grey {
657
+ background-color: #7B7B7B !important;
658
+ border-color: #7B7B7B;
659
+ color: #FFFFFF !important;
660
+ }
661
+ .wpmud .wrap-wp-hummingbird button.button-ghost.button-large:not(.wph-button):not(#collapse-button),
662
+ .wpmud .wrap-wp-hummingbird .button-ghost.button-large,
663
+ .wpmud .wphb-modal .button-ghost.button-large {
664
+ padding: 9px 20px 9px !important;
665
+ }
666
+
667
+ .wpmud .wphb-modal .button-content-cta {
668
+ box-shadow: none;
669
+ background-color: #1ABC9C !important;
670
+ color: #FFFFFF;
671
+ }
672
+ .wpmud .wrap-wp-hummingbird .button-content-cta {
673
+ box-shadow: none;
674
+ background-color: #1ABC9C;
675
+ color: #FFFFFF;
676
+ }
677
+
678
+ .wpmud .wrap-wp-hummingbird .button-content-cta:hover:not(:focus):not(:active),
679
+ .wpmud .wphb-modal .button-content-cta:hover:not(:focus):not(:active),
680
+ .wpmud .wrap-wp-hummingbird .button-content-cta:active,
681
+ .wpmud .wrap-wp-hummingbird .button-content-cta:focus,
682
+ .wpmud .wphb-modal .button-content-cta:active,
683
+ .wpmud .wphb-modal .button-content-cta:focus {
684
+ background: #0DAF8F !important;
685
+ border-color: #0DAF8F;
686
+ }
687
+
688
+ .wpmud .wrap-wp-hummingbird .button-content-cta.button-ghost {
689
+ background: transparent;
690
+ color: #1ABC9C !important;
691
+ border-color: #1ABC9C;
692
+ border-radius: 20px;
693
+ }
694
+ .wpmud .wrap-wp-hummingbird .button-content-cta.button-ghost:active {
695
+ color: #FFFFFF !important;
696
+ border-color: #0DAF8F;
697
+ }
698
+
699
+
700
+ .wpmud .wrap-wp-hummingbird .button-notice {
701
+ background-color: #E6E6E6 !important;
702
+ color: #AAAAAA !important;
703
+ margin-top: 20px;
704
+ }
705
+ .wpmud .wrap-wp-hummingbird .button-notice:hover:not(:focus):not(:active):not(.wph-button):not(#collapse-button):not([tooltip]),
706
+ .wpmud .wrap-wp-hummingbird .button-notice:hover:not(:focus):not(:active),
707
+ .wpmud .wrap-wp-hummingbird .button-notice:active,
708
+ .wpmud .wrap-wp-hummingbird .button-notice:focus {
709
+ background-color: #888888 !important;
710
+ color: #FFFFFF !important;
711
+ }
712
+
713
+ .wrap-wp-hummingbird .button-load-more {
714
+ background-color: transparent;
715
+ border: 1px solid #ddd;
716
+ border-radius: 50%;
717
+ color: #bababa;
718
+ font-family: 'Roboto Condensed', 'Roboto', Arial, sans-serif;
719
+ font-size: 13px;
720
+ font-weight: 700;
721
+ line-height: 18px;
722
+ height: 140px;
723
+ padding: 0;
724
+ transition: color .4s, background-color .4s;
725
+ width: 140px;
726
+ }
727
+ .wrap-wp-hummingbird .button-load-more:hover:not(:focus):not(:active) {
728
+ background-color: #fafafa;
729
+ border-color: #ddd;
730
+ color: #777771;
731
+ }
732
+ .wrap-wp-hummingbird .button-load-more:active,
733
+ .wrap-wp-hummingbird .button-load-more:focus {
734
+ background: #777771;
735
+ }
736
+
737
+ /* Button Labels */
738
+ .wpmud .wphb-button-label {
739
+ border: 1px solid transparent;
740
+ border-radius: 15px;
741
+ color: #fff;
742
+ font: 500 13px/26px 'Roboto';
743
+ display: inline-block;
744
+ height: 26px;
745
+ margin: 0;
746
+ padding: 0 12px;
747
+ text-decoration: none;
748
+ text-shadow: none;
749
+ text-transform: none;
750
+ white-space: nowrap;
751
+ }
752
+ .wpmud .wphb-button-label-red {
753
+ background: #fd6e70;
754
+ }
755
+ .wpmud .wphb-button-label-yellow {
756
+ background: #FFD000;
757
+ color: #333333;
758
+ }
759
+ .wpmud .wphb-button-label-green {
760
+ background: #1ABC9C;
761
+ }
762
+ .wpmud .wphb-button-label-light {
763
+ color: #333333;
764
+ background-color: #F2F2F2;
765
+ }
766
+
767
+ /* Labels */
768
+ .wpmud .wrap-wp-hummingbird .wphb-label {
769
+ color: #fff;
770
+ display: block;
771
+ font: 500 15px/20px 'Roboto';
772
+ text-shadow: none;
773
+ white-space: nowrap;
774
+ }
775
+ .wpmud .wrap-wp-hummingbird .wphb-label-error {
776
+ color: #fd6e70;
777
+ font-size: 12px;
778
+ }
779
+ .wpmud .wrap-wp-hummingbird .wphb-label-notice {
780
+ background: #14485F;
781
+ border-radius: 3px;
782
+ padding: 5px 10px;
783
+ }
784
+ .wpmud .wrap-wp-hummingbird .wphb-label-notice-warning {
785
+ background: #FECF2F;
786
+ color: #4E4B10;
787
+ }
788
+ .wpmud .wrap-wp-hummingbird .wphb-label-notice-inline {
789
+ display: inline-block;
790
+ font-size: 13px;
791
+ color: #888888;
792
+ }
793
+ .wpmud .wrap-wp-hummingbird .wphb-label-disabled {
794
+ background: #F2F2F2;
795
+ border-radius: 20px;
796
+ color: #C0C0C0;
797
+ display: inline-block;
798
+ font: 500 12px/20px 'Roboto', Arial, sans-serif;
799
+ min-width: 120px;
800
+ padding: 5px;
801
+ text-align: center;
802
+ text-transform: uppercase;
803
+ }
804
+
805
+ /* Icons */
806
+ @font-face {
807
+ font-family: 'hummingbird';
808
+ src: url('../fonts/hummingbird.eot?9sde7j');
809
+ src: url('../fonts/hummingbird.eot?9sde7j#iefix') format('embedded-opentype'),
810
+ url('../fonts/hummingbird.ttf?9sde7j') format('truetype'),
811
+ url('../fonts/hummingbird.woff?9sde7j') format('woff'),
812
+ url('../fonts/hummingbird.svg?9sde7j#hummingbird') format('svg');
813
+ font-weight: normal;
814
+ font-style: normal;
815
+ }
816
+
817
+ .wpmud [class^="hb-"], .wpmud [class*=" hb-"] {
818
+ font-family: 'hummingbird' !important;
819
+ speak: none;
820
+ font-style: normal;
821
+ font-weight: normal;
822
+ font-variant: normal;
823
+ text-transform: none;
824
+ line-height: 1;
825
+ -webkit-font-smoothing: antialiased;
826
+ -moz-osx-font-smoothing: grayscale;
827
+ font-size: 15px;
828
+ }
829
+
830
+ .wpmud .hb-icon-cache:before { content: "\e900"; }
831
+ .wpmud .hb-icon-cloudflare:before { content: "\e901"; }
832
+ .wpmud .hb-icon-gzip:before { content: "\e902"; }
833
+ .wpmud .hb-icon-minify-combine:before { content: "\e903"; }
834
+ .wpmud .hb-icon-minify-footer:before { content: "\e904"; }
835
+ .wpmud .hb-icon-minify:before { content: "\e905"; }
836
+ .wpmud .hb-icon-performancetest:before { content: "\e906"; }
837
+ .wpmud .hb-icon-restore:before { content: "\e907"; }
838
+ .wpmud .hb-icon-smush:before { content: "\e908"; }
839
+ .wpmud .hb-icon-audit:before { content: "\e909"; }
840
+ .wpmud .hb-icon-reports:before { content: "\e90a"; }
841
+ .wpmud .hb-wpmudev-icon-cross:before { content: "\e90c"; }
842
+ .wpmud .hb-wpmudev-icon-info:before { content: "\e90d"; }
843
+ .wpmud .hb-wpmudev-icon-tick:before { content: "\e90e"; }
844
+ .wpmud .hb-wpmudev-icon-warning:before { content: "\e90f"; }
845
+
846
+ .wpmud .wphb-icon {
847
+ position: relative;
848
+ }
849
+ .wpmud .wphb-icon-left {
850
+ display: block;
851
+ float: left;
852
+ }
853
+
854
+ /* ****************************************************************************
855
+ * 2. COMMON/GENERAL STYLES
856
+ */
857
+
858
+ .wpmud .footer-love {
859
+ text-align: center;
860
+ margin-top: 50px;
861
+ color: #C0C0C0;
862
+ font-size: 13px;
863
+ }
864
+ .wpmud .footer-love > .dashicons-heart {
865
+ font-size: 14px;
866
+ line-height: 22px;
867
+ }
868
+ /* Tables */
869
+ .wpmud .wphb-table-wrapper.complex {
870
+ min-height: .01%;
871
+ overflow-x: auto;
872
+ border-bottom: 1px solid #eee;
873
+ }
874
+ .wpmud .wphb-table {
875
+ font-weight: 400;
876
+ max-width: 100%;
877
+ width: 100%;
878
+ color: #333333;
879
+ }
880
+ .wpmud .wphb-border-frame {
881
+ border: 1px solid #E6E6E6;
882
+ border-radius: 5px;
883
+ margin: 10px 0 0 !important;
884
+ }
885
+ .wpmud .list-table.wphb-table tr:hover .wphb-table-td-has-tooltip {
886
+ z-index: 3;
887
+ }
888
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-heading-cta,
889
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-item-cta {
890
+ text-align: right;
891
+ }
892
+ .wpmud .performance-report-table {
893
+ text-align: left;
894
+ margin-top: 30px;
895
+ overflow: hidden;
896
+ }
897
+ .wpmud .performance-report-table p,
898
+ .wpmud .performance-report-table ol li {
899
+ font-size: 13px !important;
900
+ color: #888888;
901
+ line-height: 22px;
902
+ }
903
+ .wpmud .performance-report-table ol > p {
904
+ margin-left: -30px;
905
+ margin-bottom: 15px;
906
+ }
907
+ .wpmud .performance-report-table > thead > tr > th:first-child {
908
+ padding-left: 30px;
909
+ }
910
+ .wpmud .performance-report-table .wphb-performance-report-item {
911
+ position: relative;
912
+ }
913
+ .wpmud .performance-report-table .wphb-performance-report-item:hover td {
914
+ cursor: pointer;
915
+ }
916
+ .wpmud .performance-report-table .wphb-performance-report-item-type {
917
+ color: #888888;
918
+ font-size: 13px;
919
+ transition: color .3s;
920
+ text-transform: capitalize;
921
+ }
922
+ .wpmud .performance-report-table .wphb-performance-report-item:hover .wphb-performance-report-item-type {
923
+ color: #333333;
924
+ }
925
+ .wpmud .performance-report-table .wphb-performance-report-item-cta {
926
+ text-align: right;
927
+ width: 15%;
928
+ }
929
+ .wpmud .wphb-performance-report-item .trigger-additional-content {
930
+ color: #888888;
931
+ cursor: pointer;
932
+ display: inline-block;
933
+ font-size: 14px;
934
+ line-height: 1em;
935
+ height: 14px;
936
+ margin: 8px 30px 8px 15px;
937
+ transition: color .3s;
938
+ vertical-align: middle;
939
+ }
940
+ .wpmud .wphb-performance-report-item .trigger-additional-content .dev-icon-caret_down:before {
941
+ display: inline-block;
942
+ transition: transform 0.5s;
943
+ transform: rotate(0);
944
+ }
945
+ .wpmud .wphb-performance-report-item-opened .trigger-additional-content .dev-icon-caret_down:before {
946
+ transform: rotate(-180deg);
947
+ }
948
+ .wpmud .performance-report-table .wphb-performance-report-item-opened {
949
+ background: #f9f9f9;
950
+ }
951
+ .wpmud .performance-report-table .wphb-performance-report-item-opened:hover > td:first-child:after,
952
+ .wpmud .performance-report-table .wphb-performance-report-item-opened:hover > td:last-child:after {
953
+ content: '';
954
+ display: none;
955
+ }
956
+ .wpmud .performance-report-table .wphb-performance-report-item-additional-content {
957
+ background: #f9f9f9;
958
+ display: none;
959
+ position: relative;
960
+ }
961
+ .wpmud .wphb-table.performance-report-table .wphb-performance-report-item-additional-content:hover,
962
+ .wpmud .wphb-table.performance-report-table .wphb-performance-report-item-opened:hover {
963
+ background: #f9f9f9;
964
+ }
965
+ .wpmud .performance-report-table .wphb-performance-report-item-additional-content-opened {
966
+ display: table-row;
967
+ }
968
+ .wpmud .performance-report-table .wphb-performance-report-item-additional-content > td {
969
+ padding: 30px 0;
970
+ position: relative;
971
+ }
972
+
973
+ .wpmud .wphb-performance-report-item-additional-content .dev-box .box-content {
974
+ text-align: left;
975
+ }
976
+ .wpmud .wphb-performance-report-item-additional-content .dev-box:last-child {
977
+ margin: 0 30px 0;
978
+ }
979
+ .wpmud .wphb-performance-report-item-additional-content-heading {
980
+ font-size: 22px;
981
+ line-height: 26px;
982
+ margin: 0 0 30px;
983
+ max-width: 100%;
984
+ text-align: center;
985
+ text-transform: uppercase;
986
+ }
987
+ .wpmud .wphb-performance-report-item-additional-content .wphb-performance-report-additional-title,
988
+ .wpmud .wphb-performance-report-item-additional-content .wphb-performance-report-additional-sub-title {
989
+ color: #333333;
990
+ font-size: 13px;
991
+ text-transform: none;
992
+ line-height: 23px;
993
+ margin: 0 0 20px;
994
+ text-align: left;
995
+ }
996
+ .wpmud .wphb-performance-report-item-additional-content .wphb-performance-report-additional-title {
997
+ font-weight: 700;
998
+ }
999
+ .wpmud .wphb-performance-report-item-additional-content .wphb-performance-report-additional-sub-title {
1000
+ font-weight: 400;
1001
+ }
1002
+
1003
+ .box-dashboard-welcome .box-content,
1004
+ .box-performance-welcome .box-content,
1005
+ .box-minification-summary-meta-box .box-content,
1006
+ .box-uptime-summary .box-content {
1007
+ padding: 30px 30px 10px !important;
1008
+ }
1009
+
1010
+ .box-dashboard-reports-no-membership,
1011
+ .box-dashboard-uptime-no-membership,
1012
+ .box-dashboard-smush-no-membership {
1013
+ background-repeat: no-repeat;
1014
+ background-position: 30px 100%;
1015
+ }
1016
+ .box-dashboard-reports-no-membership {
1017
+ background-image: url('../image/hb-graphic-upsell-reports.png');
1018
+ }
1019
+ .box-dashboard-uptime-no-membership {
1020
+ background-image: url('../image/hb-graphic-upsell-uptime.png');
1021
+ }
1022
+ .box-dashboard-smush-no-membership {
1023
+ background-image: url('../image/smush-share-widget.png');
1024
+ }
1025
+ @media
1026
+ only screen and (-webkit-min-device-pixel-ratio: 2),
1027
+ only screen and ( min--moz-device-pixel-ratio: 2),
1028
+ only screen and ( -o-min-device-pixel-ratio: 2/1),
1029
+ only screen and ( min-device-pixel-ratio: 2),
1030
+ only screen and ( min-resolution: 192dpi),
1031
+ only screen and ( min-resolution: 2dppx) {
1032
+ .box-dashboard-reports-no-membership,
1033
+ .box-dashboard-uptime-no-membership,
1034
+ .box-dashboard-smush-no-membership {
1035
+ background-size: 107px 148px;
1036
+ }
1037
+ .box-dashboard-reports-no-membership {
1038
+ background-image: url("../image/hb-graphic-upsell-reports@2x.png");
1039
+ }
1040
+ .box-dashboard-uptime-no-membership {
1041
+ background-image: url('../image/hb-graphic-upsell-uptime@2x.png');
1042
+ }
1043
+ .box-dashboard-smush-no-membership {
1044
+ background-image: url('../image/smush-share-widget@2x.png');
1045
+ }
1046
+ }
1047
+
1048
+
1049
+ /* Images */
1050
+ .wpmud section[class^="box-dashboard-"] .box-title:before {
1051
+ font-family: 'hummingbird';
1052
+ color: #333333;
1053
+ float: left;
1054
+ font-size: 20px;
1055
+ margin: 18px 10px 18px 0;
1056
+ }
1057
+ .wpmud section[class^="box-dashboard-performance"] .box-title:before { content: '\e906'; }
1058
+ .wpmud section[class^="box-dashboard-minification"] .box-title:before { content: '\e905'; }
1059
+ .wpmud section[class^="box-dashboard-caching"] .box-title:before { content: '\e900'; }
1060
+ .wpmud section[class^="box-dashboard-gzip"] .box-title:before { content: '\e902'; }
1061
+ .wpmud section[class^="box-dashboard-uptime"] .box-title:before { content: '\e90a'; }
1062
+ .wpmud section[class^="box-dashboard-smush"] .box-title:before { content: '\e908'; }
1063
+ .wpmud section[class^="box-dashboard-cloudflare"] .box-title:before { content: '\e901'; }
1064
+ .wpmud section[class^="box-dashboard-reports"] .box-title:before { content: '\e909'; }
1065
+
1066
+ .wpmud .wphb-image,
1067
+ .wpmud .wphb-image-icon-content {
1068
+ display: block;
1069
+ height: auto;
1070
+ max-width: 100%;
1071
+ }
1072
+ .wpmud .wphb-image-center,
1073
+ .wpmud .wphb-image-icon-content-center {
1074
+ margin-right: auto;
1075
+ margin-left: auto;
1076
+ }
1077
+ .wpmud .wphb-image-icon-content-top {
1078
+ margin-bottom: 30px;
1079
+ }
1080
+
1081
+ /* Lists */
1082
+ .wpmud .wphb-listing {
1083
+ margin: 0;
1084
+ }
1085
+ .wpmud .wphb-listing li {
1086
+ font-family: 'Roboto', Arial, sans-serif;
1087
+ font-size: 15px;
1088
+ font-weight: 400;
1089
+ line-height: 21px;
1090
+ margin-top: 10px;
1091
+ margin-bottom: 0;
1092
+ }
1093
+ .wpmud .wphb-listing li:first-child {
1094
+ margin-top: 0;
1095
+ }
1096
+ .wpmud .wphb-listing.bold li {
1097
+ font-weight: 500;
1098
+ }
1099
+ .wpmud .wphb-listing-ordered {
1100
+ padding-left: 20px;
1101
+ }
1102
+ .wpmud .wphb-listing li strong {
1103
+ font-weight: 500;
1104
+ }
1105
+ .wpmud .wphb-listing li:before {
1106
+ color: #17A8E3;
1107
+ top: 0;
1108
+ }
1109
+ .wpmud .wphb-listing li p {
1110
+ font-size: 13px;
1111
+ line-height: 22px;
1112
+ margin-top: 5px;
1113
+ }
1114
+
1115
+ /* Forms */
1116
+ .wpmud .wphb-select-group {
1117
+ clear: both;
1118
+ }
1119
+ .wpmud .wphb-select-group:after {
1120
+ content: '';
1121
+ display: table;
1122
+ clear: both;
1123
+ }
1124
+ .wpmud .wphb-select-group > label,
1125
+ .wpmud .wphb-select-group > div {
1126
+ float: left;
1127
+ display: block;
1128
+ }
1129
+ .wpmud .wphb-select-group > label {
1130
+ line-height: 43px;
1131
+ margin-right: 10px;
1132
+ }
1133
+ .wpmud .select-container {
1134
+ overflow: hidden;
1135
+ }
1136
+ .wpmud .select-container.active {
1137
+ overflow: visible;
1138
+ }
1139
+ .wpmud .wphb-select-group .spinner {
1140
+ margin: 11px;
1141
+ }
1142
+
1143
+ /* Notices */
1144
+ .wpmud .wrap-wp-hummingbird .notice {
1145
+ margin: 15px 0 0;
1146
+ }
1147
+ .wpmud .wrap-wp-hummingbird > .wphb-notice:not(.notice) {
1148
+ width: 600px;
1149
+ box-shadow: 0 5px 25px 0 rgba(0,0,0,0.15);
1150
+ border-radius: 0 0 5px 5px;
1151
+ padding: 10px 30px;
1152
+ position: absolute !important;
1153
+ z-index: 100;
1154
+ left: 50%;
1155
+ margin-left: -300px;
1156
+ top: 0;
1157
+ }
1158
+ .wpmud .wphb-notice:not(.notice) {
1159
+ /*background: #fff;*/
1160
+ border-radius: 5px;
1161
+ color: #333;
1162
+ font-family: 'Roboto', Arial, sans-serif;
1163
+ font-size: 15px;
1164
+ font-weight: 400;
1165
+ line-height: 18px;
1166
+ padding: 15px 30px;
1167
+ position: relative;
1168
+ width: 100%;
1169
+ }
1170
+ .wpmud .wphb-notice.notice p {
1171
+ font-size: 14px;
1172
+ line-height: 1.5;
1173
+ margin: 10px 0;
1174
+ }
1175
+ .wpmud .wphb-notice p,
1176
+ .wpmud .wphb-notice p a {
1177
+ color: #333333;
1178
+ font-weight: 400;
1179
+ }
1180
+ .wpmud .wphb-notice:not(.notice) p,
1181
+ .wpmud .wphb-notice:not(.notice) span,
1182
+ .wpmud .wphb-notice ul,
1183
+ .wpmud .wphb-notice strong {
1184
+ margin: 0 0 10px;
1185
+ padding: 0 0 0 30px;
1186
+ }
1187
+ .wpmud .wphb-notice:not(.notice) p:last-of-type {
1188
+ margin: 0;
1189
+ }
1190
+ .wpmud .wphb-notice p a {
1191
+ font-weight: 500;
1192
+ }
1193
+ .wpmud .wphb-notice p a:hover {
1194
+ color: #333;
1195
+ }
1196
+ .wpmud .wphb-notice .wphb-icon,
1197
+ .wpmud .wphb-notice .wphb-icon .wdv-icon {
1198
+ font-size: 22px;
1199
+ height: 22px;
1200
+ line-height: 22px;
1201
+ width: 22px;
1202
+ }
1203
+ .wpmud .wphb-notice.can-close .close {
1204
+ cursor: pointer;
1205
+ display: block;
1206
+ height: 15px;
1207
+ width: 15px;
1208
+ line-height: 15px;
1209
+ margin: 0;
1210
+ position: absolute;
1211
+ text-shadow: none;
1212
+ right: 10px;
1213
+ top: 15px;
1214
+ }
1215
+ .wpmud .wphb-notice.can-close .close:after {
1216
+ bottom: 0;
1217
+ color: #333;
1218
+ content: "\79";
1219
+ font-style: normal;
1220
+ font-weight: normal;
1221
+ font-variant: normal;
1222
+ font-family: 'WPMU-DEV-App-Icons';
1223
+ font-size: 15px;
1224
+ -webkit-font-smoothing: antialiased;
1225
+ -moz-osx-font-smoothing: grayscale;
1226
+ left: 0;
1227
+ line-height: 15px;
1228
+ opacity: 0.8;
1229
+ position: absolute;
1230
+ right: 0;
1231
+ speak: none;
1232
+ text-align: center;
1233
+ text-transform: none;
1234
+ top: 0;
1235
+ transition: opacity 0.3s;
1236
+ }
1237
+ .wpmud .wphb-notice.can-close .close:hover:after {
1238
+ opacity: 1;
1239
+ }
1240
+ .wpmud .wphb-block-entry-third span.status-ok:before,
1241
+ .wpmud .wphb-notice-error.can-close p:before,
1242
+ .wpmud .wphb-notice-success.can-close p:before,
1243
+ .wpmud .wphb-notice-success p:first-child:before,
1244
+ .wpmud .wphb-notice-error p:first-child:before,
1245
+ .wpmud .wphb-notice-warning p:first-child:before,
1246
+ .wpmud .wphb-notice-blue p:first-child:before {
1247
+ font-family: 'hummingbird';
1248
+ font-size: 20px;
1249
+ vertical-align: middle;
1250
+ line-height: 20px;
1251
+ top: -2px;
1252
+ position: relative;
1253
+ margin-left: -30px;
1254
+ margin-right: 10px;
1255
+ }
1256
+ .wpmud .wphb-notice-error.can-close p:before,
1257
+ .wpmud .wphb-notice-success.can-close p:before {
1258
+ margin-right: 20px;
1259
+ }
1260
+
1261
+ .wpmud .wphb-notice-success {
1262
+ background-color: #D1F1EA;
1263
+ }
1264
+ .wpmud .wphb-notice-error {
1265
+ background-color: #FFE5E9;
1266
+ }
1267
+ .wpmud .wphb-notice-warning {
1268
+ background-color: #FFF5D5;
1269
+ color: #333333;
1270
+ }
1271
+ .wpmud .wphb-notice-blue {
1272
+ background-color: #E1F6FF;
1273
+ margin-top: 30px;
1274
+ }
1275
+ .wpmud .cloudflare-step .wphb-notice-blue {
1276
+ margin-top: 0;
1277
+ }
1278
+ .wpmud .wphb-block-entry-third span.status-ok:before,
1279
+ .wpmud .wphb-notice-success p:before {
1280
+ content: '\e90e';
1281
+ color: #1ABC9C;
1282
+ }
1283
+ .wpmud .wphb-block-entry-third span.status-ok:before {
1284
+ margin-right: 0;
1285
+ line-height: 20px;
1286
+ }
1287
+ .wpmud .wphb-notice-error p:before {
1288
+ content: '\e90f';
1289
+ color: #FF7F83;
1290
+ }
1291
+ .wpmud .wphb-notice-warning p:before {
1292
+ content: '\e90d';
1293
+ color: #FECF2F;
1294
+ font-size: 18px;
1295
+ line-height: 18px;
1296
+ }
1297
+ .wpmud .wphb-notice-blue p:before {
1298
+ content: '\e90e';
1299
+ color: #17A8E3;
1300
+ }
1301
+ .wpmud .dev-overlay .wphb-notice-warning p {
1302
+ font-size: 14px;
1303
+ line-height: 22px;
1304
+ }
1305
+ .wpmud .wphb-notice-warning p,
1306
+ .wpmud .wphb-notice-warning p a,
1307
+ .wpmud .wphb-notice-warning.can-close .close:after {
1308
+ color: #4E4B10;
1309
+ }
1310
+
1311
+ .wpmud .wphb-heading-status-green {
1312
+ color: #1ABC9C;
1313
+ }
1314
+ .wpmud .wphb-heading-status {
1315
+ font-family: 'Roboto Condensed', 'Roboto', sans-serif;
1316
+ font-size: 30px;
1317
+ margin-top: 0;
1318
+ }
1319
+
1320
+ /* Modals */
1321
+ .wpmud .dev-overlay .title .close {
1322
+ color: #888888;
1323
+ font-size: 34px;
1324
+ }
1325
+ .wpmud .wphb-modal * {
1326
+ -webkit-box-sizing: border-box;
1327
+ box-sizing: border-box;
1328
+ font-family: 'Roboto', sans-serif;
1329
+ }
1330
+ .wpmud .wphb-modal .wphb-dialog-content > * {
1331
+ margin-bottom: 30px;
1332
+ }
1333
+ .wpmud .wphb-modal .wphb-dialog-content > *:last-child {
1334
+ margin-bottom: 0;
1335
+ }
1336
+ .wpmud .wphb-modal .wphb-dialog-content .wphb-modal-image-bottom {
1337
+ margin-bottom: -40px;
1338
+ }
1339
+ .wpmud .wphb-progress-modal .wphb-progress,
1340
+ .wpmud .wphb-progress-modal .wphb-block-test {
1341
+ max-width: 100%;
1342
+ }
1343
+ .wpmud .wphb-progress-modal .wphb-dialog-content p {
1344
+ color: #666666;
1345
+ }
1346
+ .wpmud .wphb-progress-modal .wphb-notice-box p {
1347
+ color: #333333;
1348
+ font-size: 13px;
1349
+ line-height: 22px;
1350
+ }
1351
+
1352
+ .wpmud .wphb-modal .wphb-dialog-content .button {
1353
+ margin-bottom: 15px;
1354
+ }
1355
+ .wpmud .wphb-modal .wphb-dialog-content .button.standalone {
1356
+ margin-bottom: 30px;
1357
+ }
1358
+ .wpmud .wphb-modal .wphb-progress-state {
1359
+ margin-top: -20px;
1360
+ }
1361
+ .wpmud .wphb-modal .wphb-dialog-footer {
1362
+ border-top: 1px solid #EAEAEA;
1363
+ margin: 30px -30px;
1364
+ padding: 30px 30px 0;
1365
+ }
1366
+ .wpmud .wphb-modal .alignleft,
1367
+ .wpmud .wphb-modal .button {
1368
+ margin-bottom: 0 !important;
1369
+ }
1370
+ /* CDN modal */
1371
+ .wpmud .wphb-modal.wphb-quick-setup-modal .wphb-block-test,
1372
+ .wpmud.hummingbird_page_wphb-minification .wphb-modal .wphb-block-test,
1373
+ .wpmud.toplevel_page_wphb-minification .wphb-modal .wphb-block-test {
1374
+ display: flex;
1375
+ align-content: center;
1376
+ align-items: center;
1377
+ height: auto;
1378
+ padding: 20px 30px;
1379
+ margin-bottom: 30px;
1380
+ }
1381
+ .wpmud .wphb-modal.wphb-quick-setup-modal .wphb-block-test > p {
1382
+ font-size: 13px;
1383
+ line-height: 22px;
1384
+ margin-right: 14px;
1385
+ margin-bottom: 0;
1386
+ }
1387
+ .wpmud.hummingbird_page_wphb-minification .wphb-modal .wphb-block-test > label {
1388
+ margin: 0;
1389
+ }
1390
+
1391
+ /* Box-footer with buttons */
1392
+ .wpmud .box-footer.buttons.buttons-on-left {
1393
+ text-align: left;
1394
+ }
1395
+ .wpmud .box-footer.buttons.buttons-on-right {
1396
+ text-align: right;
1397
+ }
1398
+
1399
+ /* Toggles */
1400
+ .wpmud .toggle .toggle-label {
1401
+ text-align: left;
1402
+ }
1403
+ .wpmud .toggle .toggle-cross {
1404
+ color: rgba(221,221,221,1);
1405
+ }
1406
+ .wpmud .toggle-group {
1407
+ display: inline-block;
1408
+ }
1409
+ .wpmud .toggle .toggle-checkbox:checked:disabled + .toggle-label {
1410
+ background: transparent;
1411
+ }
1412
+ .wpmud .toggle .toggle-checkbox:checked:disabled + .toggle-label:before {
1413
+ bottom: 0;
1414
+ left: 0;
1415
+ right: 0;
1416
+ top: 0;
1417
+ }
1418
+ .wpmud .toggle .toggle-checkbox:checked:disabled + .toggle-label:after {
1419
+ margin-left: 1px;
1420
+ }
1421
+ .wpmud .toggle-item.bordered,
1422
+ .wpmud .wphb-block-entry.bordered {
1423
+ border-top: 1px solid #E6E6E6;
1424
+ padding-top: 30px;
1425
+ }
1426
+ .wpmud .toggle-item.space-top,
1427
+ .wpmud .wphb-block-entry.space-top {
1428
+ margin: 30px 0 0;
1429
+ }
1430
+ .wpmud .toggle-item.space-top-small {
1431
+ margin: 15px 0 0;
1432
+ }
1433
+ .wpmud .toggle-item label {
1434
+ text-align: left;
1435
+ }
1436
+ .wpmud .toggle-item .toggle-item-group {
1437
+ display: table;
1438
+ width: 100%;
1439
+ }
1440
+ .wpmud .toggle-item .toggle-info,
1441
+ .wpmud .toggle-item .toggle-actions {
1442
+ display: table-cell;
1443
+ }
1444
+ .wpmud .toggle-item .toggle-item-title {
1445
+ color: #555;
1446
+ font: 400 15px/20px 'Roboto', Arial, sans-serif;
1447
+ margin: 0;
1448
+ }
1449
+ .wpmud .toggle-item .toggle-item-description {
1450
+ color: #888;
1451
+ font: 400 13px/22px 'Roboto', Arial, sans-serif;
1452
+ margin: 10px 0;
1453
+ }
1454
+ .wpmud .toggle-item .toggle-item-description:last-child {
1455
+ margin-bottom: 0;
1456
+ }
1457
+ .wpmud .toggle-item .toggle-actions {
1458
+ padding-left: 30px;
1459
+ vertical-align: middle;
1460
+ text-align: right;
1461
+ }
1462
+
1463
+ /* Checkbox groups */
1464
+ .wpmud .checkbox-group {
1465
+ border: 1px solid #DDD;
1466
+ border-radius: 5px;
1467
+ border-spacing: 0;
1468
+ border-collapse: separate;
1469
+ position: relative;
1470
+ display: flex;
1471
+ width: 210px;
1472
+ height: 52px;
1473
+ }
1474
+ /* We do not use display: none, because screen readers don't see the element */
1475
+ .wpmud .checkbox-group input[type="checkbox"] {
1476
+ border: 0;
1477
+ clip: rect(0 0 0 0);
1478
+ height: 1px;
1479
+ margin: -1px;
1480
+ overflow: hidden;
1481
+ padding: 0;
1482
+ position: absolute;
1483
+ width: 1px;
1484
+ display: block;
1485
+ }
1486
+ .wpmud .checkbox-group input[type="checkbox"]:first-child + label {
1487
+ border-radius: 4px 0 0 4px;
1488
+ }
1489
+ .wpmud .checkbox-group input[type="checkbox"] + label:last-child {
1490
+ border-radius: 0 4px 4px 0;
1491
+ border-right: 0;
1492
+ }
1493
+ .wpmud .checkbox-group input[type="checkbox"] + label {
1494
+ text-align: center;
1495
+ width: 70px;
1496
+ height: 50px;
1497
+ display: table-cell;
1498
+ border-right: 1px solid #DDD;
1499
+ position: relative;
1500
+ padding: 0 10px;
1501
+ transition-property: background, color;
1502
+ transition-duration: 0.3s;
1503
+ font-size: 10px;
1504
+ color: transparent !important;
1505
+ }
1506
+ /* In modal window start */
1507
+ .wpmud .wphb-modal .checkbox-group input[type="checkbox"] + label {
1508
+ padding: 10px 10px;
1509
+ }
1510
+ .wpmud .wphb-modal .checkbox-group {
1511
+ width: 100%;
1512
+ height: 72px;
1513
+ }
1514
+ .wpmud .wphb-modal .checkbox-group input[type="checkbox"] + label {
1515
+ width: 100%;
1516
+ height: 70px;
1517
+ }
1518
+ /* In modal window end */
1519
+ .wpmud .wphb-modal .toggle-label-background,
1520
+ .wpmud .checkbox-group input[type="checkbox"]:checked + label {
1521
+ box-shadow: none;
1522
+ background-color: #EFFAFF;
1523
+ }
1524
+ .wpmud .checkbox-group input[type="checkbox"] + label > span:not(.toggle),
1525
+ .wpmud .checkbox-group input[type="checkbox"] + label > i {
1526
+ color: #888888;
1527
+ }
1528
+ .wpmud .checkbox-group input[type="checkbox"]:checked + label > span:not(.toggle),
1529
+ .wpmud .checkbox-group input[type="checkbox"]:checked + label > i {
1530
+ color: #17A8E3;
1531
+ }
1532
+ .wpmud .checkbox-group input[type="checkbox"]:disabled + label > span:not(.toggle),
1533
+ .wpmud .checkbox-group input[type="checkbox"]:disabled + label > i {
1534
+ color: #BCBCBC;
1535
+ }
1536
+ .wpmud .checkbox-group input[type="checkbox"]:disabled + label {
1537
+ background-color: #F8F8F8;
1538
+ }
1539
+ .wpmud .checkbox-group input[type="checkbox"] + label > [tooltip] {
1540
+ position: absolute;
1541
+ left: 0;
1542
+ top: 0;
1543
+ bottom: 0;
1544
+ right: 0;
1545
+ z-index: 9;
1546
+ }
1547
+ .wpmud .checkbox-group label [class^="hb-"] {
1548
+ display: block;
1549
+ padding: 10px 0 4px;
1550
+
1551
+ }
1552
+
1553
+ /* ****************************************************************************
1554
+ * 3. COMPONENTS/MODULES
1555
+ */
1556
+ /* Pills */
1557
+ .wphb-pills {
1558
+ display: inline-block;
1559
+ background-color: #FFD000;
1560
+ color: #333333;
1561
+ border-radius: 15px;
1562
+ width: 39px;
1563
+ height: 26px;
1564
+ font-size: 12px;
1565
+ line-height: 26px;
1566
+ /*margin: 16px 0 0 10px;*/
1567
+ text-align: center;
1568
+ font-weight: 500;
1569
+ }
1570
+ .wpmud .box-title .wphb-pills {
1571
+ margin: 16px 0 0 10px;
1572
+ }
1573
+ .wphb-pills.grey {
1574
+ background-color: #F2F2F2;
1575
+ color: #555;
1576
+ }
1577
+ .wphb-pills.red {
1578
+ background-color: #FF6D6D;
1579
+ color: #fff;
1580
+ }
1581
+ .wphb-pills.green {
1582
+ background-color: #1ABC9C;
1583
+ color: #fff;
1584
+ }
1585
+ .wphb-pills.with-arrow:after {
1586
+ border: 8px solid transparent;
1587
+ content: '';
1588
+ height: 0;
1589
+ pointer-events: none;
1590
+ position: absolute;
1591
+ width: 0;
1592
+ z-index: 1;
1593
+ }
1594
+ .wphb-pills.with-arrow.right:after {
1595
+ border-left-color: #19B4CF;
1596
+ left: 50%;
1597
+ margin-top: -8px;
1598
+ top: 50%;
1599
+ }
1600
+ .wphb-pills.with-arrow.left:after {
1601
+ border-right-color: #19B4CF;
1602
+ right: 100%;
1603
+ margin-top: -8px;
1604
+ top: 50%;
1605
+ }
1606
+ .wphb-pills.with-arrow.right.grey:after {
1607
+ border-left-color: #F2F2F2;
1608
+ }
1609
+ .wphb-pills.with-arrow.left.grey:after {
1610
+ border-right-color: #F2F2F2;
1611
+ }
1612
+ .wphb-pills-group {
1613
+ border-collapse: collapse;
1614
+ border-spacing: 0;
1615
+ font-size: 0;
1616
+ display: inline-block;
1617
+ position: relative;
1618
+ }
1619
+ .wphb-pills-group.stacked .wphb-pills {
1620
+ font-size: 10px;
1621
+ line-height: 12px;
1622
+ height: 12px;
1623
+ text-align:left;
1624
+ max-width: 69px;
1625
+ color: #888888;
1626
+ display: block;
1627
+ background-color: transparent;
1628
+ }
1629
+ .wphb-pills-group.stacked .wphb-pills:last-child {
1630
+ color: #1ABC9C;
1631
+ background-color: transparent;
1632
+ }
1633
+ .wphb-pills-group.stacked .dev-icon.dev-icon-caret_down {
1634
+ color: #1ABC9C;
1635
+ margin-left: 7px;
1636
+ }
1637
+ .wphb-pills-group .wphb-pills {
1638
+ border-radius: 0;
1639
+ width: 80px;
1640
+ line-height: 30px;
1641
+ height: 30px;
1642
+ margin: 0;
1643
+ }
1644
+ .wphb-pills-group .wphb-pills:first-child {
1645
+ border-radius: 5px 0 0 5px !important;
1646
+ }
1647
+ .wphb-pills-group .wphb-pills:last-child {
1648
+ background-color: #17A8E3;
1649
+ color: #FFFFFF;
1650
+ border-radius: 0 5px 5px 0 !important;
1651
+ }
1652
+
1653
+ /* Block: Section */
1654
+ .wpmud .wphb-block-section {
1655
+ margin-top: 40px;
1656
+ }
1657
+ .wpmud .wphb-block-section:first-child {
1658
+ margin-top: 0;
1659
+ }
1660
+ .wpmud .wphb-block-section-content * {
1661
+ color: #555;
1662
+ line-height: 20px;
1663
+ }
1664
+
1665
+ /* Box: Content */
1666
+ .wpmud .content-box .wphb-block-entry-image-bottom {
1667
+ margin-bottom: -30px;
1668
+ }
1669
+ .wpmud .content-box .wphb-block-entry-image-center {
1670
+ margin-top: 30px;
1671
+ }
1672
+ .wpmud .content-box .wphb-block-entry-image-center img {
1673
+ margin-left: auto;
1674
+ margin-right: auto;
1675
+ }
1676
+ .wpmud .minification-settings-screen .wphb-block-entry-image-bottom {
1677
+ margin-bottom: 0;
1678
+ }
1679
+
1680
+ /* Box: Content One Col */
1681
+ .wpmud .content-box-one-col {}
1682
+
1683
+ /* Box: Content One Col Center */
1684
+ .wpmud .content-box-one-col-center .box-content {
1685
+ text-align: left;
1686
+ }
1687
+ .wpmud .content-box-one-col-center .box-content .button {
1688
+ margin-top: 30px;
1689
+ }
1690
+ .wpmud .content-box-one-col-center .wphb-block-entry-content {
1691
+ margin: 0 auto;
1692
+ }
1693
+ .wpmud .content-box-flex {
1694
+ display: flex;
1695
+ justify-content: space-between;
1696
+ align-items: flex-end;
1697
+ }
1698
+
1699
+ /* Box: Content w/Image (left) */
1700
+ .wpmud .content-box-two-cols-image-left .box-content {
1701
+ text-align: left;
1702
+ }
1703
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-image,
1704
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-content {
1705
+ display: block;
1706
+ }
1707
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-image {
1708
+ float: left;
1709
+ }
1710
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-content {
1711
+ margin: 35px 0 0 285px;
1712
+ }
1713
+ .wpmud .box-dashboard-smush-no-membership .content-box-two-cols-image-left .wphb-block-entry-content {
1714
+ margin-top: 45px;
1715
+ }
1716
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-content .title {
1717
+ text-align: left;
1718
+ }
1719
+
1720
+ /* Block: Content */
1721
+ .wpmud .wphb-block + .wphb-block {
1722
+ margin-top: 30px;
1723
+ }
1724
+ .wpmud .wphb-block-header {
1725
+ margin-bottom: 30px;
1726
+ }
1727
+ .wpmud .wphb-block-title {
1728
+ font-family: 'Roboto Condensed', 'Roboto', sans-serif;
1729
+ font-size: 22px;
1730
+ line-height: 26px;
1731
+ margin: 0;
1732
+ overflow: hidden;
1733
+ text-align: left;
1734
+ text-overflow: ellipsis;
1735
+ white-space: nowrap;
1736
+ }
1737
+ .wpmud .wphb-block-content + .wphb-block-content {
1738
+ margin-top: 30px;
1739
+ }
1740
+ .wpmud .wphb-block-content > *:last-child {
1741
+ margin-bottom: 0;
1742
+ }
1743
+ #wphb-box-dashboard-cloudflare .wphb-block-entry .wphb-block-entry-content {
1744
+ padding-top: 0;
1745
+ }
1746
+ .wpmud .wphb-block-content-center {
1747
+ text-align: center;
1748
+ }
1749
+ .wpmud .wphb-block-content pre {
1750
+ background-color: #FAFAFA;
1751
+ border: none;
1752
+ border-radius: 5px;
1753
+ margin: 0;
1754
+ padding: 20px 30px;
1755
+ white-space: pre;
1756
+ overflow-x: scroll;
1757
+ max-width: 100%;
1758
+ }
1759
+ .wpmud .wphb-block-content-blue {
1760
+ background-color: #e0f6ff;
1761
+ border-radius: 5px;
1762
+ padding: 20px 30px;
1763
+ }
1764
+ .wpmud .wphb-block-content .tooltip-box,
1765
+ .wpmud .wphb-block-content .toggle,
1766
+ .wpmud .wphb-block-content .toggle .toggle-label {
1767
+ height: 21px;
1768
+ vertical-align: top;
1769
+ }
1770
+ .wpmud .wphb-block-content-group {
1771
+ border-collapse: separate;
1772
+ border-spacing: 0;
1773
+ display: table;
1774
+ width: 100%;
1775
+ }
1776
+ .wpmud .wphb-block-content-group-inner {
1777
+ display: table-row;
1778
+ }
1779
+ .wpmud .wphb-block-content-group-item {
1780
+ display: table-cell;
1781
+ vertical-align: middle;
1782
+ width: 100%;
1783
+ }
1784
+ .wpmud .wphb-block-content-group-item .wphb-block-content {
1785
+ margin-left: 30px;
1786
+ }
1787
+ .wpmud .wphb-block-content-group-item:first-child .wphb-block-content {
1788
+ margin-left: 0;
1789
+ }
1790
+ .wpmud .wphb-block-content-group .wphb-block-content.small {
1791
+ padding: 20px 23px;
1792
+ width: 80px;
1793
+ }
1794
+
1795
+ /* Block: Entry Content */
1796
+ .wpmud .wphb-block-entry:after {
1797
+ content: '';
1798
+ clear: both;
1799
+ display: block;
1800
+ }
1801
+ .wpmud .wphb-block-entry-content .title {
1802
+ color: #333333;
1803
+ font-size: 22px;
1804
+ font-weight: bold;
1805
+ line-height: 1.333em;
1806
+ margin: 0 0 0.5em;
1807
+ max-width: 100%;
1808
+ text-transform: uppercase;
1809
+ }
1810
+ .wpmud .wphb-block-entry-content .title,
1811
+ .wpmud .wphb-block-entry-content .content > p {
1812
+ margin: 0 0 20px;
1813
+ }
1814
+ .wpmud .wphb-block-entry-content .content > p:last-child,
1815
+ .wpmud .wphb-block-entry-content .content > p:last-of-type {
1816
+ margin-bottom: 0;
1817
+ }
1818
+ .wpmud .wphb-block-entry-content .buttons-group .button {
1819
+ display: inline-block;
1820
+ }
1821
+
1822
+ /* Progress bar */
1823
+ @keyframes spinner {
1824
+ 0% {
1825
+ -webkit-transform: rotate(0deg);
1826
+ transform: rotate(0deg)
1827
+ }
1828
+
1829
+ 50% {
1830
+ -webkit-transform: rotate(180deg);
1831
+ transform: rotate(180deg)
1832
+ }
1833
+
1834
+ 100% {
1835
+ -webkit-transform: rotate(360deg);
1836
+ transform: rotate(360deg)
1837
+ }
1838
+ }
1839
+ .wphb-scan-progress {
1840
+ overflow: hidden;
1841
+ width: 100%;
1842
+ }
1843
+ .not-present .wphb-scan-progress-text:before,
1844
+ .wphb-scan-progress .wphb-scan-progress-text:before {
1845
+ content: " ";
1846
+ width: 18px;
1847
+ height: 18px;
1848
+ display: inline-block;
1849
+ position: relative;
1850
+ top: 5px;
1851
+ left: 1px;
1852
+ margin-right: 10px;
1853
+ border: 2px solid #A9E0EC;
1854
+ border-bottom-color: #17A8E3;
1855
+ border-radius: 100%;
1856
+ background: 0 0;
1857
+ box-sizing: border-box;
1858
+ animation: spinner .75s 0s linear infinite;
1859
+ }
1860
+ .wphb-scan-progress .wphb-scan-progress-text {
1861
+ width: 65px;
1862
+ float: left;
1863
+ text-align: left;
1864
+ }
1865
+ .wphb-scan-progress .wphb-scan-progress-text img {
1866
+ display: inline-block;
1867
+ vertical-align: middle;
1868
+ margin-right: 10px;
1869
+ }
1870
+ .wphb-scan-progress .wphb-scan-progress-text span {
1871
+ font-weight: bold;
1872
+ font-family: "Roboto Condensed", sans-serif;
1873
+ font-size: 13px;
1874
+ color: #333333;
1875
+ vertical-align: middle;
1876
+ line-height: 30px;
1877
+ }
1878
+ .wphb-scan-progress .wphb-scan-progress-bar {
1879
+ background: #E6E6E6;
1880
+ -webkit-border-radius: 5px;
1881
+ -moz-border-radius: 5px;
1882
+ border-radius: 5px;
1883
+ height: 10px;
1884
+ overflow: hidden;
1885
+ width: auto;
1886
+ margin-top: 10px;
1887
+ position: relative;
1888
+ }
1889
+ .wphb-scan-progress .wphb-scan-progress-bar span {
1890
+ background: #17A8E3;
1891
+ height: 10px;
1892
+ display: inline-block;
1893
+ position: absolute;
1894
+ top: 0;
1895
+ left: 0;
1896
+ -webkit-transition: 1000ms width ease-in-out;
1897
+ -moz-transition: 1000ms width ease-in-out;
1898
+ transition: 1000ms width ease-in-out;
1899
+ }
1900
+
1901
+ /* Block: Test with progress bar */
1902
+ .wphb-block-test {
1903
+ background-color: #F4F4F4;
1904
+ border-radius: 5px;
1905
+ max-width: 700px;
1906
+ width: 100%;
1907
+ height: 60px;
1908
+ padding: 15px 30px;
1909
+ }
1910
+ .wphb-block-test-header {
1911
+ margin-bottom: 10px;
1912
+ }
1913
+ .wphb-progress-state {
1914
+ margin-top: 10px;
1915
+ text-align: center;
1916
+ }
1917
+ .wphb-progress-state .wphb-progress-state-text {
1918
+ color: #8B8B8B;
1919
+ font-size: 13px;
1920
+ line-height: 22px;
1921
+ }
1922
+ .wphb-block-test-standalone {
1923
+ max-width: 100%;
1924
+ text-align: center;
1925
+ margin-top: 25px;
1926
+ }
1927
+ .wphb-block-test-standalone .wphb-progress {
1928
+ margin: 0 auto;
1929
+ }
1930
+
1931
+ /* Filename Extensions Icons */
1932
+ .wphb-filename-extension {
1933
+ border-radius: 5px;
1934
+ display: block;
1935
+ float: left;
1936
+ font-family: 'Roboto', sans-serif;
1937
+ font-size: 9px;
1938
+ color: #fff;
1939
+ text-transform: uppercase;
1940
+ line-height: 43px;
1941
+ letter-spacing: -1px;
1942
+ padding-right: 2px;
1943
+ height: 30px;
1944
+ margin: 0 20px 0 0;
1945
+ text-align: right;
1946
+ width: 30px;
1947
+ }
1948
+ .wphb-filename-extension-html {
1949
+ background-color: #F56418;
1950
+ }
1951
+ .wphb-filename-extension-other {
1952
+ background-color: #AAAAAA;
1953
+ }
1954
+ .wphb-filename-extension-css {
1955
+ background-color: #25A8DE;
1956
+ }
1957
+ .wphb-filename-extension-js {
1958
+ background-color: #F7E100;
1959
+ color: #333333;
1960
+ }
1961
+ .wphb-filename-info {
1962
+ display: block;
1963
+ float: left;
1964
+ max-width: 400px;
1965
+ overflow: hidden;
1966
+ position: relative;
1967
+ width: 100%;
1968
+ white-space: nowrap;
1969
+ }
1970
+ .wphb-filename-info:after {
1971
+ background: -webkit-linear-gradient(left, rgba(255,255,255,0) 0%, #fff 100%);
1972
+ background: -o-linear-gradient(left, rgba(255,255,255,0) 0%, #fff 100%);
1973
+ background: linear-gradient(to right, rgba(255,255,255,0) 0%, #fff 100%);
1974
+ content: '';
1975
+ height: 100%;
1976
+ pointer-events: none;
1977
+ position: absolute;
1978
+ right: 0;
1979
+ top: 0;
1980
+ width: 40px;
1981
+ }
1982
+
1983
+ /* Performance Results */
1984
+ .wphb-score {
1985
+ display: inline-block;
1986
+ position: relative;
1987
+ }
1988
+ .wphb-score-type-circle {
1989
+ border-radius: 100%;
1990
+ height: 30px;
1991
+ width: 30px;
1992
+ }
1993
+ .wphb-score-type-circle.large {
1994
+ height: 80px;
1995
+ width: 80px;
1996
+ }
1997
+ .wphb-score-type-circle .wphb-score-graph-circle {
1998
+ stroke: #E5E5E5;
1999
+ stroke-dashoffset: 80;
2000
+ stroke-width: 5px;
2001
+ -ms-transition: stroke-dashoffset 1s linear;
2002
+ -moz-transition: stroke-dashoffset 1s linear;
2003
+ -webkit-transition: stroke-dashoffset 1s linear;
2004
+ transition: stroke-dashoffset 1s linear;
2005
+ }
2006
+ .wphb-score-type-circle.large .wphb-score-graph-circle {
2007
+ stroke-dashoffset: 219.8;
2008
+ stroke-width: 10px;
2009
+ }
2010
+ .wphb-score-type-circle .wphb-score-graph-result {
2011
+ transform: rotate(-80deg) translateX(-27px) translateY(2.5px);
2012
+ -moz-transform: rotate(-80deg) translateX(-27px) translateY(2.5px);
2013
+ -webkit-transform: rotate(-80deg) translateX(-27px) translateY(2.5px);
2014
+ }
2015
+ .wphb-score-type-circle.large .wphb-score-graph-result {
2016
+ transform: rotate(-80deg) translateX(-72.5px) translateY(6.5px);
2017
+ -moz-transform: rotate(-80deg) translateX(-72.5px) translateY(6.5px);
2018
+ -webkit-transform: rotate(-80deg) translateX(-72.5px) translateY(6.5px);
2019
+ }
2020
+ .wphb-score-result {
2021
+ cursor: pointer;
2022
+ position: relative;
2023
+ }
2024
+
2025
+ .wpmud .list-table.hover-effect > tbody > tr[class*="wphb-table-score"] td:first-child {
2026
+ padding-left: 30px;
2027
+ }
2028
+ .wpmud .list-table.hover-effect > tbody > tr[class*="wphb-table-score"] td:first-child:before {
2029
+ font-family: 'hummingbird';
2030
+ speak: none;
2031
+ font-style: normal;
2032
+ font-weight: normal;
2033
+ font-variant: normal;
2034
+ text-transform: none;
2035
+ line-height: 1;
2036
+ -webkit-font-smoothing: antialiased;
2037
+ -moz-osx-font-smoothing: grayscale;
2038
+ font-size: 20px;
2039
+ vertical-align: middle;
2040
+ margin-right: 10px;
2041
+ }
2042
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-success:hover > td:first-child:after,
2043
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-warning:hover td:first-child:after,
2044
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-error:hover td:first-child:after {
2045
+ content: normal;
2046
+ }
2047
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-success:hover td:first-child,
2048
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-additional-success td:first-child,
2049
+ .wphb-table-score-success td:first-child {
2050
+ border-left: 4px solid #1ABC9C;
2051
+ }
2052
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-success td:first-child:before {
2053
+ color: #1ABC9C;
2054
+ content: "\e90e";
2055
+ }
2056
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-warning:hover td:first-child,
2057
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-additional-warning td:first-child,
2058
+ .wphb-table-score-warning td:first-child {
2059
+ border-left: 4px solid #FFD000;
2060
+ }
2061
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-warning td:first-child:before {
2062
+ color: #FFD000;
2063
+ content: "\e90f";
2064
+ }
2065
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-error:hover td:first-child,
2066
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-additional-error td:first-child,
2067
+ .wphb-table-score-error td:first-child {
2068
+ border-left: 4px solid #FF6D6D;
2069
+ }
2070
+ .wpmud .list-table.hover-effect > tbody > tr.wphb-table-score-error td:first-child:before {
2071
+ color: #FF6D6D;
2072
+ content: "\e90f";
2073
+ }
2074
+
2075
+ .wphb-score-result-grade-aplus,
2076
+ .wphb-score-result-grade-a {
2077
+ color: #1ABC9C;
2078
+ }
2079
+ .wphb-score-result-grade-aplus .wphb-score-type-circle .wphb-score-graph-result,
2080
+ .wphb-score-result-grade-a .wphb-score-type-circle .wphb-score-graph-result {
2081
+ stroke: #1ABC9C;
2082
+ }
2083
+ .wphb-score-result-grade-b {
2084
+ color: #1ABC9C;
2085
+ }
2086
+ .wphb-score-result-grade-b .wphb-score-type-circle .wphb-score-graph-result {
2087
+ stroke: #1ABC9C;
2088
+ }
2089
+ .wphb-score-result-grade-c {
2090
+ color: #FFD000;
2091
+ }
2092
+ .wphb-score-result-grade-c .wphb-score-type-circle .wphb-score-graph-result {
2093
+ stroke: #FFD000;
2094
+ }
2095
+ .wphb-score-result-grade-d {
2096
+ color: #FFD000;
2097
+ }
2098
+ .wphb-score-result-grade-d .wphb-score-type-circle .wphb-score-graph-result {
2099
+ stroke: #FFD000;
2100
+ }
2101
+ .wphb-score-result-grade-e,
2102
+ .wphb-score-result-grade-f {
2103
+ color: #FF6D6D;
2104
+ }
2105
+ .wphb-score-result-grade-e .wphb-score-type-circle .wphb-score-graph-result,
2106
+ .wphb-score-result-grade-f .wphb-score-type-circle .wphb-score-graph-result {
2107
+ stroke: #FF6D6D;
2108
+ }
2109
+ .wphb-score-have-label .wphb-score-type,
2110
+ .wphb-score-have-label .wphb-score-result-label {
2111
+ float: left;
2112
+ display: block;
2113
+ }
2114
+ .wphb-score-have-label.inside .wphb-score-type,
2115
+ .wphb-score-have-label.inside .wphb-score-result-label {
2116
+ float: none;
2117
+ }
2118
+ .wphb-score-have-label .wphb-score-result-label {
2119
+ font-family: 'Roboto', Arial, sans-serif;
2120
+ font-size: 15px;
2121
+ color: #888888;
2122
+ padding-left: 10px;
2123
+ }
2124
+ .wphb-score-have-label .wphb-score-type-circle + .wphb-score-result-label {
2125
+ line-height: 30px;
2126
+ min-width: 35px;
2127
+ text-align: left;
2128
+ }
2129
+ .wphb-score-have-label.inside .wphb-score-type {
2130
+ position: relative;
2131
+ }
2132
+ .wphb-score-have-label.inside .wphb-score-result-label {
2133
+ font-size: 26px;
2134
+ left: 0;
2135
+ line-height: 34px;
2136
+ margin: -17px 0 0;
2137
+ min-width: 100%;
2138
+ padding: 0;
2139
+ position: absolute;
2140
+ right: 0;
2141
+ text-align: center;
2142
+ top: 50%;
2143
+ }
2144
+ #wphb-error-details {
2145
+ display:none;
2146
+ }
2147
+ #wphb-error-details-link {
2148
+ color:white;
2149
+ text-decoration: none;
2150
+ margin-top:10px;
2151
+ margin-bottom:10px;
2152
+ display:inline-block;
2153
+ font-weight:400;
2154
+ }
2155
+ #wphb-error-details-link > .dashicons {
2156
+ text-decoration:none;
2157
+ }
2158
+ #wphb-error-details-link.expanded {
2159
+ display:none;
2160
+ }
2161
+
2162
+ /* Tabs */
2163
+ .wpmud .wphb-tabs a {
2164
+ color: #333;
2165
+ display: block;
2166
+ }
2167
+ .wpmud .wphb-tabs .wphb-tab {
2168
+ padding: 5px 20px;
2169
+ height: 30px;
2170
+ }
2171
+ .wpmud .wphb-tabs .wphb-tab.current {
2172
+ background-color: #E6E6E6;
2173
+ border-radius: 20px;
2174
+ font-weight: 500;
2175
+ }
2176
+ .wpmud .wphb-tab .wphb-button-label {
2177
+ position: relative;
2178
+ top: -25px;
2179
+ left: 100%;
2180
+ margin-left: -22px;
2181
+ width: 39px;
2182
+ height: 26px;
2183
+ text-align: center;
2184
+ font-size: 12px;
2185
+ font-weight: 500;
2186
+ line-height: 24px;
2187
+ }
2188
+ .wpmud .wphb-tab > i {
2189
+ color: #FF6D6D;
2190
+ position: relative;
2191
+ top: -23px;
2192
+ left: 100%;
2193
+ margin-left: -5px;
2194
+ font-size: 21px;
2195
+ }
2196
+
2197
+ /* ****************************************************************************
2198
+ * 4. WELCOME / DASHBOARD
2199
+ */
2200
+ .wpmud .wphb-block-entry-third {
2201
+ color: #333333;
2202
+ width: calc( 100% / 2 - 98px );
2203
+ padding-left: 5%;
2204
+ display: inline-block;
2205
+ vertical-align: middle;
2206
+ }
2207
+ .wpmud .wphb-block-entry-third span {
2208
+ font-weight: 400;
2209
+ }
2210
+ .wpmud .wphb-block-entry-third p {
2211
+ font-size: 13px;
2212
+ margin-top: 0;
2213
+ color: #888888;
2214
+ }
2215
+ div.wphb-block-entry {
2216
+ width: 100%;
2217
+ }
2218
+ .wpmud .wphb-block-entry-third span.not-present {
2219
+ font-size: 55px;
2220
+ line-height: 30px;
2221
+ margin-bottom: 20px;
2222
+ }
2223
+ .wpmud .wphb-block-entry-third span.score-span {
2224
+ font-size: 13px;
2225
+ margin-left: -12px;
2226
+ }
2227
+ .wpmud .wphb-block-entry-third .current-performance-score {
2228
+ margin-bottom: 20px;
2229
+ }
2230
+ .wpmud .wphb-block-entry-third .hb-wpmudev-icon-warning,
2231
+ .wpmud .wphb-block-entry-third .hb-wpmudev-icon-tick {
2232
+ position: relative;
2233
+ top: -22px;
2234
+ left: 5px;
2235
+ font-size: 20px;
2236
+ }
2237
+ .wpmud .wphb-block-entry-third .hb-wpmudev-icon-warning {
2238
+ color: #FECF2F;
2239
+ }
2240
+ .wpmud .wphb-block-entry-third .hb-wpmudev-icon-tick {
2241
+ color: #1ABC9C;
2242
+ }
2243
+ .wpmud .wphb-block-entry-third .dev-list {
2244
+ margin: 0 !important;
2245
+ border-bottom: 0;
2246
+ }
2247
+ .wpmud .wphb-block-entry-third .dev-list li:first-child span {
2248
+ padding-top: 4px;
2249
+ }
2250
+ .wpmud .caching-table {
2251
+ margin: 30px 0 0;
2252
+ }
2253
+ .wpmud .box-dashboard-caching-module .wphb-caching-summary-item-type {
2254
+ /*width: 40%;*/
2255
+ width: 60%;
2256
+ color: #333333;
2257
+ font-size: 13px;
2258
+ font-weight: 500;
2259
+ }
2260
+ /*.wpmud .box-dashboard-caching-module .wphb-caching-summary-heading-expiry,
2261
+ .wpmud .box-dashboard-caching-module .wphb-caching-summary-item-expiry {
2262
+ width: 30%;
2263
+ }
2264
+ .wpmud .box-dashboard-caching-module .wphb-caching-summary-heading-status,
2265
+ .wpmud .box-dashboard-caching-module .wphb-caching-summary-item-status {
2266
+ width: 30%;
2267
+ }*/
2268
+ .wpmud .box-dashboard-caching-module .wphb-caching-summary-heading-status,
2269
+ .wpmud .box-dashboard-caching-module .wphb-caching-summary-item-status {
2270
+ text-align: right;
2271
+ }
2272
+ .wpmud .wphb-caching-summary-heading,
2273
+ .wpmud .box-dashboard-gzip-module .list-label,
2274
+ .wpmud .box-gzip-summary .list-label {
2275
+ text-transform: none !important;
2276
+ color: #333333;
2277
+ font-size: 13px;
2278
+ }
2279
+
2280
+ .wpmud .box-dashboard-performance-module .dashboard-performance-report-table {
2281
+ text-align: left;
2282
+ }
2283
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-heading {
2284
+ text-transform: none;
2285
+ color: #333333;
2286
+ font-size: 13px;
2287
+ }
2288
+ .wpmud .box-dashboard-performance-module span {
2289
+ font-size: 13px;
2290
+ line-height: 30px;
2291
+ }
2292
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-item-recommendation {
2293
+ color: #333333;
2294
+ font-size: 13px;
2295
+ font-weight: 500;
2296
+ }
2297
+ .wpmud .box-dashboard-performance-module .button {
2298
+ margin-top: 0 !important;
2299
+ }
2300
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-heading-recommendation,
2301
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-item-recommendation,
2302
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-heading-score,
2303
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-item-score {
2304
+ width: 50%;
2305
+ }
2306
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-heading-score,
2307
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-item-score {
2308
+ text-align: center;
2309
+ }
2310
+ .wpmud .box-dashboard-uptime .status-text {
2311
+ color: #888888;
2312
+ font-size: 13px;
2313
+ line-height: 22px;
2314
+ margin-top: 5px;
2315
+ }
2316
+ .wpmud .box-dashboard-smush .content .wphb-notice,
2317
+ .wpmud .box-dashboard-smush-no-membership .content .wphb-notice {
2318
+ margin-top: 30px !important;
2319
+ }
2320
+
2321
+ .wpmud .callout-box .callout-title {
2322
+ font-family: 'Roboto Condensed', Arial, sans-serif;
2323
+ font-size: 22px;
2324
+ font-weight: bold;
2325
+ line-height: 60px;
2326
+ color: #333333;
2327
+ padding-bottom: 30px;
2328
+ text-transform: uppercase;
2329
+ }
2330
+ .wpmud .callout-box p:first-of-type {
2331
+ margin-bottom: 30px;
2332
+ }
2333
+
2334
+ .wpmud .wphb-upsell-free-message p {
2335
+ position: relative;
2336
+ border-radius: 4px;
2337
+ background-color: #E1F6FF;
2338
+ padding: 20px 30px;
2339
+ margin-left: -140px;
2340
+ color: #333333;
2341
+ font-size: 13px;
2342
+ line-height: 22px;
2343
+ }
2344
+ .wpmud .wphb-upsell-free-message p:after {
2345
+ position: absolute;
2346
+ top: 43%;
2347
+ left: 0;
2348
+ margin-left: -7px;
2349
+ content: '';
2350
+ width: 0;
2351
+ height: 0;
2352
+ border-top: 7px solid transparent;
2353
+ border-bottom: 7px solid transparent;
2354
+ border-right: 7px solid #E1F6FF;
2355
+ }
2356
+
2357
+ .wpmud .wrap-wp-hummingbird .report-status {
2358
+ background-color: #F8F8F8;
2359
+ height: 140px;
2360
+ width: 100%;
2361
+ position: relative;
2362
+ -webkit-border-radius: 7px;
2363
+ -moz-border-radius: 7px;
2364
+ border-radius: 7px;
2365
+ margin-bottom: 10px;
2366
+ display: flex;
2367
+ flex-direction: column;
2368
+ align-items: center;
2369
+ justify-content: center;
2370
+ }
2371
+ .wpmud .wrap-wp-hummingbird .report-status:hover {
2372
+ background-color: #f2f2f2;
2373
+ cursor: pointer;
2374
+ }
2375
+ .wpmud .wrap-wp-hummingbird .report-status i {
2376
+ color: #666666;
2377
+ font-size: 24px;
2378
+ }
2379
+ .wpmud .wrap-wp-hummingbird .report-status strong {
2380
+ font-family: "Roboto Condensed", sans-serif;
2381
+ color: #666666;
2382
+ font-weight: bold;
2383
+ margin-top: 10px;
2384
+ font-size: 13px;
2385
+ line-height: 20px;
2386
+ text-transform: uppercase;
2387
+ }
2388
+ .wpmud .wrap-wp-hummingbird .report-status button {
2389
+ border-radius: 20px !important;
2390
+ margin-top: 10px !important;
2391
+ background-color: #D1F1EA !important;
2392
+ color: #1ABC9C !important;
2393
+ }
2394
+ .wpmud .wrap-wp-hummingbird .report-status button i {
2395
+ color: #1ABC9C;
2396
+ font-size: 16px;
2397
+ position: relative ;
2398
+ line-height: 10px;
2399
+ top: 3px;
2400
+ }
2401
+ .wpmud .wrap-wp-hummingbird .report-status button.inactive {
2402
+ background-color: #E6E6E6 !important;
2403
+ color: #AAAAAA !important;
2404
+ }
2405
+ .wpmud .wrap-wp-hummingbird .report-status .corner {
2406
+ position: absolute;
2407
+ top: 0;
2408
+ right: 0;
2409
+ color: #1ABC9C;
2410
+ font-weight: bold;
2411
+ font-family: "Roboto Condensed", sans-serif;
2412
+ padding-right: 6px;
2413
+ padding-top: 10px;
2414
+ text-transform: uppercase;
2415
+ font-size: 13px;
2416
+ }
2417
+ .wpmud .wrap-wp-hummingbird .report-status.with-corner.grey .corner i {
2418
+ color: #888888;
2419
+ font-size: 16px;
2420
+ margin-right: 4px;
2421
+ }
2422
+ .wpmud .wrap-wp-hummingbird .report-status.with-corner:before {
2423
+ content: '';
2424
+ position: absolute;
2425
+ top: 0;
2426
+ right: 0;
2427
+ border: solid transparent;
2428
+ border-top-right-radius: 7px;
2429
+ }
2430
+ .wpmud .wrap-wp-hummingbird .report-status.with-corner:before {
2431
+ border-width: 30px;
2432
+ border-right-color: #D1F1EA;
2433
+ border-top-color: #D1F1EA;
2434
+ }
2435
+ .wpmud .wrap-wp-hummingbird .report-status.with-corner.grey:before {
2436
+ border-right-color: #E6E6E6;
2437
+ border-top-color: #E6E6E6;
2438
+ }
2439
+
2440
+ .wpmud #cloudflare-how-to-title,
2441
+ .wpmud #cloudflare-how-to {
2442
+ text-align:left;
2443
+ }
2444
+ .wpmud #cloudflare-how-to a {
2445
+ font-weight: 500;
2446
+ text-decoration: underline;
2447
+ color: inherit;
2448
+ }
2449
+ .wpmud #cloudflare-info {
2450
+ clear:both;
2451
+ }
2452
+ .wpmud #cloudflare-info.wphb-notice {
2453
+ margin-top: 30px;
2454
+ }
2455
+ .wpmud .cloudflare-submit {
2456
+ margin-bottom:0;
2457
+ }
2458
+ .wpmud #cloudflare-zone .clear {
2459
+ padding:0;
2460
+ }
2461
+ .wpmud #cloudflare-zone label {
2462
+ margin-bottom:13px;
2463
+ }
2464
+ .wpmud #cloudflare-zone .cloudflare-submit {
2465
+ margin-top: 22px;
2466
+ }
2467
+ .wpmud #cloudflare-steps .wphb-notice-success {
2468
+ margin-top:0;
2469
+ }
2470
+
2471
+ @media screen and (max-width: 1200px) and (min-width: 783px) {
2472
+ .wpmud #cloudflare-how-to-title {
2473
+ float:none;
2474
+ display: block;
2475
+ text-align: center;
2476
+ margin-bottom:0;
2477
+ }
2478
+ .wpmud .cloudflare-step p.cloudflare-submit {
2479
+ float:none;
2480
+ position:relative;
2481
+ }
2482
+ .wpmud .cloudflare-step p.cloudflare-submit .cloudflare-spinner {
2483
+ position:absolute;
2484
+ right:0;
2485
+ top: 10px;
2486
+ }
2487
+ }
2488
+
2489
+ /* ****************************************************************************
2490
+ * 5. PEFORMANCE
2491
+ */
2492
+ .wpmud .dev-box-performance-report-additional-content-how-to-fix h5 {
2493
+ color: #888888;
2494
+ font-size: 13px;
2495
+ line-height: 30px;
2496
+ text-align: left;
2497
+ font-weight: 400;
2498
+ margin: 0 !important;
2499
+ }
2500
+
2501
+ .wrap-wphb-performance #dash-performance-resume-view-test,
2502
+ .wrap-wphb-performance #dash-performance-resume-run-new-test {
2503
+ display:none;
2504
+ }
2505
+
2506
+ .wrap-wphb-performance .dev-box .box-content.no-vertical-padding {
2507
+ margin-bottom: 0;
2508
+ }
2509
+
2510
+ .wrap-wphb-performance .wphb-performance-report-item-recommendation {
2511
+ font-weight: 500;
2512
+ }
2513
+ .wrap-wphb-performance .wphb-performance-report-item-score {
2514
+ padding-top: 14px !important;
2515
+ padding-bottom: 9px !important;
2516
+ }
2517
+ .wpmud .dev-box-performance-report-additional-content:not(:last-child):after {
2518
+ height: 1px;
2519
+ display: block;
2520
+ width: calc( 100% - 60px );
2521
+ margin: 0 30px;
2522
+ background-color: #E6E6E6;
2523
+ border-right: 1px white;
2524
+ content: '';
2525
+ }
2526
+
2527
+ .wpmud .dev-box-performance-report-additional-content .button {
2528
+ margin-top: 10px !important;
2529
+ margin-bottom: 10px;
2530
+ }
2531
+
2532
+ /* Reporting */
2533
+ .wpmud .wrap-wphb-performance .scan-settings .buttons {
2534
+ margin-top: 30px;
2535
+ }
2536
+ .wpmud .wrap-wphb-performance .scan-settings .row {
2537
+ box-shadow: 0 11px 0 -10px #E6E6E6;
2538
+ padding-bottom: 30px;
2539
+ }
2540
+ .wpmud .wrap-wphb-performance form span.sub {
2541
+ display: block;
2542
+ font-size: 13px;
2543
+ color: #888;
2544
+ line-height: 22px;
2545
+ margin: 10px 0 0;
2546
+ }
2547
+ .wpmud .wrap-wphb-performance form .col-two-third > label {
2548
+ display: inline-block;
2549
+ padding: 2px 10px 0;
2550
+ color: #333;
2551
+ line-height: 30px;
2552
+ margin: 0;
2553
+ }
2554
+ .wpmud .wrap-wphb-performance .schedule-box label,
2555
+ .wpmud .wrap-wphb-caching .cloudflare-step label {
2556
+ margin-top: 25px;
2557
+ padding: 0;
2558
+ color: #AAAAAA;
2559
+ font-size: 13px;
2560
+ }
2561
+ .wrap-wphb-caching .cloudflare-step label:first-child {
2562
+ margin-top: 0;
2563
+ }
2564
+
2565
+ .wpmud .wrap-wphb-performance .list-results {
2566
+ max-height: 200px;
2567
+ overflow-y: scroll;
2568
+ }
2569
+ .wpmud .wrap-wphb-performance .recipient {
2570
+ margin-bottom: 10px;
2571
+ padding: 5px 10px;
2572
+ }
2573
+ .wpmud .wrap-wphb-performance .recipient:hover {
2574
+ border-radius: 4px;
2575
+ background-color: #F8F8F8;
2576
+ }
2577
+ .wpmud .wrap-wphb-performance .recipient,
2578
+ .wpmud .wrap-wphb-performance .recipient .name,
2579
+ .wpmud .wrap-wphb-performance .add-recipient {
2580
+ display: flex;
2581
+ flex-flow: row nowrap;
2582
+ justify-content: space-between;
2583
+ align-items: center;
2584
+ align-content: center;
2585
+ }
2586
+ .wpmud .wrap-wphb-performance .recipient img {
2587
+ -webkit-border-radius: 50px;
2588
+ -moz-border-radius: 50px;
2589
+ border-radius: 50px;
2590
+ width: 30px;
2591
+ height: 30px;
2592
+ margin-right: 10px;
2593
+ display: inline-block;
2594
+ vertical-align: middle;
2595
+ }
2596
+ .wpmud .wrap-wphb-performance .recipient .name {
2597
+ color: #333333;
2598
+ font-weight: 500;
2599
+ }
2600
+ .wpmud .wrap-wphb-performance .recipient a > i {
2601
+ color: #888888;
2602
+ }
2603
+ .wpmud .wrap-wphb-performance .recipient:hover a > i {
2604
+ color: #333333;
2605
+ }
2606
+ .wpmud .wrap-wphb-performance .add-recipient {
2607
+ margin-top: 15px;
2608
+ }
2609
+ .wpmud .wrap-wphb-performance .add-recipient > * {
2610
+ margin-bottom: 0;
2611
+ border-radius: 0;
2612
+ border: 1px solid #E6E6E6;
2613
+ font-weight: normal;
2614
+ }
2615
+ .wpmud .wrap-wphb-performance .add-recipient .wdv-icon-plus {
2616
+ color: #FFFFFF;
2617
+ font-size: 20px;
2618
+ }
2619
+ .wpmud .wrap-wphb-performance .add-recipient > button {
2620
+ background-color: #888888 !important;
2621
+ border-radius: 0 4px 4px 0 !important;
2622
+ }
2623
+ .wpmud .wrap-wphb-performance .add-recipient > input::placeholder {
2624
+ color: #AAAAAA;
2625
+ font-weight: 400;
2626
+ }
2627
+ .wpmud .wrap-wphb-performance .add-recipient #wphb-first-name {
2628
+ border-radius: 4px 0 0 4px;
2629
+ border-right: 0;
2630
+ background-color: #F8F8F8;
2631
+ }
2632
+ .wpmud .wrap-wphb-performance .add-recipient #wphb-username-search {
2633
+ background-color: #F8F8F8;
2634
+ }
2635
+ .wpmud .wrap-wphb-performance .wphb-tag {
2636
+ -webkit-border-radius: 16px;
2637
+ -moz-border-radius: 16px;
2638
+ border-radius: 16px;
2639
+ font-size: 13px;
2640
+ padding: 4px 16px;
2641
+ color: #fff;
2642
+ text-transform: uppercase;
2643
+ }
2644
+ .wpmud .wrap-wphb-performance .wphb-tag.tag-generic {
2645
+ background: #E6E6E6;
2646
+ color: #333;
2647
+ }
2648
+
2649
+ /* ****************************************************************************
2650
+ * 6. MINIFICATION
2651
+ */
2652
+ .wpmud .wphb-border-row.out-of-filter {
2653
+ display: none;
2654
+ }
2655
+
2656
+ #wphb-minification-filter {
2657
+ margin-bottom: 20px !important;
2658
+ }
2659
+
2660
+ #wphb-minification-filter .wphb-block-title {
2661
+ font: 700 15px/2em 'Roboto Condensed', 'Roboto', sans-serif;
2662
+ text-transform: uppercase;
2663
+ float: left;
2664
+ margin-top: 7px;
2665
+ margin-left: 30px;
2666
+ margin-right: 20px;
2667
+ }
2668
+
2669
+ #wphb-minification-filter .wphb-filters-data {
2670
+ margin: 20px 30px 6px;
2671
+ display: -webkit-box;
2672
+ display: -ms-flexbox;
2673
+ display: flex;
2674
+ }
2675
+
2676
+ .wrap-wphb-minification .box-minification-enqueued-files .alignright {
2677
+ margin-top: 20px;
2678
+ }
2679
+ #wphb-box-minification-advanced-settings .toggle-item-description {
2680
+ font-size: 13px;
2681
+ line-height: 22px;
2682
+ font-weight: 400;
2683
+ }
2684
+ #wphb-box-minification-advanced-settings p {
2685
+ font-size: 13px;
2686
+ }
2687
+ .wrap-wphb-minification .box-minification-enqueued-files .box-footer span {
2688
+ color: #888888;
2689
+ font-size: 13px;
2690
+ line-height: 20px;
2691
+ }
2692
+
2693
+
2694
+ .wpmud .wphb-enqueued-files {
2695
+ border: 1px solid #eee;
2696
+ border-radius: 5px;
2697
+ }
2698
+ .wpmud .box-minification-enqueued-files .alignleft,
2699
+ .wpmud .box-minification-enqueued-files .alignright {
2700
+ margin-bottom: 0;
2701
+ }
2702
+ .wpmud .box-minification-enqueued-files .alignleft > .button-grey {
2703
+ margin-top: 20px;
2704
+ }
2705
+ .wpmud .wphb-enqueued-files .buttons {
2706
+ margin: 30px;
2707
+ }
2708
+ .wpmud .wphb-border-row,
2709
+ .wpmud .wphb-border-row-header {
2710
+ padding: 20px 30px;
2711
+ -webkit-box-pack: justify;
2712
+ -ms-flex-pack: justify;
2713
+ justify-content: space-between;
2714
+ border-bottom: 1px solid #eee;
2715
+ }
2716
+ .wpmud .wphb-border-row:last-child {
2717
+ border-bottom: 0;
2718
+ }
2719
+ .wpmud .box-content.disabled {
2720
+ padding-bottom: 0;
2721
+ }
2722
+ .wpmud .box-content.disabled,
2723
+ .wpmud .wphb-border-row.disabled {
2724
+ background-color: rgba(242,242,242,0.5);
2725
+ }
2726
+ .wpmud .box-content.disabled strong,
2727
+ .wpmud .wphb-border-row.disabled .wphb-filename-info-name {
2728
+ color: #929292;
2729
+ }
2730
+ .wpmud .box-content.disabled span,
2731
+ .wpmud .box-content.disabled label,
2732
+ .wpmud .wphb-border-row.disabled .wphb-filename-info-url {
2733
+ color: #BFBFBF !important;
2734
+ }
2735
+ .wpmud .box-content.disabled img.avatar {
2736
+ background-color: #000000;
2737
+ opacity: 0.3;
2738
+ }
2739
+ .wpmud .box-content.disabled .list-value,
2740
+ .wpmud .box-content.disabled .dropdown-handle {
2741
+ background-color: #F5F5F5;
2742
+ color: #979797;
2743
+ }
2744
+ .wpmud .box-content.disabled input::placeholder {
2745
+ color: #979797;
2746
+ font-weight: 400;
2747
+ }
2748
+ .wpmud .box-performance-summary .box-footer {
2749
+ padding: 0 30px 42px 30px;
2750
+ }
2751
+
2752
+ .wpmud .wphb-border-row-header > * {
2753
+ font-size: 13px;
2754
+ font-weight: bold;
2755
+ color: #333333;
2756
+ }
2757
+
2758
+ .wpmud .wphb-border-row,
2759
+ .wpmud .wphb-border-row-header,
2760
+ .wpmud .wphb-minification-row-details {
2761
+ display: -webkit-box;
2762
+ display: -ms-flexbox;
2763
+ display: flex;
2764
+ -webkit-box-orient: horizontal;
2765
+ -webkit-box-direction: normal;
2766
+ -ms-flex-flow: row wrap;
2767
+ flex-flow: row wrap;
2768
+ -webkit-box-align: center;
2769
+ -ms-flex-align: center;
2770
+ align-items: center;
2771
+ -ms-flex-line-pack: center;
2772
+ align-content: center;
2773
+ }
2774
+
2775
+ .wpmud .wphb-border-row > div.wphb-minification-row-details,
2776
+ .wpmud .wphb-border-row-header > div.wphb-minification-row-details {
2777
+ -webkit-box-pack: justify;
2778
+ -ms-flex-pack: justify;
2779
+ justify-content: space-between;
2780
+ }
2781
+ .wpmud .wphb-minification-row-details > div:not(.wphb-minification-configuration) {
2782
+ /*margin-left: 30px;*/
2783
+ }
2784
+
2785
+ .wpmud .wphb-minification-file-select,
2786
+ .wpmud .wphb-minification-file-details,
2787
+ .wpmud .wphb-minification-row-details {
2788
+ order: 1;
2789
+ }
2790
+ .wpmud .wphb-minification-file-select {
2791
+ flex: 0 0 4%;
2792
+ }
2793
+ .wpmud .wphb-minification-file-details {
2794
+ flex: 0 0 47%;
2795
+ }
2796
+ .wpmud .wphb-minification-row-details {
2797
+ flex: 0 0 41%;
2798
+ }
2799
+
2800
+ .wpmud .wphb-minification-file-details .wphb-filename-info {
2801
+ display: -webkit-box;
2802
+ display: -ms-flexbox;
2803
+ display: flex;
2804
+ -webkit-box-orient: vertical;
2805
+ -webkit-box-direction: normal;
2806
+ -ms-flex-flow: column wrap;
2807
+ flex-flow: column wrap;
2808
+ }
2809
+ .wpmud .wphb-minification-file-details .wphb-filename-info .wphb-filename-info-name {
2810
+ color: #333333;
2811
+ font-weight: 500;
2812
+ line-height: 20px;
2813
+ }
2814
+ .wpmud .wphb-minification-file-details .wphb-filename-info .wphb-filename-info-url {
2815
+ color: #888888;
2816
+ font-size: 12px;
2817
+ line-height: 20px;
2818
+ }
2819
+ .wpmud .wphb-minification-file-size {
2820
+ text-align: center;
2821
+ font-size: 10px;
2822
+ line-height: 12px;
2823
+ color: #1ABC9C;
2824
+ }
2825
+ .wpmud .wphb-minification-file-size > div > span {
2826
+ display: block;
2827
+ }
2828
+ .wpmud .wphb-minification-file-size > span,
2829
+ .wpmud .wphb-minification-file-size > div > span:first-child {
2830
+ color: #888888;
2831
+ }
2832
+ .wpmud .wphb-minification-file-size .wphb-scan-progress,
2833
+ .wpmud .wphb-minification-configuration > strong,
2834
+ .wpmud .wphb-minification-file-size > strong {
2835
+ display: none;
2836
+ }
2837
+
2838
+ .wpmud .wphb-minification-exclude {
2839
+ order: 2;
2840
+ margin-left: 30px;
2841
+ }
2842
+ .wpmud .wphb-minification-exclude label {
2843
+ padding: 0;
2844
+ margin: 0;
2845
+ }
2846
+
2847
+ .wpmud .wphb-filename-extension {
2848
+ margin: 4px 20px 0 0;
2849
+ }
2850
+
2851
+
2852
+ /* ****************************************************************************
2853
+ * 7. BROWSER CACHING
2854
+ */
2855
+ .wpmud .box-caching-summary .wphb-caching-summary-heading th,
2856
+ .wpmud .box-caching-summary .wphb-caching-summary-item td {
2857
+ width: 25%;
2858
+ font-size: 13px;
2859
+ }
2860
+ .wpmud .box-caching-summary .wphb-caching-summary-item td:first-child {
2861
+ font-weight: 500;
2862
+ }
2863
+ .wpmud .wphb-caching-error {
2864
+ text-align:left;
2865
+ }
2866
+ .wpmud .wphb-caching-error a {
2867
+ text-decoration:underline;
2868
+ }
2869
+ .wpmud .wrap-wphb-caching .wphb-spinner {
2870
+ float:none;
2871
+ background-size: 15px 15px;
2872
+ }
2873
+ .wpmud .wphb-caching-cloudflare-box > p {
2874
+ margin: 0 0 20px 0;
2875
+ }
2876
+ .wpmud .box-gzip-enable .box-footer {
2877
+ padding: 0;
2878
+ }
2879
+ .wpmud .box-caching-enable .buttons {
2880
+ margin-top: -20px;
2881
+ }
2882
+
2883
+ /* ****************************************************************************
2884
+ * 8. GZIP COMPRESSION
2885
+ */
2886
+ .wpmud #wphb-code-snippet {
2887
+ margin-top: 20px;
2888
+ }
2889
+ .wpmud .wphb-gzip-error {
2890
+ text-align:left;
2891
+ }
2892
+ .wpmud .wphb-gzip-error a {
2893
+ text-decoration:underline;
2894
+ }
2895
+
2896
+ /* ****************************************************************************
2897
+ * 9. UPTIME
2898
+ */
2899
+
2900
+ .wpmud .wphb-block-uptime-status .wphb-uptime-icon {
2901
+ max-height: 110px;
2902
+ }
2903
+ .wpmud .wphb-block-content-uptime-data-range {
2904
+ padding-top: 9px;
2905
+ padding-bottom: 9px;
2906
+ }
2907
+ .wpmud .uptime-chart svg g g rect {
2908
+ fill: #E6E6E6;
2909
+ stroke: transparent;
2910
+ stroke-width: 0;
2911
+ }
2912
+ .wpmud .uptime-chart svg g g text {
2913
+ fill: #fff;
2914
+ font-family: 'Roboto', Arial, sans-serif;
2915
+ font-size: 13px;
2916
+ font-weight: 400;
2917
+ }
2918
+ .wpmud .uptime-chart svg g g text:last-of-type {
2919
+ fill: #AAAAAA;
2920
+ font-weight: 500;
2921
+ }
2922
+ .wrap-wp-hummingbird .button-cta-green:hover {
2923
+ box-shadow: none;
2924
+ }
2925
+ .wpmud .wrap-wphb-uptime .wphb-pills.red,
2926
+ .wpmud .wrap-wphb-uptime .wphb-pills.green {
2927
+ height: 40px;
2928
+ line-height: 40px;
2929
+ width: 200px;
2930
+ border-radius: 5px;
2931
+ }
2932
+ .wpmud .wphb-block-uptime-downtime .dev-list {
2933
+ margin-top: 30px;
2934
+ }
2935
+
2936
+ .wrap-wphb-uptime .wphb-block-entry .wphb-block-content-center {
2937
+ max-width:600px;
2938
+ margin:0 auto;
2939
+ }
2940
+
2941
+ /* ****************************************************************************
2942
+ * 10. RESPONSIVE/MQ
2943
+ */
2944
+
2945
+ .for-resposive-table {
2946
+ display: none;
2947
+ }
2948
+
2949
+ /* VERY LARGE DESKTOP */
2950
+ @media screen and (max-width: 1600px) {
2951
+ /* Page: Minification */
2952
+ #wphb-minification-filter .wphb-minification-filter-field-item {
2953
+ margin-left: 20px;
2954
+ }
2955
+ .wpmud .wphb-filename-info {
2956
+ max-width: 350px;
2957
+ }
2958
+ }
2959
+
2960
+ /* WIDE DESKTOP */
2961
+ @media screen and (max-width: 1440px) {
2962
+
2963
+ .wpmud .wphb-filename-info {
2964
+ max-width: 280px;
2965
+ }
2966
+
2967
+ /* Page: Performance */
2968
+ .wpmud .performance-report-table .wphb-performance-report-item-cta {
2969
+ width: 23%;
2970
+ }
2971
+
2972
+ /* Page: Minification */
2973
+ #wphb-minification-filter .wphb-minification-filter-field {
2974
+ float: none;
2975
+ margin: 0 15px;
2976
+ width: 35%;
2977
+ display: inline-block;
2978
+ }
2979
+ #wphb-minification-filter .wphb-minification-filter-field:last-child {
2980
+ margin: 0;
2981
+ }
2982
+ }
2983
+
2984
+ @media screen and (max-width: 1250px) {
2985
+ /* Page: minification */
2986
+ .wpmud .wphb-minification-file-details .wphb-filename-info {
2987
+ max-width: 250px;
2988
+ }
2989
+ }
2990
+
2991
+ /* LARGE DESKTOP */
2992
+ @media screen and (max-width: 1200px) {
2993
+
2994
+ /* Responsive Class Helpers */
2995
+ .hide-to-large {
2996
+ display: none;
2997
+ }
2998
+
2999
+ /* Block: Steps */
3000
+ .wphb-steps {
3001
+ text-align: center;
3002
+ }
3003
+ .wphb-step-number {
3004
+ float: none;
3005
+ margin-bottom: 10px;
3006
+ }
3007
+ .wphb-step-number-inner {
3008
+ margin: 0 auto;
3009
+ }
3010
+ .wphb-step-content {
3011
+ margin-left: 0;
3012
+ }
3013
+
3014
+ /* Page: Dashboard */
3015
+ .wpmud .box-dashboard-smush-no-membership .content-box-two-cols-image-left .wphb-block-entry-content {
3016
+ margin-top: 65px;
3017
+ }
3018
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-content {
3019
+ margin-top: 65px;
3020
+ }
3021
+
3022
+ /* Page: Minification */
3023
+
3024
+ .wpmud .wphb-filename-info {
3025
+ float: none;
3026
+ width: auto;
3027
+ }
3028
+
3029
+ /* Page: Performance */
3030
+ .wpmud .performance-report-table .wphb-performance-report-item-cta {
3031
+ width: 26%;
3032
+ }
3033
+
3034
+ /* Page: Caching */
3035
+ .wpmud .wrap-wphb-caching .row {
3036
+ display: block;
3037
+ table-layout: inherit;
3038
+ }
3039
+ .wpmud .wrap-wphb .row .col-half,
3040
+ .wpmud .wrap-wphb-caching .row .col-half,
3041
+ .wpmud .wrap-wphb-gzip .row .col-half {
3042
+ display: block;
3043
+ margin-top: 30px;
3044
+ padding: 0;
3045
+ width: 100%;
3046
+ }
3047
+ .wpmud .wrap-wphb .row .col-half:first-child,
3048
+ .wpmud .wrap-wphb-caching .row .col-half:first-child,
3049
+ .wpmud .wrap-wphb-gzip .row .col-half:first-child {
3050
+ margin-top: 0;
3051
+ }
3052
+ }
3053
+
3054
+ /* DESKTOP */
3055
+ @media screen and (max-width: 1100px) {
3056
+
3057
+ /* Box: Content w/Image (left) */
3058
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry {
3059
+ text-align: center;
3060
+ }
3061
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-image {
3062
+ float: none;
3063
+ margin-bottom: 30px;
3064
+ }
3065
+ .wpmud .wphb-block-entry-third {
3066
+ width: 49%;
3067
+ }
3068
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-image .wphb-image {
3069
+ margin: 0 auto;
3070
+ }
3071
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-content {
3072
+ margin: 35px 0 0 155px;
3073
+ }
3074
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-content .title {
3075
+ text-align: center;
3076
+ }
3077
+
3078
+ .wpmud .wphb-block-entry-third {
3079
+ text-align: left;
3080
+ padding-left: 0;
3081
+ }
3082
+
3083
+ /* Responsive Uitlities */
3084
+ .hide-to-desktop {
3085
+ display: none !important;
3086
+ }
3087
+
3088
+ /* Page: Dashboard */
3089
+ .wpmud .box-dashboard-performance-module-resume .box-content {
3090
+ padding: 30px;
3091
+ }
3092
+ .wpmud .box-dashboard-performance-module-resume .content {
3093
+ margin-top: 0;
3094
+ }
3095
+ .wpmud .box-dashboard-performance-module-resume .results {
3096
+ margin-top: 15px;
3097
+ }
3098
+ .wpmud .box-dashboard-performance-module-resume .current-score {
3099
+ display: block;
3100
+ padding: 0;
3101
+ }
3102
+ .wpmud .box-dashboard-uptime-no-membership .wphb-block-entry-image,
3103
+ .wpmud .box-dashboard-reports-no-membership .wphb-block-entry-image {
3104
+ display: none;
3105
+ }
3106
+ .wpmud .wphb-upsell-free-message p {
3107
+ margin-left: auto;
3108
+ margin-top: 30px;
3109
+ }
3110
+ .wpmud .wphb-upsell-free-message p:after {
3111
+ display: none;
3112
+ }
3113
+
3114
+ /* Page: Performance */
3115
+ .wpmud .wrap-wphb-performance #header h1,
3116
+ .wpmud .wrap-wphb-performance #header .actions {
3117
+ display: block;
3118
+ float: none;
3119
+ }
3120
+ .wpmud .wrap-wphb-performance #header .actions {
3121
+ margin-top: 15px;
3122
+ margin-bottom: 5px;
3123
+ }
3124
+ .wpmud .performance-report-table .wphb-performance-report-item-cta {
3125
+ width: 31%;
3126
+ }
3127
+ .wpmud .performance-report-table .wphb-performance-report-item-score {
3128
+ width: 105px;
3129
+ padding-left: 20px !important;
3130
+ }
3131
+
3132
+ /* Page: Minification */
3133
+ }
3134
+
3135
+ @media screen and (max-width: 1160px) {
3136
+
3137
+ /* Page Minification */
3138
+ .wpmud .wphb-enqueued-files {
3139
+ margin-left: -30px !important;
3140
+ margin-right: -30px !important;
3141
+ border-radius: 0;
3142
+ border-left: 0;
3143
+ border-right: 0;
3144
+ }
3145
+ .wpmud .wphb-minification-file-details {
3146
+ flex: 0 0 46%;
3147
+ }
3148
+ .wpmud .wphb-minification-row-details {
3149
+ flex: 0 0 42%;
3150
+ }
3151
+ .wpmud .wphb-border-row > .wphb-minification-exclude,
3152
+ .wpmud .wphb-minification-row-details > div:not(.wphb-minification-configuration) {
3153
+ margin-left: 10px;
3154
+ }
3155
+
3156
+ }
3157
+
3158
+ @media screen and (max-width: 1060px) {
3159
+
3160
+ .wpmud .wphb-border-row-header,
3161
+ .wpmud .wphb-border-row {
3162
+ padding: 15px 15px;
3163
+ }
3164
+ .wpmud .wphb-minification-file-details {
3165
+ flex: 0 0 42%;
3166
+ }
3167
+ .wpmud .wphb-minification-row-details {
3168
+ flex: 0 0 46%;
3169
+ }
3170
+ }
3171
+
3172
+ /* SMALL DESKTOP */
3173
+ @media screen and (max-width: 960px) {
3174
+
3175
+ /* Generic */
3176
+ .wpmud .row {
3177
+ display: block;
3178
+ }
3179
+ .wpmud .row .col-fifth {
3180
+ display: block;
3181
+ width: 100%;
3182
+ padding: 0;
3183
+ }
3184
+ .wpmud .row .col-four-fifths {
3185
+ display: block;
3186
+ width: 100%;
3187
+ padding: 0;
3188
+ }
3189
+
3190
+ .wpmud .dev-overlay {
3191
+ left: 35px;
3192
+ top: 15px;
3193
+ }
3194
+ .wpmud .wrap-wphb #header h1,
3195
+ .wpmud .wrap-wphb #header .actions {
3196
+ display: block;
3197
+ float: none;
3198
+ }
3199
+ .wpmud .wrap-wphb #header .actions {
3200
+ margin-top: 15px;
3201
+ margin-bottom: 5px;
3202
+ }
3203
+
3204
+ .wpmud .wphb-table.stack {
3205
+ display: block;
3206
+ }
3207
+ .wpmud .wphb-table.stack > thead,
3208
+ .wpmud .wphb-table.stack > tfoot {
3209
+ display: none;
3210
+ }
3211
+ .wpmud .wphb-table.stack > tbody {
3212
+ display: block;
3213
+ width: 100%;
3214
+ }
3215
+ .wpmud .wphb-table.stack > tbody > tr {
3216
+ display: block;
3217
+ position: relative;
3218
+ width: 100%;
3219
+ }
3220
+ .wpmud .wphb-table.stack > tbody > tr:before {
3221
+ background: transparent;
3222
+ border-top: 1px solid #EAEAEA;
3223
+ border-bottom: 1px solid transparent;
3224
+ bottom: 0;
3225
+ content: "";
3226
+ display: block;
3227
+ left: 0;
3228
+ margin: 0 -30px;
3229
+ position: absolute;
3230
+ right: 0;
3231
+ top: 0;
3232
+ }
3233
+ .wpmud .wphb-table.stack > tbody > tr:first-child:before {
3234
+ border-top-color: transparent;
3235
+ }
3236
+ .wpmud .wphb-table.stack > tbody > tr > td {
3237
+ border-bottom: none;
3238
+ display: block;
3239
+ padding-left: 0;
3240
+ position: relative;
3241
+ text-align: left;
3242
+ width: 100%;
3243
+ }
3244
+ .wpmud .wphb-table.stack > tbody > tr > td:before {
3245
+ content: attr(th-data);
3246
+ display: block;
3247
+ float: left;
3248
+ font-size: 15px;
3249
+ font-weight: 700;
3250
+ line-height: 1.5em;
3251
+ min-width: 150px;
3252
+ max-width: 300px;
3253
+ margin-right: 20px;
3254
+ text-transform: uppercase;
3255
+ /*width: 40%;*/
3256
+ }
3257
+ .wpmud .wphb-table.stack > tbody > tr > td.has-button-label:before {
3258
+ line-height: 2em;
3259
+ }
3260
+ .wpmud .wphb-table.stack > tbody > tr > td.has-select {
3261
+ max-height: 64px;
3262
+ }
3263
+ .wpmud .wphb-table.stack > tbody > tr > td.has-select:before {
3264
+ line-height: 2.867em;
3265
+ }
3266
+ .wpmud .wphb-table.stack > tbody > tr,
3267
+ .wpmud .wphb-table.stack > tbody > tr > td:first-child {
3268
+ border-top: none;
3269
+ }
3270
+ .wpmud .wphb-table.stack > tbody > tr > td:last-child {
3271
+ border-bottom: none;
3272
+ }
3273
+ .wpmud .wphb-table.stack > tbody > tr:hover:before {
3274
+ background: #FBFBFB;
3275
+ }
3276
+ .wpmud .wphb-table.stack > tbody > tr:first-child:hover:before {
3277
+ border-top-color: #EAEAEA;
3278
+ }
3279
+ .wpmud .wphb-table.stack > tbody > tr:last-child:hover:before {
3280
+ border-bottom-color: #EAEAEA;
3281
+ }
3282
+ .wpmud .wphb-table.stack > tbody > tr:hover > td {
3283
+ border-bottom: none;
3284
+ }
3285
+ .wpmud .wphb-table.stack > tbody > tr:hover > td:first-child:after,
3286
+ .wpmud .wphb-table.stack > tbody > tr:hover > td:last-child:after {
3287
+ display: none;
3288
+ }
3289
+ .wpmud .wphb-table.stack > tbody > tr > td > * {
3290
+ display: inline-block;
3291
+ }
3292
+ .wpmud .wphb-block-entry-third {
3293
+ padding-left: 0;
3294
+ }
3295
+
3296
+ /* Page: Minification */
3297
+ }
3298
+
3299
+ /* TABLET */
3300
+ @media screen and (max-width: 783px) {
3301
+
3302
+ /* Generic */
3303
+ .wpmud .box-content .with-padding {
3304
+ padding: 0;
3305
+ }
3306
+ .wpmud .dev-overlay {
3307
+ left: 0;
3308
+ top: 0;
3309
+ }
3310
+ .wpmud .row,
3311
+ .wpmud .row-sep {
3312
+ display: block;
3313
+ table-layout: inherit;
3314
+ }
3315
+ .wpmud .row .col-third,
3316
+ .wpmud .row .col-two-third,
3317
+ .wpmud .row .col-half,
3318
+ .wpmud .row .col-quarter,
3319
+ .wpmud .row .col-three-quarters {
3320
+ display: block;
3321
+ margin-top: 30px;
3322
+ padding: 0;
3323
+ width: 100%;
3324
+ }
3325
+ .wpmud .row .col-third:first-child,
3326
+ .wpmud .row .col-two-third:first-child,
3327
+ .wpmud .row .col-half:first-child,
3328
+ .wpmud .row .col-quarter:first-child,
3329
+ .wpmud .row .col-three-quarters:first-child {
3330
+ margin-top: 0;
3331
+ }
3332
+ .wpmud .content-box-two-cols-image-left .wphb-block-entry-image {
3333
+ display: none;
3334
+ }
3335
+
3336
+ .wpmud #header .actions {
3337
+ float: none;
3338
+ }
3339
+ .wpmud #header .actions:last-child {
3340
+ position: relative;
3341
+ margin-top: 20px !important;
3342
+ }
3343
+ .wpmud #header .actions:last-child > a {
3344
+ margin-left: 0;
3345
+ }
3346
+
3347
+ .wpmud .wphb-border-frame {
3348
+ border: 0
3349
+ }
3350
+
3351
+ .wpmud .wphb-table-wrapper.complex {
3352
+ overflow-y: hidden;
3353
+ width: 100%;
3354
+ padding: 0;
3355
+ }
3356
+ .wpmud .wphb-table-wrapper.complex p {
3357
+ padding: 0 20px;
3358
+ }
3359
+ .wpmud .wphb-table-wrapper.complex .alignleft {
3360
+ padding-left: 20px;
3361
+ }
3362
+ .wpmud .wphb-table-wrapper.complex .alignright {
3363
+ padding-right: 20px;
3364
+ }
3365
+ .wpmud .wphb-table-wrapper.complex .wphb-table > thead > tr > th,
3366
+ .wpmud .wphb-table-wrapper.complex .wphb-table > thead > tr > td,
3367
+ .wpmud .wphb-table-wrapper.complex .wphb-table > tbody > tr > th,
3368
+ .wpmud .wphb-table-wrapper.complex .wphb-table > tbody > tr > td,
3369
+ .wpmud .wphb-table-wrapper.complex .wphb-table > tfoot > tr > th,
3370
+ .wpmud .wphb-table-wrapper.complex .wphb-table > tfoot > tr > td {
3371
+ /*white-space: nowrap;*/
3372
+ padding: 20px;
3373
+ }
3374
+
3375
+ .wpmud .list-table > thead > tr > th,
3376
+ .wpmud .list-table > tbody > tr > td {
3377
+ /*width: 50%;*/
3378
+ width: 100%;
3379
+ }
3380
+
3381
+ .wpmud .wphb-table.stack > tbody > tr > td:before {
3382
+ max-width: 220px;
3383
+ width: 40%;
3384
+ }
3385
+
3386
+ .wpmud .dev-box .box-title .toggle-group {
3387
+ margin-top: 0;
3388
+ }
3389
+
3390
+ .wpmud .wrap-wp-hummingbird > .wphb-notice {
3391
+ width: 85%;
3392
+ }
3393
+
3394
+ /* Page: Dashboard */
3395
+ .wpmud .box-dashboard-performance-module-resume .results {
3396
+ margin-top: 0;
3397
+ }
3398
+ .wpmud .box-dashboard-performance-module-resume .results .dev-list-stats > li:first-child .list-label-stats,
3399
+ .wpmud .box-dashboard-performance-module-resume .results .dev-list-stats > li:first-child .list-detail-stats-heading {
3400
+ padding-top: 10px;
3401
+ }
3402
+
3403
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-heading-recommendation,
3404
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-item-recommendation {
3405
+ width: 75%;
3406
+ }
3407
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-heading-score,
3408
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-item-score,
3409
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-heading-cta,
3410
+ .wpmud .box-dashboard-performance-module .wphb-performance-report-item-cta {
3411
+ width: 100%;
3412
+ }
3413
+ .wpmud .callout-box .callout-title {
3414
+ line-height: 30px;
3415
+ }
3416
+
3417
+ /* Page: Performance */
3418
+ .wpmud .performance-report-table th,
3419
+ .wpmud .performance-report-table td {
3420
+ width: 70% !important;
3421
+ }
3422
+ .wpmud .wphb-performance-report-item-additional-content-inner {
3423
+ white-space: normal;
3424
+ }
3425
+ .wpmud .wphb-performance-report-item-additional-content .dev-box:last-child {
3426
+ margin: -30px 0 0;
3427
+ }
3428
+ .wpmud .wphb-performance-report-heading.wphb-performance-report-heading-type,
3429
+ .wpmud .wphb-performance-report-item-type,
3430
+ .wpmud .wphb-performance-report-item-cta > button {
3431
+ display: none !important;
3432
+ }
3433
+ .wpmud .wphb-performance-report-item-additional-content-inner > .row {
3434
+ display: table;
3435
+ table-layout: fixed;
3436
+ }
3437
+ .wpmud .wphb-performance-report-item-additional-content > td {
3438
+ padding: 30px 0 0 !important;
3439
+ }
3440
+
3441
+ /* Page: Minification */
3442
+ #wphb-minification-filter .wphb-minification-filter-block {
3443
+ border-top: 1px solid #EAEAEA;
3444
+ float: none;
3445
+ margin: 0 0 30px;
3446
+ padding-top: 30px;
3447
+ width: 100%;
3448
+ }
3449
+ #wphb-minification-filter .wphb-minification-filter-block:last-child {
3450
+ margin: 0;
3451
+ }
3452
+ #wphb-minification-filter .wphb-minification-filter-block:first-child {
3453
+ border-top: none;
3454
+ padding-top: 0;
3455
+ }
3456
+
3457
+ .wpmud .wphb-border-row-header {
3458
+ display: none;
3459
+ }
3460
+ /*
3461
+ .wpmud .wphb-enqueued-files {
3462
+ margin: 0 !important;
3463
+ }
3464
+ */
3465
+ .wpmud .wphb-border-row,
3466
+ .wpmud .wphb-minification-row-details {
3467
+ display: block;
3468
+ }
3469
+ .wpmud .wphb-border-row {
3470
+ border-top: 1px solid #eee;
3471
+ border-bottom: 1px solid #eee;
3472
+ }
3473
+
3474
+ .wpmud .wphb-minification-file-select {
3475
+ float: left;
3476
+ margin-top: 9px;
3477
+ margin-right: 15px;
3478
+ }
3479
+
3480
+ .wpmud .wphb-minification-row-details {
3481
+ display: none;
3482
+ }
3483
+
3484
+ .wpmud .wphb-minification-configuration .checkbox-group,
3485
+ .wpmud .wphb-minification-configuration .checkbox-group input[type="checkbox"] + label{
3486
+ width: 100%;
3487
+ }
3488
+
3489
+ .wpmud .wphb-minification-configuration,
3490
+ .wpmud .wphb-minification-file-size {
3491
+ margin-top: 20px;
3492
+ }
3493
+
3494
+ .wpmud .wphb-minification-configuration > strong,
3495
+ .wpmud .wphb-minification-file-size > strong {
3496
+ display: block;
3497
+ color: #333333;
3498
+ font-size: 13px;
3499
+ font-weight: bold;
3500
+ line-height: 30px;
3501
+ }
3502
+
3503
+ .wpmud .wphb-minification-exclude {
3504
+ position: relative;
3505
+ top: -32px;
3506
+ left: 100%;
3507
+ margin-left: -20px !important;
3508
+ margin-bottom: -25px;
3509
+ }
3510
+
3511
+ .wpmud .wphb-minification-file-size {
3512
+ text-align: left;
3513
+ margin-left: 0 !important;
3514
+ }
3515
+ .wpmud .wphb-minification-file-size > div:first-child {
3516
+ margin-top: 15px;
3517
+ }
3518
+ .wpmud .wphb-minification-file-size > div:last-child > div {
3519
+ margin-top: 5px;
3520
+ }
3521
+ .wpmud .wphb-minification-file-size > div > span {
3522
+ display: inline-block;
3523
+ }
3524
+
3525
+ .wpmud .wphb-minification-file-size > div > span:nth-child(2),
3526
+ .wpmud .wphb-minification-file-size > div > span:nth-child(3) {
3527
+ position: relative ;
3528
+ left: 100%;
3529
+ margin-left: -90px;
3530
+ }
3531
+ .wpmud .wphb-minification-file-size > div > span:nth-child(2) {
3532
+ top: 3px;
3533
+ }
3534
+ .wpmud .wphb-minification-file-size > div > span:nth-child(3) {
3535
+ margin-left: 0;
3536
+ }
3537
+
3538
+ .wpmud .wphb-minification-file-size .wphb-scan-progress {
3539
+ display: block;
3540
+ }
3541
+ .wpmud .wphb-minification-file-size .wphb-scan-progress-bar {
3542
+ background-color: #1ABC9C;
3543
+ margin-bottom: 10px;
3544
+ }
3545
+ .wpmud .wphb-minification-file-size .wphb-scan-progress-bar span {
3546
+ background-color: #E6E6E6;
3547
+ }
3548
+
3549
+ }
3550
+
3551
+ /* LARGE MOBILE */
3552
+ @media screen and (max-width: 600px) {
3553
+
3554
+ /* Responsive Class Helpers */
3555
+ .hide-to-mobile {
3556
+ display: none !important;
3557
+ }
3558
+
3559
+ .wpmud #header .actions {
3560
+ margin-top: 82px !important;
3561
+ }
3562
+
3563
+ .wpmud .wphb-block-entry-third {
3564
+ display: block;
3565
+ text-align: center;
3566
+ width: 100%;
3567
+ }
3568
+ .wpmud .wphb-block-entry-third .dev-list {
3569
+ text-align: left;
3570
+ }
3571
+
3572
+ /* Generic */
3573
+ .wpmud .dev-box .box-title h3,
3574
+ .wpmud .dev-box .box-title .buttons,
3575
+ .wpmud .dev-box .box-title .actions,
3576
+ .wpmud .dev-box .box-title .extra,
3577
+ .wpmud .dev-box .box-title .test-results {
3578
+ float: none;
3579
+ display: block;
3580
+ }
3581
+ .wpmud .dev-box .box-title .buttons,
3582
+ .wpmud .dev-box .box-title .actions,
3583
+ .wpmud .dev-box .box-title .extra {
3584
+ margin-top: 15px;
3585
+ }
3586
+ .wpmud .dev-box .box-title {
3587
+ padding: 15px 20px;
3588
+ }
3589
+ .wpmud .dev-box .box-title h3 {
3590
+ line-height: 34px;
3591
+ display: inline-block;
3592
+ }
3593
+ .wpmud section[class^="box-dashboard-"] .box-title:before {
3594
+ margin: 5px 10px 5px 0;
3595
+ }
3596
+ .wphb-pills {
3597
+ margin: 0 0 0 10px;
3598
+ }
3599
+ .wphb-pills-group .wphb-pills:first-child {
3600
+ border-radius: 5px 5px 0 0 !important;
3601
+ }
3602
+ .wphb-pills-group .wphb-pills:last-child {
3603
+ border-radius: 0 0 5px 5px !important;
3604
+ }
3605
+ .wpmud .dev-box .box-title .buttons {
3606
+ margin-top: 0;
3607
+ float: right;
3608
+ }
3609
+ .wpmud .wrap-wp-hummingbird > .wphb-notice {
3610
+ width: 100%;
3611
+ top: 46px;
3612
+ margin-left: -251px;
3613
+ }
3614
+
3615
+ /* Page: Dashboard */
3616
+ .wpmud .wphb-block-entry-third .current-performance-score {
3617
+ margin-bottom: 5px;
3618
+ }
3619
+
3620
+ }
3621
+
3622
+ /* MOBILE */
3623
+ @media screen and (max-width: 480px) {
3624
+
3625
+ /* Compoents: Pills */
3626
+ .wphb-pills-group {
3627
+ border-collapse: inherit;
3628
+ border-spacing: inherit;
3629
+ }
3630
+ .wphb-pills {
3631
+ display: block;
3632
+ }
3633
+ .wphb-pills.with-arrow.right:after,
3634
+ .wphb-pills.with-arrow.left:after {
3635
+ border-top-color: #19B4CF;
3636
+ margin-top: 0;
3637
+ margin-left: -8px;
3638
+ top: 50%;
3639
+ }
3640
+ .wphb-pills.with-arrow.right:after {
3641
+ border-left-color: transparent;
3642
+ left: 50%;
3643
+ }
3644
+ .wphb-pills.with-arrow.left:after {
3645
+ border-right-color: transparent;
3646
+ right: 50%;
3647
+ }
3648
+ .wphb-pills.with-arrow.right.grey:after {
3649
+ border-top-color: #eee;
3650
+ border-left-color: transparent;
3651
+ }
3652
+ .wphb-pills.with-arrow.left.grey:after {
3653
+ border-top-color: #eee;
3654
+ border-right-color: transparent;
3655
+ }
3656
+
3657
+ }
3658
+
3659
+ /* HELPER CLASSES */
3660
+ @media screen and (min-width: 960px) {
3661
+ .hide-on-large {
3662
+ display: none !important;
3663
+ }
3664
+ }
3665
+ @media screen and (max-width: 960px) {
3666
+ .hide-on-mobile {
3667
+ display: none !important;
3668
+ }
3669
+ }
admin/assets/css/app.css ADDED
@@ -0,0 +1,2 @@
 
 
1
+ .cf:after{content:"";display:table;clear:both}@media only screen and (max-width:1200px){.hide-to-large{display:none}}@media only screen and (max-width:1100px){.hide-to-desktop{display:none}}
2
+ /*# sourceMappingURL=app.css.map*/
admin/assets/css/app.css.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"app.css","sourceRoot":""}
admin/assets/css/wphb-font.css ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @font-face {
2
+ font-family: 'wphb';
3
+ src: url('../fonts/wphb.eot?xjiybk');
4
+ src: url('../fonts/wphb.eot?xjiybk#iefix') format('embedded-opentype'),
5
+ url('../fonts/wphb.ttf?xjiybk') format('truetype'),
6
+ url('../fonts/wphb.woff?xjiybk') format('woff'),
7
+ url('../fonts/wphb.svg?xjiybk#icomoon') format('svg');
8
+ font-weight: normal;
9
+ font-style: normal;
10
+ }
11
+
12
+ #toplevel_page_wphb-minification .wp-menu-image:before,
13
+ #toplevel_page_wphb .wp-menu-image:before {
14
+ font-family: 'wphb';
15
+ content: "\e900";
16
+ }
admin/assets/fonts/hummingbird.eot ADDED
Binary file
admin/assets/fonts/hummingbird.svg ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata>Generated by IcoMoon</metadata>
5
+ <defs>
6
+ <font id="hummingbird" horiz-adv-x="1024">
7
+ <font-face units-per-em="1024" ascent="960" descent="-64" />
8
+ <missing-glyph horiz-adv-x="1024" />
9
+ <glyph unicode="&#x20;" horiz-adv-x="512" d="" />
10
+ <glyph unicode="&#xe900;" glyph-name="hb-icon-cache" d="M0 240.042c3.708 17.161 6.603 34.551 11.299 51.448 8.704 31.285 23.111 60.169 39.636 88.029 18.856 31.78 37.57 63.647 56.32 95.497 1.66 2.807 3.178 5.703 5.191 9.34-17.002 11.105-33.933 21.575-50.176 33.015-8.333 5.862-16.596 12.588-22.828 20.515-11.758 14.972-9.993 32.15 4.467 44.562 7.415 6.356 16.402 11.511 25.494 15.237 55.737 22.775 111.668 45.056 167.6 67.355 5.844 2.313 11.952 4.202 18.114 5.473 31.903 6.585 58.138-11.758 62.87-43.838 0.865-5.915 1.448-11.935 1.483-17.902 0.265-57.98 0.618-115.96 0.265-173.94-0.053-9.763-1.977-20.021-5.455-29.114-6.638-17.373-22.493-25.229-40.448-20.498-8.845 2.33-17.249 6.762-25.459 11.017-6.479 3.337-12.341 7.857-18.485 11.847-6.144 3.972-12.288 7.945-19.138 12.376-1.624-2.119-3.337-3.972-4.608-6.109-18.273-30.579-36.564-61.14-54.678-91.825-10.558-17.885-18.803-36.67-21.839-57.468-6.532-44.774 13.347-80.102 56.161-94.88 17.020-5.862 35.663-9.11 53.671-9.604 47.598-1.306 95.267-0.441 143.73-0.441v-127.418c-2.278-0.212-4.82-0.636-7.362-0.636-47.651-0.018-95.32-0.689-142.953 0.265-52.559 1.024-103.388 10.54-149.097 38.418-46.521 28.354-74.575 69.279-81.99 123.728-0.265 1.907-1.183 3.708-1.783 5.561v39.989zM529.99 960c8.033-1.801 16.137-3.355 24.099-5.42 55.102-14.371 97.385-47.916 129.765-92.902 26.182-36.352 48.092-75.794 71.821-113.93 5.402-8.686 10.434-17.585 16.137-27.242 17.726 11.652 34.339 23.234 51.623 33.686 8.686 5.244 18.255 9.781 28.036 12.306 16.861 4.343 31.779-3.125 38.259-19.191 3.637-9.040 5.897-19.28 5.967-28.99 0.388-59.304 0.088-118.608-0.371-177.912-0.053-8.21-1.342-16.702-3.796-24.541-9.657-30.879-39.918-43.785-73.94-31.056-39.565 14.777-78.795 30.473-118.13 45.815-19.527 7.627-39.088 15.113-58.456 23.128-15.854 6.55-30.543 15.448-32.662 34.357-2.136 19.015 10.505 30.72 24.523 40.572 13.047 9.181 26.536 17.708 40.148 26.73-0.477 1.518-0.618 2.843-1.236 3.867-22.175 37.164-43.396 74.947-67.072 111.105-10.558 16.119-24.47 31.038-39.671 42.902-32.415 25.282-72.916 25.53-105.472 0.371-15.748-12.164-28.248-28.778-41.207-44.244-6.744-8.033-11.282-17.92-17.090-27.419-33.88 20.233-67.231 40.148-100.987 60.31 34.551 60.452 75.175 113.753 140.482 142.072 16.843 7.292 35.434 10.523 53.23 15.625h35.999zM735.889 160.060c30.985 0.6 60.928-2.366 90.359 5.703 56.655 15.519 82.573 60.981 63.77 116.737-7.345 21.804-20.039 41.843-30.79 62.429-5.349 10.275-11.794 19.986-18.361 30.985 32.944 19.739 65.412 39.159 97.597 58.439 1.095-0.477 1.995-0.565 2.26-1.006 30.226-50.123 62.764-99.134 76.27-157.362 12.341-53.248 10.099-104.661-20.692-151.888-26.818-41.137-66.683-64.089-112.498-78.019-31.126-9.446-63.152-13.33-95.585-13.912-16.949-0.3-33.898-0.053-52.224-0.053 0-16.808 0.494-33.015-0.194-49.17-0.388-8.863-1.554-18.061-4.52-26.342-5.932-16.402-20.974-23.958-37.817-19.191-8.492 2.401-16.878 6.303-24.329 11.088-53.477 34.445-106.76 69.191-159.99 104.007-39.3 25.706-39.106 61.387 0.441 87.235 49.893 32.627 99.875 65.113 149.839 97.634 5.579 3.637 11.087 7.398 16.896 10.664 32.132 18.132 58.262 3.566 59.462-33.457 0.583-17.638 0.106-35.293 0.106-54.52z" />
11
+ <glyph unicode="&#xe901;" glyph-name="hb-icon-cloudflare" d="M157.569 399.14c-12.601 48.599 0.489 89.238 43.354 116.587 43.289 27.621 86.217 20.578 126.953-10.669 24.466 75.172 73.002 128.355 148.405 156.089 49.465 18.195 100.165 19.155 150.506 3.923 59.684-18.056 105.658-53.992 136.94-107.167 31.233-53.092 38.256-110.063 24.847-171.853 5.338 3.668 8.465 5.986 11.756 8.052 49.368 31.011 100.823 34.4 151.671 5.958 52.049-29.115 75.612-75.35 71.553-133.933-0.981-14.155-6.561-28.102-10.986-41.845-0.908-2.817-5.933-4.699-9.414-6.245-1.956-0.867-4.639-0.164-6.995-0.164-325.329 0-650.657 0.063-975.984-0.273-11.326-0.012-15.161 3.298-17.402 13.951-16.019 76.112 39.282 154.285 117.458 164.766 11.919 1.599 24.024 1.853 37.34 2.823zM981.825 589.732c-20.335-24.367-40.671-48.735-61.008-73.102 0.414-0.685 0.826-1.37 1.24-2.055 28.699 7.199 57.401 14.398 86.102 21.597 0.26-0.432 0.521-0.861 0.781-1.293-23.186-16.483-46.374-32.965-69.56-49.448 0.061-0.732 0.121-1.465 0.182-2.195 24.801-1.069 49.602-2.136 74.403-3.203 0.19-0.697 0.382-1.395 0.571-2.092-16.328-7.14-32.632-14.335-49.035-21.312-1.231-0.523-3.27 0.236-4.732 0.855-35.036 14.861-71.48 19.784-109.888 14.438-2.372 12.326-4.199 24.277-7.019 36.002-8.017 33.323-22.005 64.133-40.933 92.927-2.439 3.711-3.359 9.976-2.057 14.188 6.587 21.326 14.14 42.365 23.129 63.359 3.046-30.728 6.095-61.457 9.143-92.185 0.741-0.275 1.484-0.552 2.225-0.829 15.981 25.103 31.962 50.204 47.943 75.305 0.773-0.263 1.548-0.525 2.324-0.788-5.719-29.976-11.437-59.95-17.154-89.925 0.66-0.354 1.32-0.711 1.978-1.065 21.779 20.358 43.556 40.718 65.335 61.077 0.525-0.281 1.052-0.564 1.579-0.845l-33.835-76.892c0.408-0.629 0.816-1.259 1.223-1.888 25.286 13.531 50.571 27.064 75.857 40.598 0.402-0.41 0.806-0.819 1.207-1.229zM764.304 678.285c5.166-15.819 9.888-30.285 14.782-45.269-17.977 10.841-23.636 25.141-14.782 45.269z" />
12
+ <glyph unicode="&#xe902;" glyph-name="hb-icon-gzip" d="M543.337 404.299v80.826l227.404-80.831h-146.345c73.056-0.007 143.737-0.021 203.106-0.035 32.626 0 48.694-23.043 36.417-51.972-22.307-52.51-74.864-86.701-134.313-86.822-84.585-0.191-169.188-0.052-253.792-0.052-83.080 0-166.178-0.017-249.258 0-86.235 0.017-149.384 60.011-149.547 142.805-0.272 137.769-0.272 275.539-0.036 413.325 0.127 76.056 64.745 138.012 144.143 138.134 169.587 0.243 339.175 0.695 508.744-0.26 62.55-0.347 107.255-30.405 133.189-84.791 14.49-30.405-2.067-53.76-36.943-53.76-151.071-0.035-374.684 0.017-525.755 0.017-48.332 0-78.419-28.79-78.437-74.997-0.036-87.881-0.054-175.745-0.054-263.627 0.018-50.635 29.053-78.036 82.155-78.001 69.133 0.032 153.612 0.042 239.323 0.040zM547.863 213.049h217.629v-121.204c26.841 0 16.467-0.191 42.365 0.278 2.775 0.052 6.057 3.473 8.125 6.060 20.638 25.647 54.19 35.111 84.893 23.702 30.015-11.148 48.948-40.476 46.029-71.316-2.902-30.579-26.514-55.775-59.213-61.54-28.927-5.088-52.848 4.341-70.802 26.481-4.153 5.123-8.052 7.172-14.799 7.067-23.74-0.434-11.244-0.174-34.857-0.174 0-29.849-30.142-86.405-110.193-86.405-76.17 0-109.359 60.202-109.359 86.405-25.789 0-15.506 0.174-41.476-0.278-2.775-0.052-6.039-3.49-8.107-6.060-20.657-25.665-54.153-35.111-84.912-23.702-29.997 11.113-48.912 40.459-46.010 71.316 2.884 30.596 26.514 55.792 59.213 61.54 28.927 5.088 52.848-4.341 70.802-26.481 4.171-5.123 8.052-7.172 14.799-7.067 23.722 0.434 11.19 0.174 35.872 0.174v121.204zM770.746 601.058l-227.404 80.831v80.814l227.404-80.814v-80.831zM770.746 739.853l-227.404 80.831h227.404v-80.831zM770.746 462.264l-227.404 80.831v80.814l227.404-80.814v-80.831z" />
13
+ <glyph unicode="&#xe903;" glyph-name="hb-icon-minify-combine" d="M715.731 383.715h-247.323l-358.048-358.048c-25.403-25.403-66.093-25.389-91.198-0.285-25.28 25.28-24.977 65.935 0.285 91.198l331.421 331.421-331.421 331.421c-25.262 25.262-25.565 65.918-0.285 91.198 25.105 25.105 65.795 25.118 91.198-0.285l358.048-358.048h247.323v163.14c0 17.961 11.44 23.27 25.222 12.124l270.982-219.152c13.93-11.265 13.782-29.649 0-40.795l-270.982-219.152c-13.93-11.265-25.222-5.399-25.222 12.124v163.14z" />
14
+ <glyph unicode="&#xe904;" glyph-name="hb-icon-minify-footer" d="M0 384c0 18 6.167 33.167 18.5 45.5s27.5 18.5 45.5 18.5h896c17.333 0 32.333-6.333 45-19s19-27.667 19-45v-384c0-18-6.167-33.167-18.5-45.5s-27.5-18.5-45.5-18.5h-896c-17.333 0-32.333 6.333-45 19s-19 27.667-19 45v384zM0 672c0 8.667 3.167 16.167 9.5 22.5s13.833 9.5 22.5 9.5h960c8.667 0 16.167-3.167 22.5-9.5s9.5-13.833 9.5-22.5c0-8.667-3.167-16.167-9.5-22.5s-13.833-9.5-22.5-9.5h-960c-8.667 0-16.167 3.167-22.5 9.5s-9.5 13.833-9.5 22.5zM0 800c0 8.667 3.167 16.167 9.5 22.5s13.833 9.5 22.5 9.5h960c8.667 0 16.167-3.167 22.5-9.5s9.5-13.833 9.5-22.5c0-8.667-3.167-16.167-9.5-22.5s-13.833-9.5-22.5-9.5h-960c-8.667 0-16.167 3.167-22.5 9.5s-9.5 13.833-9.5 22.5zM0 928c0 8.667 3.167 16.167 9.5 22.5s13.833 9.5 22.5 9.5h960c8.667 0 16.167-3.167 22.5-9.5s9.5-13.833 9.5-22.5c0-8.667-3.167-16.167-9.5-22.5s-13.833-9.5-22.5-9.5h-960c-8.667 0-16.167 3.167-22.5 9.5s-9.5 13.833-9.5 22.5zM0 544c0 8.667 3.167 16.167 9.5 22.5s13.833 9.5 22.5 9.5h960c8.667 0 16.167-3.167 22.5-9.5s9.5-13.833 9.5-22.5c0-8.667-3.167-16.167-9.5-22.5s-13.833-9.5-22.5-9.5h-960c-8.667 0-16.167 3.167-22.5 9.5s-9.5 13.833-9.5 22.5z" />
15
+ <glyph unicode="&#xe905;" glyph-name="hb-icon-minify" d="M244.547 72.901c-2.278-3.513-4.025-7.556-6.921-10.47-34.48-34.728-68.943-69.491-103.812-103.83-23.181-22.846-57.132-28.743-86.369-15.996-28.495 12.429-48.022 42.249-47.263 73.092 0.53 21.787 8.686 40.466 24.205 55.949 33.845 33.774 67.566 67.655 101.429 101.394 2.931 2.931 6.515 5.191 10.734 8.492-4.59 4.961-7.45 8.263-10.558 11.37-29.749 29.784-59.551 59.551-89.353 89.318-1.871 1.889-4.696 3.478-5.402 5.738-2.278 7.203-6.762 15.801-4.573 21.681 1.73 4.696 11.988 8.598 18.52 8.722 43.237 0.742 86.493 0.371 129.73 0.371 59.551-0.018 119.102-0.035 178.67-0.053 3.407-0.018 6.85 0.071 10.222-0.335 14.265-1.66 18.414-6.003 18.52-20.568 0.23-29.979 0.141-59.957 0.141-89.936 0-74.77 0.018-149.522-0.035-224.291-0.018-8.58 1.589-18.079-9.304-22.122-10.275-3.831-17.514 1.677-24.135 8.316-30.596 30.579-61.14 61.193-91.507 92.001-3.16 3.196-4.961 7.733-7.398 11.635-1.854-0.159-3.69-0.318-5.544-0.477zM886.027 186.007c5.756-6.215 8.21-9.022 10.823-11.652 34.586-34.675 69.438-69.085 103.706-104.077 21.31-21.787 28.46-48.040 19.756-77.542-8.545-28.955-28.107-47.598-57.379-54.325-28.178-6.462-53.371 0.689-74.152 21.416-34.675 34.604-69.279 69.244-103.936 103.848-2.383 2.383-4.89 4.643-7.945 7.521-3.319-3.107-6.391-5.844-9.287-8.757-29.802-29.802-59.568-59.639-89.37-89.441-2.666-2.684-5.12-6.462-8.386-7.503-6.426-2.030-14.442-5.049-19.738-2.807-4.308 1.801-7.839 10.717-7.874 16.508-0.512 73.287-0.335 146.591-0.318 219.878 0 32.662-0.088 65.324 0.141 97.986 0.106 16.578 5.191 21.804 21.998 21.839 105.896 0.106 211.791 0.106 317.704-0.071 15.96-0.035 22.74-13.118 14.212-26.748-2.383-3.796-5.756-7.044-8.969-10.24-29.802-29.802-59.586-59.622-89.6-89.212-2.895-2.86-7.221-4.255-11.388-6.621zM245.691 823.257c31.55 31.497 60.804 60.716 90.077 89.918 5.65 5.632 10.593 12.535 17.284 16.366 5.932 3.407 14.195 5.455 20.78 4.326 8.563-1.483 8.439-10.346 8.439-17.743-0.053-105.19-0.053-210.397-0.177-315.586-0.018-18.573-4.89-23.128-24.029-23.128-104.377-0.053-208.772-0.159-313.149 0.3-6.25 0.035-14.76 3.249-18.149 7.945-5.297 7.309-1.801 16.207 4.502 22.669 15.413 15.731 31.055 31.232 46.645 46.786 19.050 18.997 38.135 37.941 57.891 57.609-3.531 3.725-6.268 6.744-9.163 9.64-34.551 34.692-69.455 69.067-103.618 104.166-21.257 21.822-28.213 48.234-19.121 77.648 9.039 29.29 29.308 47.687 59.127 53.937 27.913 5.862 52.542-1.977 72.863-22.334 34.074-34.11 68.166-68.202 102.17-102.418 2.648-2.666 4.608-6.056 7.627-10.099zM775.107 822.418c39.936 40.042 76.676 77.365 113.964 114.123 38.082 37.535 100.087 28.548 125.175-17.673 16.967-31.285 11.582-67.902-14.46-94.226-33.916-34.269-68.166-68.202-102.259-102.294-2.878-2.895-5.597-5.967-9.551-10.187 21.204-20.833 41.807-40.978 62.287-61.228 13.489-13.347 27.224-26.483 40.042-40.466 4.29-4.679 7.698-11.476 8.545-17.708 1.359-9.905-5.491-15.219-17.867-15.289-31.514-0.159-63.011-0.071-94.508-0.053-72.492 0.035-144.984 0.088-217.476 0.141-23.587 0-27.648 4.078-27.63 27.913 0.053 102.912 0.159 205.807 0.23 308.719 0.018 7.98-0.918 16.455 8.616 20.286 9.551 3.814 17.108-0.477 23.552-6.886 30.402-30.279 60.681-60.663 90.836-91.171 3.708-3.761 6.409-8.492 10.505-14.001z" />
16
+ <glyph unicode="&#xe906;" glyph-name="hb-icon-performancetest" d="M414.582 28.434c0 0 47.76-56.244 94.35-92.434-281.355 1.654-508.932 230.226-508.932 511.98 0 121.119 42.080 232.392 112.38 320.061 45.419-18.706 88.372-38.523 105.367-53.542 0 0 39.525-78.040 66.888-136.822 27.364-58.784 46.621-91.215 54.728-161.147s65.874-184.457 168.235-221.958c-66.89-96.282-93.017-166.138-93.017-166.138zM486.997 592.482c0 0-31.085 196.004-244.927 145.327-41.987 18.926-81.243 34.231-116.173 46.426 93.863 107.695 232.029 175.765 386.104 175.765 190.936 0 357.439-104.533 445.464-259.481-62.831-10.027-227.191-34.434-402.291-45.478-33.885-2.138-56.036-36.23-68.177-62.559zM625.494 376.95l392.255 151.125c4.101-26.098 6.25-52.844 6.25-80.095 0-261.811-196.503-477.695-450.059-508.278-0.155 19.095 0.341 36.429 1.25 51.945 2.538 43.363 11.636 86.080 26.945 126.729 15.191 40.335 38.054 118.875 31.131 213.019-1.132 15.42-3.853 30.652-7.773 45.554z" />
17
+ <glyph unicode="&#xe907;" glyph-name="hb-icon-restore" d="M902.64 323.64c-54.449-169.391-209.853-291.64-393.065-291.64-132.494 0-254.648 64.449-332.218 171.518l94.867 72.464c55.492-76.596 142.639-122.575 237.351-122.575 130.156 0 240.664 86.376 280.121 206.348l-66.184-49.013c-23.042-17.064-54.657-11.593-70.614 12.219s-10.213 56.949 12.829 74.013l220.862 163.561 129.987-228.053c14.243-24.988 6.22-57.64-17.919-72.932s-55.254-7.431-69.497 17.557l-26.522 46.531zM121.36 572.36c54.449 169.391 209.853 291.64 393.065 291.64 132.494 0 254.648-64.449 332.218-171.518l-94.867-72.464c-55.492 76.596-142.639 122.575-237.351 122.575-130.156 0-240.664-86.376-280.121-206.348l66.184 49.013c23.042 17.064 54.657 11.593 70.614-12.219s10.213-56.949-12.829-74.013l-220.862-163.561-129.987 228.053c-14.243 24.988-6.22 57.64 17.919 72.932s55.254 7.431 69.497-17.557l26.522-46.531z" />
18
+ <glyph unicode="&#xe908;" glyph-name="hb-icon-smush" d="M0 908.8l51.757-92.949 460.375-828.651 511.868 921.6h-1024zM512.002 104.813l-414.733 747.178h829.463l-414.73-747.178zM213.99 782.555l298.011-536.892 298.008 536.892h-596.019zM311.259 722.586h401.485l-200.742-361.655-200.742 361.655z" />
19
+ <glyph unicode="&#xe909;" glyph-name="hb-icon-audit" d="M716.8 608.137c-26.123-19.54-48.301-43.688-65.351-71.25-21.784 47.187-43.918 104.997-66.403 173.474l-103.264-737.457c-2.893-20.479-20.425-36.009-41.639-36.862-0.614 0-1.227-0.043-1.841-0.043-20.425 0-38.308 13.823-42.778 33.406l-143.325 627.766-79.64-206.838c-6.443-16.639-22.792-27.689-41.069-27.689h-131.491v85.329h101.116l120.84 313.627c6.794 17.663 24.238 28.969 44.137 27.604 19.329-1.323 35.459-14.89 39.71-33.321l122.155-535.227 98.399 702.386c2.849 20.223 19.943 35.625 40.85 36.819 20.907 1.664 39.754-12.074 45.014-31.87 29.498-110.629 68.375-229.834 104.579-319.856zM844.8 550.4c98.829 0 179.2-80.371 179.2-179.2s-80.371-179.2-179.2-179.2c-98.829 0-179.2 80.371-179.2 179.2s80.371 179.2 179.2 179.2zM844.8 460.8c-49.504 0-89.6-40.096-89.6-89.6s40.096-89.6 89.6-89.6c49.504 0 89.6 40.096 89.6 89.6s-40.096 89.6-89.6 89.6z" />
20
+ <glyph unicode="&#xe90a;" glyph-name="hb-icon-reports" d="M42.667 178.59v414.476h170.667v-414.476h-170.667zM554.667 178.59v704.61h170.709v-704.61h-170.709zM810.667 178.59v580.267h170.667v-580.267h-170.667zM298.667 178.59v580.267h170.667v-580.267h-170.667zM981.333 95.695c23.552 0 42.667-18.569 42.667-41.448s-19.115-41.448-42.667-41.448h-938.667c-23.552 0-42.667 18.569-42.667 41.448s19.115 41.448 42.667 41.448h938.667z" />
21
+ <glyph unicode="&#xe90c;" glyph-name="wpmudev-icon-cross" d="M512 520.408l-117.396 117.396c-19.995 19.995-52.413 19.995-72.408 0s-19.995-52.413 0-72.408l117.396-117.396-117.396-117.396c-19.995-19.995-19.995-52.413 0-72.408s52.413-19.995 72.408 0l117.396 117.396 117.396-117.396c19.995-19.995 52.413-19.995 72.408 0s19.995 52.413 0 72.408l-117.396 117.396 117.396 117.396c19.995 19.995 19.995 52.413 0 72.408s-52.413 19.995-72.408 0l-117.396-117.396zM512 960c282.77 0 512-229.23 512-512s-229.23-512-512-512c-282.77 0-512 229.23-512 512s229.23 512 512 512z" />
22
+ <glyph unicode="&#xe90d;" glyph-name="wpmudev-icon-info" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512c282.77 0 512 229.23 512 512s-229.23 512-512 512zM563.2 448.472v-205.744c0-27.638-22.923-50.728-51.2-50.728-28.474 0-51.2 22.712-51.2 50.728v205.744c0 27.638 22.923 50.728 51.2 50.728 28.474 0 51.2-22.712 51.2-50.728zM588.8 627.2c0-42.711-34.385-76.8-76.8-76.8-42.711 0-76.8 34.385-76.8 76.8 0 42.711 34.385 76.8 76.8 76.8 42.711 0 76.8-34.385 76.8-76.8z" />
23
+ <glyph unicode="&#xe90e;" glyph-name="wpmudev-icon-tick" d="M512 960c282.77 0 512-229.23 512-512s-229.23-512-512-512c-282.77 0-512 229.23-512 512s229.23 512 512 512zM337.735 469.234c-21.661 18.176-53.956 15.351-72.132-6.311s-15.351-53.956 6.311-72.132l205.624-172.539 265.625 316.559c18.176 21.661 15.351 53.956-6.311 72.132s-53.956 15.351-72.132-6.311l-199.803-238.116-127.181 106.718z" />
24
+ <glyph unicode="&#xe90f;" glyph-name="wpmudev-icon-warning" d="M512-64c-282.77 0-512 229.23-512 512s229.23 512 512 512c282.77 0 512-229.23 512-512s-229.23-512-512-512zM563.2 447.528v205.744c0 27.638-22.923 50.728-51.2 50.728-28.474 0-51.2-22.712-51.2-50.728v-205.744c0-27.638 22.923-50.728 51.2-50.728 28.474 0 51.2 22.712 51.2 50.728zM588.8 268.8c0 42.711-34.385 76.8-76.8 76.8-42.711 0-76.8-34.385-76.8-76.8 0-42.711 34.385-76.8 76.8-76.8 42.711 0 76.8 34.385 76.8 76.8z" />
25
+ </font></defs></svg>
admin/assets/fonts/hummingbird.ttf ADDED
Binary file
admin/assets/fonts/hummingbird.woff ADDED
Binary file
admin/assets/fonts/wphb.eot ADDED
Binary file
admin/assets/fonts/wphb.svg ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata>Generated by IcoMoon</metadata>
5
+ <defs>
6
+ <font id="icomoon" horiz-adv-x="1024">
7
+ <font-face units-per-em="1024" ascent="960" descent="-64" />
8
+ <missing-glyph horiz-adv-x="1024" />
9
+ <glyph unicode="&#x20;" horiz-adv-x="512" d="" />
10
+ <glyph unicode="&#xe900;" glyph-name="hb-black" d="M243.833 739.689c215.087 51.368 249.263-143.657 249.263-143.657s18.679 66.415 57.352 66.415c131.446 0 335.534 30.406 405.165 41.509-90.137 154.223-254.902 256.186-443.482 256.186-151.958 0-288.453-66.206-382.213-171.347zM414.955 25.971s4.531 48.428 90.836 170.465c-181.569 86.478-172.644 284.235-172.644 284.235s-51.368 100.487-113.874 231.484l-106.333 56.591c-70.355-86.948-112.947-198.882-112.947-320.763 0-282.741 229.207-511.948 511.948-511.948 0.015 0 0.029 0 0.044 0h2.592zM626.306 377.97c23.799-252.238-43.862-177.833-49.95-437.958 253.747 33.26 447.628 248.132 447.628 508.288 0 28.158-2.271 55.786-6.641 82.709-151.702-62.653-358.211-142.109-391.038-153.039z" />
11
+ </font></defs></svg>
admin/assets/fonts/wphb.ttf ADDED
Binary file
admin/assets/fonts/wphb.woff ADDED
Binary file
admin/assets/image/dev-team.png ADDED
Binary file
admin/assets/image/dev-team@2x.png ADDED
Binary file
admin/assets/image/graphic-hb-minify-summary.png ADDED
Binary file
admin/assets/image/graphic-hb-minify-summary@2x.png ADDED
Binary file
admin/assets/image/hb-graphic-dash-top.png ADDED
Binary file
admin/assets/image/hb-graphic-dash-top@2x.png ADDED
Binary file
admin/assets/image/hb-graphic-reports-disabled@1x.png ADDED
Binary file
admin/assets/image/hb-graphic-reports-disabled@2x.png ADDED
Binary file
admin/assets/image/hb-graphic-upsell-reports.png ADDED
Binary file
admin/assets/image/hb-graphic-upsell-reports@2x.png ADDED
Binary file
admin/assets/image/hb-graphic-upsell-uptime.png ADDED
Binary file
admin/assets/image/hb-graphic-upsell-uptime@2x.png ADDED
Binary file
admin/assets/image/hb-graphic-uptime-disabled@1x.png ADDED
Binary file
admin/assets/image/hb-graphic-uptime-disabled@2x.png ADDED
Binary file
admin/assets/image/hb-graphic-uptime-up.png ADDED
Binary file
admin/assets/image/hb-graphic-uptime-up@2x.png ADDED
Binary file
admin/assets/image/hummingbird-circle.png ADDED
Binary file
admin/assets/image/hummingbird-circle@1x.jpg ADDED
Binary file
admin/assets/image/hummingbird-modal-quicksetup.png ADDED
Binary file
admin/assets/image/hummingbird-modal-quicksetup@2x.png ADDED
Binary file
admin/assets/image/hummingbird-upsell-minify.png ADDED
Binary file
admin/assets/image/hummingbird-upsell-minify@2x.png ADDED
Binary file
admin/assets/image/icon-uptime-small.png ADDED
Binary file
admin/assets/image/icon-uptime.png ADDED
Binary file
admin/assets/image/loading.gif ADDED
Binary file
admin/assets/image/smush-share-widget.png ADDED
Binary file
admin/assets/image/smush-share-widget@2x.png ADDED
Binary file
admin/assets/image/spin.gif ADDED
Binary file
admin/assets/image/uptime-average-response-time-placeholder.png ADDED
Binary file
admin/assets/image/websiteup.png ADDED
Binary file
admin/assets/js/admin.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ !function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,i){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:i})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=28)}([function(e,t,n){"use strict";function i(){function e(e){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"GET";i.nonce=n,i.action=e;var s={data:i,method:o};return s.url=t,new Promise(function(e,t){jQuery.ajax(s).done(e).fail(t)}).then(function(e){return r(e)})}var t=ajaxurl,n=wphb.nonces.HBFetchNonce,i={caching:{setExpiration:function(t,n){return e("wphb_caching_set_expiration",{type:t,value:n},"POST")},setServer:function(t){return e("wphb_caching_set_server_type",{value:t},"POST")},reloadSnippets:function(t){return e("wphb_caching_reload_snippet",{type:t},"POST").then(function(e){return e})}},cloudflare:{connect:function(t,n,i){return e("wphb_cloudflare_connect",{step:t,formData:n,cfData:i},"POST").then(function(e){return e})},setExpiration:function(t){return e("wphb_cloudflare_set_expiry",{value:t},"POST")},purgeCache:function(){return e("wphb_cloudflare_purge_cache",{},"POST")}},dashboard:{toggleMinification:function(t){return e("wphb_dash_toggle_network_minification",{value:t},"POST")},skipSetup:function(){return e("wphb_dash_skip_setup",{},"POST")}},minification:{toggleCDN:function(t){return e("wphb_minification_toggle_cdn",{value:t},"POST")},toggleMinification:function(t){return e("wphb_minification_toggle_minification",{value:t},"POST")},startCheck:function(t){return e("wphb_minification_start_check",{progress:t},"POST").then(function(e){return e})},checkStep:function(t,n){return e("wphb_minification_check_step",{progress:t,step:n},"POST").then(function(e){return e})},cancelScan:function(){return e("wphb_minification_cancel_scan",{},"POST")}},performance:{runTest:function(){return e("wphb_performance_run_test",{},"POST").then(function(e){return e})},addRecipient:function(t,n){return e("wphb_pro_performance_add_recipient",{email:t,name:n},"POST").then(function(e){return e})},saveReportsSettings:function(t){return e("wphb_pro_performance_save_reports_settings",{data:t},"POST")}}};(0,c.default)(this,i)}function r(e){if("object"!==(void 0===e?"undefined":o(e))&&(e=JSON.parse(e)),e.success)return e.data;var t=e.data||{},n=new Error(t.message||"Error trying to fetch response from server");throw n.response=e,n}Object.defineProperty(t,"__esModule",{value:!0});var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},s=n(58),c=function(e){return e&&e.__esModule?e:{default:e}}(s),a=new i;t.default=a},function(e,t,n){function i(e){return null==e?void 0===e?a:c:u&&u in Object(e)?o(e):s(e)}var r=n(6),o=n(46),s=n(52),c="[object Null]",a="[object Undefined]",u=r?r.toStringTag:void 0;e.exports=i},function(e,t,n){var i=n(10),r="object"==typeof self&&self&&self.Object===Object&&self,o=i||r||Function("return this")();e.exports=o},function(e,t,n){function i(e){return null!=e&&o(e.length)&&!r(e)}var r=n(15),o=n(16);e.exports=i},function(e,t){function n(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}e.exports=n},function(e,t){function n(e){return null!=e&&"object"==typeof e}e.exports=n},function(e,t,n){var i=n(2),r=i.Symbol;e.exports=r},function(e,t,n){function i(e,t,n){var i=e[t];c.call(e,t)&&o(i,n)&&(void 0!==n||t in e)||r(e,t,n)}var r=n(8),o=n(13),s=Object.prototype,c=s.hasOwnProperty;e.exports=i},function(e,t,n){function i(e,t,n){"__proto__"==t&&r?r(e,t,{configurable:!0,enumerable:!0,value:n,writable:!0}):e[t]=n}var r=n(9);e.exports=i},function(e,t,n){var i=n(45),r=function(){try{var e=i(Object,"defineProperty");return e({},"",{}),e}catch(e){}}();e.exports=r},function(e,t,n){(function(t){var n="object"==typeof t&&t&&t.Object===Object&&t;e.exports=n}).call(t,n(66))},function(e,t){function n(e,t){return!!(t=null==t?i:t)&&("number"==typeof e||r.test(e))&&e>-1&&e%1==0&&e<t}var i=9007199254740991,r=/^(?:0|[1-9]\d*)$/;e.exports=n},function(e,t){function n(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||i)}var i=Object.prototype;e.exports=n},function(e,t){function n(e,t){return e===t||e!==e&&t!==t}e.exports=n},function(e,t){function n(e){return e}e.exports=n},function(e,t,n){function i(e){if(!o(e))return!1;var t=r(e);return t==c||t==a||t==s||t==u}var r=n(1),o=n(4),s="[object AsyncFunction]",c="[object Function]",a="[object GeneratorFunction]",u="[object Proxy]";e.exports=i},function(e,t){function n(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=i}var i=9007199254740991;e.exports=n},function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},function(e,t,n){"use strict";jQuery(document).ready(function(){WPHB_Admin.init()})},function(e,t,n){"use strict";var i=n(0),r=function(e){return e&&e.__esModule?e:{default:e}}(i);!function(e){WPHB_Admin.caching={module:"caching",selectedServer:"",$serverSelector:null,$serverInstructions:[],$expirySelectors:[],$snippets:[],init:function(){var t=this,n=e("#wphb-box-caching-enable"),i=n.find(".box-content"),o=i.find(".spinner"),s=n.find(".box-footer");return wphbCachingStrings&&(t.strings=wphbCachingStrings),this.$serverSelector=e("#wphb-server-type"),this.selectedServer=this.$serverSelector.val(),t.$snippets.apache=e("#wphb-code-snippet-apache").find("pre").first(),t.$snippets.nginx=e("#wphb-code-snippet-nginx").find("pre").first(),e(".wphb-server-instructions").each(function(){t.$serverInstructions[e(this).data("server")]=e(this)}),e(".wphb-expiry-select").each(function(){var n=e(this).data("type");n&&e(this).change(function(){i.find(".wphb-content").hide(),s.hide(),o.fadeIn(),e(".wphb-notice").hide(),function(i){var o=e(i).val();r.default.caching.setExpiration(n,o).then(function(){t.reloadSnippets()})}(this)})}),this.showServerInstructions(this.selectedServer),this.$serverSelector.change(function(){var n=e(this).val();t.hideCurrentInstructions(),t.showServerInstructions(n),t.setServer(n),t.selectedServer=n}),e("#toggle-apache-instructions").click(function(t){t.preventDefault(),e(".apache-instructions").slideToggle()}),e("#toggle-litespeed-instructions").click(function(t){t.preventDefault(),e(".litespeed-instructions").slideToggle()}),this},setServer:function(e){r.default.caching.setServer(e)},hideCurrentInstructions:function(){var e=this.selectedServer;this.$serverInstructions[e]&&this.$serverInstructions[e].hide()},showServerInstructions:function(t){void 0!==this.$serverInstructions[t]&&this.$serverInstructions[t].show(),"apache"===t||"LiteSpeed"===t?e("#enable-cache-wrap").show():e("#enable-cache-wrap").hide()},reloadSnippets:function(){var t=this;for(var n in t.$snippets)t.$snippets.hasOwnProperty(n)&&r.default.caching.reloadSnippets(n).then(function(n){t.$snippets[n.type].text(n.code),n.type===t.selectedServer&&("apache"===n.type&&n.updatedFile?(e("#wphb-notice-code-snippet-htaccess-updated").show(),location.href=t.strings.recheckURL+"&caching-updated=true"):"apache"===n.type&&t.strings.cacheEnabled&&!n.updatedFile?(e("#wphb-notice-code-snippet-htaccess-error").show(),location.href=t.strings.htaccessErrorURL):(e("#wphb-notice-code-snippet-updated").show(),location.href=t.strings.recheckURL+"&caching-updated=true"))})}}}(jQuery)},function(e,t,n){"use strict";var i=n(0),r=function(e){return e&&e.__esModule?e:{default:e}}(i);!function(e){WPHB_Admin.cloudflare={module:"cloudflare",$cfSelector:!1,$spinner:!1,init:function(){this.$spinner=e(".wphb-spinner"),this.$cfSelector=e("#wphb-caching-cloudflare-summary-set-expiry");var t=this;return wphb.cloudflare.is.connected&&this.$cfSelector.change(function(){t.setExpiry.call(t,[this])}),this},setExpiry:function(t){this.displaySpinner();var n=e(t).val();r.default.cloudflare.setExpiration(n).then(function(){window.location.reload()})},displaySpinner:function(){this.$spinner.css("visibility","visible")}}}(jQuery)},function(e,t,n){"use strict";var i=n(0),r=function(e){return e&&e.__esModule?e:{default:e}}(i);!function(e){WPHB_Admin.DashboardCloudFlare={init:function(t){this.currentStep=t.currentStep,this.data=t,this.email=t.email,this.apiKey=t.apiKey,this.$stepsContainer=e("#cloudflare-steps"),this.$infoBox=e("#cloudflare-info"),this.$spinner=e(".cloudflare-spinner"),this.$deactivateButton=e("#wphb-box-dashboard-cloudflare").find(".box-title .buttons"),this.renderStep(this.currentStep),e("body").on("click",".cloudflare-clear-cache .button",function(t){t.preventDefault(),this.purgeCache.apply(e(t.target),[this])}.bind(this))},purgeCache:function(t){var n=this;n.attr("disabled",!0),t.showSpinner(),r.default.cloudflare.purgeCache().then(function(){var i=e("#wphb-notice-cloudflare-purge-cache");window.scrollTo(0,0),i.slideDown(),setTimeout(function(){i.slideUp()},5e3),n.removeAttr("disabled"),t.hideSpinner()})},renderStep:function(t){var n=WPHB_Admin.DashboardCloudFlare.template("#cloudflare-step-"+t),i=n(this.data),r=this;i&&(this.currentStep=t,this.$stepsContainer.hide().html(n(this.data)).fadeIn().find("form").on("submit",function(t){t.preventDefault(),r.submitStep.call(r,e(this))}),this.$spinner=this.$stepsContainer.find(".cloudflare-spinner")),this.bindEvents()},bindEvents:function(){var t=e("#cloudflare-how-to");t.hide(),e("#cloudflare-how-to-title > a").click(function(e){e.preventDefault(),t.toggle()}),this.$stepsContainer.find("select").each(function(){WDP.wpmuSelect(this)}),"final"===this.currentStep?this.$deactivateButton.removeClass("hidden"):this.$deactivateButton.addClass("hidden")},emptyInfoBox:function(){this.$infoBox.html(""),this.$infoBox.removeClass()},showInfoBox:function(e){this.$infoBox.addClass("wphb-notice"),this.$infoBox.addClass("wphb-notice-error"),this.$infoBox.text(e)},showSpinner:function(){this.$spinner.css("visibility","visible")},hideSpinner:function(){this.$spinner.css("visibility","hidden")},submitStep:function(e){var t=this;e.find("input[type=submit]").attr("disabled","true"),this.emptyInfoBox(),this.showSpinner(),r.default.cloudflare.connect(this.currentStep,e.serialize(),this.data).then(function(e){t.data=e.newData,t.renderStep(e.nextStep),"final"===e.nextStep&&(window.location.href=e.redirect)}).catch(function(e){t.showInfoBox(e)}),e.find("input[type=submit]").removeAttr("disabled"),t.hideSpinner()}},WPHB_Admin.DashboardCloudFlare.template=_.memoize(function(t){var n=void 0,i={evaluate:/<#([\s\S]+?)#>/g,interpolate:/\{\{\{([\s\S]+?)\}\}\}/g,escape:/\{\{([^\}]+?)\}\}(?!\})/g,variable:"data"};return function(r){return _.templateSettings=i,(n=n||_.template(e(t).html()))(r)}})}(jQuery)},function(e,t,n){"use strict";var i=n(0),r=function(e){return e&&e.__esModule?e:{default:e}}(i);!function(e){WPHB_Admin.dashboard={module:"dashboard",init:function(){var t=this;return wphbDashboardStrings&&(this.strings=wphbDashboardStrings),e("#wphb-activate-minification").change(function(){var n=e(this).val();r.default.dashboard.toggleMinification(n).then(function(){var i=e('input[name="use_cdn"]');"false"===n?(i.prop("checked",!1),i.prop("disabled",!0)):i.prop("disabled",!1),t.showNotice()})}),e("#use_cdn").change(function(){var n=e(this).is(":checked");r.default.minification.toggleCDN(n).then(function(){t.showNotice()})}),e(".wphb-performance-report-item").click(function(){var t=e(this).data("performance-url");t&&(location.href=t)}),this},showNotice:function(){var t=e("#wphb-notice-minification-settings-updated");t.slideDown(),setTimeout(function(){t.slideUp()},5e3)},startQuickSetup:function(){WDP.showOverlay("#wphb-quick-setup-modal",{class:"wphb-modal small wphb-quick-setup-modal no-close"})},skipSetup:function(){r.default.dashboard.skipSetup().then(function(){window.location.reload(!0)})},runPerformanceTest:function(){WDP.showOverlay("#run-performance-test-modal",{class:"wphb-modal small wphb-progress-modal no-close"}),WPHB_Admin.getModule("performance").performanceTest(this.strings.finishedTestURLsLink)}}}(jQuery)},function(e,t,n){"use strict";var i=n(0),r=function(e){return e&&e.__esModule?e:{default:e}}(i);!function(e){WPHB_Admin.gzip={module:"gzip",selectedServer:"",$serverSelector:null,$serverInstructions:[],init:function(){var t=this;return this.$serverSelector=e("#wphb-server-type"),this.selectedServer=this.$serverSelector.val(),e(".wphb-server-instructions").each(function(){t.$serverInstructions[e(this).data("server")]=e(this)}),this.showServerInstructions(this.selectedServer),this.$serverSelector.change(function(){var n=e(this).val();t.hideCurrentInstructions(),t.showServerInstructions(n),t.setServer(n),t.selectedServer=n}),e("#toggle-apache-instructions").click(function(t){t.preventDefault(),e(".apache-instructions").toggle()}),e("#toggle-litespeed-instructions").click(function(t){t.preventDefault(),e(".litespeed-instructions").toggle()}),this},hideCurrentInstructions:function(){var e=this.selectedServer;this.$serverInstructions[e]&&this.$serverInstructions[e].hide()},showServerInstructions:function(t){void 0!==this.$serverInstructions[t]&&this.$serverInstructions[t].show(),"apache"===t||"LiteSpeed"===t?e("#enable-cache-wrap").show():e("#enable-cache-wrap").hide()},setServer:function(e){r.default.caching.setServer(e)}}}(jQuery)},function(e,t,n){"use strict";!function(e){var t={modules:[],init:function(){function t(e){var t=e.find(".wphb-score-result-label"),n=parseInt(t.text(),10)||100,i=e.find(".wphb-score-graph-result"),r=void 0,o=void 0,s=void 0;r=i.attr("r"),o=Math.PI*(2*r),n<0&&(n=0),n>100&&(n=100),s=(100-n)/100*o,i.css({strokeDashoffset:s})}function n(){e(".wphb-performance-report-overall-score").each(function(){t(e(this))}),e(".wphb-performance-report-current-score").each(function(){t(e(this))}),e(".wphb-performance-report-item-score").each(function(){t(e(this))})}window.register_events_performance=function(){setTimeout(n,500)},e(function(){setTimeout(n,500)})},initModule:function(e){return this.hasOwnProperty(e)?(this.modules[e]=this[e].init(),this.modules[e]):{}},getModule:function(e){return void 0!==this.modules[e]?this.modules[e]:this.initModule(e)}};t.utils={membershipModal:{open:function(){e("#wphb-upgrade-membership-modal-link").trigger("click")}},post:function(t,n){return t.action="wphb_ajax",t.module=n,e.ajax({url:ajaxurl,method:"POST",data:t})}},t.notices={init:function(){e(".wphb-notice:not(.notice) a.wphb-dismiss").click(function(t){t.preventDefault();e(this).data("id"),e(this).data("nonce");e(this).parent(".error").hide()})}},window.WPHB_Admin=t}(jQuery)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}var r=n(0),o=i(r),s=n(31),c=n(29),a=i(c),u=n(30),l=i(u);!function(e){WPHB_Admin.minification={$checkFilesButton:null,$checkFilesResultsContainer:null,module:"minification",checkURLSList:null,checkedURLS:0,$spinner:null,init:function(){var t=this;e("#wphb-minification-filter-button").on("click",function(t){t.preventDefault(),e("#wphb-minification-filter").toggle("slow")}),this.$checkFilesButton=e("#check-files"),this.$disableMinification=e("#wphb-disable-minification"),this.$spinner=e(".spinner"),this.$checkFilesButton.length&&this.$checkFilesButton.click(function(n){n.preventDefault(),e(this).attr("disabled",!0),t.checkFiles((0,s.getLink)("minification"))}),e(".wphb-discard").click(function(e){return e.preventDefault(),confirm((0,s.__)("discardAlert"))&&location.reload(),!1}),e(".wphb-enqueued-files input").on("change",function(){e(".wphb-discard").attr("disabled",!1)}),e("#use_cdn").change(function(){var t=e(this).is(":checked");o.default.minification.toggleCDN(t).then(function(){var t=e("#wphb-notice-minification-advanced-settings-updated");t.slideDown(),setTimeout(function(){t.slideUp()},5e3)})}),this.$disableMinification.change(function(){var n=e(this).is(":checked");t.$spinner.css("visibility","visible"),t.timer&&n&&(clearTimeout(t.timer),t.$spinner.css("visibility","hidden")),t.timer=setTimeout(function(){o.default.minification.toggleMinification(n).then(function(){location.reload()})},3e3)}),this.rowsCollection=new WPHB_Admin.minification.RowsCollection,e(".wphb-border-row").each(function(n,i){var r=void 0;r=e(i).data("filter-secondary")?new WPHB_Admin.minification.Row(e(i),e(i).data("filter"),e(i).data("filter-secondary")):new WPHB_Admin.minification.Row(e(i),e(i).data("filter")),t.rowsCollection.push(r)}),e("#wphb-s").keyup(function(){t.rowsCollection.addFilter(e(this).val(),"primary"),t.rowsCollection.applyFilters()}),e("#wphb-secondary-filter").change(function(){t.rowsCollection.addFilter(e(this).val(),"secondary"),t.rowsCollection.applyFilters()}),e(".filter-toggles").change(function(){var n=e(this),i=n.data("toggles"),r=n.prop("checked"),o=t.rowsCollection.getVisibleItems();for(var s in o)o[s].change(i,r)}),e("input.wphb-minification-file-selector").click(function(){var n=e(this),i=t.rowsCollection.getItemById(n.data("type"),n.data("handle"));i&&(n.is(":checked")?i.select():i.unSelect())}),e("#minification-bulk-file").click(function(){var n=e(this),i=t.rowsCollection.getItems();for(var r in i)i.hasOwnProperty(r)&&(n.is(":checked")?i[r].select():i[r].unSelect())}),e(".toggle-cross").on("click",function(){var n=e(this),i=n.find("input.toggle-include"),r=t.rowsCollection.getItemById(n.data("type"),n.data("handle"));r&&(r.change("include",!i.prop("checked")),r.getElement().find("input:not(.toggle-include)").prop("disabled",!i.prop("checked")))});var n=e("input[type=checkbox][name=use_cdn]");n.change(function(){var t=e(this).prop("checked");n.each(function(){this.checked=t})}),e("body").on("click",".wphb-minification-file-details",function(){window.innerWidth<783&&e(this).parent().find(".wphb-minification-row-details").toggle("slow")});var i=_.debounce(function(){window.innerWidth>=783?e(".wphb-minification-row-details").css("display","flex"):e(".wphb-minification-row-details").css("display","none")},250);return window.addEventListener("resize",i),this},checkFiles:function(t){var n=this,i=this;if(void 0===t&&(t=!1),i.minificationStarted){var r=sessionStorage.getItem("progress"),s=Math.round(80/sessionStorage.getItem("steps"));o.default.minification.checkStep(r,s).then(function(r){if(void 0!==r.finished){if(r.finished&&t)sessionStorage.clear(),n.updateProgressBar(100),!0===r.show_cdn&&e("#enable-cdn-modal").length?WDP.showOverlay("#enable-cdn-modal",{class:"wphb-modal small wphb-progress-modal no-close"}):window.location.href=t;else if(!r.finished){var o=parseInt(sessionStorage.getItem("progress"))+Math.round(80/sessionStorage.getItem("steps"));sessionStorage.setItem("progress",o),n.updateProgressBar(o),window.setTimeout(function(){i.checkFiles(t)},3e3)}}else window.location.href=t})}else{null===sessionStorage.getItem("progress")&&sessionStorage.setItem("progress",10);var c=sessionStorage.getItem("progress");this.updateProgressBar(c),o.default.minification.startCheck(c).then(function(e){void 0!==e.steps&&null===sessionStorage.getItem("steps")&&sessionStorage.setItem("steps",e.steps),i.minificationStarted=!0,i.checkFiles(t)})}},updateProgressBar:function(t){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];t>100&&(t=100),e(".wphb-scan-progress .wphb-scan-progress-text span").text(t+"%"),t>=90&&e(".wphb-progress-state .wphb-progress-state-text").text("Finalizing..."),n&&e(".wphb-progress-state .wphb-progress-state-text").text("Cancelling..."),e(".wphb-scan-progress .wphb-scan-progress-bar span").width(t+"%")},cancelScan:function(){var e=this;o.default.minification.cancelScan().then(function(){sessionStorage.clear(),e.updateProgressBar(0,!0),window.location.href=(0,s.getLink)("minification")})}},WPHB_Admin.minification.Row=a.default,WPHB_Admin.minification.RowsCollection=l.default}(jQuery)},function(e,t,n){"use strict";var i=n(0),r=function(e){return e&&e.__esModule?e:{default:e}}(i);!function(e){WPHB_Admin.performance={module:"performance",iteration:0,progress:0,init:function(){var t=this,n=e("body");wphbPerformanceStrings&&(this.strings=wphbPerformanceStrings),this.$runTestButton=e("#run-performance-test");var i=e(".performance-report-table");i.off("click","button"),i.on("click","tr.wphb-performance-report-item",function(t){t.preventDefault();var n=e(this).closest(".wphb-performance-report-item"),i=n.nextUntil(".wphb-performance-report-item");i.toggleClass("wphb-performance-report-item-additional-content-opened"),i.hasClass("wphb-performance-report-item-additional-content-opened")?n.addClass("wphb-performance-report-item-opened"):n.removeClass("wphb-performance-report-item-opened")}),this.$runTestButton.length&&this.$runTestButton.click(function(n){n.preventDefault(),e(this).attr("disabled",!0),t.performanceTest(t.strings.finishedTestURLsLink)});var o=window.location.hash;if(o){var s=e(o);s.length&&s.find(".trigger-additional-content").trigger("click")}return e('select[name="email-frequency"]').change(function(){"1"===e(this).val()?e(this).closest(".schedule-box").find("div.days-container").hide():e(this).closest(".schedule-box").find("div.days-container").show()}).change(),n.on("click",".wphb-remove-recipient",function(t){t.preventDefault(),e(this).closest(".recipient").remove(),e(".scan-settings").find("input[id='scan_recipient'][value="+e(this).attr("data-id")+"]").remove()}),e("#add-receipt").click(function(){var n=e("#wphb-username-search").val(),i=e("#wphb-first-name").val();return r.default.performance.addRecipient(n,i).then(function(i){var r=e('<div class="recipient"/>'),o=e("<img/>").attr({src:i.avatar,width:"30"}),s=e("<span/>").html(i.name);r.append('<span class="name"/>'),r.find(".name").append(o,s),r.append(e('<span class="email"/>').html(n)),r.append(e("<a/>").attr({"data-id":i.user_id,class:"remove float-r wphb-remove-recipient",href:"#",alt:t.strings.removeButtonText}).html('<i class="dev-icon dev-icon-cross"></i>')),e("<input>").attr({type:"hidden",id:"scan_recipient",name:"email-recipients[]",value:JSON.stringify({email:i.email,name:i.name})}).appendTo(r),e(".receipt .recipients").append(r),e("#wphb-username-search").val(""),e("#wphb-first-name").val("")}).catch(function(e){alert(e.message)}),!1}),n.on("submit",".scan-frm",function(n){n.preventDefault();var i=e(this).serialize(),o=e(this);return o.find(".button").attr("disabled","disabled"),r.default.performance.saveReportsSettings(i).then(function(){o.find(".button").removeAttr("disabled"),t.showUpdateMessage()}),!1}),this},showUpdateMessage:function(){var t=e("#wphb-notice-performance-report-settings-updated");window.scrollTo(0,0),t.slideDown(),setTimeout(function(){t.slideUp()},5e3)},performanceTest:function(e){var t=this;void 0===e&&(e=!1),t.updateProgressBar(),r.default.performance.runTest().then(function(n){n.finished?e&&(window.location=e):window.setTimeout(function(){t.performanceTest(e)},5e3)})},updateProgressBar:function(){this.progress<90&&(this.progress+=35),this.progress>100&&(this.progress=90),e(".wphb-scan-progress .wphb-scan-progress-text span").text(this.progress+"%"),e(".wphb-scan-progress .wphb-scan-progress-bar span").attr("style","width:"+this.progress+"%")}}}(jQuery)},function(e,t,n){"use strict";!function(e){WPHB_Admin.uptime={module:"uptime",$dataRangeSelector:null,chartData:null,timer:null,$spinner:null,init:function(){this.$spinner=e(".spinner"),this.strings=wphbUptimeStrings,this.$dataRangeSelector=e("#wphb-uptime-data-range"),this.chartData=e("#uptime-chart-json").val(),this.$disableUptime=e("#wphb-disable-uptime"),this.$dataRangeSelector.change(function(){window.location.href=e(this).find(":selected").data("url")});var t=this;this.$disableUptime.change(function(){t.$spinner.css("visibility","visible"),e(this).is(":checked")&&t.timer?(clearTimeout(t.timer),t.$spinner.css("visibility","hidden")):t.timer=setTimeout(function(){location.href=t.strings.disableUptimeURL},3e3)}),this.drawChart(),e("#uptime-re-check-status").on("click",function(e){e.preventDefault(),location.reload()})},drawChart:function(){var t=new google.visualization.DataTable;t.addColumn("datetime","Day"),t.addColumn("number","Response Time (ms)");for(var n=JSON.parse(this.chartData),i=0;i<n.length;i++)n[i][0]=new Date(n[i][0]),n[i][1]=Math.round(n[i][1]),0==Math.round(n[i][1])&&(n[i][1]=-100);t.addRows(n);var r={chartArea:{left:80,top:20,width:"90%",height:"90%"},colors:["#24ADE5"],curveType:"function",legend:{position:"none"},vAxis:{format:"#,### ms",viewWindow:{min:0}},tooltip:{isHtml:!0},series:{0:{axis:"Resp"}},axes:{y:{Resp:{label:"Response Time (ms)"}}}},o=new google.visualization.LineChart(document.getElementById("uptime-chart"));o.draw(t,r),e(window).resize(function(){o.draw(t,r)})}}}(jQuery)},function(e,t,n){"use strict";n(24),n(26),n(23),n(19),n(25),n(22),n(21),n(27),n(20),n(18)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(e,t,n){var i=e,r=t.toLowerCase(),o=!1,s=!1,c=!0,a=i.find(".toggle-include"),u=i.find(".toggle-combine"),l=i.find(".toggle-minify"),f=i.find(".toggle-position-footer"),p=i.find(".toggle-cross > i");return n&&(o=n.toLowerCase()),{hide:function(){i.addClass("out-of-filter"),c=!1},show:function(){i.removeClass("out-of-filter"),c=!0},getElement:function(){return i},getId:function(){return i.attr("id")},getFilter:function(){return r},matchFilter:function(e){return""===e||(e=e.toLowerCase(),r.search(e)>-1)},matchSecondaryFilter:function(e){return""===e||!!o&&(e=e.toLowerCase(),o===e)},isVisible:function(){return c},isSelected:function(){return s},select:function(){s=!0},unSelect:function(){s=!1},change:function(e,t){switch(e){case"minify":l.prop("checked",t);break;case"combine":u.prop("checked",t);break;case"include":p.removeClass(),a.prop("checked",t),t?(i.removeClass("disabled"),p.addClass("dev-icon dev-icon-cross"),a.attr("checked",!0)):(i.addClass("disabled"),p.addClass("wdv-icon wdv-icon-refresh"),a.removeAttr("checked"));break;case"footer":f.prop("checked",t)}}}};t.default=i},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r=function(){var e=[],t="",n="";return{push:function(t){"object"===(void 0===t?"undefined":i(t))&&e.push(t)},getItems:function(){return e},getItem:function(t){return!!e[t]&&e[t]},getItemById:function(t,n){var i=!1;for(var r in e)if("wphb-file-"+t+"-"+n===e[r].getId()){i=e[r];break}return i},getVisibleItems:function(){var t=[];for(var n in e)e[n].isVisible()&&t.push(e[n]);return t},getSelectedItems:function(){var t=[];for(var n in e)e[n].isVisible()&&e[n].isSelected()&&t.push(e[n]);return t},addFilter:function(e,i){"secondary"===i?n=e:t=e},applyFilters:function(){for(var i in e)e[i]&&(e[i].matchFilter(t)&&e[i].matchSecondaryFilter(n)?e[i].show():e[i].hide())}}};t.default=r},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});t.__=function(e){return wphb.strings[e]||""},t.getLink=function(e){return wphb.links[e]||""}},function(e,t){function n(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}e.exports=n},function(e,t,n){function i(e,t){var n=s(e),i=!n&&o(e),l=!n&&!i&&c(e),p=!n&&!i&&!l&&u(e),d=n||i||l||p,h=d?r(e.length,String):[],v=h.length;for(var b in e)!t&&!f.call(e,b)||d&&("length"==b||l&&("offset"==b||"parent"==b)||p&&("buffer"==b||"byteLength"==b||"byteOffset"==b)||a(b,v))||h.push(b);return h}var r=n(40),o=n(60),s=n(61),c=n(62),a=n(11),u=n(63),l=Object.prototype,f=l.hasOwnProperty;e.exports=i},function(e,t,n){function i(e){return o(e)&&r(e)==s}var r=n(1),o=n(5),s="[object Arguments]";e.exports=i},function(e,t,n){function i(e){return!(!s(e)||o(e))&&(r(e)?h:u).test(c(e))}var r=n(15),o=n(49),s=n(4),c=n(57),a=/[\\^$.*+?()[\]{}|]/g,u=/^\[object .+?Constructor\]$/,l=Function.prototype,f=Object.prototype,p=l.toString,d=f.hasOwnProperty,h=RegExp("^"+p.call(d).replace(a,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=i},function(e,t,n){function i(e){return s(e)&&o(e.length)&&!!c[r(e)]}var r=n(1),o=n(16),s=n(5),c={};c["[object Float32Array]"]=c["[object Float64Array]"]=c["[object Int8Array]"]=c["[object Int16Array]"]=c["[object Int32Array]"]=c["[object Uint8Array]"]=c["[object Uint8ClampedArray]"]=c["[object Uint16Array]"]=c["[object Uint32Array]"]=!0,c["[object Arguments]"]=c["[object Array]"]=c["[object ArrayBuffer]"]=c["[object Boolean]"]=c["[object DataView]"]=c["[object Date]"]=c["[object Error]"]=c["[object Function]"]=c["[object Map]"]=c["[object Number]"]=c["[object Object]"]=c["[object RegExp]"]=c["[object Set]"]=c["[object String]"]=c["[object WeakMap]"]=!1,e.exports=i},function(e,t,n){function i(e){if(!r(e))return o(e);var t=[];for(var n in Object(e))c.call(e,n)&&"constructor"!=n&&t.push(n);return t}var r=n(12),o=n(50),s=Object.prototype,c=s.hasOwnProperty;e.exports=i},function(e,t,n){function i(e,t){return s(o(e,t,r),e+"")}var r=n(14),o=n(54),s=n(55);e.exports=i},function(e,t,n){var i=n(59),r=n(9),o=n(14),s=r?function(e,t){return r(e,"toString",{configurable:!0,enumerable:!1,value:i(t),writable:!0})}:o;e.exports=s},function(e,t){function n(e,t){for(var n=-1,i=Array(e);++n<e;)i[n]=t(n);return i}e.exports=n},function(e,t){function n(e){return function(t){return e(t)}}e.exports=n},function(e,t,n){function i(e,t,n,i){var s=!n;n||(n={});for(var c=-1,a=t.length;++c<a;){var u=t[c],l=i?i(n[u],e[u],u,n,e):void 0;void 0===l&&(l=e[u]),s?o(n,u,l):r(n,u,l)}return n}var r=n(7),o=n(8);e.exports=i},function(e,t,n){var i=n(2),r=i["__core-js_shared__"];e.exports=r},function(e,t,n){function i(e){return r(function(t,n){var i=-1,r=n.length,s=r>1?n[r-1]:void 0,c=r>2?n[2]:void 0;for(s=e.length>3&&"function"==typeof s?(r--,s):void 0,c&&o(n[0],n[1],c)&&(s=r<3?void 0:s,r=1),t=Object(t);++i<r;){var a=n[i];a&&e(t,a,i,s)}return t})}var r=n(38),o=n(48);e.exports=i},function(e,t,n){function i(e,t){var n=o(e,t);return r(n)?n:void 0}var r=n(35),o=n(47);e.exports=i},function(e,t,n){function i(e){var t=s.call(e,a),n=e[a];try{e[a]=void 0;var i=!0}catch(e){}var r=c.call(e);return i&&(t?e[a]=n:delete e[a]),r}var r=n(6),o=Object.prototype,s=o.hasOwnProperty,c=o.toString,a=r?r.toStringTag:void 0;e.exports=i},function(e,t){function n(e,t){return null==e?void 0:e[t]}e.exports=n},function(e,t,n){function i(e,t,n){if(!c(n))return!1;var i=typeof t;return!!("number"==i?o(n)&&s(t,n.length):"string"==i&&t in n)&&r(n[t],e)}var r=n(13),o=n(3),s=n(11),c=n(4);e.exports=i},function(e,t,n){function i(e){return!!o&&o in e}var r=n(43),o=function(){var e=/[^.]+$/.exec(r&&r.keys&&r.keys.IE_PROTO||"");return e?"Symbol(src)_1."+e:""}();e.exports=i},function(e,t,n){var i=n(53),r=i(Object.keys,Object);e.exports=r},function(e,t,n){(function(e){var i=n(10),r="object"==typeof t&&t&&!t.nodeType&&t,o=r&&"object"==typeof e&&e&&!e.nodeType&&e,s=o&&o.exports===r,c=s&&i.process,a=function(){try{return c&&c.binding&&c.binding("util")}catch(e){}}();e.exports=a}).call(t,n(17)(e))},function(e,t){function n(e){return r.call(e)}var i=Object.prototype,r=i.toString;e.exports=n},function(e,t){function n(e,t){return function(n){return e(t(n))}}e.exports=n},function(e,t,n){function i(e,t,n){return t=o(void 0===t?e.length-1:t,0),function(){for(var i=arguments,s=-1,c=o(i.length-t,0),a=Array(c);++s<c;)a[s]=i[t+s];s=-1;for(var u=Array(t+1);++s<t;)u[s]=i[s];return u[t]=n(a),r(e,this,u)}}var r=n(32),o=Math.max;e.exports=i},function(e,t,n){var i=n(39),r=n(56),o=r(i);e.exports=o},function(e,t){function n(e){var t=0,n=0;return function(){var s=o(),c=r-(s-n);if(n=s,c>0){if(++t>=i)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}var i=800,r=16,o=Date.now;e.exports=n},function(e,t){function n(e){if(null!=e){try{return r.call(e)}catch(e){}try{return e+""}catch(e){}}return""}var i=Function.prototype,r=i.toString;e.exports=n},function(e,t,n){var i=n(7),r=n(42),o=n(44),s=n(3),c=n(12),a=n(64),u=Object.prototype,l=u.hasOwnProperty,f=o(function(e,t){if(c(t)||s(t))return void r(t,a(t),e);for(var n in t)l.call(t,n)&&i(e,n,t[n])});e.exports=f},function(e,t){function n(e){return function(){return e}}e.exports=n},function(e,t,n){var i=n(34),r=n(5),o=Object.prototype,s=o.hasOwnProperty,c=o.propertyIsEnumerable,a=i(function(){return arguments}())?i:function(e){return r(e)&&s.call(e,"callee")&&!c.call(e,"callee")};e.exports=a},function(e,t){var n=Array.isArray;e.exports=n},function(e,t,n){(function(e){var i=n(2),r=n(65),o="object"==typeof t&&t&&!t.nodeType&&t,s=o&&"object"==typeof e&&e&&!e.nodeType&&e,c=s&&s.exports===o,a=c?i.Buffer:void 0,u=a?a.isBuffer:void 0,l=u||r;e.exports=l}).call(t,n(17)(e))},function(e,t,n){var i=n(36),r=n(41),o=n(51),s=o&&o.isTypedArray,c=s?r(s):i;e.exports=c},function(e,t,n){function i(e){return s(e)?r(e):o(e)}var r=n(33),o=n(37),s=n(3);e.exports=i},function(e,t){function n(){return!1}e.exports=n},function(e,t){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(n=window)}e.exports=n}]);
2
+ //# sourceMappingURL=admin.min.js.map
admin/assets/js/admin.min.js.map ADDED
@@ -0,0 +1 @@
 
1
+ {"version":3,"sources":["webpack:///admin.min.js","webpack:///webpack/bootstrap 1371ae49cdc9501be886","webpack:///./_src/admin/js/utils/fetcher.js","webpack:///./~/lodash/_baseGetTag.js","webpack:///./~/lodash/_root.js","webpack:///./~/lodash/isArrayLike.js","webpack:///./~/lodash/isObject.js","webpack:///./~/lodash/isObjectLike.js","webpack:///./~/lodash/_Symbol.js","webpack:///./~/lodash/_assignValue.js","webpack:///./~/lodash/_baseAssignValue.js","webpack:///./~/lodash/_defineProperty.js","webpack:///./~/lodash/_freeGlobal.js","webpack:///./~/lodash/_isIndex.js","webpack:///./~/lodash/_isPrototype.js","webpack:///./~/lodash/eq.js","webpack:///./~/lodash/identity.js","webpack:///./~/lodash/isFunction.js","webpack:///./~/lodash/isLength.js","webpack:///(webpack)/buildin/module.js","webpack:///./_src/admin/js/admin-app.js","webpack:///./_src/admin/js/admin-caching.js","webpack:///./_src/admin/js/admin-cloudflare.js","webpack:///./_src/admin/js/admin-dashboard-cloudflare.js","webpack:///./_src/admin/js/admin-dashboard.js","webpack:///./_src/admin/js/admin-gzip.js","webpack:///./_src/admin/js/admin-main.js","webpack:///./_src/admin/js/admin-minification.js","webpack:///./_src/admin/js/admin-performance.js","webpack:///./_src/admin/js/admin-uptime.js","webpack:///./_src/admin/js/index.js","webpack:///./_src/admin/js/minification/Row.js","webpack:///./_src/admin/js/minification/RowsCollection.js","webpack:///./_src/admin/js/utils/helpers.js","webpack:///./~/lodash/_apply.js","webpack:///./~/lodash/_arrayLikeKeys.js","webpack:///./~/lodash/_baseIsArguments.js","webpack:///./~/lodash/_baseIsNative.js","webpack:///./~/lodash/_baseIsTypedArray.js","webpack:///./~/lodash/_baseKeys.js","webpack:///./~/lodash/_baseRest.js","webpack:///./~/lodash/_baseSetToString.js","webpack:///./~/lodash/_baseTimes.js","webpack:///./~/lodash/_baseUnary.js","webpack:///./~/lodash/_copyObject.js","webpack:///./~/lodash/_coreJsData.js","webpack:///./~/lodash/_createAssigner.js","webpack:///./~/lodash/_getNative.js","webpack:///./~/lodash/_getRawTag.js","webpack:///./~/lodash/_getValue.js","webpack:///./~/lodash/_isIterateeCall.js","webpack:///./~/lodash/_isMasked.js","webpack:///./~/lodash/_nativeKeys.js","webpack:///./~/lodash/_nodeUtil.js","webpack:///./~/lodash/_objectToString.js","webpack:///./~/lodash/_overArg.js","webpack:///./~/lodash/_overRest.js","webpack:///./~/lodash/_setToString.js","webpack:///./~/lodash/_shortOut.js","webpack:///./~/lodash/_toSource.js","webpack:///./~/lodash/assign.js","webpack:///./~/lodash/constant.js","webpack:///./~/lodash/isArguments.js","webpack:///./~/lodash/isArray.js","webpack:///./~/lodash/isBuffer.js","webpack:///./~/lodash/isTypedArray.js","webpack:///./~/lodash/keys.js","webpack:///./~/lodash/stubFalse.js","webpack:///(webpack)/buildin/global.js"],"names":["modules","__webpack_require__","moduleId","installedModules","exports","module","i","l","call","m","c","value","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","Fetcher","request","action","data","arguments","length","undefined","method","nonce","fetchNonce","args","url","fetchUrl","Promise","resolve","reject","jQuery","ajax","done","fail","then","response","checkStatus","ajaxurl","wphb","nonces","HBFetchNonce","methods","caching","setExpiration","type","actionPrefix","setServer","reloadSnippets","cloudflare","connect","step","formData","cfData","purgeCache","dashboard","toggleMinification","skipSetup","minification","toggleCDN","startCheck","progress","checkStep","cancelScan","performance","runTest","addRecipient","email","actionPrefixPro","saveReportsSettings","_assign2","default","this","_typeof","JSON","parse","success","error","Error","message","Symbol","iterator","obj","constructor","_assign","HBFetcher","baseGetTag","undefinedTag","nullTag","symToStringTag","getRawTag","objectToString","toStringTag","freeGlobal","freeSelf","self","root","Function","isArrayLike","isLength","isFunction","isObject","isObjectLike","assignValue","key","objValue","eq","baseAssignValue","objectProto","writable","getNative","func","e","global","isIndex","MAX_SAFE_INTEGER","reIsUint","test","isPrototype","Ctor","other","identity","tag","funcTag","genTag","asyncTag","proxyTag","webpackPolyfill","deprecate","paths","children","document","ready","WPHB_Admin","init","_fetcher","_fetcher2","$","selectedServer","$serverSelector","$serverInstructions","$expirySelectors","$snippets","cachingMetabox","cachingContent","find","cachingContentSpinner","cachingFooter","wphbCachingStrings","strings","val","apache","first","nginx","each","change","hide","fadeIn","element","showServerInstructions","hideCurrentInstructions","click","preventDefault","slideToggle","selected","server","show","text","code","updatedFile","location","href","recheckURL","cacheEnabled","htaccessErrorURL","$cfSelector","$spinner","is","connected","setExpiry","selector","displaySpinner","window","reload","css","DashboardCloudFlare","settings","currentStep","apiKey","$stepsContainer","$infoBox","$deactivateButton","renderStep","on","apply","target","bind","$button","attr","showSpinner","$notice","scrollTo","slideDown","setTimeout","slideUp","removeAttr","hideSpinner","template","content","html","submitStep","bindEvents","$howToInstructions","toggle","WDP","wpmuSelect","removeClass","addClass","emptyInfoBox","showInfoBox","$form","serialize","newData","nextStep","redirect","catch","_","memoize","id","compiled","options","evaluate","interpolate","escape","variable","templateSettings","wphbDashboardStrings","CDNcheckbox","prop","showNotice","notice","startQuickSetup","showOverlay","class","runPerformanceTest","getModule","performanceTest","finishedTestURLsLink","gzip","updatePerformanceGraph","$wrap","$item","parseInt","$circle","r","pct","Math","PI","strokeDashoffset","updatePerformanceResultsGraphs","register_events_performance","initModule","utils","membershipModal","open","trigger","post","notices","parent","_interopRequireDefault","_helpers","_Row","_Row2","_RowsCollection","_RowsCollection2","$checkFilesButton","$checkFilesResultsContainer","checkURLSList","checkedURLS","$disableMinification","checkFiles","getLink","confirm","__","cdn_value","timer","clearTimeout","rowsCollection","RowsCollection","index","row","_row","Row","push","keyup","addFilter","applyFilters","what","visibleItems","getVisibleItems","$this","getItemById","select","unSelect","items","getItems","checkbox","getElement","checkboxes","checkedState","checked","innerWidth","minification_resize_rows","debounce","addEventListener","_this","minificationStarted","sessionStorage","getItem","round","finished","clear","updateProgressBar","show_cdn","setItem","steps","cancel","width","_this2","iteration","body","wphbPerformanceStrings","$runTestButton","performanceReportTable","off","getParentPerformanceItem","closest","getNextAdditionalContentRow","nextUntil","toggleClass","hasClass","hash","remove","user_row","img","src","avatar","append","data-id","user_id","alt","removeButtonText","stringify","appendTo","alert","form_data","that","showUpdateMessage","uptime","$dataRangeSelector","chartData","wphbUptimeStrings","$disableUptime","disableUptimeURL","drawChart","google","visualization","DataTable","addColumn","chart_array","Date","addRows","chartArea","left","top","height","colors","curveType","legend","position","vAxis","format","viewWindow","min","tooltip","isHtml","series","0","axis","axes","y","Resp","label","chart","LineChart","getElementById","draw","resize","_element","_filter","_filter_sec","$el","filter","toLowerCase","filterSecondary","visible","$include","$combine","$minify","$posFooter","$disableIcon","getId","getFilter","matchFilter","search","matchSecondaryFilter","isVisible","isSelected","currentFilter","currentSecondaryFilter","getSelectedItems","str","screen","links","thisArg","arrayLikeKeys","inherited","isArr","isArray","isArg","isArguments","isBuff","isBuffer","isType","isTypedArray","skipIndexes","result","baseTimes","String","baseIsArguments","argsTag","baseIsNative","isMasked","reIsNative","reIsHostCtor","toSource","reRegExpChar","funcProto","funcToString","toString","RegExp","replace","baseIsTypedArray","typedArrayTags","baseKeys","nativeKeys","baseRest","start","setToString","overRest","constant","baseSetToString","string","iteratee","Array","baseUnary","copyObject","source","props","customizer","isNew","newValue","coreJsData","createAssigner","assigner","sources","guard","isIterateeCall","getValue","isOwn","unmasked","nativeObjectToString","maskSrcKey","uid","exec","keys","IE_PROTO","overArg","freeExports","nodeType","freeModule","moduleExports","freeProcess","process","nodeUtil","binding","transform","arg","nativeMax","array","otherArgs","max","shortOut","count","lastCalled","stamp","nativeNow","remaining","HOT_SPAN","HOT_COUNT","now","assign","propertyIsEnumerable","stubFalse","Buffer","nativeIsBuffer","nodeIsTypedArray","g","eval"],"mappings":"CAAS,SAAUA,GCInB,QAAAC,GAAAC,GAGA,GAAAC,EAAAD,GACA,MAAAC,GAAAD,GAAAE,OAGA,IAAAC,GAAAF,EAAAD,IACAI,EAAAJ,EACAK,GAAA,EACAH,WAUA,OANAJ,GAAAE,GAAAM,KAAAH,EAAAD,QAAAC,IAAAD,QAAAH,GAGAI,EAAAE,GAAA,EAGAF,EAAAD,QAvBA,GAAAD,KA4BAF,GAAAQ,EAAAT,EAGAC,EAAAS,EAAAP,EAGAF,EAAAK,EAAA,SAAAK,GAA2C,MAAAA,IAG3CV,EAAAW,EAAA,SAAAR,EAAAS,EAAAC,GACAb,EAAAc,EAAAX,EAAAS,IACAG,OAAAC,eAAAb,EAAAS,GACAK,cAAA,EACAC,YAAA,EACAC,IAAAN,KAMAb,EAAAoB,EAAA,SAAAhB,GACA,GAAAS,GAAAT,KAAAiB,WACA,WAA2B,MAAAjB,GAAA,SAC3B,WAAiC,MAAAA,GAEjC,OADAJ,GAAAW,EAAAE,EAAA,IAAAA,GACAA,GAIAb,EAAAc,EAAA,SAAAQ,EAAAC,GAAsD,MAAAR,QAAAS,UAAAC,eAAAlB,KAAAe,EAAAC,IAGtDvB,EAAA0B,EAAA,GAGA1B,IAAA2B,EAAA,MDMM,SAAUvB,EAAQD,EAASH,GAEjC,YEtEA,SAAS4B,KAML,QAASC,GAASC,GAAoC,GAA5BC,GAA4BC,UAAAC,OAAA,OAAAC,KAAAF,UAAA,GAAAA,UAAA,MAAjBG,EAAiBH,UAAAC,OAAA,OAAAC,KAAAF,UAAA,GAAAA,UAAA,GAAR,KAC1CD,GAAKK,MAASC,EACdN,EAAKD,OAASA,CACd,IAAIQ,IAASP,OAAMI,SAEnB,OADAG,GAAKC,IAAMC,EACJ,GAAIC,SAAS,SAAEC,EAASC,GAC3BC,OAAOC,KAAMP,GAAOQ,KAAMJ,GAAUK,KAAMJ,KAEzCK,KAAM,SAAEC,GAAF,MAAgBC,GAAaD,KAb5C,GAAMT,GAAkBW,QAClBd,EAAkBe,KAAKC,OAAOC,aAgB9BC,GAIFC,SAOIC,cAAe,SAAEC,EAAMhD,GAEnB,MAAOmB,GADQ8B,+BACWD,OAAMhD,SAAS,SAQ7CkD,UAAW,SAAElD,GAET,MAAOmB,GADQ8B,gCACWjD,SAAS,SAQvCmD,eAAgB,SAAEH,GAEd,MAAO7B,GADQ8B,+BACWD,QAAQ,QAC7BV,KAAM,SAAEC,GACL,MAAOA,OAQvBa,YAQLC,QAAS,SAAEC,EAAMC,EAAUC,GAEd,MAAOrC,GADJ8B,2BACuBK,OAAMC,WAAUC,UAAU,QAC/ClB,KAAM,SAAEC,GACL,MAAOA,MASnBQ,cAAe,SAAE/C,GAEb,MAAOmB,GADQ8B,8BACWjD,SAAS,SAMhDyD,WAAY,WAEC,MAAOtC,GADQ8B,iCACa,UAOpCS,WAMIC,mBAAoB,SAAE3D,GAElB,MAAOmB,GADQ8B,yCACWjD,SAAS,SAMhD4D,UAAW,WAEE,MAAOzC,GADQ8B,0BACa,UAOpCY,cAMIC,UAAW,SAAE9D,GAET,MAAOmB,GADQ8B,gCACWjD,SAAS,SAQvC2D,mBAAoB,SAAE3D,GAElB,MAAOmB,GADQ8B,yCACWjD,SAAS,SAQvC+D,WAAY,SAAEC,GAEV,MAAO7C,GADQ8B,iCACWe,YAAY,QACjC1B,KAAM,SAAEC,GACL,MAAOA,MAUnB0B,UAAW,SAAED,EAAUV,GAEnB,MAAOnC,GADQ8B,gCACWe,WAAUV,QAAQ,QACvChB,KAAM,SAAEC,GACL,MAAOA,MAO5B2B,WAAY,WAEX,MAAO/C,GADQ8B,mCACa,UAOxBkB,aAILC,QAAS,WAEI,MAAOjD,GADQ8B,+BACa,QACvBX,KAAM,SAAEC,GACN,MAAOA,MAUlB8B,aAAc,SAAEC,EAAOpE,GAEnB,MAAOiB,GADQoD,sCACWD,QAAOpE,QAAQ,QACpCoC,KAAM,SAAEC,GACL,MAAOA,MAUnBiC,oBAAqB,SAAEnD,GAEnB,MAAOF,GADQoD,8CACWlD,QAAQ,YAK9C,EAAAoD,EAAAC,SAAQC,KAAM9B,GAMlB,QAASL,GAAaD,GAIlB,GAHyB,gBAApB,KAAOA,EAAP,YAAAqC,EAAOrC,MACRA,EAAWsC,KAAKC,MAAOvC,IAEtBA,EAASwC,QACV,MAAOxC,GAASlB,IAGpB,IAAIA,GAAOkB,EAASlB,SACd2D,EAAQ,GAAIC,OAAO5D,EAAK6D,SAAW,6CAEzC,MADAF,GAAMzC,SAAWA,EACXyC,EFrKV3E,OAAOC,eAAeb,EAAS,cAC3BO,OAAO,GAGX,IAAI4E,GAA4B,kBAAXO,SAAoD,gBAApBA,QAAOC,SAAwB,SAAUC,GAAO,aAAcA,IAAS,SAAUA,GAAO,MAAOA,IAAyB,kBAAXF,SAAyBE,EAAIC,cAAgBH,QAAUE,IAAQF,OAAOrE,UAAY,eAAkBuE,IE/EtQE,EAAAjG,EAAA,IFmFImF,EAEJ,SAAgCY,GAAO,MAAOA,IAAOA,EAAI1E,WAAa0E,GAAQX,QAASW,IAFjDE,GE+IhCC,EAAY,GAAItE,EFkFtBzB,GAAQiF,QEjFOc,GFoGT,SAAU9F,EAAQD,EAASH,GGrTjC,QAAAmG,GAAAzF,GACA,aAAAA,MACAwB,KAAAxB,EAAA0F,EAAAC,EAEAC,OAAAvF,QAAAL,GACA6F,EAAA7F,GACA8F,EAAA9F,GAxBA,GAAAmF,GAAA7F,EAAA,GACAuG,EAAAvG,EAAA,IACAwG,EAAAxG,EAAA,IAGAqG,EAAA,gBACAD,EAAA,qBAGAE,EAAAT,IAAAY,gBAAAvE,EAkBA9B,GAAAD,QAAAgG,GH8UM,SAAU/F,EAAQD,EAASH,GIzWjC,GAAA0G,GAAA1G,EAAA,IAGA2G,EAAA,gBAAAC,kBAAA7F,iBAAA6F,KAGAC,EAAAH,GAAAC,GAAAG,SAAA,gBAEA1G,GAAAD,QAAA0G,GJgXM,SAAUzG,EAAQD,EAASH,GK5VjC,QAAA+G,GAAArG,GACA,aAAAA,GAAAsG,EAAAtG,EAAAuB,UAAAgF,EAAAvG,GA7BA,GAAAuG,GAAAjH,EAAA,IACAgH,EAAAhH,EAAA,GA+BAI,GAAAD,QAAA4G,GL+XM,SAAU3G,EAAQD,GMtYxB,QAAA+G,GAAAxG,GACA,GAAAgD,SAAAhD,EACA,cAAAA,IAAA,UAAAgD,GAAA,YAAAA,GAGAtD,EAAAD,QAAA+G,GNsaM,SAAU9G,EAAQD,GO5axB,QAAAgH,GAAAzG,GACA,aAAAA,GAAA,gBAAAA,GAGAN,EAAAD,QAAAgH,GP2cM,SAAU/G,EAAQD,EAASH,GQvejC,GAAA6G,GAAA7G,EAAA,GAGA6F,EAAAgB,EAAAhB,MAEAzF,GAAAD,QAAA0F,GR8eM,SAAUzF,EAAQD,EAASH,GShejC,QAAAoH,GAAA9F,EAAA+F,EAAA3G,GACA,GAAA4G,GAAAhG,EAAA+F,EACA5F,GAAAlB,KAAAe,EAAA+F,IAAAE,EAAAD,EAAA5G,SACAwB,KAAAxB,GAAA2G,IAAA/F,KACAkG,EAAAlG,EAAA+F,EAAA3G,GAvBA,GAAA8G,GAAAxH,EAAA,GACAuH,EAAAvH,EAAA,IAGAyH,EAAA1G,OAAAS,UAGAC,EAAAgG,EAAAhG,cAoBArB,GAAAD,QAAAiH,GT0fM,SAAUhH,EAAQD,EAASH,GU1gBjC,QAAAwH,GAAAlG,EAAA+F,EAAA3G,GACA,aAAA2G,GAAArG,EACAA,EAAAM,EAAA+F,GACApG,cAAA,EACAC,YAAA,EACAR,QACAgH,UAAA,IAGApG,EAAA+F,GAAA3G,EApBA,GAAAM,GAAAhB,EAAA,EAwBAI,GAAAD,QAAAqH,GV4hBM,SAAUpH,EAAQD,EAASH,GWpjBjC,GAAA2H,GAAA3H,EAAA,IAEAgB,EAAA,WACA,IACA,GAAA4G,GAAAD,EAAA5G,OAAA,iBAEA,OADA6G,MAAW,OACXA,EACG,MAAAC,OAGHzH,GAAAD,QAAAa,GX2jBM,SAAUZ,EAAQD,EAASH,IYrkBjC,SAAA8H,GACA,GAAApB,GAAA,gBAAAoB,SAAA/G,iBAAA+G,CAEA1H,GAAAD,QAAAuG,IZykB6BnG,KAAKJ,EAASH,EAAoB,MAIzD,SAAUI,EAAQD,GalkBxB,QAAA4H,GAAArH,EAAAuB,GAEA,SADAA,EAAA,MAAAA,EAAA+F,EAAA/F,KAEA,gBAAAvB,IAAAuH,EAAAC,KAAAxH,KACAA,GAAA,GAAAA,EAAA,MAAAA,EAAAuB,EAjBA,GAAA+F,GAAA,iBAGAC,EAAA,kBAiBA7H,GAAAD,QAAA4H,GbulBM,SAAU3H,EAAQD,GclmBxB,QAAAgI,GAAAzH,GACA,GAAA0H,GAAA1H,KAAAsF,WAGA,OAAAtF,MAFA,kBAAA0H,MAAA5G,WAAAiG,GAXA,GAAAA,GAAA1G,OAAAS,SAgBApB,GAAAD,QAAAgI,GdmnBM,SAAU/H,EAAQD,GepmBxB,QAAAoH,GAAA7G,EAAA2H,GACA,MAAA3H,KAAA2H,GAAA3H,OAAA2H,MAGAjI,EAAAD,QAAAoH,Gf2oBM,SAAUnH,EAAQD,GgB/pBxB,QAAAmI,GAAA5H,GACA,MAAAA,GAGAN,EAAAD,QAAAmI,GhBsrBM,SAAUlI,EAAQD,EAASH,GiBhrBjC,QAAAiH,GAAAvG,GACA,IAAAwG,EAAAxG,GACA,QAIA,IAAA6H,GAAApC,EAAAzF,EACA,OAAA6H,IAAAC,GAAAD,GAAAE,GAAAF,GAAAG,GAAAH,GAAAI,EAjCA,GAAAxC,GAAAnG,EAAA,GACAkH,EAAAlH,EAAA,GAGA0I,EAAA,yBACAF,EAAA,oBACAC,EAAA,6BACAE,EAAA,gBA6BAvI,GAAAD,QAAA8G,GjBitBM,SAAU7G,EAAQD,GkBxtBxB,QAAA6G,GAAAtG,GACA,sBAAAA,IACAA,GAAA,GAAAA,EAAA,MAAAA,GAAAsH,EA9BA,GAAAA,GAAA,gBAiCA5H,GAAAD,QAAA6G,GlB4vBM,SAAU5G,EAAQD,GmB9xBxBC,EAAAD,QAAA,SAAAC,GAoBA,MAnBAA,GAAAwI,kBACAxI,EAAAyI,UAAA,aACAzI,EAAA0I,SAEA1I,EAAA2I,WAAA3I,EAAA2I,aACAhI,OAAAC,eAAAZ,EAAA,UACAc,YAAA,EACAC,IAAA,WACA,MAAAf,GAAAE,KAGAS,OAAAC,eAAAZ,EAAA,MACAc,YAAA,EACAC,IAAA,WACA,MAAAf,GAAAC,KAGAD,EAAAwI,gBAAA,GAEAxI,InBsyBM,SAAUA,EAAQD,EAASH,GAEjC,YoB5zBA4C,QAAOoG,UAAUC,MAAO,WACpBC,WAAWC,UpBo0BT,SAAU/I,EAAQD,EAASH,GAEjC,YqBv0BA,IAAAoJ,GAAApJ,EAAA,GrB40BIqJ,EAEJ,SAAgCtD,GAAO,MAAOA,IAAOA,EAAI1E,WAAa0E,GAAQX,QAASW,IAFhDqD,IqB10BrC,SAAUE,GAERJ,WAAW1F,SAEPpD,OAAQ,UACRmJ,eAAgB,GAChBC,gBAAiB,KACjBC,uBACAC,oBACAC,aAEAR,KAAM,WACF,GAAIvC,GAA0BvB,KAC1BuE,EAA0BN,EAAE,4BAC5BO,EAA0BD,EAAeE,KAAK,gBAC9CC,EAA0BF,EAAeC,KAAK,YAC9CE,EAA0BJ,EAAeE,KAAK,cAkElD,OAhEKG,sBACDrD,EAAKsD,QAAUD,oBAEnB5E,KAAKmE,gBAAkBF,EAAG,qBAC1BjE,KAAKkE,eAAiBlE,KAAKmE,gBAAgBW,MAG3CvD,EAAK+C,UAAUS,OAASd,EAAE,6BAA6BQ,KAAK,OAAOO,QACnEzD,EAAK+C,UAAUW,MAAQhB,EAAE,4BAA4BQ,KAAK,OAAOO,QAE1Cf,EAAG,6BACTiB,KAAM,WACnB3D,EAAK6C,oBAAqBH,EAAEjE,MAAMtD,KAAK,WAAcuH,EAAEjE,QAGrCiE,EAAG,uBAETiB,KAAM,WAClB,GAAM7G,GAAO4F,EAAEjE,MAAMtD,KAAK,OACrB2B,IACD4F,EAAEjE,MAAMmF,OAAQ,WAEZX,EAAeC,KAAK,iBAAiBW,OACrCT,EAAcS,OACdV,EAAsBW,SACtBpB,EAAE,gBAAgBmB,OAGlB,SAAYE,GACR,GAAMjK,GAAQ4I,EAAGqB,GAAUR,KAE3Bd,GAAAjE,QAAQ5B,QAAQC,cAAeC,EAAMhD,GAChCsC,KAAM,WAEH4D,EAAK/C,oBAGbwB,UAMhBA,KAAKuF,uBAAwBvF,KAAKkE,gBAElClE,KAAKmE,gBAAgBgB,OAAQ,WACzB,GAAI9J,GAAQ4I,EAAEjE,MAAM8E,KACpBvD,GAAKiE,0BACLjE,EAAKgE,uBAAwBlK,GAC7BkG,EAAKhD,UAAUlD,GACfkG,EAAK2C,eAAiB7I,IAG1B4I,EAAG,+BAA+BwB,MAAO,SAAUjD,GAC/CA,EAAEkD,iBACFzB,EAAE,wBAAwB0B,gBAG9B1B,EAAG,kCAAkCwB,MAAO,SAAUjD,GAClDA,EAAEkD,iBACFzB,EAAE,2BAA2B0B,gBAI1B3F,MAGXzB,UAAW,SAAUlD,GACjB2I,EAAAjE,QAAQ5B,QAAQI,UAAWlD,IAG/BmK,wBAAyB,WACrB,GAAII,GAAW5F,KAAKkE,cACflE,MAAKoE,oBAAqBwB,IAC3B5F,KAAKoE,oBAAqBwB,GAAWR,QAI7CG,uBAAwB,SAAUM,OACqB,KAAvC7F,KAAKoE,oBAAqByB,IAClC7F,KAAKoE,oBAAqByB,GAASC,OAGlC,WAAaD,GAAU,cAAgBA,EACxC5B,EAAG,sBAAsB6B,OAGzB7B,EAAG,sBAAsBmB,QAIjC5G,eAAgB,WACZ,GAAI+C,GAAOvB,IAEX,KAAM,GAAIhF,KAAKuG,GAAK+C,UACX/C,EAAK+C,UAAUlI,eAAgBpB,IAChCgJ,EAAAjE,QAAQ5B,QAAQK,eAAgBxD,GAC3B2C,KAAM,SAAEC,GAKL2D,EAAK+C,UAAU1G,EAASS,MAAM0H,KAAMnI,EAASoI,MAGxCpI,EAASS,OAASkD,EAAK2C,iBAIvB,WAAatG,EAASS,MAAQT,EAASqI,aACxChC,EAAG,8CAA+C6B,OAClDI,SAASC,KAAO5E,EAAKsD,QAAQuB,WAAa,yBAClC,WAAaxI,EAASS,MAAQkD,EAAKsD,QAAQwB,eAAkBzI,EAASqI,aAC9EhC,EAAG,4CAA6C6B,OAChDI,SAASC,KAAO5E,EAAKsD,QAAQyB,mBAE7BrC,EAAG,qCAAsC6B,OACzCI,SAASC,KAAO5E,EAAKsD,QAAQuB,WAAa,+BAQvE7I,SrB60BG,SAAUxC,EAAQD,EAASH,GAEjC,YsBh+BA,IAAAoJ,GAAApJ,EAAA,GtBq+BIqJ,EAEJ,SAAgCtD,GAAO,MAAOA,IAAOA,EAAI1E,WAAa0E,GAAQX,QAASW,IAFhDqD,IsBn+BrC,SAAUE,GACRJ,WAAWpF,YACP1D,OAAQ,aACRwL,aAAa,EACbC,UAAU,EAEV1C,KAAM,WACF9D,KAAKwG,SAAWvC,EAAE,iBAClBjE,KAAKuG,YAActC,EAAE,8CACrB,IAAI1C,GAAOvB,IAOX,OANKjC,MAAKU,WAAWgI,GAAGC,WACpB1G,KAAKuG,YAAYpB,OAAQ,WACrB5D,EAAKoF,UAAUzL,KAAMqG,GAAOvB,SAI7BA,MAGX2G,UAAW,SAAUC,GACjB5G,KAAK6G,gBACL,IAAMxL,GAAQ4I,EAAE2C,GAAU9B,KAC1Bd,GAAAjE,QAAQtB,WAAWL,cAAe/C,GAC7BsC,KAAM,WACHmJ,OAAOZ,SAASa,YAI5BF,eAAgB,WACZ7G,KAAKwG,SAASQ,IAAK,aAAc,cAG1CzJ,StB0+BG,SAAUxC,EAAQD,EAASH,GAEjC,YuB9gCA,IAAAoJ,GAAApJ,EAAA,GvBmhCIqJ,EAEJ,SAAgCtD,GAAO,MAAOA,IAAOA,EAAI1E,WAAa0E,GAAQX,QAASW,IAFhDqD,IuBjhCrC,SAAUE,GACRJ,WAAWoD,qBACPnD,KAAM,SAAUoD,GACZlH,KAAKmH,YAAcD,EAASC,YAC5BnH,KAAKtD,KAAOwK,EACZlH,KAAKL,MAAQuH,EAASvH,MACtBK,KAAKoH,OAASF,EAASE,OACvBpH,KAAKqH,gBAAkBpD,EAAE,qBACzBjE,KAAKsH,SAAWrD,EAAE,oBAClBjE,KAAKwG,SAAWvC,EAAG,uBACnBjE,KAAKuH,kBAAoBtD,EAAE,kCAAkCQ,KAAK,uBAElEzE,KAAKwH,WAAYxH,KAAKmH,aAEtBlD,EAAE,QAAQwD,GAAI,QAAS,kCAAmC,SAASjF,GAC/DA,EAAEkD,iBACF1F,KAAKlB,WAAW4I,MAAOzD,EAAEzB,EAAEmF,SAAU3H,QACvC4H,KAAK5H,QAIXlB,WAAY,SAAUyC,GAE3B,GAAMsG,GAAU7H,IAChB6H,GAAQC,KAAM,YAAY,GAC1BvG,EAAKwG,cAEI/D,EAAAjE,QAAQtB,WAAWK,aACdnB,KAAM,WAElB,GAAMqK,GAAU/D,EAAE,sCAClB6C,QAAOmB,SAAS,EAAG,GACnBD,EAAQE,YACRC,WAAW,WACVH,EAAQI,WACN,KAEHP,EAAQQ,WAAY,YACpB9G,EAAK+G,iBAIFd,WAAY,SAAU7I,GAClB,GAAM4J,GAAW1E,WAAWoD,oBAAoBsB,SAAU,oBAAsB5J,GAC1E6J,EAAUD,EAAUvI,KAAKtD,MACzB6E,EAAOvB,IAERwI,KACDxI,KAAKmH,YAAcxI,EACnBqB,KAAKqH,gBACAjC,OACAqD,KAAMF,EAAUvI,KAAKtD,OACrB2I,SACAZ,KAAM,QACNgD,GAAI,SAAU,SAAUjF,GACrBA,EAAEkD,iBACFnE,EAAKmH,WAAWxN,KAAMqG,EAAM0C,EAAEjE,SAGtCA,KAAKwG,SAAWxG,KAAKqH,gBAAgB5C,KAAM,wBAG/CzE,KAAK2I,cAGTA,WAAY,WACR,GAAMC,GAAqB3E,EAAE,qBAE7B2E,GAAmBxD,OAEnBnB,EAAE,gCAAgCwB,MAAO,SAAUjD,GAC/CA,EAAEkD,iBACFkD,EAAmBC,WAGvB7I,KAAKqH,gBAAgB5C,KAAM,UAAWS,KAAM,WACxC4D,IAAIC,WAAY/I,QAGf,UAAYA,KAAKmH,YAClBnH,KAAKuH,kBAAkByB,YAAa,UAEpChJ,KAAKuH,kBAAkB0B,SAAU,WAIzCC,aAAc,WACVlJ,KAAKsH,SAASmB,KAAK,IACnBzI,KAAKsH,SAAS0B,eAGlBG,YAAa,SAAU5I,GACnBP,KAAKsH,SAAS2B,SAAU,eACxBjJ,KAAKsH,SAAS2B,SAAU,qBACxBjJ,KAAKsH,SAASvB,KAAMxF,IAGxBwH,YAAa,WACT/H,KAAKwG,SAASQ,IAAK,aAAc,YAGrCsB,YAAa,WACTtI,KAAKwG,SAASQ,IAAK,aAAc,WAGrC0B,WAAY,SAAUU,GAC3B,GAAM7H,GAAOvB,IAEboJ,GAAM3E,KAAM,sBAAuBqD,KAAM,WAAY,QACrD9H,KAAKkJ,eACLlJ,KAAK+H,cAEL/D,EAAAjE,QAAQtB,WAAWC,QAASsB,KAAKmH,YAAaiC,EAAMC,YAAarJ,KAAKtD,MACxDiB,KAAM,SAAEC,GACpB2D,EAAK7E,KAAOkB,EAAS0L,QACrB/H,EAAKiG,WAAY5J,EAAS2L,UAEC,UAAtB3L,EAAS2L,WACbzC,OAAOZ,SAASC,KAAOvI,EAAS4L,YAGjCC,MAAO,SAAEpJ,GACTkB,EAAK4H,YAAa9I,KAGpB+I,EAAM3E,KAAM,sBAAuB4D,WAAY,YAC/C9G,EAAK+G,gBAIJzE,WAAWoD,oBAAoBsB,SAAWmB,EAAEC,QAAQ,SAAWC,GAC3D,GAAIC,UACAC,GACIC,SAAa,kBACbC,YAAa,0BACbC,OAAa,2BACbC,SAAa,OAGrB,OAAO,UAAWxN,GAGd,MAFAgN,GAAES,iBAAmBL,GACrBD,EAAWA,GAAYH,EAAEnB,SAAUtE,EAAG2F,GAAKnB,SAC1B/L,OAG3Ba,SvBghCI,SAAUxC,EAAQD,EAASH,GAEjC,YwBrqCA,IAAAoJ,GAAApJ,EAAA,GxB0qCIqJ,EAEJ,SAAgCtD,GAAO,MAAOA,IAAOA,EAAI1E,WAAa0E,GAAQX,QAASW,IAFhDqD,IwBxqCrC,SAAUE,GACRJ,WAAW9E,WACPhE,OAAQ,YAER+I,KAAM,WACF,GAAMvC,GAAOvB,IAmCb,OAjCLoK,wBACHpK,KAAK6E,QAAUuF,sBAEPnG,EAAE,+BAA+BkB,OAAQ,WACrC,GAAM9J,GAAQ4I,EAAEjE,MAAM8E,KACtBd,GAAAjE,QAAQhB,UAAUC,mBAAoB3D,GACjCsC,KAAM,WAEH,GAAM0M,GAAcpG,EAAE,wBACjB,WAAY5I,GACbgP,EAAYC,KAAM,WAAW,GAC7BD,EAAYC,KAAM,YAAY,IAE9BD,EAAYC,KAAM,YAAY,GAElC/I,EAAKgJ,iBAIjBtG,EAAE,YAAYkB,OAAQ,WAClB,GAAM9J,GAAQ4I,EAAEjE,MAAMyG,GAAG,WACzBzC,GAAAjE,QAAQb,aAAaC,UAAW9D,GAC3BsC,KAAM,WACH4D,EAAKgJ,iBAIjBtG,EAAE,iCAAiCwB,MAAO,WACtC,GAAMvI,GAAM+G,EAAEjE,MAAMtD,KAAM,kBACrBQ,KACDgJ,SAASC,KAAOjJ,KAGjB8C,MAMXuK,WAAY,WACR,GAAMC,GAASvG,EAAE,6CACjBuG,GAAOtC,YACPC,WAAY,WACRqC,EAAOpC,WACR,MAMbqC,gBAAiB,WAEP3B,IAAI4B,YAAa,2BAA6BC,MAAO,sDAM/D1L,UAAW,WACD+E,EAAAjE,QAAQhB,UAAUE,YACbtB,KAAM,WACHmJ,OAAOZ,SAASa,QAAO,MAOzC6D,mBAAoB,WAEnB9B,IAAI4B,YAAY,+BAAiCC,MAAO,kDAGzC9G,WAAWgH,UAAU,eAC7BC,gBAAiB9K,KAAK6E,QAAQkG,yBAGrCxN,SxB4qCG,SAAUxC,EAAQD,EAASH,GAEjC,YyBpwCA,IAAAoJ,GAAApJ,EAAA,GzBywCIqJ,EAEJ,SAAgCtD,GAAO,MAAOA,IAAOA,EAAI1E,WAAa0E,GAAQX,QAASW,IAFhDqD,IyBvwCvC,SAAUE,GACNJ,WAAWmH,MACPjQ,OAAQ,OACRmJ,eAAgB,GAChBC,gBAAiB,KACjBC,uBAEAN,KAAM,WACF,GAAMvC,GAAOvB,IAwBb,OAtBAA,MAAKmE,gBAAkBF,EAAE,qBACzBjE,KAAKkE,eAAiBlE,KAAKmE,gBAAgBW,MACpBb,EAAE,6BACRiB,KAAK,WAClB3D,EAAK6C,oBAAoBH,EAAEjE,MAAMtD,KAAK,WAAauH,EAAEjE,QAEzDA,KAAKuF,uBAAuBvF,KAAKkE,gBACjClE,KAAKmE,gBAAgBgB,OAAO,WACxB,GAAM9J,GAAQ4I,EAAEjE,MAAM8E,KACtBvD,GAAKiE,0BACLjE,EAAKgE,uBAAuBlK,GAC5BkG,EAAKhD,UAAUlD,GACfkG,EAAK2C,eAAiB7I,IAE1B4I,EAAE,+BAA+BwB,MAAM,SAASjD,GAC5CA,EAAEkD,iBACFzB,EAAE,wBAAwB4E,WAE9B5E,EAAE,kCAAkCwB,MAAM,SAASjD,GAC/CA,EAAEkD,iBACFzB,EAAE,2BAA2B4E,WAE1B7I,MAGXwF,wBAAyB,WACrB,GAAMI,GAAW5F,KAAKkE,cAClBlE,MAAKoE,oBAAoBwB,IACzB5F,KAAKoE,oBAAoBwB,GAAUR,QAI3CG,uBAAwB,SAASM,OACmB,KAArC7F,KAAKoE,oBAAoByB,IAChC7F,KAAKoE,oBAAoByB,GAAQC,OAEjC,WAAaD,GAAU,cAAgBA,EACvC5B,EAAE,sBAAsB6B,OAExB7B,EAAE,sBAAsBmB,QAIhC7G,UAAW,SAAUlD,GACjB2I,EAAAjE,QAAQ5B,QAAQI,UAAWlD,MAGpCkC,SzB+wCG,SAAUxC,EAAQD,EAASH,GAEjC,c0B50CE,SAAUsJ,GAGR,GAAIJ,IACAnJ,WAEAoJ,KAAM,WAEF,QAASmH,GAAuBC,GAC5B,GAAIC,GAAQD,EAAMzG,KAAK,4BACnBK,EAAMsG,SAASD,EAAMpF,OAAQ,KAAO,IACpCsF,EAAUH,EAAMzG,KAAK,4BACrB6G,SAAGlQ,SAAGmQ,QAEVD,GAAID,EAAQvD,KAAK,KACjB1M,EAAIoQ,KAAKC,IAAM,EAAFH,GAETxG,EAAM,IAAKA,EAAM,GACjBA,EAAM,MAAOA,EAAM,KAEvByG,GAAQ,IAAIzG,GAAK,IAAK1J,EAEtBiQ,EAAQrE,KAAM0E,iBAAkBH,IAGpC,QAASI,KAGL1H,EAAE,0CAA0CiB,KAAK,WAC7C+F,EAAuBhH,EAAEjE,SAI7BiE,EAAE,0CAA0CiB,KAAK,WAC7C+F,EAAuBhH,EAAEjE,SAI7BiE,EAAE,uCAAuCiB,KAAK,WAC1C+F,EAAuBhH,EAAEjE,SAIjC8G,OAAO8E,4BAA8B,WACjCzD,WAAWwD,EAAgC,MAE/C1H,EAAE,WAAYkE,WAAWwD,EAAgC,QAG7DE,WAAY,SAAU9Q,GAClB,MAAKiF,MAAK5D,eAAgBrB,IACtBiF,KAAKtF,QAASK,GAAWiF,KAAMjF,GAAS+I,OACjC9D,KAAKtF,QAASK,QAK7B8P,UAAW,SAAU9P,GACjB,WAAuC,KAA3BiF,KAAKtF,QAASK,GACfiF,KAAKtF,QAASK,GAEdiF,KAAK6L,WAAY9Q,IAKpC8I,GAAWiI,OAEPC,iBACIC,KAAM,WACF/H,EAAG,uCAAuCgI,QAAS,WAI3DC,KAAM,SAAUxP,EAAM3B,GAGlB,MAFA2B,GAAKD,OAAS,YACdC,EAAK3B,OAASA,EACPkJ,EAAEzG,MACLN,IAAKY,QACLhB,OAAQ,OACRJ,KAAMA,MAKlBmH,EAAWsI,SAEPrI,KAAM,WACFG,EAAG,4CAA4CwB,MAAO,SAAUjD,GAC5DA,EAAEkD,gBACOzB,GAAEjE,MAAMtD,KAAM,MACXuH,EAAEjE,MAAMtD,KAAM,QAE1BuH,GAAEjE,MAAMoM,OAAQ,UAAWhH,WAKvC0B,OAAOjD,WAAaA,GAErBtG,S1Bm1CG,SAAUxC,EAAQD,EAASH,GAEjC,YAiBA,SAAS0R,GAAuB3L,GAAO,MAAOA,IAAOA,EAAI1E,WAAa0E,GAAQX,QAASW,G2B18CvF,GAAAqD,GAAApJ,EAAA,G3B87CIqJ,EAAYqI,EAAuBtI,G2B77CvCuI,EAAA3R,EAAA,IACA4R,EAAA5R,EAAA,I3Bk8CI6R,EAAQH,EAAuBE,G2Bj8CnCE,EAAA9R,EAAA,I3Bq8CI+R,EAAmBL,EAAuBI,I2Bn8C5C,SAAUxI,GAGRJ,WAAW3E,cAEPyN,kBAAmB,KACnBC,4BAA8B,KAC9B7R,OAAQ,eACR8R,cAAe,KACfC,YAAa,EACbtG,SAAU,KAEV1C,KAAM,WACF,GAAMvC,GAAOvB,IAGbiE,GAAE,oCAAoCwD,GAAG,QAAS,SAASjF,GACvDA,EAAEkD,iBACFzB,EAAE,6BAA6B4E,OAAO,UAI1C7I,KAAK2M,kBAAoB1I,EAAG,gBAC5BjE,KAAK+M,qBAAuB9I,EAAE,8BAC9BjE,KAAKwG,SAAWvC,EAAE,YAEbjE,KAAK2M,kBAAkB/P,QACxBoD,KAAK2M,kBAAkBlH,MAAO,SAAUjD,GACpCA,EAAEkD,iBACFzB,EAAEjE,MAAM8H,KAAK,YAAY,GACzBvG,EAAKyL,YAAY,EAAAV,EAAAW,SAAS,mBAIlChJ,EAAE,iBAAiBwB,MAAO,SAASjD,GAM/B,MALAA,GAAEkD,iBAEGwH,SAAS,EAAAZ,EAAAa,IAAI,kBACdjH,SAASa,UAEN,IAIX9C,EAAG,8BAA+BwD,GAAI,SAAU,WAC5CxD,EAAE,iBAAiB6D,KAAM,YAAY,KAGzC7D,EAAE,YAAYkB,OAAQ,WAClB,GAAMiI,GAAYnJ,EAAEjE,MAAMyG,GAAG,WAC7BzC,GAAAjE,QAAQb,aAAaC,UAAWiO,GAC3BzP,KAAM,WACH,GAAM6M,GAASvG,EAAE,sDACjBuG,GAAOtC,YACPC,WAAY,WACRqC,EAAOpC,WACR,SAIfpI,KAAK+M,qBAAqB5H,OAAQ,WAC9B,GAAM9J,GAAQ4I,EAAEjE,MAAMyG,GAAG,WAEzBlF,GAAKiF,SAASQ,IAAK,aAAc,WAE5BzF,EAAK8L,OAAShS,IACfiS,aAAc/L,EAAK8L,OACnB9L,EAAKiF,SAASQ,IAAK,aAAc,WAGrCzF,EAAK8L,MAAQlF,WAAY,WACrBnE,EAAAjE,QAAQb,aAAaF,mBAAoB3D,GACpCsC,KAAM,WACHuI,SAASa,YAElB,OAKP/G,KAAKuN,eAAiB,GAAI1J,YAAW3E,aAAasO,eAErCvJ,EAAE,oBAEViB,KAAM,SAAUuI,EAAOC,GACxB,GAAIC,SAEAA,GADC1J,EAAEyJ,GAAKhR,KAAK,oBACN,GAAImH,YAAW3E,aAAa0O,IAAK3J,EAAEyJ,GAAMzJ,EAAEyJ,GAAKhR,KAAK,UAAWuH,EAAEyJ,GAAKhR,KAAK,qBAG5E,GAAImH,YAAW3E,aAAa0O,IAAK3J,EAAEyJ,GAAMzJ,EAAEyJ,GAAKhR,KAAK,WAEhE6E,EAAKgM,eAAeM,KAAMF,KAG9B1J,EAAE,WAAW6J,MAAO,WAChBvM,EAAKgM,eAAeQ,UAAW9J,EAAEjE,MAAM8E,MAAO,WAC9CvD,EAAKgM,eAAeS,iBAGxB/J,EAAE,0BAA0BkB,OAAQ,WAChC5D,EAAKgM,eAAeQ,UAAW9J,EAAEjE,MAAM8E,MAAO,aAC9CvD,EAAKgM,eAAeS,iBAGxB/J,EAAE,mBAAmBkB,OAAQ,WACzB,GAAMG,GAAUrB,EAAEjE,MACZiO,EAAO3I,EAAQ5I,KAAK,WACpBrB,EAAQiK,EAAQgF,KAAM,WACtB4D,EAAe3M,EAAKgM,eAAeY,iBAEzC,KAAM,GAAInT,KAAKkT,GACXA,EAAalT,GAAGmK,OAAQ8I,EAAM5S,KAKpB4I,EAAE,yCACVwB,MAAO,WACb,GAAM2I,GAAQnK,EAAGjE,MACXsF,EAAU/D,EAAKgM,eAAec,YAAaD,EAAM1R,KAAM,QAAU0R,EAAM1R,KAAM,UAC5E4I,KAIF8I,EAAM3H,GAAI,YACXnB,EAAQgJ,SAGRhJ,EAAQiJ,cAIEtK,EAAE,2BACVwB,MAAO,WACb,GAAM2I,GAAQnK,EAAGjE,MACbwO,EAAQjN,EAAKgM,eAAekB,UAChC,KAAM,GAAIzT,KAAKwT,GACNA,EAAMpS,eAAgBpB,KAClBoT,EAAM3H,GAAI,YACX+H,EAAMxT,GAAGsT,SAGTE,EAAMxT,GAAGuT,cAOzBtK,EAAE,iBAAiBwD,GAAG,QAAS,WAC3B,GAAM2G,GAAQnK,EAAEjE,MACV0O,EAAWN,EAAM3J,KAAM,wBACvBiJ,EAAMnM,EAAKgM,eAAec,YAAaD,EAAM1R,KAAM,QAAU0R,EAAM1R,KAAM,UAE1EgR,KACDA,EAAIvI,OAAQ,WAAauJ,EAASpE,KAAM,YACxCoD,EAAIiB,aAAalK,KAAM,8BAA+B6F,KAAK,YAAcoE,EAASpE,KAAM,cAKhG,IAAMsE,GAAa3K,EAAE,qCACrB2K,GAAWzJ,OAAQ,WACf,GAAM0J,GAAe5K,EAAEjE,MAAMsK,KAAK,UAElCsE,GAAW1J,KAAM,WACblF,KAAK8O,QAAUD,MAKvB5K,EAAE,QAAQwD,GAAG,QAAS,kCAAmC,WAChDX,OAAOiI,WAAa,KACrB9K,EAAEjE,MAAMoM,SAAS3H,KAAK,kCAAkCoE,OAAO,SAQvE,IAAImG,GAA2BtF,EAAEuF,SAAS,WAEjCnI,OAAOiI,YAAc,IACtB9K,EAAE,kCAAkC+C,IAAI,UAAW,QAEnD/C,EAAE,kCAAkC+C,IAAI,UAAW,SAGxD,IAIH,OAFAF,QAAOoI,iBAAiB,SAAUF,GAE3BhP,MAGXgN,WAAY,SAAUxD,GAAW,GAAA2F,GAAAnP,KACvBuB,EAAOvB,IAKb,QAHyB,KAAbwJ,IACRA,GAAW,GAERjI,EAAK6N,oBAuBP,CACD,GAAM/P,GAAWgQ,eAAeC,QAAQ,YAClC3Q,EAAO6M,KAAK+D,MAAO,GAAKF,eAAeC,QAAQ,SACrDtL,GAAAjE,QAAQb,aAAaI,UAAWD,EAAUV,GACrChB,KAAM,SAAEC,GACL,OAAkC,KAAtBA,EAAS4R,UAEjB,GAAK5R,EAAS4R,UAAYhG,EAEtB6F,eAAeI,QAGfN,EAAKO,kBAAmB,MAGnB,IAAS9R,EAAS+R,UAAY1L,EAAE,qBAAqBrH,OACtDkM,IAAI4B,YAAa,qBAAuBC,MAAO,kDAE/C7D,OAAOZ,SAASC,KAAOqD,MAI1B,KAAO5L,EAAS4R,SAAW,CAE5B,GAAInQ,GAAW+L,SAAUiE,eAAeC,QAAQ,aAAgB9D,KAAK+D,MAAO,GAAKF,eAAeC,QAAQ,SACxGD,gBAAeO,QAAS,WAAYvQ,GAGpC8P,EAAKO,kBAAmBrQ,GAGxByH,OAAOqB,WAAY,WACf5G,EAAKyL,WAAYxD,IAClB,UAIP1C,QAAOZ,SAASC,KAAOqD,QA5DL,CAGc,OAAvC6F,eAAeC,QAAQ,aACxBD,eAAeO,QAAQ,WAAY,GAIvC,IAAMvQ,GAAWgQ,eAAeC,QAAQ,WACxCtP,MAAK0P,kBAAmBrQ,GAGxB2E,EAAAjE,QAAQb,aAAaE,WAAYC,GAC5B1B,KAAM,SAAEC,OAE4B,KAAnBA,EAASiS,OAAiE,OAApCR,eAAeC,QAAQ,UACvED,eAAeO,QAAQ,QAAShS,EAASiS,OAG7CtO,EAAK6N,qBAAsB,EAC3B7N,EAAKyL,WAAYxD,OA+CjCkG,kBAAmB,SAAUrQ,GAA2B,GAAjByQ,GAAiBnT,UAAAC,OAAA,OAAAC,KAAAF,UAAA,IAAAA,UAAA,EAC/C0C,GAAW,MACZA,EAAW,KAGf4E,EAAE,qDAAqD8B,KAAM1G,EAAW,KACnEA,GAAY,IACb4E,EAAE,kDAAkD8B,KAAK,iBAExD+J,GACb7L,EAAE,kDAAkD8B,KAAK,iBAEjD9B,EAAE,oDAAoD8L,MAAO1Q,EAAW,MAG5EE,WAAY,WAAW,GAAAyQ,GAAAhQ,IACnBgE,GAAAjE,QAAQb,aAAaK,aAChB5B,KAAM,WAElB0R,eAAeI,QAEfO,EAAKN,kBAAmB,GAAG,GAGZ5I,OAAOZ,SAASC,MAAO,EAAAmG,EAAAW,SAAS,oBAMhDpJ,WAAW3E,aAAa0O,IAAxBpB,EAAAzM,QACA8D,WAAW3E,aAAasO,eAAxBd,EAAA3M,SAEDxC,S3Bi8CG,SAAUxC,EAAQD,EAASH,GAEjC,Y4BvvDA,IAAAoJ,GAAApJ,EAAA,G5B4vDIqJ,EAEJ,SAAgCtD,GAAO,MAAOA,IAAOA,EAAI1E,WAAa0E,GAAQX,QAASW,IAFhDqD,I4B1vDrC,SAAUE,GAERJ,WAAWrE,aAEPzE,OAAQ,cACRkV,UAAW,EACX5Q,SAAU,EAEVyE,KAAM,WAEF,GAAIvC,GAAOvB,KACPkQ,EAAOjM,EAAE,OAETkM,0BACAnQ,KAAK6E,QAAUsL,wBAEnBnQ,KAAKoQ,eAAiBnM,EAAE,wBAExB,IAAIoM,GAAyBpM,EAAE,4BAE/BoM,GAAuBC,IAAI,QAAS,UACpCD,EAAuB5I,GAAG,QAA2E,kCAAmC,SAAUjF,GAC9IA,EAAEkD,gBAEF,IAAI6K,GAA2BtM,EAAEjE,MAAMwQ,QAAQ,iCAC3CC,EAA8BF,EAAyBG,UAAU,gCAErED,GAA4BE,YAAY,0DAEpCF,EAA4BG,SAAS,0DACrCL,EAAyBtH,SAAS,uCAElCsH,EAAyBvH,YAAY,yCAKzChJ,KAAKoQ,eAAexT,QACpBoD,KAAKoQ,eAAe3K,MAAM,SAAUjD,GAChCA,EAAEkD,iBACFzB,EAAEjE,MAAM8H,KAAK,YAAY,GACzBvG,EAAKuJ,gBAAgBvJ,EAAKsD,QAAQkG,uBAK1C,IAAM8F,GAAO/J,OAAOZ,SAAS2K,IAC7B,IAAIA,EAAM,CACN,GAAMnD,GAAMzJ,EAAE4M,EACVnD,GAAI9Q,QACJ8Q,EAAIjJ,KAAK,+BAA+BwH,QAAQ,SAgFxD,MA1EAhI,GAAE,kCAAkCkB,OAAO,WAClC,MAAQlB,EAAEjE,MAAM8E,MACjBb,EAAEjE,MAAMwQ,QAAQ,iBAAiB/L,KAAK,sBAAsBW,OAE5DnB,EAAEjE,MAAMwQ,QAAQ,iBAAiB/L,KAAK,sBAAsBqB,SAEjEX,SAGH+K,EAAKzI,GAAG,QAAS,yBAA0B,SAAUjF,GACjDA,EAAEkD,iBACFzB,EAAEjE,MAAMwQ,QAAQ,cAAcM,SAC9B7M,EAAE,kBAAkBQ,KAAK,oCAAsCR,EAAEjE,MAAM8H,KAAK,WAAa,KAAKgJ,WAIlG7M,EAAE,gBAAgBwB,MAAM,WACpB,GAAM9F,GAAQsE,EAAE,yBAAyBa,MACnCvJ,EAAO0I,EAAE,oBAAoBa,KAqCnC,OApCAd,GAAAjE,QAAQP,YAAYE,aAAcC,EAAOpE,GACpCoC,KAAM,SAAEC,GACL,GAAMmT,GAAW9M,EAAE,4BAEb+M,EAAM/M,EAAE,UAAU6D,MACpBmJ,IAAOrT,EAASsT,OAChBnB,MAAS,OAEPxU,EAAO0I,EAAE,WAAWwE,KAAK7K,EAASrC,KAExCwV,GAASI,OAAO,wBAChBJ,EAAStM,KAAK,SAAS0M,OAAQH,EAAKzV,GAGpCwV,EAASI,OAAOlN,EAAE,yBAAyBwE,KAAK9I,IAChDoR,EAASI,OAAOlN,EAAE,QAAQ6D,MACtBsJ,UAAWxT,EAASyT,QACpB1G,MAAS,uCACTxE,KAAQ,IACRmL,IAAO/P,EAAKsD,QAAQ0M,mBACrB9I,KAAK,4CAERxE,EAAE,WAAW6D,MACTzJ,KAAM,SACNuL,GAAI,iBACJrO,KAAM,qBACNF,MAAO6E,KAAKsR,WAAa7R,MAAO/B,EAAS+B,MAAOpE,KAAMqC,EAASrC,SAChEkW,SAASV,GAEZ9M,EAAE,wBAAwBkN,OAAOJ,GACjC9M,EAAE,yBAAyBa,IAAI,IAC/Bb,EAAE,oBAAoBa,IAAI,MAE7B2E,MAAO,SAAEpJ,GACNqR,MAAOrR,EAAME,YAEd,IAIX2P,EAAKzI,GAAG,SAAU,YAAa,SAAUjF,GACrCA,EAAEkD,gBACF,IAAMiM,GAAY1N,EAAEjE,MAAMqJ,YACtBuI,EAAO3N,EAAEjE,KASb,OAPA4R,GAAKnN,KAAK,WAAWqD,KAAK,WAAY,YAEtC9D,EAAAjE,QAAQP,YAAYK,oBAAqB8R,GACpChU,KAAM,WACHiU,EAAKnN,KAAK,WAAW4D,WAAW,YAChC9G,EAAKsQ,uBAEN,IAGJ7R,MAIX6R,kBAAmB,WACf,GAAMrH,GAASvG,EAAE,mDACjB6C,QAAOmB,SAAS,EAAE,GAClBuC,EAAOtC,YACPC,WAAY,WACRqC,EAAOpC,WACR,MAGb0C,gBAAiB,SAAWtB,GAC3B,GAAMjI,GAAOvB,SAEqB,KAAbwJ,IACRA,GAAW,GAGfjI,EAAKmO,oBAEL1L,EAAAjE,QAAQP,YAAYC,UACf9B,KAAM,SAAEC,GACbA,EAAS4R,SAKJhG,IACO1C,OAAOZ,SAAWsD,GAJpC1C,OAAOqB,WAAW,WACjB5G,EAAKuJ,gBAAiBtB,IACpB,QAODkG,kBAAmB,WACnB1P,KAAKX,SAAW,KACpBW,KAAKX,UAAY,IAEbW,KAAKX,SAAW,MACpBW,KAAKX,SAAW,IAEjB4E,EAAE,qDAAqD8B,KAAM/F,KAAKX,SAAW,KAC7E4E,EAAE,oDAAoD6D,KAAM,QAAS,SAAW9H,KAAKX,SAAW,QAGhG9B,S5ByvDG,SAAUxC,EAAQD,EAASH,GAEjC,c6B76DE,SAAUsJ,GACRJ,WAAWiO,QACP/W,OAAQ,SACRgX,mBAAoB,KACpBC,UAAW,KACX3E,MAAM,KACN7G,SAAU,KACV1C,KAAM,WACF9D,KAAKwG,SAAWvC,EAAE,YAClBjE,KAAK6E,QAAUoN,kBACfjS,KAAK+R,mBAAqB9N,EAAG,2BAC7BjE,KAAKgS,UAAY/N,EAAE,sBAAsBa,MACzC9E,KAAKkS,eAAiBjO,EAAE,wBAExBjE,KAAK+R,mBAAmB5M,OAAQ,WAC5B2B,OAAOZ,SAASC,KAAOlC,EAAEjE,MAAMyE,KAAM,aAAc/H,KAAM,QAG7D,IAAI6E,GAAOvB,IACXA,MAAKkS,eAAe/M,OAAQ,WACxB5D,EAAKiF,SAASQ,IAAK,aAAc,WACrB/C,EAAEjE,MAAMyG,GAAG,aACTlF,EAAK8L,OACfC,aAAc/L,EAAK8L,OACnB9L,EAAKiF,SAASQ,IAAK,aAAc,WAIjCzF,EAAK8L,MAAQlF,WAAY,WACrBjC,SAASC,KAAO5E,EAAKsD,QAAQsN,kBAC9B,OAMXnS,KAAKoS,YAGLnO,EAAE,2BAA2BwD,GAAI,QAAS,SAASjF,GAC/CA,EAAEkD,iBACFQ,SAASa,YAIjBqL,UAAW,WACP,GAAI1V,GAAO,GAAI2V,QAAOC,cAAcC,SACpC7V,GAAK8V,UAAU,WAAY,OAC3B9V,EAAK8V,UAAU,SAAU,qBAGzB,KAAK,GADDC,GAAcvS,KAAKC,MAAOH,KAAKgS,WAC1BhX,EAAI,EAAGA,EAAIyX,EAAY7V,OAAQ5B,IACpCyX,EAAYzX,GAAG,GAAK,GAAI0X,MAAMD,EAAYzX,GAAG,IAC7CyX,EAAYzX,GAAG,GAAKwQ,KAAK+D,MAAOkD,EAAYzX,GAAG,IAGP,GAAnCwQ,KAAK+D,MAAOkD,EAAYzX,GAAG,MAC5ByX,EAAYzX,GAAG,IAAM,IAK7B0B,GAAKiW,QAAQF,EAEb,IAAI3I,IACA8I,WACIC,KAAM,GACNC,IAAK,GACL/C,MAAO,MACPgD,OAAQ,OAEZC,QAAS,WACTC,UAAW,WAEXC,QAAUC,SAAU,QACpBC,OACIC,OAAQ,WACRC,YAAcC,IAAK,IAEvBC,SAAWC,QAAQ,GACnBC,QACIC,GAAKC,KAAM,SAEfC,MACIC,GACIC,MAAQC,MAAO,yBAKvBC,EAAQ,GAAI5B,QAAOC,cAAc4B,UAAUvQ,SAASwQ,eAAe,gBACvEF,GAAMG,KAAK1X,EAAMoN,GAEjB7F,EAAE6C,QAAQuN,OAAO,WACbJ,EAAMG,KAAK1X,EAAMoN,QAI/BvM,S7Bk7DI,SAAUxC,EAAQD,EAASH,GAEjC,Y8BthEAA,GAAQ,IACRA,EAAQ,IACRA,EAAQ,IACRA,EAAQ,IACRA,EAAQ,IACRA,EAAQ,IACRA,EAAQ,IACRA,EAAQ,IACRA,EAAQ,IACRA,EAAQ,K9B6hEF,SAAUI,EAAQD,EAASH,GAEjC,YAGAe,QAAOC,eAAeb,EAAS,cAC3BO,OAAO,G+B5iEX,IAAMuS,GAAM,SAAE0G,EAAUC,EAASC,GAC7B,GAAIC,GAAMH,EACNI,EAASH,EAAQI,cACjBC,GAAkB,EAClBhP,GAAW,EACXiP,GAAU,EAERC,EAAWL,EAAIhQ,KAAM,mBACvBsQ,EAAWN,EAAIhQ,KAAM,mBACrBuQ,EAAUP,EAAIhQ,KAAM,kBACpBwQ,EAAaR,EAAIhQ,KAAM,2BACvByQ,EAAeT,EAAIhQ,KAAM,oBAM7B,OAJK+P,KACDI,EAAkBJ,EAAYG,gBAI9BvP,KAAM,WACFqP,EAAIxL,SAAU,iBACd4L,GAAU,GAGd/O,KAAM,WACF2O,EAAIzL,YAAa,iBACjB6L,GAAU,GAGdlG,WAAY,WACR,MAAO8F,IAGXU,MAAO,WACH,MAAOV,GAAI3M,KAAM,OAGrBsN,UAAW,WACP,MAAOV,IAGXW,YAAa,SAAUtP,GACnB,MAAc,KAATA,IAILA,EAAOA,EAAK4O,cACLD,EAAOY,OAAQvP,IAAW,IAGrCwP,qBAAsB,SAAUxP,GAC5B,MAAc,KAATA,KAIE6O,IAIP7O,EAAOA,EAAK4O,cACLC,IAAoB7O,IAG/ByP,UAAW,WACP,MAAOX,IAGXY,WAAY,WACR,MAAO7P,IAGX0I,OAAQ,WACJ1I,GAAW,GAGf2I,SAAU,WACN3I,GAAW,GAGfT,OAAQ,SAAU8I,EAAM5S,GACpB,OAAS4S,GACL,IAAK,SACD+G,EAAQ1K,KAAM,UAAWjP,EACzB,MAEJ,KAAK,UACD0Z,EAASzK,KAAM,UAAWjP,EAC1B,MAEJ,KAAK,UACD6Z,EAAalM,cACb8L,EAASxK,KAAM,UAAWjP,GACrBA,GACDoZ,EAAIzL,YAAa,YACjBkM,EAAajM,SAAU,2BACvB6L,EAAShN,KAAM,WAAW,KAE1B2M,EAAIxL,SAAU,YACdiM,EAAajM,SAAU,6BACvB6L,EAASzM,WAAY,WAEzB,MAEJ,KAAK,SACD4M,EAAW3K,KAAM,UAAWjP,M/B2jEhDP,GAAQiF,Q+BljEO6N,G/BsjET,SAAU7S,EAAQD,EAASH,GAEjC,YAGAe,QAAOC,eAAeb,EAAS,cAC3BO,OAAO,GAGX,IAAI4E,GAA4B,kBAAXO,SAAoD,gBAApBA,QAAOC,SAAwB,SAAUC,GAAO,aAAcA,IAAS,SAAUA,GAAO,MAAOA,IAAyB,kBAAXF,SAAyBE,EAAIC,cAAgBH,QAAUE,IAAQF,OAAOrE,UAAY,eAAkBuE,IgC/qEhQ8M,EAAiB,WACnB,GAAIgB,MACAkH,EAAgB,GAChBC,EAAyB,EAE7B,QACI9H,KAAM,SAAUH,GACQ,gBAAf,KAAOA,EAAP,YAAAzN,EAAOyN,KACRc,EAAMX,KAAMH,IAIpBe,SAAU,WACN,MAAOD,IAGXc,QAAS,SAAUtU,GACf,QAAKwT,EAAMxT,IACAwT,EAAMxT,IAUrBqT,YAAa,SAAUhQ,EAAMuL,GACzB,GAAIvO,IAAQ,CACZ,KAAM,GAAIL,KAAKwT,GACX,GAAK,aAAenQ,EAAO,IAAMuL,IAAO4E,EAAMxT,GAAGma,QAAU,CACvD9Z,EAAQmT,EAAMxT,EACd,OAGR,MAAOK,IAGX8S,gBAAiB,WACb,GAAI0G,KACJ,KAAM,GAAI7Z,KAAKwT,GACNA,EAAMxT,GAAGwa,aACVX,EAAQhH,KAAMW,EAAMxT,GAG5B,OAAO6Z,IAGXe,iBAAkB,WACd,GAAIhQ,KAEJ,KAAM,GAAI5K,KAAKwT,GACNA,EAAMxT,GAAGwa,aAAehH,EAAMxT,GAAGya,cAClC7P,EAASiI,KAAMW,EAAMxT,GAI7B,OAAO4K,IAGXmI,UAAW,SAAU2G,EAAQrW,GACX,cAATA,EACDsX,EAAyBjB,EAGzBgB,EAAgBhB,GAIxB1G,aAAc,WACV,IAAM,GAAIhT,KAAKwT,GACNA,EAAMxT,KACFwT,EAAMxT,GAAGqa,YAAaK,IAAmBlH,EAAMxT,GAAGua,qBAAsBI,GACzEnH,EAAMxT,GAAG8K,OAGT0I,EAAMxT,GAAGoK,UhCurEjCtK,GAAQiF,QgC9qEOyN,GhCkrET,SAAUzS,EAAQD,EAASH,GAEjC,YAGAe,QAAOC,eAAeb,EAAS,cAC7BO,OAAO,GiCvwEI8R,MAAM,SAAE0I,GACjB,MAAO9X,MAAK8G,QAASgR,IAAS,IASrB5I,UAAU,SAAE6I,GACrB,MAAO/X,MAAKgY,MAAOD,IAAY,KjCqxE7B,SAAU/a,EAAQD,GkC7xExB,QAAA4M,GAAAnF,EAAAyT,EAAA/Y,GACA,OAAAA,EAAAL,QACA,aAAA2F,GAAArH,KAAA8a,EACA,cAAAzT,GAAArH,KAAA8a,EAAA/Y,EAAA,GACA,cAAAsF,GAAArH,KAAA8a,EAAA/Y,EAAA,GAAAA,EAAA,GACA,cAAAsF,GAAArH,KAAA8a,EAAA/Y,EAAA,GAAAA,EAAA,GAAAA,EAAA,IAEA,MAAAsF,GAAAmF,MAAAsO,EAAA/Y,GAGAlC,EAAAD,QAAA4M,GlC8yEM,SAAU3M,EAAQD,EAASH,GmC7yEjC,QAAAsb,GAAA5a,EAAA6a,GACA,GAAAC,GAAAC,EAAA/a,GACAgb,GAAAF,GAAAG,EAAAjb,GACAkb,GAAAJ,IAAAE,GAAAG,EAAAnb,GACAob,GAAAN,IAAAE,IAAAE,GAAAG,EAAArb,GACAsb,EAAAR,GAAAE,GAAAE,GAAAE,EACAG,EAAAD,EAAAE,EAAAxb,EAAAuB,OAAAka,WACAla,EAAAga,EAAAha,MAEA,QAAAoF,KAAA3G,IACA6a,IAAA9Z,EAAAlB,KAAAG,EAAA2G,IACA2U,IAEA,UAAA3U,GAEAuU,IAAA,UAAAvU,GAAA,UAAAA,IAEAyU,IAAA,UAAAzU,GAAA,cAAAA,GAAA,cAAAA,IAEAU,EAAAV,EAAApF,KAEAga,EAAA/I,KAAA7L,EAGA,OAAA4U,GA7CA,GAAAC,GAAAlc,EAAA,IACA2b,EAAA3b,EAAA,IACAyb,EAAAzb,EAAA,IACA6b,EAAA7b,EAAA,IACA+H,EAAA/H,EAAA,IACA+b,EAAA/b,EAAA,IAGAyH,EAAA1G,OAAAS,UAGAC,EAAAgG,EAAAhG,cAqCArB,GAAAD,QAAAmb,GnCy0EM,SAAUlb,EAAQD,EAASH,GoC52EjC,QAAAoc,GAAA1b,GACA,MAAAyG,GAAAzG,IAAAyF,EAAAzF,IAAA2b,EAdA,GAAAlW,GAAAnG,EAAA,GACAmH,EAAAnH,EAAA,GAGAqc,EAAA,oBAaAjc,GAAAD,QAAAic,GpCg4EM,SAAUhc,EAAQD,EAASH,GqC32EjC,QAAAsc,GAAA5b,GACA,SAAAwG,EAAAxG,IAAA6b,EAAA7b,MAGAuG,EAAAvG,GAAA8b,EAAAC,GACAvU,KAAAwU,EAAAhc,IA3CA,GAAAuG,GAAAjH,EAAA,IACAuc,EAAAvc,EAAA,IACAkH,EAAAlH,EAAA,GACA0c,EAAA1c,EAAA,IAMA2c,EAAA,sBAGAF,EAAA,8BAGAG,EAAA9V,SAAAtF,UACAiG,EAAA1G,OAAAS,UAGAqb,EAAAD,EAAAE,SAGArb,EAAAgG,EAAAhG,eAGA+a,EAAAO,OAAA,IACAF,EAAAtc,KAAAkB,GAAAub,QAAAL,EAAA,QACAK,QAAA,sEAmBA5c,GAAAD,QAAAmc,GrCw5EM,SAAUlc,EAAQD,EAASH,GsCh5EjC,QAAAid,GAAAvc,GACA,MAAAyG,GAAAzG,IACAsG,EAAAtG,EAAAuB,WAAAib,EAAA/W,EAAAzF,IAxDA,GAAAyF,GAAAnG,EAAA,GACAgH,EAAAhH,EAAA,IACAmH,EAAAnH,EAAA,GA8BAkd,IACAA,GAZA,yBAYAA,EAXA,yBAYAA,EAXA,sBAWAA,EAVA,uBAWAA,EAVA,uBAUAA,EATA,uBAUAA,EATA,8BASAA,EARA,wBASAA,EARA,yBAQA,EACAA,EAjCA,sBAiCAA,EAhCA,kBAiCAA,EApBA,wBAoBAA,EAhCA,oBAiCAA,EApBA,qBAoBAA,EAhCA,iBAiCAA,EAhCA,kBAgCAA,EA/BA,qBAgCAA,EA/BA,gBA+BAA,EA9BA,mBA+BAA,EA9BA,mBA8BAA,EA7BA,mBA8BAA,EA7BA,gBA6BAA,EA5BA,mBA6BAA,EA5BA,qBA4BA,EAcA9c,EAAAD,QAAA8c,GtC68EM,SAAU7c,EAAQD,EAASH,GuCx/EjC,QAAAmd,GAAA7b,GACA,IAAA6G,EAAA7G,GACA,MAAA8b,GAAA9b,EAEA,IAAA2a,KACA,QAAA5U,KAAAtG,QAAAO,GACAG,EAAAlB,KAAAe,EAAA+F,IAAA,eAAAA,GACA4U,EAAA/I,KAAA7L,EAGA,OAAA4U,GA1BA,GAAA9T,GAAAnI,EAAA,IACAod,EAAApd,EAAA,IAGAyH,EAAA1G,OAAAS,UAGAC,EAAAgG,EAAAhG,cAsBArB,GAAAD,QAAAgd,GvC+gFM,SAAU/c,EAAQD,EAASH,GwChiFjC,QAAAqd,GAAAzV,EAAA0V,GACA,MAAAC,GAAAC,EAAA5V,EAAA0V,EAAAhV,GAAAV,EAAA,IAbA,GAAAU,GAAAtI,EAAA,IACAwd,EAAAxd,EAAA,IACAud,EAAAvd,EAAA,GAcAI,GAAAD,QAAAkd,GxCmjFM,SAAUjd,EAAQD,EAASH,GyCnkFjC,GAAAyd,GAAAzd,EAAA,IACAgB,EAAAhB,EAAA,GACAsI,EAAAtI,EAAA,IAUA0d,EAAA1c,EAAA,SAAA4G,EAAA+V,GACA,MAAA3c,GAAA4G,EAAA,YACA3G,cAAA,EACAC,YAAA,EACAR,MAAA+c,EAAAE,GACAjW,UAAA,KALAY,CASAlI,GAAAD,QAAAud,GzC0kFM,SAAUtd,EAAQD,G0CtlFxB,QAAA+b,GAAA9a,EAAAwc,GAIA,IAHA,GAAA9K,IAAA,EACAmJ,EAAA4B,MAAAzc,KAEA0R,EAAA1R,GACA6a,EAAAnJ,GAAA8K,EAAA9K,EAEA,OAAAmJ,GAGA7b,EAAAD,QAAA+b,G1CsmFM,SAAU9b,EAAQD,G2ClnFxB,QAAA2d,GAAAlW,GACA,gBAAAlH,GACA,MAAAkH,GAAAlH,IAIAN,EAAAD,QAAA2d,G3CgoFM,SAAU1d,EAAQD,EAASH,G4ChoFjC,QAAA+d,GAAAC,EAAAC,EAAA3c,EAAA4c,GACA,GAAAC,IAAA7c,CACAA,UAKA,KAHA,GAAAwR,IAAA,EACA7Q,EAAAgc,EAAAhc,SAEA6Q,EAAA7Q,GAAA,CACA,GAAAoF,GAAA4W,EAAAnL,GAEAsL,EAAAF,EACAA,EAAA5c,EAAA+F,GAAA2W,EAAA3W,KAAA/F,EAAA0c,OACA9b,OAEAA,KAAAkc,IACAA,EAAAJ,EAAA3W,IAEA8W,EACA3W,EAAAlG,EAAA+F,EAAA+W,GAEAhX,EAAA9F,EAAA+F,EAAA+W,GAGA,MAAA9c,GApCA,GAAA8F,GAAApH,EAAA,GACAwH,EAAAxH,EAAA,EAsCAI,GAAAD,QAAA4d,G5CopFM,SAAU3d,EAAQD,EAASH,G6C3rFjC,GAAA6G,GAAA7G,EAAA,GAGAqe,EAAAxX,EAAA,qBAEAzG,GAAAD,QAAAke,G7CksFM,SAAUje,EAAQD,EAASH,G8C7rFjC,QAAAse,GAAAC,GACA,MAAAlB,GAAA,SAAA/b,EAAAkd,GACA,GAAA1L,IAAA,EACA7Q,EAAAuc,EAAAvc,OACAic,EAAAjc,EAAA,EAAAuc,EAAAvc,EAAA,OAAAC,GACAuc,EAAAxc,EAAA,EAAAuc,EAAA,OAAAtc,EAWA,KATAgc,EAAAK,EAAAtc,OAAA,qBAAAic,IACAjc,IAAAic,OACAhc,GAEAuc,GAAAC,EAAAF,EAAA,GAAAA,EAAA,GAAAC,KACAP,EAAAjc,EAAA,MAAAC,GAAAgc,EACAjc,EAAA,GAEAX,EAAAP,OAAAO,KACAwR,EAAA7Q,GAAA,CACA,GAAA+b,GAAAQ,EAAA1L,EACAkL,IACAO,EAAAjd,EAAA0c,EAAAlL,EAAAoL,GAGA,MAAA5c,KAhCA,GAAA+b,GAAArd,EAAA,IACA0e,EAAA1e,EAAA,GAmCAI,GAAAD,QAAAme,G9C8sFM,SAAUle,EAAQD,EAASH,G+CvuFjC,QAAA2H,GAAArG,EAAA+F,GACA,GAAA3G,GAAAie,EAAArd,EAAA+F,EACA,OAAAiV,GAAA5b,SAAAwB,GAbA,GAAAoa,GAAAtc,EAAA,IACA2e,EAAA3e,EAAA,GAeAI,GAAAD,QAAAwH,G/CyvFM,SAAUvH,EAAQD,EAASH,GgDhvFjC,QAAAuG,GAAA7F,GACA,GAAAke,GAAAnd,EAAAlB,KAAAG,EAAA4F,GACAiC,EAAA7H,EAAA4F,EAEA,KACA5F,EAAA4F,OAAApE,EACA,IAAA2c,IAAA,EACG,MAAAhX,IAEH,GAAAoU,GAAA6C,EAAAve,KAAAG,EAQA,OAPAme,KACAD,EACAle,EAAA4F,GAAAiC,QAEA7H,GAAA4F,IAGA2V,EA1CA,GAAApW,GAAA7F,EAAA,GAGAyH,EAAA1G,OAAAS,UAGAC,EAAAgG,EAAAhG,eAOAqd,EAAArX,EAAAqV,SAGAxW,EAAAT,IAAAY,gBAAAvE,EA6BA9B,GAAAD,QAAAoG,GhDgxFM,SAAUnG,EAAQD,GiDrzFxB,QAAAwe,GAAArd,EAAA+F,GACA,aAAA/F,MAAAY,GAAAZ,EAAA+F,GAGAjH,EAAAD,QAAAwe,GjDo0FM,SAAUve,EAAQD,EAASH,GkDj0FjC,QAAA0e,GAAAhe,EAAAoS,EAAAxR,GACA,IAAA4F,EAAA5F,GACA,QAEA,IAAAoC,SAAAoP,EACA,oBAAApP,EACAqD,EAAAzF,IAAAyG,EAAA+K,EAAAxR,EAAAW,QACA,UAAAyB,GAAAoP,IAAAxR,KAEAiG,EAAAjG,EAAAwR,GAAApS,GAxBA,GAAA6G,GAAAvH,EAAA,IACA+G,EAAA/G,EAAA,GACA+H,EAAA/H,EAAA,IACAkH,EAAAlH,EAAA,EA0BAI,GAAAD,QAAAue,GlDu1FM,SAAUte,EAAQD,EAASH,GmDr2FjC,QAAAuc,GAAA3U,GACA,QAAAmX,OAAAnX,GAhBA,GAAAyW,GAAAre,EAAA,IAGA+e,EAAA,WACA,GAAAC,GAAA,SAAAC,KAAAZ,KAAAa,MAAAb,EAAAa,KAAAC,UAAA,GACA,OAAAH,GAAA,iBAAAA,EAAA,KAcA5e,GAAAD,QAAAoc,GnD23FM,SAAUnc,EAAQD,EAASH,GoD94FjC,GAAAof,GAAApf,EAAA,IAGAod,EAAAgC,EAAAre,OAAAme,KAAAne,OAEAX,GAAAD,QAAAid,GpDq5FM,SAAUhd,EAAQD,EAASH,IqD15FjC,SAAAI,GAAA,GAAAsG,GAAA1G,EAAA,IAGAqf,EAAA,gBAAAlf,UAAAmf,UAAAnf,EAGAof,EAAAF,GAAA,gBAAAjf,UAAAkf,UAAAlf,EAGAof,EAAAD,KAAApf,UAAAkf,EAGAI,EAAAD,GAAA9Y,EAAAgZ,QAGAC,EAAA,WACA,IACA,MAAAF,MAAAG,SAAAH,EAAAG,QAAA,QACG,MAAA/X,OAGHzH,GAAAD,QAAAwf,IrD85F6Bpf,KAAKJ,EAASH,EAAoB,IAAII,KAI7D,SAAUA,EAAQD,GsDt6FxB,QAAAqG,GAAA9F,GACA,MAAAoe,GAAAve,KAAAG,GAjBA,GAAA+G,GAAA1G,OAAAS,UAOAsd,EAAArX,EAAAqV,QAaA1c,GAAAD,QAAAqG,GtD87FM,SAAUpG,EAAQD,GuD38FxB,QAAAif,GAAAxX,EAAAiY,GACA,gBAAAC,GACA,MAAAlY,GAAAiY,EAAAC,KAIA1f,EAAAD,QAAAif,GvD09FM,SAAUhf,EAAQD,EAASH,GwD19FjC,QAAAwd,GAAA5V,EAAA0V,EAAAuC,GAEA,MADAvC,GAAAyC,MAAA7d,KAAAob,EAAA1V,EAAA3F,OAAA,EAAAqb,EAAA,GACA,WAMA,IALA,GAAAhb,GAAAN,UACA8Q,GAAA,EACA7Q,EAAA8d,EAAAzd,EAAAL,OAAAqb,EAAA,GACA0C,EAAAnC,MAAA5b,KAEA6Q,EAAA7Q,GACA+d,EAAAlN,GAAAxQ,EAAAgb,EAAAxK,EAEAA,IAAA,CAEA,KADA,GAAAmN,GAAApC,MAAAP,EAAA,KACAxK,EAAAwK,GACA2C,EAAAnN,GAAAxQ,EAAAwQ,EAGA,OADAmN,GAAA3C,GAAAuC,EAAAG,GACAjT,EAAAnF,EAAAvC,KAAA4a,IA/BA,GAAAlT,GAAA/M,EAAA,IAGA+f,EAAAlP,KAAAqP,GAgCA9f,GAAAD,QAAAqd,GxD++FM,SAAUpd,EAAQD,EAASH,GyDlhGjC,GAAA0d,GAAA1d,EAAA,IACAmgB,EAAAngB,EAAA,IAUAud,EAAA4C,EAAAzC,EAEAtd,GAAAD,QAAAod,GzDyhGM,SAAUnd,EAAQD,G0DthGxB,QAAAggB,GAAAvY,GACA,GAAAwY,GAAA,EACAC,EAAA,CAEA,mBACA,GAAAC,GAAAC,IACAC,EAAAC,GAAAH,EAAAD,EAGA,IADAA,EAAAC,EACAE,EAAA,GACA,KAAAJ,GAAAM,EACA,MAAA1e,WAAA,OAGAoe,GAAA,CAEA,OAAAxY,GAAAmF,UAAA7K,GAAAF,YA/BA,GAAA0e,GAAA,IACAD,EAAA,GAGAF,EAAAxI,KAAA4I,GA+BAvgB,GAAAD,QAAAggB,G1D6iGM,SAAU/f,EAAQD,G2DpkGxB,QAAAuc,GAAA9U,GACA,SAAAA,EAAA,CACA,IACA,MAAAiV,GAAAtc,KAAAqH,GACK,MAAAC,IACL,IACA,MAAAD,GAAA,GACK,MAAAC,KAEL,SArBA,GAAA+U,GAAA9V,SAAAtF,UAGAqb,EAAAD,EAAAE,QAqBA1c,GAAAD,QAAAuc,G3DwlGM,SAAUtc,EAAQD,EAASH,G4DjnGjC,GAAAoH,GAAApH,EAAA,GACA+d,EAAA/d,EAAA,IACAse,EAAAte,EAAA,IACA+G,EAAA/G,EAAA,GACAmI,EAAAnI,EAAA,IACAkf,EAAAlf,EAAA,IAGAyH,EAAA1G,OAAAS,UAGAC,EAAAgG,EAAAhG,eAkCAmf,EAAAtC,EAAA,SAAAhd,EAAA0c,GACA,GAAA7V,EAAA6V,IAAAjX,EAAAiX,GAEA,WADAD,GAAAC,EAAAkB,EAAAlB,GAAA1c,EAGA,QAAA+F,KAAA2W,GACAvc,EAAAlB,KAAAyd,EAAA3W,IACAD,EAAA9F,EAAA+F,EAAA2W,EAAA3W,KAKAjH,GAAAD,QAAAygB,G5DwnGM,SAAUxgB,EAAQD,G6D9pGxB,QAAAsd,GAAA/c,GACA,kBACA,MAAAA,IAIAN,EAAAD,QAAAsd,G7DwrGM,SAAUrd,EAAQD,EAASH,G8DjtGjC,GAAAoc,GAAApc,EAAA,IACAmH,EAAAnH,EAAA,GAGAyH,EAAA1G,OAAAS,UAGAC,EAAAgG,EAAAhG,eAGAof,EAAApZ,EAAAoZ,qBAoBAlF,EAAAS,EAAA,WAA8C,MAAApa,eAAoBoa,EAAA,SAAA1b,GAClE,MAAAyG,GAAAzG,IAAAe,EAAAlB,KAAAG,EAAA,YACAmgB,EAAAtgB,KAAAG,EAAA,UAGAN,GAAAD,QAAAwb,G9DwtGM,SAAUvb,EAAQD,G+DpuGxB,GAAAsb,GAAAoC,MAAApC,OAEArb,GAAAD,QAAAsb,G/DkwGM,SAAUrb,EAAQD,EAASH,IgE3xGjC,SAAAI,GAAA,GAAAyG,GAAA7G,EAAA,GACA8gB,EAAA9gB,EAAA,IAGAqf,EAAA,gBAAAlf,UAAAmf,UAAAnf,EAGAof,EAAAF,GAAA,gBAAAjf,UAAAkf,UAAAlf,EAGAof,EAAAD,KAAApf,UAAAkf,EAGA0B,EAAAvB,EAAA3Y,EAAAka,WAAA7e,GAGA8e,EAAAD,IAAAlF,aAAA3Z,GAmBA2Z,EAAAmF,GAAAF,CAEA1gB,GAAAD,QAAA0b,IhE+xG6Btb,KAAKJ,EAASH,EAAoB,IAAII,KAI7D,SAAUA,EAAQD,EAASH,GiEx0GjC,GAAAid,GAAAjd,EAAA,IACA8d,EAAA9d,EAAA,IACA2f,EAAA3f,EAAA,IAGAihB,EAAAtB,KAAA5D,aAmBAA,EAAAkF,EAAAnD,EAAAmD,GAAAhE,CAEA7c,GAAAD,QAAA4b,GjE+0GM,SAAU3b,EAAQD,EAASH,GkEz0GjC,QAAAkf,GAAA5d,GACA,MAAAyF,GAAAzF,GAAAga,EAAAha,GAAA6b,EAAA7b,GAjCA,GAAAga,GAAAtb,EAAA,IACAmd,EAAAnd,EAAA,IACA+G,EAAA/G,EAAA,EAkCAI,GAAAD,QAAA+e,GlEg3GM,SAAU9e,EAAQD,GmEv4GxB,QAAA2gB,KACA,SAGA1gB,EAAAD,QAAA2gB,GnE25GM,SAAU1gB,EAAQD,GoE56GxB,GAAA+gB,EAGAA,GAAA,WACA,MAAA7b,QAGA,KAEA6b,KAAApa,SAAA,qBAAAqa,MAAA,QACC,MAAAtZ,GAED,gBAAAsE,UACA+U,EAAA/U,QAOA/L,EAAAD,QAAA+gB","file":"admin.min.js","sourcesContent":["/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// identity function for calling harmony imports with the correct context\n/******/ \t__webpack_require__.i = function(value) { return value; };\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 28);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _assign = __webpack_require__(58);\n\nvar _assign2 = _interopRequireDefault(_assign);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction Fetcher() {\n var fetchUrl = ajaxurl;\n var fetchNonce = wphb.nonces.HBFetchNonce;\n var actionPrefix = 'wphb_';\n var actionPrefixPro = 'wphb_pro_';\n\n function request(action) {\n var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var method = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'GET';\n\n data.nonce = fetchNonce;\n data.action = action;\n var args = { data: data, method: method };\n args.url = fetchUrl;\n return new Promise(function (resolve, reject) {\n jQuery.ajax(args).done(resolve).fail(reject);\n }).then(function (response) {\n return checkStatus(response);\n });\n }\n\n var methods = {\n /**\n * Caching module actions.\n */\n caching: {\n /**\n * Set expiration for browser caching.\n *\n * @param type File type.\n * @param value Expiry value.\n */\n setExpiration: function setExpiration(type, value) {\n var action = actionPrefix + 'caching_set_expiration';\n return request(action, { type: type, value: value }, 'POST');\n },\n\n /**\n * Set server type.\n *\n * @param value Server type.\n */\n setServer: function setServer(value) {\n var action = actionPrefix + 'caching_set_server_type';\n return request(action, { value: value }, 'POST');\n },\n\n /**\n * Reload snippet.\n *\n * @param type Server type.\n */\n reloadSnippets: function reloadSnippets(type) {\n var action = actionPrefix + 'caching_reload_snippet';\n return request(action, { type: type }, 'POST').then(function (response) {\n return response;\n });\n }\n },\n\n /**\n * CLoudflare module actions.\n */\n cloudflare: {\n /**\n * Connect to CloudFlare.\n *\n * @param step\n * @param formData\n * @param cfData\n */\n connect: function connect(step, formData, cfData) {\n var action = actionPrefix + 'cloudflare_connect';\n return request(action, { step: step, formData: formData, cfData: cfData }, 'POST').then(function (response) {\n return response;\n });\n },\n\n /**\n * Set expiry for CloudFlare cache.\n *\n * @param value Expiry value.\n */\n setExpiration: function setExpiration(value) {\n var action = actionPrefix + 'cloudflare_set_expiry';\n return request(action, { value: value }, 'POST');\n },\n\n /**\n * Purge CloudFlare cache.\n */\n purgeCache: function purgeCache() {\n var action = actionPrefix + 'cloudflare_purge_cache';\n return request(action, {}, 'POST');\n }\n },\n\n /**\n * Dashboard module actions.\n */\n dashboard: {\n /**\n * Toggle global minification settings for network installs.\n *\n * @param value Accepts: 'super-admins', 'false' and 'true'. Default: 'true'.\n */\n toggleMinification: function toggleMinification(value) {\n var action = actionPrefix + 'dash_toggle_network_minification';\n return request(action, { value: value }, 'POST');\n },\n\n /**\n * Skip quick setup.\n */\n skipSetup: function skipSetup() {\n var action = actionPrefix + 'dash_skip_setup';\n return request(action, {}, 'POST');\n }\n },\n\n /**\n * Minification module actions.\n */\n minification: {\n /**\n * Toggle CDN settings.\n *\n * @param value CDN checkbox value.\n */\n toggleCDN: function toggleCDN(value) {\n var action = actionPrefix + 'minification_toggle_cdn';\n return request(action, { value: value }, 'POST');\n },\n\n /**\n * Toggle minificatiojn settings on per site basis.\n *\n * @param value\n */\n toggleMinification: function toggleMinification(value) {\n var action = actionPrefix + 'minification_toggle_minification';\n return request(action, { value: value }, 'POST');\n },\n\n /**\n * Start minification check.\n *\n * @param progress\n */\n startCheck: function startCheck(progress) {\n var action = actionPrefix + 'minification_start_check';\n return request(action, { progress: progress }, 'POST').then(function (response) {\n return response;\n });\n },\n\n /**\n * Do a step in minification process.\n *\n * @param progress\n * @param step\n */\n checkStep: function checkStep(progress, step) {\n var action = actionPrefix + 'minification_check_step';\n return request(action, { progress: progress, step: step }, 'POST').then(function (response) {\n return response;\n });\n },\n\n /**\n * Cancel minification scan.\n */\n cancelScan: function cancelScan() {\n var action = actionPrefix + 'minification_cancel_scan';\n return request(action, {}, 'POST');\n }\n },\n\n /**\n * Performance module actions.\n */\n performance: {\n /**\n * Run performance test.\n */\n runTest: function runTest() {\n var action = actionPrefix + 'performance_run_test';\n return request(action, {}, 'POST').then(function (response) {\n return response;\n });\n },\n\n /**\n * Add a single email/name recipient to the reports list.\n *\n * @param email\n * @param name\n */\n addRecipient: function addRecipient(email, name) {\n var action = actionPrefixPro + 'performance_add_recipient';\n return request(action, { email: email, name: name }, 'POST').then(function (response) {\n return response;\n });\n },\n\n /**\n * Save reporting settings on minification page.\n *\n * @param data From data.\n */\n saveReportsSettings: function saveReportsSettings(data) {\n var action = actionPrefixPro + 'performance_save_reports_settings';\n return request(action, { data: data }, 'POST');\n }\n }\n };\n\n (0, _assign2.default)(this, methods);\n}\n\nvar HBFetcher = new Fetcher();\nexports.default = HBFetcher;\n\n\nfunction checkStatus(response) {\n if ((typeof response === 'undefined' ? 'undefined' : _typeof(response)) !== 'object') {\n response = JSON.parse(response);\n }\n if (response.success) {\n return response.data;\n }\n\n var data = response.data || {};\n var error = new Error(data.message || 'Error trying to fetch response from server');\n error.response = response;\n throw error;\n}\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar Symbol = __webpack_require__(6),\n getRawTag = __webpack_require__(46),\n objectToString = __webpack_require__(52);\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nmodule.exports = baseGetTag;\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar freeGlobal = __webpack_require__(10);\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nmodule.exports = root;\n\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar isFunction = __webpack_require__(15),\n isLength = __webpack_require__(16);\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\nmodule.exports = isArrayLike;\n\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports) {\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nmodule.exports = isObject;\n\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports) {\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar root = __webpack_require__(2);\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nmodule.exports = Symbol;\n\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseAssignValue = __webpack_require__(8),\n eq = __webpack_require__(13);\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nmodule.exports = assignValue;\n\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar defineProperty = __webpack_require__(9);\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n}\n\nmodule.exports = baseAssignValue;\n\n\n/***/ }),\n/* 9 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar getNative = __webpack_require__(45);\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nmodule.exports = defineProperty;\n\n\n/***/ }),\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nmodule.exports = freeGlobal;\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(66)))\n\n/***/ }),\n/* 11 */\n/***/ (function(module, exports) {\n\n/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n length = length == null ? MAX_SAFE_INTEGER : length;\n return !!length &&\n (typeof value == 'number' || reIsUint.test(value)) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nmodule.exports = isIndex;\n\n\n/***/ }),\n/* 12 */\n/***/ (function(module, exports) {\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nmodule.exports = isPrototype;\n\n\n/***/ }),\n/* 13 */\n/***/ (function(module, exports) {\n\n/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nmodule.exports = eq;\n\n\n/***/ }),\n/* 14 */\n/***/ (function(module, exports) {\n\n/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nmodule.exports = identity;\n\n\n/***/ }),\n/* 15 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseGetTag = __webpack_require__(1),\n isObject = __webpack_require__(4);\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nmodule.exports = isFunction;\n\n\n/***/ }),\n/* 16 */\n/***/ (function(module, exports) {\n\n/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nmodule.exports = isLength;\n\n\n/***/ }),\n/* 17 */\n/***/ (function(module, exports) {\n\nmodule.exports = function(module) {\r\n\tif(!module.webpackPolyfill) {\r\n\t\tmodule.deprecate = function() {};\r\n\t\tmodule.paths = [];\r\n\t\t// module.parent = undefined by default\r\n\t\tif(!module.children) module.children = [];\r\n\t\tObject.defineProperty(module, \"loaded\", {\r\n\t\t\tenumerable: true,\r\n\t\t\tget: function() {\r\n\t\t\t\treturn module.l;\r\n\t\t\t}\r\n\t\t});\r\n\t\tObject.defineProperty(module, \"id\", {\r\n\t\t\tenumerable: true,\r\n\t\t\tget: function() {\r\n\t\t\t\treturn module.i;\r\n\t\t\t}\r\n\t\t});\r\n\t\tmodule.webpackPolyfill = 1;\r\n\t}\r\n\treturn module;\r\n};\r\n\n\n/***/ }),\n/* 18 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\njQuery(document).ready(function () {\n WPHB_Admin.init();\n});\n\n/***/ }),\n/* 19 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _fetcher = __webpack_require__(0);\n\nvar _fetcher2 = _interopRequireDefault(_fetcher);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(function ($) {\n 'use strict';\n\n WPHB_Admin.caching = {\n\n module: 'caching',\n selectedServer: '',\n $serverSelector: null,\n $serverInstructions: [],\n $expirySelectors: [],\n $snippets: [],\n\n init: function init() {\n var self = this,\n cachingMetabox = $('#wphb-box-caching-enable'),\n cachingContent = cachingMetabox.find('.box-content'),\n cachingContentSpinner = cachingContent.find('.spinner'),\n cachingFooter = cachingMetabox.find('.box-footer');\n\n if (wphbCachingStrings) self.strings = wphbCachingStrings;\n\n this.$serverSelector = $('#wphb-server-type');\n this.selectedServer = this.$serverSelector.val();\n //this.$spinner = $('#wphb-box-caching-enable .spinner');\n\n self.$snippets.apache = $('#wphb-code-snippet-apache').find('pre').first();\n self.$snippets.nginx = $('#wphb-code-snippet-nginx').find('pre').first();\n\n var instructionsList = $('.wphb-server-instructions');\n instructionsList.each(function () {\n self.$serverInstructions[$(this).data('server')] = $(this);\n });\n\n var expirySelectors = $('.wphb-expiry-select');\n\n expirySelectors.each(function () {\n var type = $(this).data('type');\n if (type) {\n $(this).change(function () {\n //self.$spinner.css( 'visibility', 'visible' );\n cachingContent.find('.wphb-content').hide();\n cachingFooter.hide();\n cachingContentSpinner.fadeIn();\n $('.wphb-notice').hide();\n\n // Expiration selector has changed\n (function (element) {\n var value = $(element).val();\n // Change the plugin settings\n _fetcher2.default.caching.setExpiration(type, value).then(function () {\n // And reload the code snippet\n self.reloadSnippets();\n });\n return false;\n })(this);\n });\n }\n });\n\n this.showServerInstructions(this.selectedServer);\n\n this.$serverSelector.change(function () {\n var value = $(this).val();\n self.hideCurrentInstructions();\n self.showServerInstructions(value);\n self.setServer(value);\n self.selectedServer = value;\n });\n\n $('#toggle-apache-instructions').click(function (e) {\n e.preventDefault();\n $('.apache-instructions').slideToggle();\n });\n\n $('#toggle-litespeed-instructions').click(function (e) {\n e.preventDefault();\n $('.litespeed-instructions').slideToggle();\n });\n\n return this;\n },\n\n setServer: function setServer(value) {\n _fetcher2.default.caching.setServer(value);\n },\n\n hideCurrentInstructions: function hideCurrentInstructions() {\n var selected = this.selectedServer;\n if (this.$serverInstructions[selected]) {\n this.$serverInstructions[selected].hide();\n }\n },\n\n showServerInstructions: function showServerInstructions(server) {\n if (typeof this.$serverInstructions[server] !== 'undefined') {\n this.$serverInstructions[server].show();\n }\n\n if ('apache' === server || 'LiteSpeed' === server) {\n $('#enable-cache-wrap').show();\n } else {\n $('#enable-cache-wrap').hide();\n }\n },\n\n reloadSnippets: function reloadSnippets() {\n var self = this;\n var stop = false;\n for (var i in self.$snippets) {\n if (self.$snippets.hasOwnProperty(i)) {\n _fetcher2.default.caching.reloadSnippets(i).then(function (response) {\n if (stop) {\n return;\n }\n\n self.$snippets[response.type].text(response.code);\n\n // Make sure that we only do things when server displayed is the processed one\n if (response.type !== self.selectedServer) {\n return;\n }\n\n if ('apache' === response.type && response.updatedFile) {\n $('#wphb-notice-code-snippet-htaccess-updated').show();\n location.href = self.strings.recheckURL + '&caching-updated=true';\n } else if ('apache' === response.type && self.strings.cacheEnabled && !response.updatedFile) {\n $('#wphb-notice-code-snippet-htaccess-error').show();\n location.href = self.strings.htaccessErrorURL;\n } else {\n $('#wphb-notice-code-snippet-updated').show();\n location.href = self.strings.recheckURL + '&caching-updated=true';\n }\n //self.$spinner.css( 'visibility', 'hidden' );\n });\n }\n }\n }\n };\n})(jQuery);\n\n/***/ }),\n/* 20 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _fetcher = __webpack_require__(0);\n\nvar _fetcher2 = _interopRequireDefault(_fetcher);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(function ($) {\n WPHB_Admin.cloudflare = {\n module: 'cloudflare',\n $cfSelector: false,\n $spinner: false,\n\n init: function init() {\n this.$spinner = $('.wphb-spinner');\n this.$cfSelector = $('#wphb-caching-cloudflare-summary-set-expiry');\n var self = this;\n if (wphb.cloudflare.is.connected) {\n this.$cfSelector.change(function () {\n self.setExpiry.call(self, [this]);\n });\n }\n\n return this;\n },\n\n setExpiry: function setExpiry(selector) {\n this.displaySpinner();\n var value = $(selector).val();\n _fetcher2.default.cloudflare.setExpiration(value).then(function () {\n window.location.reload();\n });\n },\n\n displaySpinner: function displaySpinner() {\n this.$spinner.css('visibility', 'visible');\n }\n };\n})(jQuery);\n\n/***/ }),\n/* 21 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _fetcher = __webpack_require__(0);\n\nvar _fetcher2 = _interopRequireDefault(_fetcher);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(function ($) {\n WPHB_Admin.DashboardCloudFlare = {\n init: function init(settings) {\n this.currentStep = settings.currentStep;\n this.data = settings;\n this.email = settings.email;\n this.apiKey = settings.apiKey;\n this.$stepsContainer = $('#cloudflare-steps');\n this.$infoBox = $('#cloudflare-info');\n this.$spinner = $('.cloudflare-spinner');\n this.$deactivateButton = $('#wphb-box-dashboard-cloudflare').find('.box-title .buttons');\n\n this.renderStep(this.currentStep);\n\n $('body').on('click', '.cloudflare-clear-cache .button', function (e) {\n e.preventDefault();\n this.purgeCache.apply($(e.target), [this]);\n }.bind(this));\n },\n\n purgeCache: function purgeCache(self) {\n // Show spinner\n var $button = this;\n $button.attr('disabled', true);\n self.showSpinner();\n\n _fetcher2.default.cloudflare.purgeCache().then(function () {\n // Show notice\n var $notice = $('#wphb-notice-cloudflare-purge-cache');\n window.scrollTo(0, 0);\n $notice.slideDown();\n setTimeout(function () {\n $notice.slideUp();\n }, 5e3);\n // Remove spinner\n $button.removeAttr('disabled');\n self.hideSpinner();\n });\n },\n\n renderStep: function renderStep(step) {\n var template = WPHB_Admin.DashboardCloudFlare.template('#cloudflare-step-' + step);\n var content = template(this.data);\n var self = this;\n\n if (content) {\n this.currentStep = step;\n this.$stepsContainer.hide().html(template(this.data)).fadeIn().find('form').on('submit', function (e) {\n e.preventDefault();\n self.submitStep.call(self, $(this));\n });\n\n this.$spinner = this.$stepsContainer.find('.cloudflare-spinner');\n }\n\n this.bindEvents();\n },\n\n bindEvents: function bindEvents() {\n var $howToInstructions = $('#cloudflare-how-to');\n\n $howToInstructions.hide();\n\n $('#cloudflare-how-to-title > a').click(function (e) {\n e.preventDefault();\n $howToInstructions.toggle();\n });\n\n this.$stepsContainer.find('select').each(function () {\n WDP.wpmuSelect(this);\n });\n\n if ('final' === this.currentStep) {\n this.$deactivateButton.removeClass('hidden');\n } else {\n this.$deactivateButton.addClass('hidden');\n }\n },\n\n emptyInfoBox: function emptyInfoBox() {\n this.$infoBox.html('');\n this.$infoBox.removeClass();\n },\n\n showInfoBox: function showInfoBox(message) {\n this.$infoBox.addClass('wphb-notice');\n this.$infoBox.addClass('wphb-notice-error');\n this.$infoBox.text(message);\n },\n\n showSpinner: function showSpinner() {\n this.$spinner.css('visibility', 'visible');\n },\n\n hideSpinner: function hideSpinner() {\n this.$spinner.css('visibility', 'hidden');\n },\n\n submitStep: function submitStep($form) {\n var self = this;\n\n $form.find('input[type=submit]').attr('disabled', 'true');\n this.emptyInfoBox();\n this.showSpinner();\n\n _fetcher2.default.cloudflare.connect(this.currentStep, $form.serialize(), this.data).then(function (response) {\n self.data = response.newData;\n self.renderStep(response.nextStep);\n\n if (response.nextStep === 'final') {\n window.location.href = response.redirect;\n }\n }).catch(function (error) {\n self.showInfoBox(error);\n });\n\n $form.find('input[type=submit]').removeAttr('disabled');\n self.hideSpinner();\n }\n };\n\n WPHB_Admin.DashboardCloudFlare.template = _.memoize(function (id) {\n var compiled = void 0,\n options = {\n evaluate: /<#([\\s\\S]+?)#>/g,\n interpolate: /\\{\\{\\{([\\s\\S]+?)\\}\\}\\}/g,\n escape: /\\{\\{([^\\}]+?)\\}\\}(?!\\})/g,\n variable: 'data'\n };\n\n return function (data) {\n _.templateSettings = options;\n compiled = compiled || _.template($(id).html());\n return compiled(data);\n };\n });\n})(jQuery);\n\n/***/ }),\n/* 22 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _fetcher = __webpack_require__(0);\n\nvar _fetcher2 = _interopRequireDefault(_fetcher);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(function ($) {\n WPHB_Admin.dashboard = {\n module: 'dashboard',\n\n init: function init() {\n var self = this;\n\n if (wphbDashboardStrings) this.strings = wphbDashboardStrings;\n\n $('#wphb-activate-minification').change(function () {\n var value = $(this).val();\n _fetcher2.default.dashboard.toggleMinification(value).then(function () {\n // If disabled, uncheck CDN checkbox and disable it.\n var CDNcheckbox = $('input[name=\"use_cdn\"]');\n if ('false' === value) {\n CDNcheckbox.prop('checked', false);\n CDNcheckbox.prop('disabled', true);\n } else {\n CDNcheckbox.prop('disabled', false);\n }\n self.showNotice();\n });\n });\n\n $('#use_cdn').change(function () {\n var value = $(this).is(':checked');\n _fetcher2.default.minification.toggleCDN(value).then(function () {\n self.showNotice();\n });\n });\n\n $('.wphb-performance-report-item').click(function () {\n var url = $(this).data('performance-url');\n if (url) {\n location.href = url;\n }\n });\n return this;\n },\n\n /**\n * Notice on settings update.\n */\n showNotice: function showNotice() {\n var notice = $('#wphb-notice-minification-settings-updated');\n notice.slideDown();\n setTimeout(function () {\n notice.slideUp();\n }, 5000);\n },\n\n /**\n * Run quick setup.\n */\n startQuickSetup: function startQuickSetup() {\n // Show quick setup modal\n WDP.showOverlay('#wphb-quick-setup-modal', { class: 'wphb-modal small wphb-quick-setup-modal no-close' });\n },\n\n /**\n * Skip quick setup.\n */\n skipSetup: function skipSetup() {\n _fetcher2.default.dashboard.skipSetup().then(function () {\n window.location.reload(true);\n });\n },\n\n /**\n * Run performance test after quick setup.\n */\n runPerformanceTest: function runPerformanceTest() {\n // Show quick setup modal\n WDP.showOverlay(\"#run-performance-test-modal\", { class: 'wphb-modal small wphb-progress-modal no-close' });\n\n // Run performance test\n var module = WPHB_Admin.getModule('performance');\n module.performanceTest(this.strings.finishedTestURLsLink);\n }\n };\n})(jQuery);\n\n/***/ }),\n/* 23 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _fetcher = __webpack_require__(0);\n\nvar _fetcher2 = _interopRequireDefault(_fetcher);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(function ($) {\n WPHB_Admin.gzip = {\n module: \"gzip\",\n selectedServer: \"\",\n $serverSelector: null,\n $serverInstructions: [],\n\n init: function init() {\n var self = this;\n\n this.$serverSelector = $(\"#wphb-server-type\");\n this.selectedServer = this.$serverSelector.val();\n var instructionsList = $(\".wphb-server-instructions\");\n instructionsList.each(function () {\n self.$serverInstructions[$(this).data(\"server\")] = $(this);\n });\n this.showServerInstructions(this.selectedServer);\n this.$serverSelector.change(function () {\n var value = $(this).val();\n self.hideCurrentInstructions();\n self.showServerInstructions(value);\n self.setServer(value);\n self.selectedServer = value;\n });\n $(\"#toggle-apache-instructions\").click(function (e) {\n e.preventDefault();\n $(\".apache-instructions\").toggle();\n });\n $(\"#toggle-litespeed-instructions\").click(function (e) {\n e.preventDefault();\n $(\".litespeed-instructions\").toggle();\n });\n return this;\n },\n\n hideCurrentInstructions: function hideCurrentInstructions() {\n var selected = this.selectedServer;\n if (this.$serverInstructions[selected]) {\n this.$serverInstructions[selected].hide();\n }\n },\n\n showServerInstructions: function showServerInstructions(server) {\n if (typeof this.$serverInstructions[server] !== \"undefined\") {\n this.$serverInstructions[server].show();\n }\n if (\"apache\" === server || 'LiteSpeed' === server) {\n $(\"#enable-cache-wrap\").show();\n } else {\n $(\"#enable-cache-wrap\").hide();\n }\n },\n\n setServer: function setServer(value) {\n _fetcher2.default.caching.setServer(value);\n }\n };\n})(jQuery);\n\n/***/ }),\n/* 24 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n(function ($) {\n 'use strict';\n\n var WPHB_Admin = {\n modules: [],\n // Common functionality to all screens\n init: function init() {\n\n function updatePerformanceGraph($wrap) {\n var $item = $wrap.find('.wphb-score-result-label'),\n val = parseInt($item.text(), 10) || 100,\n $circle = $wrap.find(\".wphb-score-graph-result\"),\n r = void 0,\n c = void 0,\n pct = void 0;\n r = $circle.attr('r');\n c = Math.PI * (r * 2);\n\n if (val < 0) {\n val = 0;\n }\n if (val > 100) {\n val = 100;\n }\n\n pct = (100 - val) / 100 * c;\n\n $circle.css({ strokeDashoffset: pct });\n }\n\n function updatePerformanceResultsGraphs() {\n\n // Update Overall Score\n $(\".wphb-performance-report-overall-score\").each(function () {\n updatePerformanceGraph($(this));\n });\n\n // Update Current Score\n $(\".wphb-performance-report-current-score\").each(function () {\n updatePerformanceGraph($(this));\n });\n\n // Update All Scores\n $(\".wphb-performance-report-item-score\").each(function () {\n updatePerformanceGraph($(this));\n });\n }\n window.register_events_performance = function () {\n setTimeout(updatePerformanceResultsGraphs, 500);\n };\n $(function () {\n setTimeout(updatePerformanceResultsGraphs, 500);\n });\n },\n initModule: function initModule(module) {\n if (this.hasOwnProperty(module)) {\n this.modules[module] = this[module].init();\n return this.modules[module];\n }\n\n return {};\n },\n getModule: function getModule(module) {\n if (typeof this.modules[module] !== 'undefined') return this.modules[module];else return this.initModule(module);\n }\n };\n\n WPHB_Admin.utils = {\n\n membershipModal: {\n open: function open() {\n $('#wphb-upgrade-membership-modal-link').trigger('click');\n }\n },\n\n post: function post(data, module) {\n data.action = 'wphb_ajax';\n data.module = module;\n return $.ajax({\n url: ajaxurl,\n method: 'POST',\n data: data\n });\n }\n };\n\n WPHB_Admin.notices = {\n\n init: function init() {\n $('.wphb-notice:not(.notice) a.wphb-dismiss').click(function (e) {\n e.preventDefault();\n var id = $(this).data('id');\n var nonce = $(this).data('nonce');\n\n $(this).parent('.error').hide();\n });\n }\n };\n\n window.WPHB_Admin = WPHB_Admin;\n})(jQuery);\n\n/***/ }),\n/* 25 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _fetcher = __webpack_require__(0);\n\nvar _fetcher2 = _interopRequireDefault(_fetcher);\n\nvar _helpers = __webpack_require__(31);\n\nvar _Row = __webpack_require__(29);\n\nvar _Row2 = _interopRequireDefault(_Row);\n\nvar _RowsCollection = __webpack_require__(30);\n\nvar _RowsCollection2 = _interopRequireDefault(_RowsCollection);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(function ($) {\n 'use strict';\n\n WPHB_Admin.minification = {\n\n $checkFilesButton: null,\n $checkFilesResultsContainer: null,\n module: 'minification',\n checkURLSList: null,\n checkedURLS: 0,\n $spinner: null,\n\n init: function init() {\n var self = this;\n\n // Filter action button on Minification page\n $('#wphb-minification-filter-button').on('click', function (e) {\n e.preventDefault();\n $('#wphb-minification-filter').toggle('slow');\n });\n\n // Check files button\n this.$checkFilesButton = $('#check-files');\n this.$disableMinification = $('#wphb-disable-minification');\n this.$spinner = $('.spinner');\n\n if (this.$checkFilesButton.length) {\n this.$checkFilesButton.click(function (e) {\n e.preventDefault();\n $(this).attr('disabled', true);\n self.checkFiles((0, _helpers.getLink)('minification'));\n });\n }\n\n $('.wphb-discard').click(function (e) {\n e.preventDefault();\n\n if (confirm((0, _helpers.__)('discardAlert'))) {\n location.reload();\n }\n return false;\n });\n\n $('.wphb-enqueued-files input').on('change', function () {\n $('.wphb-discard').attr('disabled', false);\n });\n\n $('#use_cdn').change(function () {\n var cdn_value = $(this).is(':checked');\n _fetcher2.default.minification.toggleCDN(cdn_value).then(function () {\n var notice = $('#wphb-notice-minification-advanced-settings-updated');\n notice.slideDown();\n setTimeout(function () {\n notice.slideUp();\n }, 5000);\n });\n });\n\n this.$disableMinification.change(function () {\n var value = $(this).is(':checked');\n\n self.$spinner.css('visibility', 'visible');\n\n if (self.timer && value) {\n clearTimeout(self.timer);\n self.$spinner.css('visibility', 'hidden');\n }\n\n self.timer = setTimeout(function () {\n _fetcher2.default.minification.toggleMinification(value).then(function () {\n location.reload();\n });\n }, 3000);\n });\n\n this.rowsCollection = new WPHB_Admin.minification.RowsCollection();\n\n var rows = $('.wphb-border-row');\n\n rows.each(function (index, row) {\n var _row = void 0;\n if ($(row).data('filter-secondary')) {\n _row = new WPHB_Admin.minification.Row($(row), $(row).data('filter'), $(row).data('filter-secondary'));\n } else {\n _row = new WPHB_Admin.minification.Row($(row), $(row).data('filter'));\n }\n self.rowsCollection.push(_row);\n });\n\n $('#wphb-s').keyup(function () {\n self.rowsCollection.addFilter($(this).val(), 'primary');\n self.rowsCollection.applyFilters();\n });\n\n $('#wphb-secondary-filter').change(function () {\n self.rowsCollection.addFilter($(this).val(), 'secondary');\n self.rowsCollection.applyFilters();\n });\n\n $('.filter-toggles').change(function () {\n var element = $(this);\n var what = element.data('toggles');\n var value = element.prop('checked');\n var visibleItems = self.rowsCollection.getVisibleItems();\n\n for (var i in visibleItems) {\n visibleItems[i].change(what, value);\n }\n });\n\n // Files selectors\n var filesList = $('input.wphb-minification-file-selector');\n filesList.click(function () {\n var $this = $(this);\n var element = self.rowsCollection.getItemById($this.data('type'), $this.data('handle'));\n if (!element) {\n return;\n }\n\n if ($this.is(':checked')) {\n element.select();\n } else {\n element.unSelect();\n }\n });\n\n var selectAll = $('#minification-bulk-file');\n selectAll.click(function () {\n var $this = $(this);\n var items = self.rowsCollection.getItems();\n for (var i in items) {\n if (items.hasOwnProperty(i)) {\n if ($this.is(':checked')) {\n items[i].select();\n } else {\n items[i].unSelect();\n }\n }\n }\n });\n\n // Include/exclude file checkbox\n $('.toggle-cross').on('click', function () {\n var $this = $(this);\n var checkbox = $this.find('input.toggle-include');\n var row = self.rowsCollection.getItemById($this.data('type'), $this.data('handle'));\n // Mark the item as include or not in the rows list\n if (row) {\n row.change('include', !checkbox.prop('checked'));\n row.getElement().find('input:not(.toggle-include)').prop('disabled', !checkbox.prop('checked'));\n }\n });\n\n // Handle two CDN checkboxes on Minification page\n var checkboxes = $(\"input[type=checkbox][name=use_cdn]\");\n checkboxes.change(function () {\n var checkedState = $(this).prop('checked');\n\n checkboxes.each(function () {\n this.checked = checkedState;\n });\n });\n\n /* Show details of minification row on mobile devices */\n $('body').on('click', '.wphb-minification-file-details', function () {\n if (window.innerWidth < 783) {\n $(this).parent().find('.wphb-minification-row-details').toggle('slow');\n }\n });\n\n /*\n Catch window resize and revert styles for responsive divs\n 1/4 of a second should be enough to trigger during device rotations (from portrait to landscape mode)\n */\n var minification_resize_rows = _.debounce(function () {\n\n if (window.innerWidth >= 783) {\n $('.wphb-minification-row-details').css('display', 'flex');\n } else {\n $('.wphb-minification-row-details').css('display', 'none');\n }\n }, 250);\n\n window.addEventListener('resize', minification_resize_rows);\n\n return this;\n },\n\n checkFiles: function checkFiles(redirect) {\n var _this = this;\n\n var self = this;\n\n if (typeof redirect === 'undefined') redirect = false;\n\n if (!self.minificationStarted) {\n // Store the progress in session storage to persist during page reloads\n // If there is no previous value, we init one with 10%\n if (sessionStorage.getItem('progress') === null) {\n sessionStorage.setItem('progress', 10);\n }\n\n // Update progress bar\n var progress = sessionStorage.getItem('progress');\n this.updateProgressBar(progress);\n\n // Send an AJAX request that will flag the check files as started\n _fetcher2.default.minification.startCheck(progress).then(function (response) {\n // Set the number of steps to be used in percentage count. Only if not set already.\n if (typeof response.steps !== 'undefined' && sessionStorage.getItem('steps') === null) {\n sessionStorage.setItem('steps', response.steps);\n }\n\n self.minificationStarted = true;\n self.checkFiles(redirect);\n });\n } else {\n var _progress = sessionStorage.getItem('progress');\n var step = Math.round(80 / sessionStorage.getItem('steps'));\n _fetcher2.default.minification.checkStep(_progress, step).then(function (response) {\n if (typeof response.finished !== 'undefined') {\n // Finished\n if (response.finished && redirect) {\n // Clear session storage\n sessionStorage.clear();\n\n // Update progress bar\n _this.updateProgressBar(100);\n\n // Show enable cdn modal only for members\n if (true === response.show_cdn && $('#enable-cdn-modal').length) {\n WDP.showOverlay('#enable-cdn-modal', { class: 'wphb-modal small wphb-progress-modal no-close' });\n } else {\n window.location.href = redirect;\n }\n }\n // Next step\n else if (!response.finished) {\n // Store the progress in session storage to persist during page reloads\n var _progress2 = parseInt(sessionStorage.getItem('progress')) + Math.round(80 / sessionStorage.getItem('steps'));\n sessionStorage.setItem('progress', _progress2);\n\n // Update progress bar.\n _this.updateProgressBar(_progress2);\n\n // Wait 3 seconds before calling again\n window.setTimeout(function () {\n self.checkFiles(redirect);\n }, 3000);\n }\n } else {\n // Error\n window.location.href = redirect;\n }\n });\n } // End else\n }, // End checkFiles\n\n updateProgressBar: function updateProgressBar(progress) {\n var cancel = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n if (progress > 100) {\n progress = 100;\n }\n // Update progress bar\n $('.wphb-scan-progress .wphb-scan-progress-text span').text(progress + '%');\n if (progress >= 90) {\n $('.wphb-progress-state .wphb-progress-state-text').text('Finalizing...');\n }\n if (cancel) {\n $('.wphb-progress-state .wphb-progress-state-text').text('Cancelling...');\n }\n $('.wphb-scan-progress .wphb-scan-progress-bar span').width(progress + '%');\n },\n\n cancelScan: function cancelScan() {\n var _this2 = this;\n\n _fetcher2.default.minification.cancelScan().then(function () {\n // Clear session storage\n sessionStorage.clear();\n\n _this2.updateProgressBar(0, true);\n\n // Reload page\n window.location.href = (0, _helpers.getLink)('minification');\n });\n }\n\n }; // End WPHB_Admin.minification\n\n WPHB_Admin.minification.Row = _Row2.default;\n WPHB_Admin.minification.RowsCollection = _RowsCollection2.default;\n})(jQuery);\n\n/***/ }),\n/* 26 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nvar _fetcher = __webpack_require__(0);\n\nvar _fetcher2 = _interopRequireDefault(_fetcher);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n(function ($) {\n 'use strict';\n\n WPHB_Admin.performance = {\n\n module: 'performance',\n iteration: 0,\n progress: 0,\n\n init: function init() {\n\n var self = this;\n var body = $('body');\n\n if (wphbPerformanceStrings) this.strings = wphbPerformanceStrings;\n\n this.$runTestButton = $('#run-performance-test');\n\n var performanceReportTable = $(\".performance-report-table\");\n\n performanceReportTable.off('click', 'button');\n performanceReportTable.on('click', '.wphb-performance-report-item-cta .additional-content-opener' && 'tr.wphb-performance-report-item', function (e) {\n e.preventDefault();\n\n var getParentPerformanceItem = $(this).closest(\".wphb-performance-report-item\"),\n getNextAdditionalContentRow = getParentPerformanceItem.nextUntil(\".wphb-performance-report-item\");\n\n getNextAdditionalContentRow.toggleClass(\"wphb-performance-report-item-additional-content-opened\");\n\n if (getNextAdditionalContentRow.hasClass(\"wphb-performance-report-item-additional-content-opened\")) {\n getParentPerformanceItem.addClass(\"wphb-performance-report-item-opened\");\n } else {\n getParentPerformanceItem.removeClass(\"wphb-performance-report-item-opened\");\n }\n });\n\n if (this.$runTestButton.length) {\n this.$runTestButton.click(function (e) {\n e.preventDefault();\n $(this).attr('disabled', true);\n self.performanceTest(self.strings.finishedTestURLsLink);\n });\n }\n\n // If a hash is present in URL, let's open the rule extra content\n var hash = window.location.hash;\n if (hash) {\n var row = $(hash);\n if (row.length) {\n row.find('.trigger-additional-content').trigger('click');\n }\n }\n\n // Schedule show/hide day of week\n $('select[name=\"email-frequency\"]').change(function () {\n if ('1' === $(this).val()) {\n $(this).closest('.schedule-box').find('div.days-container').hide();\n } else {\n $(this).closest('.schedule-box').find('div.days-container').show();\n }\n }).change();\n\n // Remove recipient\n body.on('click', '.wphb-remove-recipient', function (e) {\n e.preventDefault();\n $(this).closest('.recipient').remove();\n $('.scan-settings').find(\"input[id='scan_recipient'][value=\" + $(this).attr('data-id') + \"]\").remove();\n });\n\n // Add recipient\n $('#add-receipt').click(function () {\n var email = $(\"#wphb-username-search\").val();\n var name = $(\"#wphb-first-name\").val();\n _fetcher2.default.performance.addRecipient(email, name).then(function (response) {\n var user_row = $('<div class=\"recipient\"/>');\n\n var img = $('<img/>').attr({\n 'src': response.avatar,\n 'width': '30'\n });\n var name = $('<span/>').html(response.name);\n\n user_row.append('<span class=\"name\"/>');\n user_row.find('.name').append(img, name);\n\n user_row.append($('<span class=\"email\"/>').html(email));\n user_row.append($('<a/>').attr({\n 'data-id': response.user_id,\n 'class': 'remove float-r wphb-remove-recipient',\n 'href': '#',\n 'alt': self.strings.removeButtonText\n }).html('<i class=\"dev-icon dev-icon-cross\"></i>'));\n\n $('<input>').attr({\n type: 'hidden',\n id: 'scan_recipient',\n name: 'email-recipients[]',\n value: JSON.stringify({ email: response.email, name: response.name })\n }).appendTo(user_row);\n\n $('.receipt .recipients').append(user_row);\n $(\"#wphb-username-search\").val('');\n $(\"#wphb-first-name\").val('');\n }).catch(function (error) {\n alert(error.message);\n });\n return false;\n });\n\n // Save report settings\n body.on('submit', '.scan-frm', function (e) {\n e.preventDefault();\n var form_data = $(this).serialize();\n var that = $(this);\n\n that.find('.button').attr('disabled', 'disabled');\n\n _fetcher2.default.performance.saveReportsSettings(form_data).then(function () {\n that.find('.button').removeAttr('disabled');\n self.showUpdateMessage();\n });\n return false;\n });\n\n return this;\n },\n\n showUpdateMessage: function showUpdateMessage() {\n var notice = $('#wphb-notice-performance-report-settings-updated');\n window.scrollTo(0, 0);\n notice.slideDown();\n setTimeout(function () {\n notice.slideUp();\n }, 5000);\n },\n\n performanceTest: function performanceTest(redirect) {\n var self = this;\n\n if (typeof redirect === 'undefined') redirect = false;\n\n // Update progress bar\n self.updateProgressBar();\n\n _fetcher2.default.performance.runTest().then(function (response) {\n if (!response.finished) {\n // Try again 5 seconds later\n window.setTimeout(function () {\n self.performanceTest(redirect);\n }, 5000);\n } else if (redirect) {\n window.location = redirect;\n }\n });\n },\n\n updateProgressBar: function updateProgressBar() {\n if (this.progress < 90) {\n this.progress += 35;\n }\n if (this.progress > 100) {\n this.progress = 90;\n }\n $('.wphb-scan-progress .wphb-scan-progress-text span').text(this.progress + '%');\n $('.wphb-scan-progress .wphb-scan-progress-bar span').attr('style', 'width:' + this.progress + '%');\n }\n };\n})(jQuery);\n\n/***/ }),\n/* 27 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n(function ($) {\n WPHB_Admin.uptime = {\n module: 'uptime',\n $dataRangeSelector: null,\n chartData: null,\n timer: null,\n $spinner: null,\n init: function init() {\n this.$spinner = $('.spinner');\n this.strings = wphbUptimeStrings;\n this.$dataRangeSelector = $('#wphb-uptime-data-range');\n this.chartData = $('#uptime-chart-json').val();\n this.$disableUptime = $('#wphb-disable-uptime');\n\n this.$dataRangeSelector.change(function () {\n window.location.href = $(this).find(':selected').data('url');\n });\n\n var self = this;\n this.$disableUptime.change(function () {\n self.$spinner.css('visibility', 'visible');\n var value = $(this).is(':checked');\n if (value && self.timer) {\n clearTimeout(self.timer);\n self.$spinner.css('visibility', 'hidden');\n } else {\n // you have 3 seconds to change your mind\n self.timer = setTimeout(function () {\n location.href = self.strings.disableUptimeURL;\n }, 3000);\n }\n\n return;\n });\n\n this.drawChart();\n\n /* Re-check Uptime status */\n $('#uptime-re-check-status').on('click', function (e) {\n e.preventDefault();\n location.reload();\n });\n },\n\n drawChart: function drawChart() {\n var data = new google.visualization.DataTable();\n data.addColumn('datetime', 'Day');\n data.addColumn('number', 'Response Time (ms)');\n\n var chart_array = JSON.parse(this.chartData);\n for (var i = 0; i < chart_array.length; i++) {\n chart_array[i][0] = new Date(chart_array[i][0]);\n chart_array[i][1] = Math.round(chart_array[i][1]);\n\n /* brings the graph below the x axis */\n if (Math.round(chart_array[i][1]) == 0) {\n chart_array[i][1] = -100;\n }\n }\n\n data.addRows(chart_array);\n\n var options = {\n chartArea: {\n left: 80,\n top: 20,\n width: '90%',\n height: '90%'\n },\n colors: ['#24ADE5'],\n curveType: 'function',\n /*interpolateNulls: true,*/\n legend: { position: 'none' },\n vAxis: {\n format: '#,### ms',\n viewWindow: { min: 0 /* don't display negative values */\n } },\n tooltip: { isHtml: true },\n series: {\n 0: { axis: 'Resp' }\n },\n axes: {\n y: {\n Resp: { label: 'Response Time (ms)' }\n }\n }\n };\n\n var chart = new google.visualization.LineChart(document.getElementById('uptime-chart'));\n chart.draw(data, options);\n\n $(window).resize(function () {\n chart.draw(data, options);\n });\n }\n };\n})(jQuery);\n\n/***/ }),\n/* 28 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n__webpack_require__(24);\n__webpack_require__(26);\n__webpack_require__(23);\n__webpack_require__(19);\n__webpack_require__(25);\n__webpack_require__(22);\n__webpack_require__(21);\n__webpack_require__(27);\n__webpack_require__(20);\n__webpack_require__(18);\n\n/***/ }),\n/* 29 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nvar Row = function Row(_element, _filter, _filter_sec) {\n var $el = _element,\n filter = _filter.toLowerCase(),\n filterSecondary = false,\n selected = false,\n visible = true;\n\n var $include = $el.find('.toggle-include'),\n $combine = $el.find('.toggle-combine'),\n $minify = $el.find('.toggle-minify'),\n $posFooter = $el.find('.toggle-position-footer'),\n $disableIcon = $el.find('.toggle-cross > i');\n\n if (_filter_sec) {\n filterSecondary = _filter_sec.toLowerCase();\n }\n\n return {\n hide: function hide() {\n $el.addClass('out-of-filter');\n visible = false;\n },\n\n show: function show() {\n $el.removeClass('out-of-filter');\n visible = true;\n },\n\n getElement: function getElement() {\n return $el;\n },\n\n getId: function getId() {\n return $el.attr('id');\n },\n\n getFilter: function getFilter() {\n return filter;\n },\n\n matchFilter: function matchFilter(text) {\n if (text === '') {\n return true;\n }\n\n text = text.toLowerCase();\n return filter.search(text) > -1;\n },\n\n matchSecondaryFilter: function matchSecondaryFilter(text) {\n if (text === '') {\n return true;\n }\n\n if (!filterSecondary) {\n return false;\n }\n\n text = text.toLowerCase();\n return filterSecondary === text;\n },\n\n isVisible: function isVisible() {\n return visible;\n },\n\n isSelected: function isSelected() {\n return selected;\n },\n\n select: function select() {\n selected = true;\n },\n\n unSelect: function unSelect() {\n selected = false;\n },\n\n change: function change(what, value) {\n switch (what) {\n case 'minify':\n {\n $minify.prop('checked', value);\n break;\n }\n case 'combine':\n {\n $combine.prop('checked', value);\n break;\n }\n case 'include':\n {\n $disableIcon.removeClass();\n $include.prop('checked', value);\n if (value) {\n $el.removeClass('disabled');\n $disableIcon.addClass('dev-icon dev-icon-cross');\n $include.attr('checked', true);\n } else {\n $el.addClass('disabled');\n $disableIcon.addClass('wdv-icon wdv-icon-refresh');\n $include.removeAttr('checked');\n }\n break;\n }\n case 'footer':\n {\n $posFooter.prop('checked', value);\n break;\n }\n }\n }\n\n };\n};\n\nexports.default = Row;\n\n/***/ }),\n/* 30 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar RowsCollection = function RowsCollection() {\n var items = [];\n var currentFilter = '';\n var currentSecondaryFilter = '';\n\n return {\n push: function push(row) {\n if ((typeof row === 'undefined' ? 'undefined' : _typeof(row)) === 'object') {\n items.push(row);\n }\n },\n\n getItems: function getItems() {\n return items;\n },\n\n getItem: function getItem(i) {\n if (items[i]) {\n return items[i];\n }\n return false;\n },\n\n /**\n * Get a collection item by type and ID\n * @param type\n * @param id\n */\n getItemById: function getItemById(type, id) {\n var value = false;\n for (var i in items) {\n if ('wphb-file-' + type + '-' + id === items[i].getId()) {\n value = items[i];\n break;\n }\n }\n return value;\n },\n\n getVisibleItems: function getVisibleItems() {\n var visible = [];\n for (var i in items) {\n if (items[i].isVisible()) {\n visible.push(items[i]);\n }\n }\n return visible;\n },\n\n getSelectedItems: function getSelectedItems() {\n var selected = [];\n\n for (var i in items) {\n if (items[i].isVisible() && items[i].isSelected()) {\n selected.push(items[i]);\n }\n }\n\n return selected;\n },\n\n addFilter: function addFilter(filter, type) {\n if (type === 'secondary') {\n currentSecondaryFilter = filter;\n } else {\n currentFilter = filter;\n }\n },\n\n applyFilters: function applyFilters() {\n for (var i in items) {\n if (items[i]) {\n if (items[i].matchFilter(currentFilter) && items[i].matchSecondaryFilter(currentSecondaryFilter)) {\n items[i].show();\n } else {\n items[i].hide();\n }\n }\n }\n }\n };\n};\n\nexports.default = RowsCollection;\n\n/***/ }),\n/* 31 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/**\n * Strings internationalization\n *\n * @param str\n *\n * @returns {*|string}\n */\nvar __ = exports.__ = function __(str) {\n return wphb.strings[str] || '';\n};\n\n/**\n * Get a link to a HB screen\n *\n * @param {string} screen Screen slug\n * @returns {string}\n */\nvar getLink = exports.getLink = function getLink(screen) {\n return wphb.links[screen] || '';\n};\n\n/***/ }),\n/* 32 */\n/***/ (function(module, exports) {\n\n/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nmodule.exports = apply;\n\n\n/***/ }),\n/* 33 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseTimes = __webpack_require__(40),\n isArguments = __webpack_require__(60),\n isArray = __webpack_require__(61),\n isBuffer = __webpack_require__(62),\n isIndex = __webpack_require__(11),\n isTypedArray = __webpack_require__(63);\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = arrayLikeKeys;\n\n\n/***/ }),\n/* 34 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseGetTag = __webpack_require__(1),\n isObjectLike = __webpack_require__(5);\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nmodule.exports = baseIsArguments;\n\n\n/***/ }),\n/* 35 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar isFunction = __webpack_require__(15),\n isMasked = __webpack_require__(49),\n isObject = __webpack_require__(4),\n toSource = __webpack_require__(57);\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nmodule.exports = baseIsNative;\n\n\n/***/ }),\n/* 36 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseGetTag = __webpack_require__(1),\n isLength = __webpack_require__(16),\n isObjectLike = __webpack_require__(5);\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nmodule.exports = baseIsTypedArray;\n\n\n/***/ }),\n/* 37 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar isPrototype = __webpack_require__(12),\n nativeKeys = __webpack_require__(50);\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = baseKeys;\n\n\n/***/ }),\n/* 38 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar identity = __webpack_require__(14),\n overRest = __webpack_require__(54),\n setToString = __webpack_require__(55);\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nmodule.exports = baseRest;\n\n\n/***/ }),\n/* 39 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar constant = __webpack_require__(59),\n defineProperty = __webpack_require__(9),\n identity = __webpack_require__(14);\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nmodule.exports = baseSetToString;\n\n\n/***/ }),\n/* 40 */\n/***/ (function(module, exports) {\n\n/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nmodule.exports = baseTimes;\n\n\n/***/ }),\n/* 41 */\n/***/ (function(module, exports) {\n\n/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nmodule.exports = baseUnary;\n\n\n/***/ }),\n/* 42 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar assignValue = __webpack_require__(7),\n baseAssignValue = __webpack_require__(8);\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n}\n\nmodule.exports = copyObject;\n\n\n/***/ }),\n/* 43 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar root = __webpack_require__(2);\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nmodule.exports = coreJsData;\n\n\n/***/ }),\n/* 44 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseRest = __webpack_require__(38),\n isIterateeCall = __webpack_require__(48);\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\nmodule.exports = createAssigner;\n\n\n/***/ }),\n/* 45 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseIsNative = __webpack_require__(35),\n getValue = __webpack_require__(47);\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nmodule.exports = getNative;\n\n\n/***/ }),\n/* 46 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar Symbol = __webpack_require__(6);\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nmodule.exports = getRawTag;\n\n\n/***/ }),\n/* 47 */\n/***/ (function(module, exports) {\n\n/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nmodule.exports = getValue;\n\n\n/***/ }),\n/* 48 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar eq = __webpack_require__(13),\n isArrayLike = __webpack_require__(3),\n isIndex = __webpack_require__(11),\n isObject = __webpack_require__(4);\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nmodule.exports = isIterateeCall;\n\n\n/***/ }),\n/* 49 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar coreJsData = __webpack_require__(43);\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nmodule.exports = isMasked;\n\n\n/***/ }),\n/* 50 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar overArg = __webpack_require__(53);\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nmodule.exports = nativeKeys;\n\n\n/***/ }),\n/* 51 */\n/***/ (function(module, exports, __webpack_require__) {\n\n/* WEBPACK VAR INJECTION */(function(module) {var freeGlobal = __webpack_require__(10);\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n try {\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n}());\n\nmodule.exports = nodeUtil;\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17)(module)))\n\n/***/ }),\n/* 52 */\n/***/ (function(module, exports) {\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nmodule.exports = objectToString;\n\n\n/***/ }),\n/* 53 */\n/***/ (function(module, exports) {\n\n/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nmodule.exports = overArg;\n\n\n/***/ }),\n/* 54 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar apply = __webpack_require__(32);\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nmodule.exports = overRest;\n\n\n/***/ }),\n/* 55 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseSetToString = __webpack_require__(39),\n shortOut = __webpack_require__(56);\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nmodule.exports = setToString;\n\n\n/***/ }),\n/* 56 */\n/***/ (function(module, exports) {\n\n/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nmodule.exports = shortOut;\n\n\n/***/ }),\n/* 57 */\n/***/ (function(module, exports) {\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nmodule.exports = toSource;\n\n\n/***/ }),\n/* 58 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar assignValue = __webpack_require__(7),\n copyObject = __webpack_require__(42),\n createAssigner = __webpack_require__(44),\n isArrayLike = __webpack_require__(3),\n isPrototype = __webpack_require__(12),\n keys = __webpack_require__(64);\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns own enumerable string keyed properties of source objects to the\n * destination object. Source objects are applied from left to right.\n * Subsequent sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object` and is loosely based on\n * [`Object.assign`](https://mdn.io/Object/assign).\n *\n * @static\n * @memberOf _\n * @since 0.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assignIn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assign({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'c': 3 }\n */\nvar assign = createAssigner(function(object, source) {\n if (isPrototype(source) || isArrayLike(source)) {\n copyObject(source, keys(source), object);\n return;\n }\n for (var key in source) {\n if (hasOwnProperty.call(source, key)) {\n assignValue(object, key, source[key]);\n }\n }\n});\n\nmodule.exports = assign;\n\n\n/***/ }),\n/* 59 */\n/***/ (function(module, exports) {\n\n/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nmodule.exports = constant;\n\n\n/***/ }),\n/* 60 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseIsArguments = __webpack_require__(34),\n isObjectLike = __webpack_require__(5);\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n};\n\nmodule.exports = isArguments;\n\n\n/***/ }),\n/* 61 */\n/***/ (function(module, exports) {\n\n/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nmodule.exports = isArray;\n\n\n/***/ }),\n/* 62 */\n/***/ (function(module, exports, __webpack_require__) {\n\n/* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(2),\n stubFalse = __webpack_require__(65);\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nmodule.exports = isBuffer;\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17)(module)))\n\n/***/ }),\n/* 63 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar baseIsTypedArray = __webpack_require__(36),\n baseUnary = __webpack_require__(41),\n nodeUtil = __webpack_require__(51);\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nmodule.exports = isTypedArray;\n\n\n/***/ }),\n/* 64 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar arrayLikeKeys = __webpack_require__(33),\n baseKeys = __webpack_require__(37),\n isArrayLike = __webpack_require__(3);\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nmodule.exports = keys;\n\n\n/***/ }),\n/* 65 */\n/***/ (function(module, exports) {\n\n/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nmodule.exports = stubFalse;\n\n\n/***/ }),\n/* 66 */\n/***/ (function(module, exports) {\n\nvar g;\r\n\r\n// This works in non-strict mode\r\ng = (function() {\r\n\treturn this;\r\n})();\r\n\r\ntry {\r\n\t// This works if eval is allowed (see CSP)\r\n\tg = g || Function(\"return this\")() || (1,eval)(\"this\");\r\n} catch(e) {\r\n\t// This works if the window reference is available\r\n\tif(typeof window === \"object\")\r\n\t\tg = window;\r\n}\r\n\r\n// g can still be undefined, but nothing to do about it...\r\n// We return undefined, instead of nothing here, so it's\r\n// easier to handle this case. if(!global) { ...}\r\n\r\nmodule.exports = g;\r\n\n\n/***/ })\n/******/ ]);\n\n\n// WEBPACK FOOTER //\n// admin.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 28);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 1371ae49cdc9501be886","import assign from 'lodash/assign';\n\nfunction Fetcher() {\n let fetchUrl = ajaxurl;\n let fetchNonce = wphb.nonces.HBFetchNonce;\n const actionPrefix = 'wphb_';\n const actionPrefixPro = 'wphb_pro_';\n\n function request( action, data = {}, method = 'GET' ) {\n data.nonce = fetchNonce;\n data.action = action;\n let args = { data, method };\n args.url = fetchUrl;\n return new Promise( ( resolve, reject ) => {\n jQuery.ajax( args ).done( resolve ).fail( reject );\n })\n .then( ( response ) => checkStatus( response ) );\n\n }\n\n const methods = {\n /**\n * Caching module actions.\n */\n caching: {\n /**\n * Set expiration for browser caching.\n *\n * @param type File type.\n * @param value Expiry value.\n */\n setExpiration: ( type, value ) => {\n const action = actionPrefix + 'caching_set_expiration';\n return request( action, { type, value }, 'POST' );\n },\n\n /**\n * Set server type.\n *\n * @param value Server type.\n */\n setServer: ( value ) => {\n const action = actionPrefix + 'caching_set_server_type';\n return request( action, { value }, 'POST' );\n },\n\n /**\n * Reload snippet.\n *\n * @param type Server type.\n */\n reloadSnippets: ( type ) => {\n const action = actionPrefix + 'caching_reload_snippet';\n return request( action, { type }, 'POST' )\n .then( ( response ) => {\n return response;\n });\n }\n },\n\n /**\n * CLoudflare module actions.\n */\n cloudflare: {\n\t\t\t/**\n\t\t\t * Connect to CloudFlare.\n\t\t\t *\n\t\t\t * @param step\n\t\t\t * @param formData\n\t\t\t * @param cfData\n\t\t\t */\n\t\t\tconnect: ( step, formData, cfData ) => {\n\t\t\t\tconst action = actionPrefix + 'cloudflare_connect';\n return request( action, { step, formData, cfData }, 'POST' )\n .then( ( response ) => {\n return response;\n });\n },\n\n /**\n * Set expiry for CloudFlare cache.\n *\n * @param value Expiry value.\n */\n setExpiration: ( value ) => {\n const action = actionPrefix + 'cloudflare_set_expiry';\n return request( action, { value }, 'POST' );\n },\n\n\t\t\t/**\n * Purge CloudFlare cache.\n\t\t\t */\n\t\t\tpurgeCache: () => {\n const action = actionPrefix + 'cloudflare_purge_cache';\n return request( action, {}, 'POST' );\n }\n },\n\n /**\n * Dashboard module actions.\n */\n dashboard: {\n /**\n * Toggle global minification settings for network installs.\n *\n * @param value Accepts: 'super-admins', 'false' and 'true'. Default: 'true'.\n */\n toggleMinification: ( value ) => {\n const action = actionPrefix + 'dash_toggle_network_minification';\n return request( action, { value }, 'POST' );\n },\n\n\t\t\t/**\n * Skip quick setup.\n\t\t\t */\n\t\t\tskipSetup: () => {\n const action = actionPrefix + 'dash_skip_setup';\n return request( action, {}, 'POST' );\n }\n },\n\n /**\n * Minification module actions.\n */\n minification: {\n /**\n * Toggle CDN settings.\n *\n * @param value CDN checkbox value.\n */\n toggleCDN: ( value ) => {\n const action = actionPrefix + 'minification_toggle_cdn';\n return request( action, { value }, 'POST' );\n },\n\n /**\n * Toggle minificatiojn settings on per site basis.\n *\n * @param value\n */\n toggleMinification: ( value ) => {\n const action = actionPrefix + 'minification_toggle_minification';\n return request( action, { value }, 'POST' );\n },\n\n /**\n * Start minification check.\n *\n * @param progress\n */\n startCheck: ( progress ) => {\n const action = actionPrefix + 'minification_start_check';\n return request( action, { progress }, 'POST' )\n .then( ( response ) => {\n return response;\n });\n },\n\n /**\n * Do a step in minification process.\n *\n * @param progress\n * @param step\n */\n checkStep: ( progress, step ) => {\n const action = actionPrefix + 'minification_check_step';\n return request( action, { progress, step }, 'POST' )\n .then( ( response ) => {\n return response;\n });\n },\n\n\t\t\t/**\n * Cancel minification scan.\n\t\t\t */\n\t\t\tcancelScan: function cancelScan() {\n\t\t\t\tconst action = actionPrefix + 'minification_cancel_scan';\n\t\t\t\treturn request( action, {}, 'POST' );\n\t\t\t}\n },\n\n /**\n * Performance module actions.\n */\n performance: {\n\t\t\t/**\n * Run performance test.\n\t\t\t */\n\t\t\trunTest: () => {\n const action = actionPrefix + 'performance_run_test';\n return request( action, {}, 'POST' )\n .then( ( response ) => {\n return response;\n });\n },\n\n /**\n * Add a single email/name recipient to the reports list.\n *\n * @param email\n * @param name\n */\n addRecipient: ( email, name ) => {\n const action = actionPrefixPro + 'performance_add_recipient';\n return request( action, { email, name }, 'POST' )\n .then( ( response ) => {\n return response;\n });\n\n },\n\n /**\n * Save reporting settings on minification page.\n *\n * @param data From data.\n */\n saveReportsSettings: ( data ) => {\n const action = actionPrefixPro + 'performance_save_reports_settings';\n return request( action, { data }, 'POST' );\n }\n }\n };\n\n assign( this, methods );\n}\n\nconst HBFetcher = new Fetcher();\nexport default HBFetcher;\n\nfunction checkStatus( response ) {\n if ( typeof response !== 'object' ) {\n response = JSON.parse( response );\n }\n if ( response.success ) {\n return response.data;\n }\n\n let data = response.data || {};\n const error = new Error( data.message || 'Error trying to fetch response from server' );\n error.response = response;\n throw error;\n}\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/utils/fetcher.js","var Symbol = require('./_Symbol'),\n getRawTag = require('./_getRawTag'),\n objectToString = require('./_objectToString');\n\n/** `Object#toString` result references. */\nvar nullTag = '[object Null]',\n undefinedTag = '[object Undefined]';\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * The base implementation of `getTag` without fallbacks for buggy environments.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the `toStringTag`.\n */\nfunction baseGetTag(value) {\n if (value == null) {\n return value === undefined ? undefinedTag : nullTag;\n }\n return (symToStringTag && symToStringTag in Object(value))\n ? getRawTag(value)\n : objectToString(value);\n}\n\nmodule.exports = baseGetTag;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseGetTag.js\n// module id = 1\n// module chunks = 0","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\nmodule.exports = root;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_root.js\n// module id = 2\n// module chunks = 0","var isFunction = require('./isFunction'),\n isLength = require('./isLength');\n\n/**\n * Checks if `value` is array-like. A value is considered array-like if it's\n * not a function and has a `value.length` that's an integer greater than or\n * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n * @example\n *\n * _.isArrayLike([1, 2, 3]);\n * // => true\n *\n * _.isArrayLike(document.body.children);\n * // => true\n *\n * _.isArrayLike('abc');\n * // => true\n *\n * _.isArrayLike(_.noop);\n * // => false\n */\nfunction isArrayLike(value) {\n return value != null && isLength(value.length) && !isFunction(value);\n}\n\nmodule.exports = isArrayLike;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isArrayLike.js\n// module id = 3\n// module chunks = 0","/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return value != null && (type == 'object' || type == 'function');\n}\n\nmodule.exports = isObject;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isObject.js\n// module id = 4\n// module chunks = 0","/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return value != null && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isObjectLike.js\n// module id = 5\n// module chunks = 0","var root = require('./_root');\n\n/** Built-in value references. */\nvar Symbol = root.Symbol;\n\nmodule.exports = Symbol;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_Symbol.js\n// module id = 6\n// module chunks = 0","var baseAssignValue = require('./_baseAssignValue'),\n eq = require('./eq');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns `value` to `key` of `object` if the existing value is not equivalent\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * for equality comparisons.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction assignValue(object, key, value) {\n var objValue = object[key];\n if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||\n (value === undefined && !(key in object))) {\n baseAssignValue(object, key, value);\n }\n}\n\nmodule.exports = assignValue;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_assignValue.js\n// module id = 7\n// module chunks = 0","var defineProperty = require('./_defineProperty');\n\n/**\n * The base implementation of `assignValue` and `assignMergeValue` without\n * value checks.\n *\n * @private\n * @param {Object} object The object to modify.\n * @param {string} key The key of the property to assign.\n * @param {*} value The value to assign.\n */\nfunction baseAssignValue(object, key, value) {\n if (key == '__proto__' && defineProperty) {\n defineProperty(object, key, {\n 'configurable': true,\n 'enumerable': true,\n 'value': value,\n 'writable': true\n });\n } else {\n object[key] = value;\n }\n}\n\nmodule.exports = baseAssignValue;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseAssignValue.js\n// module id = 8\n// module chunks = 0","var getNative = require('./_getNative');\n\nvar defineProperty = (function() {\n try {\n var func = getNative(Object, 'defineProperty');\n func({}, '', {});\n return func;\n } catch (e) {}\n}());\n\nmodule.exports = defineProperty;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_defineProperty.js\n// module id = 9\n// module chunks = 0","/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\nmodule.exports = freeGlobal;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_freeGlobal.js\n// module id = 10\n// module chunks = 0","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^(?:0|[1-9]\\d*)$/;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n length = length == null ? MAX_SAFE_INTEGER : length;\n return !!length &&\n (typeof value == 'number' || reIsUint.test(value)) &&\n (value > -1 && value % 1 == 0 && value < length);\n}\n\nmodule.exports = isIndex;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_isIndex.js\n// module id = 11\n// module chunks = 0","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Checks if `value` is likely a prototype object.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.\n */\nfunction isPrototype(value) {\n var Ctor = value && value.constructor,\n proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;\n\n return value === proto;\n}\n\nmodule.exports = isPrototype;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_isPrototype.js\n// module id = 12\n// module chunks = 0","/**\n * Performs a\n * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)\n * comparison between two values to determine if they are equivalent.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n * @example\n *\n * var object = { 'a': 1 };\n * var other = { 'a': 1 };\n *\n * _.eq(object, object);\n * // => true\n *\n * _.eq(object, other);\n * // => false\n *\n * _.eq('a', 'a');\n * // => true\n *\n * _.eq('a', Object('a'));\n * // => false\n *\n * _.eq(NaN, NaN);\n * // => true\n */\nfunction eq(value, other) {\n return value === other || (value !== value && other !== other);\n}\n\nmodule.exports = eq;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/eq.js\n// module id = 13\n// module chunks = 0","/**\n * This method returns the first argument it receives.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Util\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'a': 1 };\n *\n * console.log(_.identity(object) === object);\n * // => true\n */\nfunction identity(value) {\n return value;\n}\n\nmodule.exports = identity;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/identity.js\n// module id = 14\n// module chunks = 0","var baseGetTag = require('./_baseGetTag'),\n isObject = require('./isObject');\n\n/** `Object#toString` result references. */\nvar asyncTag = '[object AsyncFunction]',\n funcTag = '[object Function]',\n genTag = '[object GeneratorFunction]',\n proxyTag = '[object Proxy]';\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a function, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n if (!isObject(value)) {\n return false;\n }\n // The use of `Object#toString` avoids issues with the `typeof` operator\n // in Safari 9 which returns 'object' for typed arrays and other constructors.\n var tag = baseGetTag(value);\n return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;\n}\n\nmodule.exports = isFunction;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isFunction.js\n// module id = 15\n// module chunks = 0","/** Used as references for various `Number` constants. */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This method is loosely based on\n * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n * @example\n *\n * _.isLength(3);\n * // => true\n *\n * _.isLength(Number.MIN_VALUE);\n * // => false\n *\n * _.isLength(Infinity);\n * // => false\n *\n * _.isLength('3');\n * // => false\n */\nfunction isLength(value) {\n return typeof value == 'number' &&\n value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nmodule.exports = isLength;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isLength.js\n// module id = 16\n// module chunks = 0","module.exports = function(module) {\r\n\tif(!module.webpackPolyfill) {\r\n\t\tmodule.deprecate = function() {};\r\n\t\tmodule.paths = [];\r\n\t\t// module.parent = undefined by default\r\n\t\tif(!module.children) module.children = [];\r\n\t\tObject.defineProperty(module, \"loaded\", {\r\n\t\t\tenumerable: true,\r\n\t\t\tget: function() {\r\n\t\t\t\treturn module.l;\r\n\t\t\t}\r\n\t\t});\r\n\t\tObject.defineProperty(module, \"id\", {\r\n\t\t\tenumerable: true,\r\n\t\t\tget: function() {\r\n\t\t\t\treturn module.i;\r\n\t\t\t}\r\n\t\t});\r\n\t\tmodule.webpackPolyfill = 1;\r\n\t}\r\n\treturn module;\r\n};\r\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// (webpack)/buildin/module.js\n// module id = 17\n// module chunks = 0","jQuery(document).ready( function() {\n WPHB_Admin.init();\n});\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-app.js","import Fetcher from './utils/fetcher';\n\n( function( $ ) {\n 'use strict';\n WPHB_Admin.caching = {\n\n module: 'caching',\n selectedServer: '',\n $serverSelector: null,\n $serverInstructions: [],\n $expirySelectors: [],\n $snippets: [],\n\n init: function () {\n let self = this,\n cachingMetabox = $('#wphb-box-caching-enable'),\n cachingContent = cachingMetabox.find('.box-content'),\n cachingContentSpinner = cachingContent.find('.spinner'),\n cachingFooter = cachingMetabox.find('.box-footer');\n\n if ( wphbCachingStrings )\n self.strings = wphbCachingStrings;\n\n this.$serverSelector = $( '#wphb-server-type' );\n this.selectedServer = this.$serverSelector.val();\n //this.$spinner = $('#wphb-box-caching-enable .spinner');\n\n self.$snippets.apache = $('#wphb-code-snippet-apache').find('pre').first();\n self.$snippets.nginx = $('#wphb-code-snippet-nginx').find('pre').first();\n\n let instructionsList = $( '.wphb-server-instructions' );\n instructionsList.each( function() {\n self.$serverInstructions[ $(this).data('server') ] = $(this);\n });\n\n let expirySelectors = $( '.wphb-expiry-select' );\n\n expirySelectors.each( function() {\n const type = $(this).data('type');\n if ( type ) {\n $(this).change( function() {\n //self.$spinner.css( 'visibility', 'visible' );\n cachingContent.find('.wphb-content').hide();\n cachingFooter.hide();\n cachingContentSpinner.fadeIn();\n $('.wphb-notice').hide();\n\n // Expiration selector has changed\n ( function( element ) {\n const value = $( element ).val();\n // Change the plugin settings\n Fetcher.caching.setExpiration( type, value )\n .then( () => {\n // And reload the code snippet\n self.reloadSnippets();\n });\n return false;\n })( this );\n });\n }\n\n });\n\n this.showServerInstructions( this.selectedServer );\n\n this.$serverSelector.change( function() {\n let value = $(this).val();\n self.hideCurrentInstructions();\n self.showServerInstructions( value );\n self.setServer(value);\n self.selectedServer = value;\n });\n\n $( '#toggle-apache-instructions').click( function( e ) {\n e.preventDefault();\n $('.apache-instructions').slideToggle();\n });\n\n $( '#toggle-litespeed-instructions').click( function( e ) {\n e.preventDefault();\n $('.litespeed-instructions').slideToggle();\n });\n\n\n return this;\n },\n\n setServer: function( value ) {\n Fetcher.caching.setServer( value );\n },\n\n hideCurrentInstructions: function() {\n let selected = this.selectedServer;\n if ( this.$serverInstructions[ selected ] ) {\n this.$serverInstructions[ selected ].hide();\n }\n },\n\n showServerInstructions: function( server ) {\n if ( typeof this.$serverInstructions[ server ] !== 'undefined' ) {\n this.$serverInstructions[ server ].show();\n }\n\n if ( 'apache' === server || 'LiteSpeed' === server ) {\n $( '#enable-cache-wrap').show();\n }\n else {\n $( '#enable-cache-wrap').hide();\n }\n },\n\n reloadSnippets: function() {\n let self = this;\n let stop = false;\n for ( let i in self.$snippets ) {\n if ( self.$snippets.hasOwnProperty( i ) ) {\n Fetcher.caching.reloadSnippets( i )\n .then( ( response ) => {\n if ( stop ) {\n return;\n }\n\n self.$snippets[response.type].text( response.code );\n\n // Make sure that we only do things when server displayed is the processed one\n if ( response.type !== self.selectedServer ) {\n return;\n }\n\n if ( 'apache' === response.type && response.updatedFile ) {\n $( '#wphb-notice-code-snippet-htaccess-updated' ).show();\n location.href = self.strings.recheckURL + '&caching-updated=true';\n } else if ( 'apache' === response.type && self.strings.cacheEnabled && ! response.updatedFile ) {\n $( '#wphb-notice-code-snippet-htaccess-error' ).show();\n location.href = self.strings.htaccessErrorURL;\n } else {\n $( '#wphb-notice-code-snippet-updated' ).show();\n location.href = self.strings.recheckURL + '&caching-updated=true';\n }\n //self.$spinner.css( 'visibility', 'hidden' );\n });\n }\n }\n }\n };\n}( jQuery ));\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-caching.js","import Fetcher from './utils/fetcher';\n\n( function( $ ) {\n WPHB_Admin.cloudflare = {\n module: 'cloudflare',\n $cfSelector: false,\n $spinner: false,\n\n init: function () {\n this.$spinner = $('.wphb-spinner');\n this.$cfSelector = $('#wphb-caching-cloudflare-summary-set-expiry');\n let self = this;\n if ( wphb.cloudflare.is.connected ) {\n this.$cfSelector.change( function() {\n self.setExpiry.call( self, [this] );\n } );\n }\n\n return this;\n },\n\n setExpiry: function( selector ) {\n this.displaySpinner();\n const value = $(selector).val();\n Fetcher.cloudflare.setExpiration( value )\n .then( () => {\n window.location.reload();\n });\n },\n\n displaySpinner: function() {\n this.$spinner.css( 'visibility', 'visible' );\n }\n };\n}( jQuery ) );\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-cloudflare.js","import Fetcher from './utils/fetcher';\n\n( function( $ ) {\n WPHB_Admin.DashboardCloudFlare = {\n init: function( settings ) {\n this.currentStep = settings.currentStep;\n this.data = settings;\n this.email = settings.email;\n this.apiKey = settings.apiKey;\n this.$stepsContainer = $('#cloudflare-steps');\n this.$infoBox = $('#cloudflare-info');\n this.$spinner = $( '.cloudflare-spinner' );\n this.$deactivateButton = $('#wphb-box-dashboard-cloudflare').find('.box-title .buttons');\n\n this.renderStep( this.currentStep );\n\n $('body').on( 'click', '.cloudflare-clear-cache .button', function(e ) {\n e.preventDefault();\n this.purgeCache.apply( $(e.target), [this] );\n }.bind(this));\n\n },\n\n purgeCache: function( self ) {\n // Show spinner\n\t\t\tconst $button = this;\n\t\t\t$button.attr( 'disabled', true );\n\t\t\tself.showSpinner();\n\n Fetcher.cloudflare.purgeCache()\n .then( () => {\n // Show notice\n\t\t\t\t\tconst $notice = $('#wphb-notice-cloudflare-purge-cache');\n\t\t\t\t\twindow.scrollTo(0, 0);\n\t\t\t\t\t$notice.slideDown();\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t$notice.slideUp();\n\t\t\t\t\t}, 5e3);\n // Remove spinner\n\t\t\t\t\t$button.removeAttr( 'disabled' );\n\t\t\t\t\tself.hideSpinner();\n });\n },\n\n renderStep: function( step ) {\n const template = WPHB_Admin.DashboardCloudFlare.template( '#cloudflare-step-' + step );\n const content = template( this.data );\n const self = this;\n\n if ( content ) {\n this.currentStep = step;\n this.$stepsContainer\n .hide()\n .html( template( this.data ) )\n .fadeIn()\n .find( 'form' )\n .on( 'submit', function( e ) {\n e.preventDefault();\n self.submitStep.call( self, $(this) );\n });\n\n this.$spinner = this.$stepsContainer.find( '.cloudflare-spinner' );\n }\n\n this.bindEvents();\n },\n\n bindEvents: function() {\n const $howToInstructions = $('#cloudflare-how-to');\n\n $howToInstructions.hide();\n\n $('#cloudflare-how-to-title > a').click( function( e ) {\n e.preventDefault();\n $howToInstructions.toggle();\n });\n\n this.$stepsContainer.find( 'select' ).each( function() {\n WDP.wpmuSelect( this );\n });\n\n if ( 'final' === this.currentStep ) {\n this.$deactivateButton.removeClass( 'hidden' );\n } else {\n this.$deactivateButton.addClass( 'hidden' );\n }\n },\n\n emptyInfoBox: function() {\n this.$infoBox.html('');\n this.$infoBox.removeClass();\n },\n\n showInfoBox: function( message ) {\n this.$infoBox.addClass( 'wphb-notice' );\n this.$infoBox.addClass( 'wphb-notice-error' );\n this.$infoBox.text( message );\n },\n\n showSpinner: function() {\n this.$spinner.css( 'visibility', 'visible' );\n },\n\n hideSpinner: function() {\n this.$spinner.css( 'visibility', 'hidden' );\n },\n\n submitStep: function( $form ) {\n\t\t\tconst self = this;\n\n\t\t\t$form.find( 'input[type=submit]' ).attr( 'disabled', 'true' );\n\t\t\tthis.emptyInfoBox();\n\t\t\tthis.showSpinner();\n\n\t\t\tFetcher.cloudflare.connect( this.currentStep, $form.serialize(), this.data )\n .then( ( response ) => {\n\t\t\t\t\tself.data = response.newData;\n\t\t\t\t\tself.renderStep( response.nextStep );\n\n\t\t\t\t\tif ( response.nextStep === 'final' ) {\n\t\t\t\t\t\twindow.location.href = response.redirect;\n\t\t\t\t\t}\n })\n\t\t\t\t.catch( ( error ) => {\n\t\t\t\t\tself.showInfoBox( error );\n\t\t\t\t});\n\n\t\t\t$form.find( 'input[type=submit]' ).removeAttr( 'disabled' );\n\t\t\tself.hideSpinner();\n }\n };\n\n WPHB_Admin.DashboardCloudFlare.template = _.memoize(function ( id ) {\n let compiled,\n options = {\n evaluate: /<#([\\s\\S]+?)#>/g,\n interpolate: /\\{\\{\\{([\\s\\S]+?)\\}\\}\\}/g,\n escape: /\\{\\{([^\\}]+?)\\}\\}(?!\\})/g,\n variable: 'data'\n };\n\n return function ( data ) {\n _.templateSettings = options;\n compiled = compiled || _.template( $( id ).html() );\n return compiled( data );\n };\n });\n}(jQuery));\n\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-dashboard-cloudflare.js","import Fetcher from './utils/fetcher';\n\n( function( $ ) {\n WPHB_Admin.dashboard = {\n module: 'dashboard',\n\n init: function() {\n const self = this;\n\n\t\t\tif (wphbDashboardStrings)\n\t\t\t\tthis.strings = wphbDashboardStrings;\n\n $('#wphb-activate-minification').change( function() {\n const value = $(this).val();\n Fetcher.dashboard.toggleMinification( value )\n .then( () => {\n // If disabled, uncheck CDN checkbox and disable it.\n const CDNcheckbox = $('input[name=\"use_cdn\"]');\n if ( 'false' === value ) {\n CDNcheckbox.prop( 'checked', false );\n CDNcheckbox.prop( 'disabled', true );\n } else {\n CDNcheckbox.prop( 'disabled', false );\n }\n self.showNotice();\n });\n });\n\n $('#use_cdn').change( function() {\n const value = $(this).is(':checked');\n Fetcher.minification.toggleCDN( value )\n .then( () => {\n self.showNotice();\n });\n });\n\n $('.wphb-performance-report-item').click( function() {\n const url = $(this).data( 'performance-url' );\n if ( url ) {\n location.href = url;\n }\n });\n return this;\n },\n\n /**\n * Notice on settings update.\n */\n showNotice: function () {\n const notice = $('#wphb-notice-minification-settings-updated');\n notice.slideDown();\n setTimeout( function() {\n notice.slideUp();\n }, 5000 );\n },\n\n\t\t/**\n * Run quick setup.\n\t\t */\n\t\tstartQuickSetup: function () {\n // Show quick setup modal\n WDP.showOverlay( '#wphb-quick-setup-modal', { class: 'wphb-modal small wphb-quick-setup-modal no-close' } );\n },\n\n\t\t/**\n * Skip quick setup.\n\t\t */\n\t\tskipSetup: function () {\n Fetcher.dashboard.skipSetup()\n .then( () => {\n window.location.reload(true);\n });\n },\n\n\t\t/**\n * Run performance test after quick setup.\n\t\t */\n\t\trunPerformanceTest: function() {\n\t\t\t// Show quick setup modal\n\t\t\tWDP.showOverlay(\"#run-performance-test-modal\", { class: 'wphb-modal small wphb-progress-modal no-close' } );\n\n\t\t\t// Run performance test\n\t\t\tconst module = WPHB_Admin.getModule('performance');\n\t\t\tmodule.performanceTest( this.strings.finishedTestURLsLink );\n }\n };\n}( jQuery ));\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-dashboard.js","import Fetcher from './utils/fetcher';\n\n(function($) {\n WPHB_Admin.gzip = {\n module: \"gzip\",\n selectedServer: \"\",\n $serverSelector: null,\n $serverInstructions: [],\n\n init: function() {\n const self = this;\n\n this.$serverSelector = $(\"#wphb-server-type\");\n this.selectedServer = this.$serverSelector.val();\n let instructionsList = $(\".wphb-server-instructions\");\n instructionsList.each(function() {\n self.$serverInstructions[$(this).data(\"server\")] = $(this);\n });\n this.showServerInstructions(this.selectedServer);\n this.$serverSelector.change(function() {\n const value = $(this).val();\n self.hideCurrentInstructions();\n self.showServerInstructions(value);\n self.setServer(value);\n self.selectedServer = value;\n });\n $(\"#toggle-apache-instructions\").click(function(e) {\n e.preventDefault();\n $(\".apache-instructions\").toggle();\n });\n $(\"#toggle-litespeed-instructions\").click(function(e) {\n e.preventDefault();\n $(\".litespeed-instructions\").toggle();\n });\n return this;\n },\n\n hideCurrentInstructions: function() {\n const selected = this.selectedServer;\n if (this.$serverInstructions[selected]) {\n this.$serverInstructions[selected].hide();\n }\n },\n\n showServerInstructions: function(server) {\n if (typeof this.$serverInstructions[server] !== \"undefined\") {\n this.$serverInstructions[server].show();\n }\n if (\"apache\" === server || 'LiteSpeed' === server) {\n $(\"#enable-cache-wrap\").show();\n } else {\n $(\"#enable-cache-wrap\").hide();\n }\n },\n\n setServer: function( value ) {\n Fetcher.caching.setServer( value );\n },\n };\n})(jQuery);\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-gzip.js","( function( $ ) {\n 'use strict';\n\n let WPHB_Admin = {\n modules: [],\n // Common functionality to all screens\n init: function() {\n\n function updatePerformanceGraph($wrap){\n let $item = $wrap.find('.wphb-score-result-label'),\n val = parseInt($item.text(), 10) || 100,\n $circle = $wrap.find(\".wphb-score-graph-result\"),\n r, c, pct\n ;\n r = $circle.attr('r');\n c = Math.PI*(r*2);\n\n if (val < 0) { val = 0;}\n if (val > 100) { val = 100;}\n\n pct = ((100-val)/100)*c;\n\n $circle.css({ strokeDashoffset: pct});\n }\n\n function updatePerformanceResultsGraphs(){\n\n // Update Overall Score\n $(\".wphb-performance-report-overall-score\").each(function(){\n updatePerformanceGraph($(this));\n });\n\n // Update Current Score\n $(\".wphb-performance-report-current-score\").each(function(){\n updatePerformanceGraph($(this));\n });\n\n // Update All Scores\n $(\".wphb-performance-report-item-score\").each(function(){\n updatePerformanceGraph($(this));\n });\n\n }\n window.register_events_performance = function(){\n setTimeout(updatePerformanceResultsGraphs, 500);\n };\n $(function(){ setTimeout(updatePerformanceResultsGraphs, 500); });\n\n },\n initModule: function( module ) {\n if ( this.hasOwnProperty( module ) ) {\n this.modules[ module ] = this[ module ].init();\n return this.modules[ module ];\n }\n\n return {};\n },\n getModule: function( module ) {\n if ( typeof this.modules[ module ] !== 'undefined' )\n return this.modules[ module ];\n else\n return this.initModule( module );\n }\n };\n \n\n WPHB_Admin.utils = {\n\n membershipModal: {\n open: function() {\n $( '#wphb-upgrade-membership-modal-link').trigger( 'click' );\n }\n },\n\n post: function( data, module ) {\n data.action = 'wphb_ajax';\n data.module = module;\n return $.ajax({\n url: ajaxurl,\n method: 'POST',\n data: data\n });\n }\n };\n\n WPHB_Admin.notices = {\n\n init: function() {\n $( '.wphb-notice:not(.notice) a.wphb-dismiss').click( function( e ) {\n e.preventDefault();\n let id = $(this).data( 'id' );\n let nonce = $(this).data( 'nonce' );\n\n $(this).parent( '.error' ).hide();\n });\n }\n };\n\n window.WPHB_Admin = WPHB_Admin;\n\n}( jQuery ) );\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-main.js","import Fetcher from './utils/fetcher';\nimport { __, getLink } from './utils/helpers';\nimport Row from './minification/Row';\nimport RowsCollection from './minification/RowsCollection';\n\n( function( $ ) {\n 'use strict';\n\n WPHB_Admin.minification = {\n\n $checkFilesButton: null,\n $checkFilesResultsContainer : null,\n module: 'minification',\n checkURLSList: null,\n checkedURLS: 0,\n $spinner: null,\n\n init: function() {\n const self = this;\n\n // Filter action button on Minification page\n $('#wphb-minification-filter-button').on('click', function(e) {\n e.preventDefault();\n $('#wphb-minification-filter').toggle('slow');\n });\n\n // Check files button\n this.$checkFilesButton = $( '#check-files' );\n this.$disableMinification = $('#wphb-disable-minification');\n this.$spinner = $('.spinner');\n\n if ( this.$checkFilesButton.length ) {\n this.$checkFilesButton.click( function( e ) {\n e.preventDefault();\n $(this).attr('disabled', true);\n self.checkFiles( getLink( 'minification' ) );\n });\n }\n\n $('.wphb-discard').click( function(e) {\n e.preventDefault();\n\n if ( confirm( __( 'discardAlert' ) ) ) {\n location.reload();\n }\n return false;\n\n });\n\n $( '.wphb-enqueued-files input' ).on( 'change', function() {\n $('.wphb-discard').attr( 'disabled', false );\n });\n\n $('#use_cdn').change( function() {\n const cdn_value = $(this).is(':checked');\n Fetcher.minification.toggleCDN( cdn_value )\n .then( () => {\n const notice = $('#wphb-notice-minification-advanced-settings-updated');\n notice.slideDown();\n setTimeout( function() {\n notice.slideUp();\n }, 5000 );\n });\n });\n\n this.$disableMinification.change( function() {\n const value = $(this).is(':checked');\n\n self.$spinner.css( 'visibility', 'visible' );\n\n if ( self.timer && value ) {\n clearTimeout( self.timer );\n self.$spinner.css( 'visibility', 'hidden' );\n }\n\n self.timer = setTimeout( function() {\n Fetcher.minification.toggleMinification( value )\n .then( () => {\n location.reload();\n });\n }, 3000 );\n\n\n });\n\n this.rowsCollection = new WPHB_Admin.minification.RowsCollection();\n\n const rows = $('.wphb-border-row');\n\n rows.each( function( index, row ) {\n let _row;\n if ( $(row).data('filter-secondary') ) {\n _row = new WPHB_Admin.minification.Row( $(row), $(row).data('filter'), $(row).data('filter-secondary') );\n }\n else {\n _row = new WPHB_Admin.minification.Row( $(row), $(row).data('filter') );\n }\n self.rowsCollection.push( _row );\n });\n\n $('#wphb-s').keyup( function() {\n self.rowsCollection.addFilter( $(this).val(), 'primary' );\n self.rowsCollection.applyFilters();\n });\n\n $('#wphb-secondary-filter').change( function() {\n self.rowsCollection.addFilter( $(this).val(), 'secondary' );\n self.rowsCollection.applyFilters();\n });\n\n $('.filter-toggles').change( function() {\n const element = $(this);\n const what = element.data('toggles');\n const value = element.prop( 'checked' );\n const visibleItems = self.rowsCollection.getVisibleItems();\n\n for ( let i in visibleItems ) {\n visibleItems[i].change( what, value );\n }\n });\n\n // Files selectors\n const filesList = $('input.wphb-minification-file-selector');\n filesList.click( function() {\n const $this = $( this );\n const element = self.rowsCollection.getItemById( $this.data( 'type' ), $this.data( 'handle' ) );\n if ( ! element ) {\n return;\n }\n\n if ( $this.is( ':checked' ) ) {\n element.select();\n }\n else {\n element.unSelect();\n }\n });\n\n const selectAll = $('#minification-bulk-file');\n selectAll.click( function() {\n const $this = $( this );\n let items = self.rowsCollection.getItems();\n for ( let i in items ) {\n if ( items.hasOwnProperty( i ) ) {\n if ( $this.is( ':checked' ) ) {\n items[i].select();\n }\n else {\n items[i].unSelect();\n }\n }\n }\n });\n\n // Include/exclude file checkbox\n $('.toggle-cross').on('click', function() {\n const $this = $(this);\n const checkbox = $this.find( 'input.toggle-include' );\n const row = self.rowsCollection.getItemById( $this.data( 'type' ), $this.data( 'handle' ) );\n // Mark the item as include or not in the rows list\n if ( row ) {\n row.change( 'include', ! checkbox.prop( 'checked' ) );\n row.getElement().find( 'input:not(.toggle-include)' ).prop('disabled', ! checkbox.prop( 'checked' ) );\n }\n });\n\n // Handle two CDN checkboxes on Minification page\n const checkboxes = $(\"input[type=checkbox][name=use_cdn]\");\n checkboxes.change( function() {\n const checkedState = $(this).prop('checked');\n\n checkboxes.each( function() {\n this.checked = checkedState;\n });\n });\n\n /* Show details of minification row on mobile devices */\n $('body').on('click', '.wphb-minification-file-details', function() {\n if ( window.innerWidth < 783 ) {\n $(this).parent().find('.wphb-minification-row-details').toggle('slow');\n }\n });\n\n /*\n Catch window resize and revert styles for responsive divs\n 1/4 of a second should be enough to trigger during device rotations (from portrait to landscape mode)\n */\n let minification_resize_rows = _.debounce(function() {\n\n if ( window.innerWidth >= 783 ) {\n $('.wphb-minification-row-details').css('display', 'flex');\n } else {\n $('.wphb-minification-row-details').css('display', 'none');\n }\n\n }, 250);\n\n window.addEventListener('resize', minification_resize_rows);\n\n return this;\n },\n\n checkFiles: function( redirect ) {\n const self = this;\n\n if ( typeof redirect === 'undefined' )\n redirect = false;\n\n if ( ! self.minificationStarted ) {\n // Store the progress in session storage to persist during page reloads\n // If there is no previous value, we init one with 10%\n if ( sessionStorage.getItem('progress') === null ) {\n sessionStorage.setItem('progress', 10);\n }\n\n // Update progress bar\n const progress = sessionStorage.getItem('progress');\n this.updateProgressBar( progress );\n\n // Send an AJAX request that will flag the check files as started\n Fetcher.minification.startCheck( progress )\n .then( ( response ) => {\n // Set the number of steps to be used in percentage count. Only if not set already.\n if ( ( typeof response.steps !== 'undefined' ) && ( sessionStorage.getItem('steps') === null ) ) {\n sessionStorage.setItem('steps', response.steps);\n }\n\n self.minificationStarted = true;\n self.checkFiles( redirect );\n });\n }\n else {\n const progress = sessionStorage.getItem('progress');\n const step = Math.round( 80 / sessionStorage.getItem('steps') );\n Fetcher.minification.checkStep( progress, step )\n .then( ( response ) => {\n if ( typeof response.finished !== 'undefined' ) {\n // Finished\n if ( response.finished && redirect ) {\n // Clear session storage\n sessionStorage.clear();\n\n // Update progress bar\n this.updateProgressBar( 100 );\n\n // Show enable cdn modal only for members\n if ( true === response.show_cdn && $('#enable-cdn-modal').length ) {\n WDP.showOverlay( '#enable-cdn-modal', { class: 'wphb-modal small wphb-progress-modal no-close' } );\n } else {\n window.location.href = redirect;\n }\n }\n // Next step\n else if ( ! response.finished ) {\n // Store the progress in session storage to persist during page reloads\n let progress = parseInt( sessionStorage.getItem('progress') ) + Math.round( 80 / sessionStorage.getItem('steps') );\n sessionStorage.setItem( 'progress', progress );\n\n // Update progress bar.\n this.updateProgressBar( progress );\n\n // Wait 3 seconds before calling again\n window.setTimeout( function() {\n self.checkFiles( redirect );\n }, 3000);\n }\n } else {\n // Error\n window.location.href = redirect;\n }\n });\n } // End else\n\n }, // End checkFiles\n\n updateProgressBar: function( progress, cancel = false ) {\n if ( progress > 100 ) {\n progress = 100;\n }\n // Update progress bar\n $('.wphb-scan-progress .wphb-scan-progress-text span').text( progress + '%' );\n if ( progress >= 90 ) {\n $('.wphb-progress-state .wphb-progress-state-text').text('Finalizing...');\n }\n if ( cancel ) {\n\t\t\t\t$('.wphb-progress-state .wphb-progress-state-text').text('Cancelling...');\n }\n $('.wphb-scan-progress .wphb-scan-progress-bar span').width( progress + '%' );\n },\n\n cancelScan: function() {\n Fetcher.minification.cancelScan()\n .then( () => {\n\t\t\t\t\t// Clear session storage\n\t\t\t\t\tsessionStorage.clear();\n\n\t\t\t\t\tthis.updateProgressBar( 0, true );\n\n\t\t\t\t\t// Reload page\n window.location.href = getLink( 'minification' );\n });\n }\n\n }; // End WPHB_Admin.minification\n\n WPHB_Admin.minification.Row = Row;\n WPHB_Admin.minification.RowsCollection = RowsCollection;\n\n}( jQuery ));\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-minification.js","import Fetcher from './utils/fetcher';\n\n( function( $ ) {\n 'use strict';\n WPHB_Admin.performance = {\n\n module: 'performance',\n iteration: 0,\n progress: 0,\n\n init: function () {\n\n let self = this;\n let body = $('body');\n\n if (wphbPerformanceStrings)\n this.strings = wphbPerformanceStrings;\n\n this.$runTestButton = $('#run-performance-test');\n\n let performanceReportTable = $(\".performance-report-table\");\n\n performanceReportTable.off('click', 'button');\n performanceReportTable.on('click', '.wphb-performance-report-item-cta .additional-content-opener' && 'tr.wphb-performance-report-item', function (e) {\n e.preventDefault();\n\n let getParentPerformanceItem = $(this).closest(\".wphb-performance-report-item\"),\n getNextAdditionalContentRow = getParentPerformanceItem.nextUntil(\".wphb-performance-report-item\");\n\n getNextAdditionalContentRow.toggleClass(\"wphb-performance-report-item-additional-content-opened\");\n\n if (getNextAdditionalContentRow.hasClass(\"wphb-performance-report-item-additional-content-opened\")) {\n getParentPerformanceItem.addClass(\"wphb-performance-report-item-opened\");\n } else {\n getParentPerformanceItem.removeClass(\"wphb-performance-report-item-opened\");\n }\n\n });\n\n if (this.$runTestButton.length) {\n this.$runTestButton.click(function (e) {\n e.preventDefault();\n $(this).attr('disabled', true);\n self.performanceTest(self.strings.finishedTestURLsLink);\n });\n }\n\n // If a hash is present in URL, let's open the rule extra content\n const hash = window.location.hash;\n if (hash) {\n const row = $(hash);\n if (row.length) {\n row.find('.trigger-additional-content').trigger('click');\n }\n\n }\n\n // Schedule show/hide day of week\n $('select[name=\"email-frequency\"]').change(function () {\n if ( '1' === $(this).val() ) {\n $(this).closest('.schedule-box').find('div.days-container').hide();\n } else {\n $(this).closest('.schedule-box').find('div.days-container').show();\n }\n }).change();\n\n // Remove recipient\n body.on('click', '.wphb-remove-recipient', function (e) {\n e.preventDefault();\n $(this).closest('.recipient').remove();\n $('.scan-settings').find(\"input[id='scan_recipient'][value=\" + $(this).attr('data-id') + \"]\").remove();\n });\n\n // Add recipient\n $('#add-receipt').click(function () {\n const email = $(\"#wphb-username-search\").val();\n const name = $(\"#wphb-first-name\").val();\n Fetcher.performance.addRecipient( email, name )\n .then( ( response ) => {\n const user_row = $('<div class=\"recipient\"/>');\n\n const img = $('<img/>').attr({\n 'src': response.avatar,\n 'width': '30'\n });\n const name = $('<span/>').html(response.name);\n\n user_row.append('<span class=\"name\"/>');\n user_row.find('.name').append( img, name);\n\n\n user_row.append($('<span class=\"email\"/>').html(email));\n user_row.append($('<a/>').attr({\n 'data-id': response.user_id,\n 'class': 'remove float-r wphb-remove-recipient',\n 'href': '#',\n 'alt': self.strings.removeButtonText\n }).html('<i class=\"dev-icon dev-icon-cross\"></i>'));\n\n $('<input>').attr({\n type: 'hidden',\n id: 'scan_recipient',\n name: 'email-recipients[]',\n value: JSON.stringify( { email: response.email, name: response.name } )\n }).appendTo(user_row);\n\n $('.receipt .recipients').append(user_row);\n $(\"#wphb-username-search\").val('');\n $(\"#wphb-first-name\").val('');\n })\n .catch( ( error ) => {\n alert( error.message );\n } );\n return false;\n });\n\n // Save report settings\n body.on('submit', '.scan-frm', function (e) {\n e.preventDefault();\n const form_data = $(this).serialize();\n let that = $(this);\n\n that.find('.button').attr('disabled', 'disabled');\n\n Fetcher.performance.saveReportsSettings( form_data )\n .then( () => {\n that.find('.button').removeAttr('disabled');\n self.showUpdateMessage();\n });\n return false;\n });\n\n return this;\n\n },\n\n showUpdateMessage: function () {\n const notice = $('#wphb-notice-performance-report-settings-updated');\n window.scrollTo(0,0);\n notice.slideDown();\n setTimeout( function() {\n notice.slideUp();\n }, 5000 );\n },\n\n\t\tperformanceTest: function ( redirect ) {\n\t\t\tconst self = this;\n\n if ( typeof redirect === 'undefined' )\n redirect = false;\n\n // Update progress bar\n self.updateProgressBar();\n\n Fetcher.performance.runTest()\n .then( ( response ) => {\n\t\t\t\t\tif ( ! response.finished ) {\n\t\t\t\t\t\t// Try again 5 seconds later\n\t\t\t\t\t\twindow.setTimeout(function () {\n\t\t\t\t\t\t\tself.performanceTest( redirect );\n\t\t\t\t\t\t}, 5000);\n\t\t\t\t\t} else if ( redirect ) {\n window.location = redirect;\n\t\t\t\t\t}\n });\n },\n\n updateProgressBar: function() {\n\t\t\tif ( this.progress < 90 ) {\n\t\t\t\tthis.progress += 35;\n\t\t\t}\n\t\t\tif ( this.progress > 100 ) {\n\t\t\t\tthis.progress = 90;\n\t\t\t}\n\t\t\t$('.wphb-scan-progress .wphb-scan-progress-text span').text( this.progress + '%' );\n\t\t\t$('.wphb-scan-progress .wphb-scan-progress-bar span').attr( 'style', 'width:' + this.progress + '%' );\n }\n };\n}( jQuery ));\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-performance.js","( function( $ ) {\n WPHB_Admin.uptime = {\n module: 'uptime',\n $dataRangeSelector: null,\n chartData: null,\n timer:null,\n $spinner: null,\n init: function() {\n this.$spinner = $('.spinner');\n this.strings = wphbUptimeStrings;\n this.$dataRangeSelector = $( '#wphb-uptime-data-range' );\n this.chartData = $('#uptime-chart-json').val();\n this.$disableUptime = $('#wphb-disable-uptime');\n\n this.$dataRangeSelector.change( function() {\n window.location.href = $(this).find( ':selected' ).data( 'url' );\n });\n\n var self = this;\n this.$disableUptime.change( function() {\n self.$spinner.css( 'visibility', 'visible' );\n var value = $(this).is(':checked');\n if ( value && self.timer ) {\n clearTimeout( self.timer );\n self.$spinner.css( 'visibility', 'hidden' );\n }\n else {\n // you have 3 seconds to change your mind\n self.timer = setTimeout( function() {\n location.href = self.strings.disableUptimeURL;\n }, 3000 );\n }\n\n return;\n });\n\n this.drawChart();\n\n /* Re-check Uptime status */\n $('#uptime-re-check-status').on( 'click', function(e){\n e.preventDefault();\n location.reload();\n });\n },\n\n drawChart: function() {\n var data = new google.visualization.DataTable();\n data.addColumn('datetime', 'Day');\n data.addColumn('number', 'Response Time (ms)');\n\n var chart_array = JSON.parse( this.chartData );\n for (var i = 0; i < chart_array.length; i++) {\n chart_array[i][0] = new Date( chart_array[i][0] );\n chart_array[i][1] = Math.round( chart_array[i][1] );\n\n /* brings the graph below the x axis */\n if ( Math.round( chart_array[i][1] ) == 0 ) {\n chart_array[i][1] = -100;\n }\n\n }\n\n data.addRows(chart_array);\n\n var options = {\n chartArea: {\n left: 80,\n top: 20,\n width: '90%',\n height: '90%'\n },\n colors: ['#24ADE5'],\n curveType: 'function',\n /*interpolateNulls: true,*/\n legend: { position: 'none' },\n vAxis: {\n format: '#,### ms',\n viewWindow: { min: 0 } /* don't display negative values */\n },\n tooltip: { isHtml: true },\n series: {\n 0: { axis: 'Resp' }\n },\n axes: {\n y: {\n Resp: { label: 'Response Time (ms)' }\n }\n }\n };\n\n var chart = new google.visualization.LineChart(document.getElementById('uptime-chart'));\n chart.draw(data, options);\n\n $(window).resize(function(){\n chart.draw(data, options);\n });\n }\n };\n}(jQuery));\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/admin-uptime.js","require('./admin-main.js');\nrequire('./admin-performance.js');\nrequire('./admin-gzip.js');\nrequire('./admin-caching.js');\nrequire('./admin-minification.js');\nrequire('./admin-dashboard.js');\nrequire('./admin-dashboard-cloudflare.js');\nrequire('./admin-uptime.js');\nrequire('./admin-cloudflare.js');\nrequire('./admin-app.js');\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/index.js","const Row = ( _element, _filter, _filter_sec ) => {\n let $el = _element,\n filter = _filter.toLowerCase(),\n filterSecondary = false,\n selected = false,\n visible = true;\n\n const $include = $el.find( '.toggle-include' ),\n $combine = $el.find( '.toggle-combine' ),\n $minify = $el.find( '.toggle-minify' ),\n $posFooter = $el.find( '.toggle-position-footer' ),\n $disableIcon = $el.find( '.toggle-cross > i' );\n\n if ( _filter_sec ) {\n filterSecondary = _filter_sec.toLowerCase();\n }\n\n return {\n hide: function() {\n $el.addClass( 'out-of-filter' );\n visible = false;\n },\n\n show: function() {\n $el.removeClass( 'out-of-filter' );\n visible = true;\n },\n\n getElement: function() {\n return $el;\n },\n\n getId: function() {\n return $el.attr( 'id' );\n },\n\n getFilter: function() {\n return filter;\n },\n\n matchFilter: function( text ) {\n if ( text === '' ) {\n return true;\n }\n\n text = text.toLowerCase();\n return filter.search( text ) > - 1;\n },\n\n matchSecondaryFilter: function( text ) {\n if ( text === '' ) {\n return true;\n }\n\n if ( ! filterSecondary ) {\n return false;\n }\n\n text = text.toLowerCase();\n return filterSecondary === text;\n },\n\n isVisible: function() {\n return visible;\n },\n\n isSelected: function() {\n return selected;\n },\n\n select: function() {\n selected = true;\n },\n\n unSelect: function() {\n selected = false;\n },\n\n change: function( what, value ) {\n switch ( what ) {\n case 'minify': {\n $minify.prop( 'checked', value );\n break;\n }\n case 'combine': {\n $combine.prop( 'checked', value );\n break;\n }\n case 'include': {\n $disableIcon.removeClass();\n $include.prop( 'checked', value );\n if ( value ) {\n $el.removeClass( 'disabled' );\n $disableIcon.addClass( 'dev-icon dev-icon-cross' );\n $include.attr( 'checked', true );\n } else {\n $el.addClass( 'disabled' );\n $disableIcon.addClass( 'wdv-icon wdv-icon-refresh' );\n $include.removeAttr( 'checked' );\n }\n break;\n }\n case 'footer': {\n $posFooter.prop( 'checked', value );\n break;\n }\n }\n }\n\n };\n};\n\nexport default Row;\n\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/minification/Row.js","const RowsCollection = () => {\n let items = [];\n let currentFilter = '';\n let currentSecondaryFilter = '';\n\n return {\n push: function( row ) {\n if ( typeof row === 'object' ) {\n items.push( row );\n }\n },\n\n getItems: function() {\n return items;\n },\n\n getItem: function( i ) {\n if ( items[i] ) {\n return items[i];\n }\n return false;\n },\n\n /**\n * Get a collection item by type and ID\n * @param type\n * @param id\n */\n getItemById: function( type, id ) {\n let value = false;\n for ( let i in items ) {\n if ( 'wphb-file-' + type + '-' + id === items[i].getId() ) {\n value = items[i];\n break;\n }\n }\n return value;\n },\n\n getVisibleItems: function() {\n let visible = [];\n for ( let i in items ) {\n if ( items[i].isVisible() ) {\n visible.push( items[i] );\n }\n }\n return visible;\n },\n\n getSelectedItems: function() {\n let selected = [];\n\n for ( let i in items ) {\n if ( items[i].isVisible() && items[i].isSelected() ) {\n selected.push( items[i] );\n }\n }\n\n return selected;\n },\n\n addFilter: function( filter, type ) {\n if ( type === 'secondary' ) {\n currentSecondaryFilter = filter;\n }\n else {\n currentFilter = filter;\n }\n },\n\n applyFilters: function() {\n for ( let i in items ) {\n if ( items[i] ) {\n if ( items[i].matchFilter( currentFilter ) && items[i].matchSecondaryFilter( currentSecondaryFilter ) ) {\n items[i].show();\n }\n else {\n items[i].hide();\n }\n }\n\n }\n }\n };\n};\n\nexport default RowsCollection;\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/minification/RowsCollection.js","/**\n * Strings internationalization\n *\n * @param str\n *\n * @returns {*|string}\n */\nexport const __ = ( str ) => {\n return wphb.strings[ str ] || '';\n};\n\n/**\n * Get a link to a HB screen\n *\n * @param {string} screen Screen slug\n * @returns {string}\n */\nexport const getLink = ( screen ) => {\n return wphb.links[ screen ] || '';\n};\n\n\n\n\n// WEBPACK FOOTER //\n// ./_src/admin/js/utils/helpers.js","/**\n * A faster alternative to `Function#apply`, this function invokes `func`\n * with the `this` binding of `thisArg` and the arguments of `args`.\n *\n * @private\n * @param {Function} func The function to invoke.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} args The arguments to invoke `func` with.\n * @returns {*} Returns the result of `func`.\n */\nfunction apply(func, thisArg, args) {\n switch (args.length) {\n case 0: return func.call(thisArg);\n case 1: return func.call(thisArg, args[0]);\n case 2: return func.call(thisArg, args[0], args[1]);\n case 3: return func.call(thisArg, args[0], args[1], args[2]);\n }\n return func.apply(thisArg, args);\n}\n\nmodule.exports = apply;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_apply.js\n// module id = 32\n// module chunks = 0","var baseTimes = require('./_baseTimes'),\n isArguments = require('./isArguments'),\n isArray = require('./isArray'),\n isBuffer = require('./isBuffer'),\n isIndex = require('./_isIndex'),\n isTypedArray = require('./isTypedArray');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates an array of the enumerable property names of the array-like `value`.\n *\n * @private\n * @param {*} value The value to query.\n * @param {boolean} inherited Specify returning inherited property names.\n * @returns {Array} Returns the array of property names.\n */\nfunction arrayLikeKeys(value, inherited) {\n var isArr = isArray(value),\n isArg = !isArr && isArguments(value),\n isBuff = !isArr && !isArg && isBuffer(value),\n isType = !isArr && !isArg && !isBuff && isTypedArray(value),\n skipIndexes = isArr || isArg || isBuff || isType,\n result = skipIndexes ? baseTimes(value.length, String) : [],\n length = result.length;\n\n for (var key in value) {\n if ((inherited || hasOwnProperty.call(value, key)) &&\n !(skipIndexes && (\n // Safari 9 has enumerable `arguments.length` in strict mode.\n key == 'length' ||\n // Node.js 0.10 has enumerable non-index properties on buffers.\n (isBuff && (key == 'offset' || key == 'parent')) ||\n // PhantomJS 2 has enumerable non-index properties on typed arrays.\n (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||\n // Skip index properties.\n isIndex(key, length)\n ))) {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = arrayLikeKeys;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_arrayLikeKeys.js\n// module id = 33\n// module chunks = 0","var baseGetTag = require('./_baseGetTag'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]';\n\n/**\n * The base implementation of `_.isArguments`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n */\nfunction baseIsArguments(value) {\n return isObjectLike(value) && baseGetTag(value) == argsTag;\n}\n\nmodule.exports = baseIsArguments;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseIsArguments.js\n// module id = 34\n// module chunks = 0","var isFunction = require('./isFunction'),\n isMasked = require('./_isMasked'),\n isObject = require('./isObject'),\n toSource = require('./_toSource');\n\n/**\n * Used to match `RegExp`\n * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).\n */\nvar reRegExpChar = /[\\\\^$.*+?()[\\]{}|]/g;\n\n/** Used to detect host constructors (Safari). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for built-in method references. */\nvar funcProto = Function.prototype,\n objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\\\$&')\n .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * The base implementation of `_.isNative` without bad shim checks.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function,\n * else `false`.\n */\nfunction baseIsNative(value) {\n if (!isObject(value) || isMasked(value)) {\n return false;\n }\n var pattern = isFunction(value) ? reIsNative : reIsHostCtor;\n return pattern.test(toSource(value));\n}\n\nmodule.exports = baseIsNative;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseIsNative.js\n// module id = 35\n// module chunks = 0","var baseGetTag = require('./_baseGetTag'),\n isLength = require('./isLength'),\n isObjectLike = require('./isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n arrayTag = '[object Array]',\n boolTag = '[object Boolean]',\n dateTag = '[object Date]',\n errorTag = '[object Error]',\n funcTag = '[object Function]',\n mapTag = '[object Map]',\n numberTag = '[object Number]',\n objectTag = '[object Object]',\n regexpTag = '[object RegExp]',\n setTag = '[object Set]',\n stringTag = '[object String]',\n weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n dataViewTag = '[object DataView]',\n float32Tag = '[object Float32Array]',\n float64Tag = '[object Float64Array]',\n int8Tag = '[object Int8Array]',\n int16Tag = '[object Int16Array]',\n int32Tag = '[object Int32Array]',\n uint8Tag = '[object Uint8Array]',\n uint8ClampedTag = '[object Uint8ClampedArray]',\n uint16Tag = '[object Uint16Array]',\n uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dataViewTag] = typedArrayTags[dateTag] =\ntypedArrayTags[errorTag] = typedArrayTags[funcTag] =\ntypedArrayTags[mapTag] = typedArrayTags[numberTag] =\ntypedArrayTags[objectTag] = typedArrayTags[regexpTag] =\ntypedArrayTags[setTag] = typedArrayTags[stringTag] =\ntypedArrayTags[weakMapTag] = false;\n\n/**\n * The base implementation of `_.isTypedArray` without Node.js optimizations.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n */\nfunction baseIsTypedArray(value) {\n return isObjectLike(value) &&\n isLength(value.length) && !!typedArrayTags[baseGetTag(value)];\n}\n\nmodule.exports = baseIsTypedArray;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseIsTypedArray.js\n// module id = 36\n// module chunks = 0","var isPrototype = require('./_isPrototype'),\n nativeKeys = require('./_nativeKeys');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction baseKeys(object) {\n if (!isPrototype(object)) {\n return nativeKeys(object);\n }\n var result = [];\n for (var key in Object(object)) {\n if (hasOwnProperty.call(object, key) && key != 'constructor') {\n result.push(key);\n }\n }\n return result;\n}\n\nmodule.exports = baseKeys;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseKeys.js\n// module id = 37\n// module chunks = 0","var identity = require('./identity'),\n overRest = require('./_overRest'),\n setToString = require('./_setToString');\n\n/**\n * The base implementation of `_.rest` which doesn't validate or coerce arguments.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n */\nfunction baseRest(func, start) {\n return setToString(overRest(func, start, identity), func + '');\n}\n\nmodule.exports = baseRest;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseRest.js\n// module id = 38\n// module chunks = 0","var constant = require('./constant'),\n defineProperty = require('./_defineProperty'),\n identity = require('./identity');\n\n/**\n * The base implementation of `setToString` without support for hot loop shorting.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar baseSetToString = !defineProperty ? identity : function(func, string) {\n return defineProperty(func, 'toString', {\n 'configurable': true,\n 'enumerable': false,\n 'value': constant(string),\n 'writable': true\n });\n};\n\nmodule.exports = baseSetToString;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseSetToString.js\n// module id = 39\n// module chunks = 0","/**\n * The base implementation of `_.times` without support for iteratee shorthands\n * or max array length checks.\n *\n * @private\n * @param {number} n The number of times to invoke `iteratee`.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the array of results.\n */\nfunction baseTimes(n, iteratee) {\n var index = -1,\n result = Array(n);\n\n while (++index < n) {\n result[index] = iteratee(index);\n }\n return result;\n}\n\nmodule.exports = baseTimes;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseTimes.js\n// module id = 40\n// module chunks = 0","/**\n * The base implementation of `_.unary` without support for storing metadata.\n *\n * @private\n * @param {Function} func The function to cap arguments for.\n * @returns {Function} Returns the new capped function.\n */\nfunction baseUnary(func) {\n return function(value) {\n return func(value);\n };\n}\n\nmodule.exports = baseUnary;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_baseUnary.js\n// module id = 41\n// module chunks = 0","var assignValue = require('./_assignValue'),\n baseAssignValue = require('./_baseAssignValue');\n\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property identifiers to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @param {Function} [customizer] The function to customize copied values.\n * @returns {Object} Returns `object`.\n */\nfunction copyObject(source, props, object, customizer) {\n var isNew = !object;\n object || (object = {});\n\n var index = -1,\n length = props.length;\n\n while (++index < length) {\n var key = props[index];\n\n var newValue = customizer\n ? customizer(object[key], source[key], key, object, source)\n : undefined;\n\n if (newValue === undefined) {\n newValue = source[key];\n }\n if (isNew) {\n baseAssignValue(object, key, newValue);\n } else {\n assignValue(object, key, newValue);\n }\n }\n return object;\n}\n\nmodule.exports = copyObject;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_copyObject.js\n// module id = 42\n// module chunks = 0","var root = require('./_root');\n\n/** Used to detect overreaching core-js shims. */\nvar coreJsData = root['__core-js_shared__'];\n\nmodule.exports = coreJsData;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_coreJsData.js\n// module id = 43\n// module chunks = 0","var baseRest = require('./_baseRest'),\n isIterateeCall = require('./_isIterateeCall');\n\n/**\n * Creates a function like `_.assign`.\n *\n * @private\n * @param {Function} assigner The function to assign values.\n * @returns {Function} Returns the new assigner function.\n */\nfunction createAssigner(assigner) {\n return baseRest(function(object, sources) {\n var index = -1,\n length = sources.length,\n customizer = length > 1 ? sources[length - 1] : undefined,\n guard = length > 2 ? sources[2] : undefined;\n\n customizer = (assigner.length > 3 && typeof customizer == 'function')\n ? (length--, customizer)\n : undefined;\n\n if (guard && isIterateeCall(sources[0], sources[1], guard)) {\n customizer = length < 3 ? undefined : customizer;\n length = 1;\n }\n object = Object(object);\n while (++index < length) {\n var source = sources[index];\n if (source) {\n assigner(object, source, index, customizer);\n }\n }\n return object;\n });\n}\n\nmodule.exports = createAssigner;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_createAssigner.js\n// module id = 44\n// module chunks = 0","var baseIsNative = require('./_baseIsNative'),\n getValue = require('./_getValue');\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n var value = getValue(object, key);\n return baseIsNative(value) ? value : undefined;\n}\n\nmodule.exports = getNative;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_getNative.js\n// module id = 45\n// module chunks = 0","var Symbol = require('./_Symbol');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/** Built-in value references. */\nvar symToStringTag = Symbol ? Symbol.toStringTag : undefined;\n\n/**\n * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.\n *\n * @private\n * @param {*} value The value to query.\n * @returns {string} Returns the raw `toStringTag`.\n */\nfunction getRawTag(value) {\n var isOwn = hasOwnProperty.call(value, symToStringTag),\n tag = value[symToStringTag];\n\n try {\n value[symToStringTag] = undefined;\n var unmasked = true;\n } catch (e) {}\n\n var result = nativeObjectToString.call(value);\n if (unmasked) {\n if (isOwn) {\n value[symToStringTag] = tag;\n } else {\n delete value[symToStringTag];\n }\n }\n return result;\n}\n\nmodule.exports = getRawTag;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_getRawTag.js\n// module id = 46\n// module chunks = 0","/**\n * Gets the value at `key` of `object`.\n *\n * @private\n * @param {Object} [object] The object to query.\n * @param {string} key The key of the property to get.\n * @returns {*} Returns the property value.\n */\nfunction getValue(object, key) {\n return object == null ? undefined : object[key];\n}\n\nmodule.exports = getValue;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_getValue.js\n// module id = 47\n// module chunks = 0","var eq = require('./eq'),\n isArrayLike = require('./isArrayLike'),\n isIndex = require('./_isIndex'),\n isObject = require('./isObject');\n\n/**\n * Checks if the given arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call,\n * else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n if (!isObject(object)) {\n return false;\n }\n var type = typeof index;\n if (type == 'number'\n ? (isArrayLike(object) && isIndex(index, object.length))\n : (type == 'string' && index in object)\n ) {\n return eq(object[index], value);\n }\n return false;\n}\n\nmodule.exports = isIterateeCall;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_isIterateeCall.js\n// module id = 48\n// module chunks = 0","var coreJsData = require('./_coreJsData');\n\n/** Used to detect methods masquerading as native. */\nvar maskSrcKey = (function() {\n var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');\n return uid ? ('Symbol(src)_1.' + uid) : '';\n}());\n\n/**\n * Checks if `func` has its source masked.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` is masked, else `false`.\n */\nfunction isMasked(func) {\n return !!maskSrcKey && (maskSrcKey in func);\n}\n\nmodule.exports = isMasked;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_isMasked.js\n// module id = 49\n// module chunks = 0","var overArg = require('./_overArg');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = overArg(Object.keys, Object);\n\nmodule.exports = nativeKeys;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_nativeKeys.js\n// module id = 50\n// module chunks = 0","var freeGlobal = require('./_freeGlobal');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Detect free variable `process` from Node.js. */\nvar freeProcess = moduleExports && freeGlobal.process;\n\n/** Used to access faster Node.js helpers. */\nvar nodeUtil = (function() {\n try {\n return freeProcess && freeProcess.binding && freeProcess.binding('util');\n } catch (e) {}\n}());\n\nmodule.exports = nodeUtil;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_nodeUtil.js\n// module id = 51\n// module chunks = 0","/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar nativeObjectToString = objectProto.toString;\n\n/**\n * Converts `value` to a string using `Object.prototype.toString`.\n *\n * @private\n * @param {*} value The value to convert.\n * @returns {string} Returns the converted string.\n */\nfunction objectToString(value) {\n return nativeObjectToString.call(value);\n}\n\nmodule.exports = objectToString;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_objectToString.js\n// module id = 52\n// module chunks = 0","/**\n * Creates a unary function that invokes `func` with its argument transformed.\n *\n * @private\n * @param {Function} func The function to wrap.\n * @param {Function} transform The argument transform.\n * @returns {Function} Returns the new function.\n */\nfunction overArg(func, transform) {\n return function(arg) {\n return func(transform(arg));\n };\n}\n\nmodule.exports = overArg;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_overArg.js\n// module id = 53\n// module chunks = 0","var apply = require('./_apply');\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * A specialized version of `baseRest` which transforms the rest array.\n *\n * @private\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @param {Function} transform The rest array transform.\n * @returns {Function} Returns the new function.\n */\nfunction overRest(func, start, transform) {\n start = nativeMax(start === undefined ? (func.length - 1) : start, 0);\n return function() {\n var args = arguments,\n index = -1,\n length = nativeMax(args.length - start, 0),\n array = Array(length);\n\n while (++index < length) {\n array[index] = args[start + index];\n }\n index = -1;\n var otherArgs = Array(start + 1);\n while (++index < start) {\n otherArgs[index] = args[index];\n }\n otherArgs[start] = transform(array);\n return apply(func, this, otherArgs);\n };\n}\n\nmodule.exports = overRest;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_overRest.js\n// module id = 54\n// module chunks = 0","var baseSetToString = require('./_baseSetToString'),\n shortOut = require('./_shortOut');\n\n/**\n * Sets the `toString` method of `func` to return `string`.\n *\n * @private\n * @param {Function} func The function to modify.\n * @param {Function} string The `toString` result.\n * @returns {Function} Returns `func`.\n */\nvar setToString = shortOut(baseSetToString);\n\nmodule.exports = setToString;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_setToString.js\n// module id = 55\n// module chunks = 0","/** Used to detect hot functions by number of calls within a span of milliseconds. */\nvar HOT_COUNT = 800,\n HOT_SPAN = 16;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeNow = Date.now;\n\n/**\n * Creates a function that'll short out and invoke `identity` instead\n * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`\n * milliseconds.\n *\n * @private\n * @param {Function} func The function to restrict.\n * @returns {Function} Returns the new shortable function.\n */\nfunction shortOut(func) {\n var count = 0,\n lastCalled = 0;\n\n return function() {\n var stamp = nativeNow(),\n remaining = HOT_SPAN - (stamp - lastCalled);\n\n lastCalled = stamp;\n if (remaining > 0) {\n if (++count >= HOT_COUNT) {\n return arguments[0];\n }\n } else {\n count = 0;\n }\n return func.apply(undefined, arguments);\n };\n}\n\nmodule.exports = shortOut;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_shortOut.js\n// module id = 56\n// module chunks = 0","/** Used for built-in method references. */\nvar funcProto = Function.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar funcToString = funcProto.toString;\n\n/**\n * Converts `func` to its source code.\n *\n * @private\n * @param {Function} func The function to convert.\n * @returns {string} Returns the source code.\n */\nfunction toSource(func) {\n if (func != null) {\n try {\n return funcToString.call(func);\n } catch (e) {}\n try {\n return (func + '');\n } catch (e) {}\n }\n return '';\n}\n\nmodule.exports = toSource;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/_toSource.js\n// module id = 57\n// module chunks = 0","var assignValue = require('./_assignValue'),\n copyObject = require('./_copyObject'),\n createAssigner = require('./_createAssigner'),\n isArrayLike = require('./isArrayLike'),\n isPrototype = require('./_isPrototype'),\n keys = require('./keys');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Assigns own enumerable string keyed properties of source objects to the\n * destination object. Source objects are applied from left to right.\n * Subsequent sources overwrite property assignments of previous sources.\n *\n * **Note:** This method mutates `object` and is loosely based on\n * [`Object.assign`](https://mdn.io/Object/assign).\n *\n * @static\n * @memberOf _\n * @since 0.10.0\n * @category Object\n * @param {Object} object The destination object.\n * @param {...Object} [sources] The source objects.\n * @returns {Object} Returns `object`.\n * @see _.assignIn\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * }\n *\n * function Bar() {\n * this.c = 3;\n * }\n *\n * Foo.prototype.b = 2;\n * Bar.prototype.d = 4;\n *\n * _.assign({ 'a': 0 }, new Foo, new Bar);\n * // => { 'a': 1, 'c': 3 }\n */\nvar assign = createAssigner(function(object, source) {\n if (isPrototype(source) || isArrayLike(source)) {\n copyObject(source, keys(source), object);\n return;\n }\n for (var key in source) {\n if (hasOwnProperty.call(source, key)) {\n assignValue(object, key, source[key]);\n }\n }\n});\n\nmodule.exports = assign;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/assign.js\n// module id = 58\n// module chunks = 0","/**\n * Creates a function that returns `value`.\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Util\n * @param {*} value The value to return from the new function.\n * @returns {Function} Returns the new constant function.\n * @example\n *\n * var objects = _.times(2, _.constant({ 'a': 1 }));\n *\n * console.log(objects);\n * // => [{ 'a': 1 }, { 'a': 1 }]\n *\n * console.log(objects[0] === objects[1]);\n * // => true\n */\nfunction constant(value) {\n return function() {\n return value;\n };\n}\n\nmodule.exports = constant;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/constant.js\n// module id = 59\n// module chunks = 0","var baseIsArguments = require('./_baseIsArguments'),\n isObjectLike = require('./isObjectLike');\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Built-in value references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is likely an `arguments` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an `arguments` object,\n * else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nvar isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {\n return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&\n !propertyIsEnumerable.call(value, 'callee');\n};\n\nmodule.exports = isArguments;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isArguments.js\n// module id = 60\n// module chunks = 0","/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an array, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(document.body.children);\n * // => false\n *\n * _.isArray('abc');\n * // => false\n *\n * _.isArray(_.noop);\n * // => false\n */\nvar isArray = Array.isArray;\n\nmodule.exports = isArray;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isArray.js\n// module id = 61\n// module chunks = 0","var root = require('./_root'),\n stubFalse = require('./stubFalse');\n\n/** Detect free variable `exports`. */\nvar freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;\n\n/** Detect free variable `module`. */\nvar freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;\n\n/** Detect the popular CommonJS extension `module.exports`. */\nvar moduleExports = freeModule && freeModule.exports === freeExports;\n\n/** Built-in value references. */\nvar Buffer = moduleExports ? root.Buffer : undefined;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;\n\n/**\n * Checks if `value` is a buffer.\n *\n * @static\n * @memberOf _\n * @since 4.3.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.\n * @example\n *\n * _.isBuffer(new Buffer(2));\n * // => true\n *\n * _.isBuffer(new Uint8Array(2));\n * // => false\n */\nvar isBuffer = nativeIsBuffer || stubFalse;\n\nmodule.exports = isBuffer;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isBuffer.js\n// module id = 62\n// module chunks = 0","var baseIsTypedArray = require('./_baseIsTypedArray'),\n baseUnary = require('./_baseUnary'),\n nodeUtil = require('./_nodeUtil');\n\n/* Node.js helper references. */\nvar nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @since 3.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nvar isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;\n\nmodule.exports = isTypedArray;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/isTypedArray.js\n// module id = 63\n// module chunks = 0","var arrayLikeKeys = require('./_arrayLikeKeys'),\n baseKeys = require('./_baseKeys'),\n isArrayLike = require('./isArrayLike');\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @since 0.1.0\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n * this.a = 1;\n * this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nfunction keys(object) {\n return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);\n}\n\nmodule.exports = keys;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/keys.js\n// module id = 64\n// module chunks = 0","/**\n * This method returns `false`.\n *\n * @static\n * @memberOf _\n * @since 4.13.0\n * @category Util\n * @returns {boolean} Returns `false`.\n * @example\n *\n * _.times(2, _.stubFalse);\n * // => [false, false]\n */\nfunction stubFalse() {\n return false;\n}\n\nmodule.exports = stubFalse;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/lodash/stubFalse.js\n// module id = 65\n// module chunks = 0","var g;\r\n\r\n// This works in non-strict mode\r\ng = (function() {\r\n\treturn this;\r\n})();\r\n\r\ntry {\r\n\t// This works if eval is allowed (see CSP)\r\n\tg = g || Function(\"return this\")() || (1,eval)(\"this\");\r\n} catch(e) {\r\n\t// This works if the window reference is available\r\n\tif(typeof window === \"object\")\r\n\t\tg = window;\r\n}\r\n\r\n// g can still be undefined, but nothing to do about it...\r\n// We return undefined, instead of nothing here, so it's\r\n// easier to handle this case. if(!global) { ...}\r\n\r\nmodule.exports = g;\r\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// (webpack)/buildin/global.js\n// module id = 66\n// module chunks = 0"],"sourceRoot":""}
admin/class-admin-ajax.php ADDED
@@ -0,0 +1,664 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class WP_Hummingbird_Admin_AJAX
5
+ *
6
+ * Handle all AJAX actions in admin side
7
+ */
8
+ class WP_Hummingbird_Admin_AJAX {
9
+
10
+ /**
11
+ * WP_Hummingbird_Admin_AJAX constructor.
12
+ */
13
+ public function __construct() {
14
+
15
+ /* Not used anywhere?
16
+ add_action( 'wp_ajax_wphb_ajax', array( $this, 'process' ) );
17
+
18
+ add_action( 'wp_ajax_minification_check_url', array( $this, 'minification_check_url' ) );
19
+ add_action( 'wp_ajax_minification_finish_check', array( $this, 'minification_finish_check' ) );
20
+
21
+ add_action( 'wp_ajax_caching_toggle_caching', array( $this, 'toggle_caching' ) );
22
+ add_action( 'wp_ajax_caching_clear_cache', array( $this, 'clear_caching_cache' ) );
23
+ add_action( 'wp_ajax_caching_write_htaccess', array( $this, 'write_caching_htaccess' ) );
24
+ add_action( 'wp_ajax_gzip_write_htaccess', array( $this, 'write_gzip_htaccess' ) );
25
+ */
26
+
27
+ // Run performance test.
28
+ add_action( 'wp_ajax_wphb_performance_run_test', array( $this, 'performance_run_test' ) );
29
+ // Set expiration for browser caching.
30
+ add_action( 'wp_ajax_wphb_caching_set_expiration', array( $this, 'caching_set_expiration' ) );
31
+ // Set server type.
32
+ add_action( 'wp_ajax_wphb_caching_set_server_type', array( $this, 'caching_set_server_type' ) );
33
+ // Reload snippet.
34
+ add_action( 'wp_ajax_wphb_caching_reload_snippet', array( $this, 'caching_reload_snippet' ) );
35
+ // CloudFlare connect.
36
+ add_action( 'wp_ajax_wphb_cloudflare_connect', array( $this, 'cloudflare_connect' ) );
37
+ // CloudFlare expirtion cache.
38
+ add_action( 'wp_ajax_wphb_cloudflare_set_expiry', array( $this, 'cloudflare_set_expiry' ) );
39
+ // CloudFlare purge cache.
40
+ add_action( 'wp_ajax_wphb_cloudflare_purge_cache', array( $this, 'cloudflare_purge_cache' ) );
41
+ // Activate network minification.
42
+ add_action( 'wp_ajax_wphb_dash_toggle_network_minification', array( $this, 'dash_toggle_network_minification' ) );
43
+ // Skip quick setup.
44
+ add_action( 'wp_ajax_wphb_dash_skip_setup', array( $this, 'dashboard_skip_setup' ) );
45
+ // Toggle CDN.
46
+ add_action( 'wp_ajax_wphb_minification_toggle_cdn', array( $this, 'minification_toggle_cdn' ) );
47
+ // Toggle minification.
48
+ add_action( 'wp_ajax_wphb_minification_toggle_minification', array( $this, 'minification_toggle_minification' ) );
49
+ // Start scan.
50
+ add_action( 'wp_ajax_wphb_minification_start_check', array( $this, 'minification_start_check' ) );
51
+ // Scan check step.
52
+ add_action( 'wp_ajax_wphb_minification_check_step', array( $this, 'minification_check_step' ) );
53
+ // Cancel scan.
54
+ add_action( 'wp_ajax_wphb_minification_cancel_scan', array( $this, 'minification_cancel_scan' ) );
55
+
56
+ }
57
+
58
+ /*
59
+ public function process() {
60
+ if ( ! isset( $_REQUEST['module_action'] ) || ! isset( $_REQUEST['module'] ) ) {
61
+ wp_send_json_error();
62
+ }
63
+
64
+ if ( ! isset( $_REQUEST['wphb_nonce'] ) || ! isset( $_REQUEST['nonce_name'] ) ) {
65
+ wp_send_json_error();
66
+ }
67
+
68
+ check_ajax_referer( $_REQUEST['nonce_name'], 'wphb_nonce' );
69
+
70
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
71
+ wp_send_json_error();
72
+ }
73
+
74
+ $method = $_REQUEST['module'] . '_' . $_REQUEST['module_action'];
75
+
76
+ if ( ! method_exists( $this, $method ) ) {
77
+ wp_send_json_error();
78
+ }
79
+
80
+ if ( ! isset( $_REQUEST['data'] ) ) {
81
+ $data = array();
82
+ } else {
83
+ $data = $_REQUEST['data'];
84
+ }
85
+
86
+ call_user_func( array( $this, $method ), $data );
87
+ }
88
+ */
89
+
90
+ /**
91
+ * Run performance test.
92
+ */
93
+ public function performance_run_test() {
94
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
95
+
96
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
97
+ return;
98
+ }
99
+
100
+ // Remove quick setup.
101
+ wphb_remove_quick_setup();
102
+
103
+ if ( wphb_performance_stopped_report() ) {
104
+ wp_send_json_success( array(
105
+ 'finished' => true,
106
+ ));
107
+ }
108
+
109
+ $started_at = wphb_performance_is_doing_report();
110
+
111
+ if ( ! $started_at ) {
112
+ wphb_performance_init_scan();
113
+ wp_send_json_success( array(
114
+ 'finished' => false,
115
+ ));
116
+ }
117
+
118
+ $now = current_time( 'timestamp' );
119
+ if ( $now >= ( $started_at + 10 ) ) {
120
+ // The report should be finished by this time, let's get the results.
121
+ wphb_performance_refresh_report();
122
+ wp_send_json_success( array(
123
+ 'finished' => true,
124
+ ));
125
+ }
126
+
127
+ // Just do nothing until the report is finished.
128
+ wp_send_json_success( array(
129
+ 'finished' => false,
130
+ ));
131
+ }
132
+
133
+ public function uptime_toggle_uptime( $data ) {
134
+ if ( ! isset( $data['value'] ) ) {
135
+ die();
136
+ }
137
+
138
+ $value = $data['value'] == 'false' ? false : true;
139
+
140
+ $options = wphb_get_settings();
141
+ $options['uptime'] = $value;
142
+ wphb_update_settings( $options );
143
+ die();
144
+ }
145
+
146
+ /**
147
+ * Set expiration for browser caching.
148
+ */
149
+ public function caching_set_expiration() {
150
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
151
+
152
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
153
+ return;
154
+ }
155
+
156
+ if ( ! isset( $_POST['type'] ) || ! isset( $_POST['value'] ) ) { // Input var okay.
157
+ die();
158
+ }
159
+
160
+ $type = sanitize_text_field( wp_unslash( $_POST['type'] ) ); // Input var okay.
161
+ $value = sanitize_text_field( wp_unslash( $_POST['value'] ) ); // Input var okay.
162
+
163
+ $frequencies = wphb_get_caching_frequencies();
164
+
165
+ if ( ! isset( $frequencies[ $value ] ) ) {
166
+ die();
167
+ }
168
+
169
+ $options = wphb_get_settings();
170
+ $options[ 'caching_expiry_' . $type ] = $value;
171
+ wphb_update_settings( $options );
172
+
173
+ /**
174
+ * Pass in caching type and value into a custom function.
175
+ *
176
+ * @since 1.0.0
177
+ *
178
+ * @param array $args {
179
+ * Array of selected type and value.
180
+ *
181
+ * @type string $type Type of cached data, can be one of following:
182
+ * `javascript`, `css`, `media` or `images`.
183
+ * @type string $value Set expiry value (for example, 1h/A3600), first part can be:
184
+ * `[n]h` for [n] hours (for example, 1h, 4h, 11h, etc),
185
+ * `[n]d` for [n] days (for example, 1d, 4d, 11d, etc),
186
+ * `[n]M` for [n] months (for example, 1M, 4M, 11M, etc),
187
+ * `[n]y` for [n] years (for example, 1y, 4y, 11y, etc),
188
+ * second part is the first part in seconds ( 1 hour = 3600 sec).
189
+ * }
190
+ */
191
+ do_action( 'wphb_caching_set_expiration', array(
192
+ 'type' => $type,
193
+ 'value' => $value,
194
+ ));
195
+
196
+ wp_send_json_success();
197
+ }
198
+
199
+ /**
200
+ * Set server type.
201
+ */
202
+ public function caching_set_server_type() {
203
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
204
+
205
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
206
+ return;
207
+ }
208
+
209
+ if ( ! isset( $_POST['value'] ) ) { // Input var okay.
210
+ die();
211
+ }
212
+
213
+ $value = sanitize_text_field( wp_unslash( $_POST['value'] ) ); // Input var okay.
214
+
215
+ if ( ! array_key_exists( $value, wphb_get_servers() ) ) {
216
+ wp_send_json_error();
217
+ }
218
+
219
+ update_user_meta( get_current_user_id(), 'wphb-server-type', $value );
220
+
221
+ wp_send_json_success();
222
+ }
223
+
224
+ /**
225
+ * Reload snippet after new expiration interval has been selected.
226
+ */
227
+ public function caching_reload_snippet() {
228
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
229
+
230
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
231
+ return;
232
+ }
233
+
234
+ if ( ! isset( $_POST['type'] ) ) { // Input var okay.
235
+ die();
236
+ }
237
+
238
+ $type = sanitize_text_field( wp_unslash( $_POST['type'] ) ); // Input var okay.
239
+
240
+ $code = wphb_get_code_snippet( 'caching', $type );
241
+
242
+ $updated_file = false;
243
+ if ( true === wphb_is_htaccess_written( 'caching' ) && 'apache' === $type ) {
244
+ $updated_file = wphb_unsave_htaccess( 'caching' );
245
+ $updated_file = wphb_save_htaccess( 'caching' );
246
+ }
247
+
248
+ wp_send_json_success( array(
249
+ 'type' => $type,
250
+ 'code' => $code,
251
+ 'updatedFile' => $updated_file,
252
+ ));
253
+ }
254
+
255
+ /**
256
+ * Toggle settings for network minification in multisite installs.
257
+ */
258
+ public function dash_toggle_network_minification() {
259
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
260
+
261
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
262
+ return;
263
+ }
264
+
265
+ if ( ! isset( $_POST['value'] ) ) { // Input var okay.
266
+ die();
267
+ }
268
+
269
+ $post_value = sanitize_text_field( wp_unslash( $_POST['value'] ) ); // Input var okay.
270
+
271
+ switch ( $post_value ) {
272
+ case 'false': {
273
+ $value = false;
274
+ break;
275
+ }
276
+ case 'super-admins': {
277
+ $value = 'super-admins';
278
+ break;
279
+ }
280
+ default: {
281
+ $value = true;
282
+ break;
283
+ }
284
+ }
285
+
286
+ wphb_toggle_minification( $value, true );
287
+ wp_send_json_success();
288
+ }
289
+
290
+ /**
291
+ * Skip quick setup and go straight to dashboard.
292
+ *
293
+ * @since 1.5.0
294
+ */
295
+ public function dashboard_skip_setup() {
296
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
297
+
298
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
299
+ return;
300
+ }
301
+
302
+ wphb_remove_quick_setup();
303
+
304
+ wp_send_json_success();
305
+ }
306
+
307
+ /**
308
+ * Toggle CDN.
309
+ *
310
+ * Used on dashboard page in minification meta box and in the minification module.
311
+ * Clear files function at the end clears all cache and on first home page reload, all the files will
312
+ * be either moved to CDN or stored local.
313
+ */
314
+ public function minification_toggle_cdn() {
315
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
316
+
317
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
318
+ return;
319
+ }
320
+
321
+ if ( ! isset( $_POST['value'] ) ) { // Input var okay.
322
+ die();
323
+ }
324
+
325
+ $value = rest_sanitize_boolean( wp_unslash( $_POST['value'] ) ); // Input var okay.
326
+
327
+ wphb_toggle_cdn( $value );
328
+
329
+ // Clear the files.
330
+ wphb_minification_clear_files();
331
+ wp_send_json_success();
332
+ }
333
+
334
+ /**
335
+ * Toggle minification on per site basis.
336
+ */
337
+ public function minification_toggle_minification() {
338
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
339
+
340
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
341
+ return;
342
+ }
343
+
344
+ if ( ! isset( $_POST['value'] ) ) { // Input var okay.
345
+ die();
346
+ }
347
+
348
+ $value = rest_sanitize_boolean( wp_unslash( $_POST['value'] ) ); // Input var okay.
349
+
350
+ wphb_toggle_minification( $value );
351
+
352
+ wp_send_json_success();
353
+ }
354
+
355
+ /**
356
+ * Start minification scan.
357
+ *
358
+ * Set a flag that marks the minification check files as started.
359
+ */
360
+ public function minification_start_check() {
361
+ if ( ! wphb_minification_is_checking_files() ) {
362
+ wphb_minification_init_scan();
363
+ }
364
+
365
+ // Get number of pages for calculating the progress.
366
+ $check_files = get_option( 'wphb-minification-check-files' );
367
+
368
+ wp_send_json_success( array(
369
+ 'finished' => false,
370
+ 'steps' => count( $check_files['urls_list'] ),
371
+ ));
372
+ }
373
+
374
+ /**
375
+ * Process step during minification scan.
376
+ */
377
+ public function minification_check_step() {
378
+ $check_files = get_option( 'wphb-minification-check-files' );
379
+
380
+ if ( false === $check_files ) {
381
+ // We have finished. Show CDN modal only for members.
382
+ $cdn_modal = true;
383
+ if ( ! wphb_is_member() ) {
384
+ $cdn_modal = false;
385
+ // Remove CDN if set.
386
+ wphb_update_setting( 'use_cdn', false );
387
+ }
388
+
389
+ wp_send_json_success( array(
390
+ 'finished' => true,
391
+ 'show_cdn' => $cdn_modal,
392
+ ));
393
+ }
394
+
395
+ if ( empty( $check_files['urls_list'] ) ) {
396
+ // We have finished with URLs, just scan home again to gain some time.
397
+ WP_Hummingbird_Module_Minify::scan( home_url() );
398
+ delete_option( 'wphb-minification-check-files' );
399
+ delete_option( 'wphb-minification-check-files-progress' );
400
+ } else {
401
+ $next_url = array_shift( $check_files['urls_list'] );
402
+ $check_files['urls_done'][] = $next_url;
403
+ update_option( 'wphb-minification-check-files', $check_files );
404
+ $progress = absint( $_POST['progress'] ) + absint( $_POST['step'] ); // Input var ok.
405
+ update_option( 'wphb-minification-check-files-progress', $progress );
406
+ WP_Hummingbird_Module_Minify::scan( $next_url );
407
+ }
408
+
409
+ $current_time = current_time( 'timestamp' );
410
+ // If more than 4 minutes has passed, kill the process.
411
+ if ( empty( $check_files['on'] ) || $current_time > ( $check_files['on'] + 240 ) ) {
412
+ delete_option( 'wphb-minification-check-files' );
413
+ delete_option( 'wphb-minification-check-files-progress' );
414
+ }
415
+
416
+ wp_send_json_success( array(
417
+ 'finished' => false,
418
+ ));
419
+ }
420
+
421
+ /**
422
+ * Cancel minification file check if cancel button pressed.
423
+ *
424
+ * @since 1.4.5
425
+ */
426
+ public function minification_cancel_scan() {
427
+ wphb_toggle_minification( false );
428
+ wphb_delete_pending_process_queue();
429
+ wphb_clear_minification_cache( false );
430
+ delete_option( 'wphb-minification-check-files' );
431
+ delete_option( 'wphb-minification-check-files-progress' );
432
+ wp_send_json_success();
433
+ }
434
+
435
+ /**
436
+ * Get all the URLs that the Minification Check Files button should process
437
+ */
438
+ /*
439
+ public function minification_check_url() {
440
+ check_ajax_referer( 'wphb-minification-check-files', 'wphb_nonce' );
441
+
442
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
443
+ wp_send_json_error();
444
+ }
445
+
446
+ $data = $_REQUEST['data'];
447
+ $url = $data['url'];
448
+ $results = WP_Hummingbird_Module_Minify::scan( $url );
449
+
450
+
451
+ wp_send_json_success( $results );
452
+ }
453
+
454
+ public function toggle_caching() {
455
+ check_ajax_referer( 'wphb-caching-toggle', 'wphb_nonce' );
456
+
457
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
458
+ die();
459
+
460
+ $options = wphb_get_settings();
461
+
462
+ $options['caching'] = $_REQUEST['data']['activate'] === 'true';
463
+ wphb_update_settings( $options );
464
+
465
+ die();
466
+ }
467
+
468
+ public function clear_caching_cache() {
469
+ check_ajax_referer( 'wphb-caching-clear', 'wphb_nonce' );
470
+
471
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
472
+ die();
473
+
474
+ wphb_clear_caching_cache();
475
+
476
+ die();
477
+
478
+
479
+ }
480
+
481
+ function write_gzip_htaccess() {
482
+ check_ajax_referer( 'wphb-write-htacces', 'wphb_nonce' );
483
+
484
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
485
+ die();
486
+
487
+ wphb_save_htaccess( 'gzip' );
488
+ }
489
+
490
+ function write_caching_htaccess() {
491
+ check_ajax_referer( 'wphb-write-htacces', 'wphb_nonce' );
492
+
493
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
494
+ die();
495
+
496
+ wphb_save_htaccess( 'caching' );
497
+ }
498
+ */
499
+
500
+ /**
501
+ * Connect to CloudFlare.
502
+ */
503
+ public function cloudflare_connect() {
504
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
505
+
506
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
507
+ return;
508
+ }
509
+
510
+ if ( ! isset( $_POST['formData'] ) || ! isset( $_POST['step'] ) ) { // Input var okay.
511
+ die();
512
+ }
513
+
514
+ $form_data = $_POST['formData']; // Input var okay.
515
+ $form_data = wp_parse_args( $form_data, array(
516
+ 'cloudflare-email' => '',
517
+ 'cloudflare-api-key' => '',
518
+ 'cloudflare-zone' => '',
519
+ ));
520
+
521
+ $step = sanitize_text_field( wp_unslash( $_POST['step'] ) ); // Input var okay.
522
+ $cfData = wp_unslash( $_POST['cfData'] ); // Input var okay.
523
+
524
+ /** @var WP_Hummingbird_Module_Cloudflare $cloudflare */
525
+ $cloudflare = wphb_get_module( 'cloudflare' );
526
+
527
+ $settings = wphb_get_settings();
528
+
529
+ switch ( $step ) {
530
+ case 'credentials': {
531
+ $settings['cloudflare-email'] = sanitize_email( $form_data['cloudflare-email'] );
532
+ $settings['cloudflare-api-key'] = sanitize_text_field( $form_data['cloudflare-api-key'] );
533
+ $settings['cloudflare-zone'] = sanitize_text_field( $form_data['cloudflare-zone'] );
534
+ $settings['cloudflare-zone-name'] = isset( $form_data['cloudflare-zone-name'] ) ? sanitize_text_field( $form_data['cloudflare-zone-name'] ) : '';
535
+ wphb_update_settings( $settings );
536
+
537
+ $zones = $cloudflare->get_zones_list();
538
+
539
+ if ( is_wp_error( $zones ) ) {
540
+ wp_send_json_error( array(
541
+ 'message' => sprintf( '<strong>%s</strong> [%s]', $zones->get_error_message(), $zones->get_error_code() ),
542
+ ));
543
+ }
544
+
545
+ $cfData['email'] = $settings['cloudflare-email'];
546
+ $cfData['apiKey'] = $settings['cloudflare-api-key'];
547
+ $cfData['zones'] = $zones;
548
+
549
+ $settings['cloudflare-connected'] = true;
550
+ wphb_update_settings( $settings );
551
+
552
+ // Try to auto select domain.
553
+ $site_url = network_site_url();
554
+ $site_url = rtrim( preg_replace( '/^https?:\/\//', '', $site_url ), '/' );
555
+ $plucked_zones = wp_list_pluck( $zones, 'label' );
556
+ $found = preg_grep( '/.*' . $site_url . '.*/', $plucked_zones );
557
+ if ( is_array( $found ) && count( $found ) === 1 && isset( $zones[ key( $found ) ]['value'] ) ) {
558
+ // Select the domain and cheat this function.
559
+ $zone_found = $zones[ key( $found ) ]['value'];
560
+ $_POST['formData'] = array(
561
+ 'cloudflare-zone' => $zone_found,
562
+ );
563
+ $_POST['step'] = 'zone';
564
+ $_POST['cfData'] = $cfData;
565
+ $this->cloudflare_connect();
566
+ }
567
+
568
+ wp_send_json_success( array(
569
+ 'nextStep' => 'zone',
570
+ 'newData' => $cfData,
571
+ ));
572
+ break;
573
+ } // End case().
574
+ case 'zone': {
575
+ $settings['cloudflare-zone'] = sanitize_text_field( $form_data['cloudflare-zone'] );
576
+
577
+ if ( empty( $settings['cloudflare-zone'] ) ) {
578
+ wp_send_json_error( array(
579
+ 'message' => __( 'Please, select a CloudFlare zone. Normally, this is your website', 'wphb' ),
580
+ ));
581
+ }
582
+
583
+ // Check that the zone exists.
584
+ $zones = $cloudflare->get_zones_list();
585
+ if ( is_wp_error( $zones ) ) {
586
+ wp_send_json_error( array(
587
+ 'message' => sprintf( '<strong>%s</strong> [%s]', $zones->get_error_message(), $zones->get_error_code() ),
588
+ ));
589
+ } else {
590
+ $filtered = wp_list_filter( $zones, array(
591
+ 'value' => $settings['cloudflare-zone'],
592
+ ));
593
+ if ( ! $filtered ) {
594
+ wp_send_json_error( array(
595
+ 'message' => __( 'The selected zone is not valid', 'wphb' ),
596
+ ));
597
+ }
598
+ $settings['cloudflare-zone-name'] = $filtered[0]['label'];
599
+ $settings['cloudflare-plan'] = $filtered[0]['plan'];
600
+ }
601
+
602
+ $settings['cloudflare-connected'] = true;
603
+
604
+ wphb_update_settings( $settings );
605
+ $cfData['zone'] = $settings['cloudflare-zone'];
606
+ $cfData['zoneName'] = $settings['cloudflare-zone-name'];
607
+ $cfData['plan'] = $settings['cloudflare-plan'];
608
+
609
+ update_site_option( 'wphb-is-cloudflare', 1 );
610
+
611
+ // And set the new CF setting.
612
+ $cloudflare->set_caching_expiration( 691200 );
613
+
614
+ $redirect = wphb_get_admin_menu_url( 'caching' );
615
+ wp_send_json_success( array(
616
+ 'nextStep' => 'final',
617
+ 'newData' => $cfData,
618
+ 'redirect' => $redirect,
619
+ ));
620
+ break;
621
+ } // End case().
622
+ } // End switch().
623
+
624
+ wp_send_json_error();
625
+ }
626
+
627
+ /**
628
+ * Set expiration for CloudFlare cache.
629
+ */
630
+ public function cloudflare_set_expiry() {
631
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
632
+
633
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
634
+ return;
635
+ }
636
+
637
+ $value = absint( $_POST['value'] );
638
+
639
+ /** @var WP_Hummingbird_Module_Cloudflare $cf */
640
+ $cf = wphb_get_module( 'cloudflare' );
641
+
642
+ $cf->set_caching_expiration( $value );
643
+
644
+ wp_send_json_success();
645
+ }
646
+
647
+ /**
648
+ * Purge CloudFlare cache.
649
+ */
650
+ public function cloudflare_purge_cache() {
651
+ check_ajax_referer( 'wphb-fetch', 'nonce' );
652
+
653
+ if ( ! current_user_can( wphb_get_admin_capability() ) ) {
654
+ return;
655
+ }
656
+
657
+ /** @var WP_Hummingbird_Module_Cloudflare $cf */
658
+ $cf = wphb_get_module( 'cloudflare' );
659
+ $cf->purge_cache();
660
+
661
+ wp_send_json_success();
662
+ }
663
+
664
+ }
admin/class-admin-notices.php ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined( 'ABSPATH' ) ) {
4
+ exit;
5
+ }
6
+
7
+ class WP_Hummingbird_Admin_Notices {
8
+
9
+ /**
10
+ * Initialize admin notices
11
+ *
12
+ * @TODO: If we're going to add more notices we might want to use a better abstraction for this
13
+ */
14
+ public function init() {
15
+ $dismiss = isset( $_GET['wphb-dismiss'] ) ? sanitize_text_field( $_GET['wphb-dismiss'] ) : false;
16
+ if ( $dismiss ) {
17
+ $this->dismiss( $dismiss );
18
+ }
19
+
20
+ if ( is_multisite() ) {
21
+ add_action( 'network_admin_notices', array( $this, 'upgrade_to_pro' ) );
22
+ add_action( 'network_admin_notices', array( $this, 'free_version_deactivated' ) );
23
+ }
24
+ else {
25
+ add_action( 'admin_notices', array( $this, 'upgrade_to_pro' ) );
26
+ add_action( 'admin_notices', array( $this, 'free_version_deactivated' ) );
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Show Upgrade to Pro notice
32
+ *
33
+ * User is authenticated into WPMU DEV but it has free version installed
34
+ */
35
+ public function upgrade_to_pro() {
36
+ if ( $this->is_dismissed( 'upgrade-to-pro' ) ) {
37
+ return;
38
+ }
39
+
40
+ if ( ! class_exists( 'WPMUDEV_Dashboard' ) ) {
41
+ return;
42
+ }
43
+
44
+ $dashboard = WPMUDEV_Dashboard::instance();
45
+ if ( ! is_object( $dashboard ) ) {
46
+ return;
47
+ }
48
+
49
+ $url = $dashboard::$ui->page_urls->plugins_url;
50
+ $cap = is_multisite() ? 'manage_network_plugins' : 'update_plugins';
51
+ if ( ! current_user_can( $cap ) ) {
52
+ return;
53
+ }
54
+
55
+ $dismiss_url = wp_nonce_url( add_query_arg( 'wphb-dismiss', 'upgrade-to-pro' ), 'wphb-dismiss-notice' );
56
+
57
+ if ( ! get_site_option( 'wphb-pro' ) && wphb_is_member() ) {
58
+ ?>
59
+ <div class="notice-info notice wphb-notice">
60
+ <p>
61
+ <?php printf( __( 'Awww yeah! You’ve got access to Hummingbird Pro! Let’s upgrade your free version so you can start using premium features. <a href="%s">Upgrade</a>', 'wphb' ), esc_url( $url ) ); ?>
62
+ <a class="wphb-dismiss" href="<?php echo esc_url ( $dismiss_url ); ?>"><span class="dashicons dashicons-dismiss"></span></a>
63
+ </p>
64
+ </div>
65
+ <style>
66
+ .wphb-notice .wphb-dismiss {
67
+ text-decoration: none;
68
+ float:right;
69
+ }
70
+ </style>
71
+ <?php
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Notice displayed when the free version is deactivated because the pro one was already active
77
+ */
78
+ public function free_version_deactivated() {
79
+ if ( ! get_plugins( '/wp-hummingbird-wporg' ) ) {
80
+ return;
81
+ }
82
+
83
+ if ( $this->is_dismissed( 'free-deactivated', 'option' ) ) {
84
+ return;
85
+ }
86
+
87
+ $cap = is_multisite() ? 'manage_network_plugins' : 'update_plugins';
88
+ if ( ! current_user_can( $cap ) ) {
89
+ return;
90
+ }
91
+
92
+ $dismiss_url = wp_nonce_url( add_query_arg( 'wphb-dismiss', 'free-deactivated' ), 'wphb-dismiss-notice' );
93
+
94
+ ?>
95
+ <div class="notice-info notice wphb-notice">
96
+ <p>
97
+ <?php _e( 'We noticed you’re running both the free and pro versions of Hummingbird. No biggie! We’ve deactivated the free version for you. Enjoy the pro features!', 'wphb' ); ?>
98
+ <a class="wphb-dismiss" href="<?php echo esc_url ( $dismiss_url ); ?>"><span class="dashicons dashicons-dismiss"></span></a>
99
+ </p>
100
+ </div>
101
+ <style>
102
+ .wphb-notice .wphb-dismiss {
103
+ text-decoration: none;
104
+ float:right;
105
+ }
106
+ </style>
107
+ <?php
108
+ }
109
+
110
+
111
+ /**
112
+ * Check if a notice has been dismissed by the current user
113
+ *
114
+ * @param string $notice
115
+ *
116
+ * @return mixed
117
+ */
118
+ public function is_dismissed( $notice, $mode = 'user' ) {
119
+ if ( 'user' === $mode ) {
120
+ return get_user_meta( get_current_user_id(), 'wphb-' . $notice . '-dismissed' );
121
+ } else {
122
+ return 'yes' !== get_site_option( 'wphb-notice-' . $notice . '-show' );
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Dismiss a notice
128
+ *
129
+ * @param string $notice
130
+ */
131
+ public function dismiss( $notice) {
132
+ check_admin_referer( 'wphb-dismiss-notice' );
133
+
134
+ $user_notices = array(
135
+ 'upgrade-to-pro'
136
+ );
137
+
138
+ $options_notices = array(
139
+ 'free-deactivated'
140
+ );
141
+
142
+ if ( in_array( $notice, $user_notices ) ) {
143
+ update_user_meta( get_current_user_id(), 'wphb-' . $notice . '-dismissed', true );
144
+ } elseif ( in_array( $notice, $options_notices ) ) {
145
+ delete_site_option( 'wphb-notice-' . $notice . '-show' );
146
+ }
147
+
148
+ $redirect = remove_query_arg( array( 'wphb-dismiss', '_wpnonce' ) );
149
+ wp_redirect( $redirect );
150
+ exit;
151
+ }
152
+
153
+ }
admin/class-admin.php ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class WP_Hummingbird_Admin
5
+ *
6
+ * Manage the admin core functionality
7
+ */
8
+ class WP_Hummingbird_Admin {
9
+
10
+ public $pages = array();
11
+
12
+ /**
13
+ * @var WP_Hummingbird_Admin_Notices
14
+ */
15
+ public $admin_notices;
16
+
17
+ public function __construct() {
18
+ $this->includes();
19
+
20
+ $this->admin_notices = new WP_Hummingbird_Admin_Notices();
21
+ $this->admin_notices->init();
22
+
23
+ add_action( 'admin_menu', array( $this, 'add_menu_pages' ) );
24
+ add_action( 'network_admin_menu', array( $this, 'add_network_menu_pages' ) );
25
+
26
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
27
+ new WP_Hummingbird_Admin_AJAX();
28
+
29
+ add_action( 'admin_footer', array( $this, 'maybe_check_files' ) );
30
+ add_action( 'admin_footer', array( $this, 'maybe_check_report' ) );
31
+ add_action( 'admin_footer', array( $this, 'maybe_show_quick_setup') );
32
+
33
+ add_filter( 'network_admin_plugin_action_links_wp-hummingbird/wp-hummingbird.php', array( $this, 'add_plugin_action_links' ) );
34
+ add_filter( 'plugin_action_links_wp-hummingbird/wp-hummingbird.php', array( $this, 'add_plugin_action_links' ) );
35
+
36
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_icon_styles' ) );
37
+
38
+ /**
39
+ * Triggered when Hummingbird Admin is loaded
40
+ */
41
+ do_action( 'wphb_admin_loaded' );
42
+ }
43
+
44
+ public function enqueue_icon_styles() {
45
+ wp_enqueue_style( 'wphb-fonts', wphb_plugin_url() . 'admin/assets/css/wphb-font.css', array() );
46
+ }
47
+
48
+ public function add_plugin_action_links( $actions ) {
49
+ if ( current_user_can( wphb_get_admin_capability() ) ) {
50
+ if ( is_multisite() && ! is_network_admin() ) {
51
+ $url = network_admin_url( 'admin.php?page=wphb' );
52
+ }
53
+ else {
54
+ $url = wphb_get_admin_menu_url( '' );
55
+ }
56
+ $actions['dashboard'] = '<a href="' . $url . '" aria-label="' . esc_attr( __( 'Go to Hummingbird Dashboard', 'wphb' ) ) . '">' . esc_html__( 'Settings', 'wphb' ) . '</a>';
57
+ }
58
+
59
+ return $actions;
60
+ }
61
+
62
+ private function includes() {
63
+ include_once( 'abstract-class-admin-page.php' );
64
+ include_once( 'class-dashboard-page.php' );
65
+ include_once( 'class-performance-page.php' );
66
+ include_once( 'class-minification-page.php' );
67
+ include_once( 'class-caching-page.php' );
68
+ include_once( 'class-gzip-page.php' );
69
+ include_once( 'class-uptime-page.php' );
70
+ include_once( 'class-admin-notices.php' );
71
+
72
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
73
+ include_once( 'class-admin-ajax.php' );
74
+ }
75
+ }
76
+
77
+
78
+ /**
79
+ * Add all the menu pages in admin for the plugin
80
+ */
81
+ public function add_menu_pages() {
82
+ $module = wphb_get_module( 'minify' );
83
+
84
+ if ( ! is_multisite() ) {
85
+ $this->pages['wphb'] = new WP_Hummingbird_Dashboard_Page( 'wphb', __( 'Hummingbird', 'wphb' ), __( 'Hummingbird', 'wphb' ), false, false );
86
+ $this->pages['wphb-dashboard'] = new WP_Hummingbird_Dashboard_Page( 'wphb', __( 'Dashboard', 'wphb' ), __( 'Dashboard', 'wphb' ), 'wphb' );
87
+ $this->pages['wphb-performance'] = new WP_Hummingbird_Performance_Report_Page( 'wphb-performance', __( 'Performance Report', 'wphb' ), __( 'Performance Report', 'wphb' ), 'wphb' );
88
+
89
+ if ( $module->can_execute_php() ) {
90
+ $this->pages['wphb-minification'] = new WP_Hummingbird_Minification_Page( 'wphb-minification', __( 'Minification', 'wphb' ), __( 'Minification', 'wphb' ), 'wphb' );
91
+ }
92
+ $this->pages['wphb-caching'] = new WP_Hummingbird_Caching_Page( 'wphb-caching', __( 'Browser Caching', 'wphb' ), __( 'Browser Caching', 'wphb' ), 'wphb' );
93
+ $this->pages['wphb-gzip'] = new WP_Hummingbird_GZIP_Page( 'wphb-gzip', __( 'GZIP Compression', 'wphb' ), __( 'GZIP Compression', 'wphb' ), 'wphb' );
94
+ $this->pages['wphb-uptime'] = new WP_Hummingbird_Uptime_Page( 'wphb-uptime', __( 'Uptime', 'wphb' ), __( 'Uptime', 'wphb' ), 'wphb' );
95
+ }
96
+ else {
97
+ $minify = wphb_get_setting( 'minify' );
98
+
99
+ if ( $module->can_execute_php() ) {
100
+ if (
101
+ ( 'super-admins' === $minify && is_super_admin() )
102
+ || ( true === $minify )
103
+ ) {
104
+ $this->pages['wphb-minification'] = new WP_Hummingbird_Minification_Page( 'wphb-minification', __( 'Minification', 'wphb' ), __( 'Hummingbird', 'wphb' ), false );
105
+ }
106
+ elseif ( isset( $_GET['page'] ) && 'wphb-minification' === $_GET['page'] ) {
107
+ // Minification is off, and is a network, let's redirect to network admin
108
+ $url = network_admin_url( 'admin.php?page=wphb#wphb-box-dashboard-minification-network-module' );
109
+ $url = add_query_arg( 'minify-instructions', 'true', $url );
110
+ wp_redirect( $url );
111
+ exit;
112
+ }
113
+ }
114
+
115
+ }
116
+
117
+ }
118
+
119
+ public function add_network_menu_pages() {
120
+ $this->pages['wphb'] = new WP_Hummingbird_Dashboard_Page( 'wphb', __( 'Hummingbird', 'wphb' ), __( 'Hummingbird', 'wphb' ), false, false );
121
+ $this->pages['wphb-dashboard'] = new WP_Hummingbird_Dashboard_Page( 'wphb', __( 'Dashboard', 'wphb' ), __( 'Dashboard', 'wphb' ), 'wphb' );
122
+ $this->pages['wphb-performance'] = new WP_Hummingbird_Performance_Report_Page( 'wphb-performance', __( 'Performance Report', 'wphb' ), __( 'Performance Report', 'wphb' ), 'wphb' );
123
+ $this->pages['wphb-caching'] = new WP_Hummingbird_Caching_Page( 'wphb-caching', __( 'Browser Caching', 'wphb' ), __( 'Browser Caching', 'wphb' ), 'wphb' );
124
+ $this->pages['wphb-gzip'] = new WP_Hummingbird_GZIP_Page( 'wphb-gzip', __( 'GZIP Compression', 'wphb' ), __( 'GZIP Compression', 'wphb' ), 'wphb' );
125
+ $this->pages['wphb-uptime'] = new WP_Hummingbird_Uptime_Page( 'wphb-uptime', __( 'Uptime', 'wphb' ), __( 'Uptime Monitoring', 'wphb' ), 'wphb' );
126
+ }
127
+
128
+ /**
129
+ * Return an instannce of a WP Hummingbird Admin Page
130
+ *
131
+ * @param string $page_slug
132
+ *
133
+ * @return bool|WP_Hummingbird_Admin_Page
134
+ */
135
+ public function get_admin_page( $page_slug ) {
136
+ if ( isset( $this->pages[ $page_slug ] ) ) {
137
+ return $this->pages[ $page_slug ];
138
+ }
139
+
140
+ return false;
141
+ }
142
+
143
+ public function maybe_check_files() {
144
+ if ( ! is_user_logged_in() )
145
+ return;
146
+
147
+ $checking_files = wphb_minification_is_checking_files();
148
+
149
+ // If we are checking files, continue with it
150
+ if ( ! $checking_files )
151
+ return;
152
+
153
+ $enqueued = wp_script_is( 'wphb-admin', 'enqueued' );
154
+
155
+ if ( ! $enqueued )
156
+ wphb_enqueue_admin_scripts( WPHB_VERSION );
157
+
158
+ // If we are in minification page, we should redirect when checking files is finished
159
+ $screen = get_current_screen();
160
+ $minification_screen_id = isset( $this->pages['wphb-minification']->page_id ) ? $this->pages['wphb-minification']->page_id : false;
161
+ $dashboard_screen_id = ! empty( $this->pages['wphb']->page_id ) ? $this->pages['wphb']->page_id : '';
162
+
163
+ $redirect = '';
164
+ if ( $screen->id === $minification_screen_id ) {
165
+ // The minification screen will do it for us
166
+ return;
167
+ }
168
+
169
+ if ( $screen->id === $dashboard_screen_id ) {
170
+ $redirect = wphb_get_admin_menu_url( '' );
171
+ }
172
+
173
+ ?>
174
+ <script>
175
+ jQuery( document ).ready( function() {
176
+ var module = WPHB_Admin.getModule( 'minification' );
177
+ module.minificationStarted = true;
178
+ module.checkFiles( '<?php echo $redirect; ?>' );
179
+ });
180
+ </script>
181
+ <?php
182
+ }
183
+
184
+ public function maybe_check_report() {
185
+ if ( ! is_user_logged_in() )
186
+ return;
187
+
188
+ $doing_report = wphb_performance_is_doing_report();
189
+
190
+ // If we are checking files, continue with it
191
+ if ( ! $doing_report )
192
+ return;
193
+
194
+ if ( wphb_performance_stopped_report() ) {
195
+ return;
196
+ }
197
+
198
+ $enqueued = wp_script_is( 'wphb-admin', 'enqueued' );
199
+
200
+ if ( ! $enqueued )
201
+ wphb_enqueue_admin_scripts( WPHB_VERSION );
202
+
203
+ // If we are in performance page, we should redirect when checking files is finished
204
+ $screen = get_current_screen();
205
+ $performance_screen_id = isset( $this->pages['wphb-performance'] ) && isset( $this->pages['wphb-performance']->page_id ) ? $this->pages['wphb-performance']->page_id : false;
206
+ $dashboard_screen_id = isset( $this->pages['wphb'] ) && isset( $this->pages['wphb']->page_id ) ? $this->pages['wphb']->page_id : false;
207
+
208
+
209
+ $redirect = '';
210
+ if ( $screen->id === $performance_screen_id || $screen->id === $performance_screen_id . '-network' ) {
211
+ $redirect = wphb_get_admin_menu_url( 'performance' );
212
+ }
213
+
214
+ if ( $screen->id === $dashboard_screen_id || $screen->id === $dashboard_screen_id . '-network' ) {
215
+ $redirect = wphb_get_admin_menu_url( '' );
216
+ }
217
+
218
+ ?>
219
+ <script>
220
+ jQuery( document ).ready( function() {
221
+ var module = WPHB_Admin.getModule( 'performance' );
222
+ module.performanceTest( '<?php echo $redirect; ?>' );
223
+ });
224
+ </script>
225
+ <?php
226
+ }
227
+
228
+ /**
229
+ * Show quick setup modal.
230
+ *
231
+ * @since 1.5.0
232
+ */
233
+ public function maybe_show_quick_setup() {
234
+
235
+ // Only run on HB pages
236
+ $hb_pages = array(
237
+ 'toplevel_page_wphb',
238
+ 'hummingbird_page_wphb-performance',
239
+ 'hummingbird_page_wphb-minification',
240
+ 'hummingbird_page_wphb-caching',
241
+ 'hummingbird_page_wphb-gzip',
242
+ 'hummingbird_page_wphb-uptime',
243
+ );
244
+ if ( ! in_array( get_current_screen()->id, $hb_pages ) )
245
+ return;
246
+
247
+ if ( ! is_user_logged_in() )
248
+ return;
249
+
250
+ // If setup has already ran - exit
251
+ $quick_setup = get_option( 'wphb-quick-setup' );
252
+ if ( true === $quick_setup['finished'] ) {
253
+ return;
254
+ }
255
+
256
+ $enqueued = wp_script_is( 'wphb-admin', 'enqueued' );
257
+
258
+ if ( ! $enqueued )
259
+ wphb_enqueue_admin_scripts( WPHB_VERSION );
260
+
261
+ // Enable automatic scans by default
262
+ if ( wphb_is_member() ) {
263
+ $settings = wphb_get_settings();
264
+ $settings['email-notifications'] = true;
265
+ // Enable automatic reports for members
266
+ wphb_update_settings( $settings );
267
+ }
268
+
269
+ wphb_quick_setup_modal();
270
+ wphb_check_performance_modal();
271
+ ?>
272
+
273
+ <script>
274
+ jQuery(document).ready( function() {
275
+ var module = WPHB_Admin.getModule('dashboard');
276
+ module.startQuickSetup();
277
+ });
278
+ </script>
279
+ <?php
280
+ }
281
+
282
+ }
283
+
284
+
285
+
admin/class-caching-page.php ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Caching_Page extends WP_Hummingbird_Admin_Page {
4
+
5
+ /**
6
+ * Run Performance, Minification, Uptime...
7
+ *
8
+ * @param string $type
9
+ * @since 1.4.5
10
+ */
11
+ private function run_actions( $type ) {
12
+
13
+ check_admin_referer( 'wphb-run-caching' );
14
+
15
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
16
+ return;
17
+
18
+ if ( 'cf-deactivate' === $type ) {
19
+ wphb_cloudflare_disconnect();
20
+ wp_redirect( remove_query_arg( array( 'run', '_wpnonce' ) ) );
21
+ exit;
22
+ }
23
+ }
24
+
25
+ public function render_header() {
26
+ ?>
27
+ <?php if ( ! wphb_is_htaccess_written( 'caching' ) ): ?>
28
+ <div class="wphb-notice wphb-notice-success hidden" id="wphb-notice-code-snippet-updated">
29
+ <p><?php _e( 'Code snippet updated', 'wphb' ); ?></p>
30
+ </div>
31
+ <?php endif; ?>
32
+
33
+ <div class="wphb-notice wphb-notice-error <?php echo ! isset( $_GET['htaccess-error'] ) ? 'hidden' : ''; ?>" id="wphb-notice-code-snippet-htaccess-error">
34
+ <p><?php _e( 'Hummingbird could not update or write your .htaccess file. Please, make .htaccess writable or paste the code yourself.', 'wphb' ); ?></p>
35
+ </div>
36
+
37
+ <div class="wphb-notice wphb-notice-success hidden" id="wphb-notice-code-snippet-htaccess-updated">
38
+ <p><?php _e( 'Apache <strong>.htaccess</strong> file updated. Please, wait while Hummingbird recheck expirations...', 'wphb' ); ?></p>
39
+ </div>
40
+
41
+ <div class="wphb-notice wphb-notice-success hidden" id="wphb-notice-cloudflare-purge-cache">
42
+ <p><?php _e( 'CloudFlare cache successfully purged. Please wait 30 seconds for the purge to complete.', 'wphb' ); ?></p>
43
+ </div>
44
+
45
+ <?php
46
+ if ( isset( $_GET['caching-updated'] ) && ! isset( $_GET['htaccess-error'] ) ) {
47
+ if ( wphb_is_htaccess_written( 'caching' ) ) {
48
+ $this->show_notice( 'updated', __( 'Your .htaccess file has been updated', 'wphb' ), 'success', true );
49
+ } else {
50
+ $this->show_notice( 'updated', __( 'Code snippet updated', 'wphb' ), 'success', true );
51
+ }
52
+ }
53
+
54
+ if ( isset( $_GET['cache-enabled'] ) ) {
55
+ $this->show_notice( 'updated', __( 'Browser cache enabled. Your .htaccess file has been updated', 'wphb' ), 'success', true );
56
+ }
57
+
58
+ if ( isset( $_GET['cache-disabled'] ) ) {
59
+ $this->show_notice( 'updated', __( 'Browser cache disabled. Your .htaccess file has been updated', 'wphb' ), 'success', true );
60
+ }
61
+
62
+ parent::render_header(); // TODO: Change the autogenerated stub
63
+ }
64
+
65
+ public function register_meta_boxes() {
66
+ $redirect = false;
67
+
68
+ if ( isset( $_GET['enable'] ) && current_user_can( wphb_get_admin_capability() ) ) {
69
+ // Enable caching in htaccess (only for apache servers)
70
+ $result = wphb_save_htaccess( 'caching' );
71
+ if ( $result ) {
72
+ wphb_get_caching_status( true );
73
+ $redirect_to = remove_query_arg( array( 'run', 'enable', 'disable', 'caching-updated', 'cache-disabled', 'htaccess-error' ) );
74
+ $redirect_to = add_query_arg( 'cache-enabled', true, $redirect_to );
75
+ wp_redirect( $redirect_to );
76
+ exit;
77
+ }
78
+ else {
79
+ $redirect_to = remove_query_arg( array( 'run', 'enable', 'disable', 'caching-updated', 'cache-enabled', 'cache-disabled' ) );
80
+ $redirect_to = add_query_arg( 'htaccess-error', true, $redirect_to );
81
+ wp_redirect( $redirect_to );
82
+ exit;
83
+ }
84
+ }
85
+
86
+ if ( isset( $_GET['disable'] ) && current_user_can( wphb_get_admin_capability() ) ) {
87
+ // Disable caching in htaccess (only for apache servers)
88
+ $result = wphb_unsave_htaccess( 'caching' );
89
+ if ( $result ) {
90
+ wphb_get_caching_status( true );
91
+ $redirect_to = remove_query_arg( array( 'run', 'enable', 'disable', 'caching-updated', 'cache-enabled', 'htaccess-error' ) );
92
+ $redirect_to = add_query_arg( 'cache-disabled', true, $redirect_to );
93
+ wp_redirect( $redirect_to );
94
+ exit;
95
+ }
96
+ else {
97
+ $redirect_to = remove_query_arg( array( 'run', 'enable', 'disable', 'caching-updated', 'cache-enabled', 'cache-disabled' ) );
98
+ $redirect_to = add_query_arg( 'htaccess-error', true, $redirect_to );
99
+ wp_redirect( $redirect_to );
100
+ exit;
101
+ }
102
+ }
103
+
104
+ if ( isset( $_GET['run'] ) && current_user_can( wphb_get_admin_capability() ) ) {
105
+ // Force a refresh of the data
106
+ wphb_get_caching_status( true );
107
+ $redirect = true;
108
+ }
109
+
110
+ if ( isset( $_GET['run'] ) && isset( $_GET['type'] ) ) {
111
+ $this->run_actions( $_GET['type'] );
112
+ }
113
+
114
+ if ( $redirect ) {
115
+ wp_redirect( remove_query_arg( array( 'run', 'enable', 'disable', 'htaccess-error', 'cache-disabled', 'cache-enabled' ) ) );
116
+ exit;
117
+ }
118
+
119
+ $disable_enable_button = ! wphb_is_htaccess_written( 'caching' ) && $this->is_caching_fully_enabled();
120
+ $footer_class = $disable_enable_button ? '' : 'box-footer buttons buttons-on-left';
121
+ $this->add_meta_box( 'caching-summary', __( 'Summary', 'wphb' ), array( $this, 'caching_summary_metabox' ), array( $this, 'caching_summary_metabox_header' ), null, 'box-caching-left', array( 'box_content_class' => 'box-content side-padding' ) );
122
+ $this->add_meta_box( 'caching-enable', __( 'Enable Caching', 'wphb' ), array( $this, 'caching_enable_metabox' ), array( $this, 'caching_enable_metabox_header' ), array( $this, 'caching_enable_metabox_footer'), 'box-caching-right', array( 'box_footer_class' => $footer_class) );
123
+ $this->add_meta_box( 'caching-cloudflare', __( 'CloudFlare', 'wphb' ), array( $this, 'caching_cloudflare_metabox' ), array( $this, 'caching_cloudflare_header' ), null, 'box-caching-right', array( 'box_class' => 'dev-box content-box content-box-one-col-center') );
124
+ }
125
+
126
+
127
+ protected function render_inner_content() {
128
+ $server_name = wphb_get_server_type();
129
+ $server_type = array_search( $server_name, wphb_get_servers() );
130
+ $this->view( $this->slug . '-page', array( 'server_type' => $server_type, 'server_name' => $server_name ) );
131
+ }
132
+
133
+
134
+ public function caching_summary_metabox() {
135
+ $options = wphb_get_settings();
136
+ $expires = array(
137
+ 'css' => $options['caching_expiry_css'],
138
+ 'javascript' => $options['caching_expiry_javascript'],
139
+ 'media' => $options['caching_expiry_media'],
140
+ 'images' => $options['caching_expiry_images'],
141
+ );
142
+
143
+ $recommended = wphb_get_recommended_caching_values();
144
+
145
+ $results = wphb_get_caching_status();
146
+ if ( false === $results ) {
147
+ // Force only when we don't have any data yet
148
+ $results = wphb_get_caching_status( true );
149
+ }
150
+ $human_results = array_map( 'wphb_human_read_time_diff', $results );
151
+
152
+ $external_problem = false;
153
+ $htaccess_written = wphb_is_htaccess_written( 'caching' );
154
+ if ( $htaccess_written && in_array( false, $results ) ) {
155
+ $external_problem = true;
156
+ }
157
+
158
+ /** @var WP_Hummingbird_Module_Cloudflare $cf_module */
159
+ $cf_module = wphb_get_module( 'cloudflare' );
160
+ $cf_active = false;
161
+ $cf_current_human = '';
162
+ $cf_tooltip = '';
163
+ $cf_current = '';
164
+ if ( $cf_module->is_active() && $cf_module->is_connected() && $cf_module->is_zone_selected() ) {
165
+ $cf_active = true;
166
+ $cf_current = $cf_module->get_caching_expiration();
167
+ if ( is_wp_error( $cf_current ) ) {
168
+ $cf_current = '';
169
+ }
170
+
171
+ $cf_tooltip = $cf_current == 691200 ? __('Caching is enabled', 'wphb') : __('Caching is enabled but you aren\'t using our recommended value', 'wphb');
172
+ $cf_current_human = wphb_human_read_time_diff( $cf_current );
173
+ }
174
+
175
+ $args = compact( 'expires', 'results', 'recommended', 'external_problem', 'human_results', 'cf_active', 'cf_tooltip', 'cf_current_human', 'cf_current' );
176
+ $this->view( 'caching/summary-meta-box', $args );
177
+ }
178
+
179
+ public function caching_summary_metabox_header() {
180
+ $recheck_url = add_query_arg( 'run', 'true' );
181
+ $this->view( 'caching/summary-meta-box-header', array( 'recheck_url' => $recheck_url, 'title' => __( 'Summary', 'wphb' ) ) );
182
+ }
183
+
184
+ public function caching_enable_metabox() {
185
+ $snippets = array(
186
+ 'apache' => wphb_get_code_snippet( 'caching', 'apache' ),
187
+ 'litespeed' => wphb_get_code_snippet( 'caching', 'LiteSpeed' ),
188
+ 'nginx' => wphb_get_code_snippet( 'caching', 'nginx' ),
189
+ 'iis' => wphb_get_code_snippet( 'caching', 'iis' ),
190
+ 'iis-7' => wphb_get_code_snippet( 'caching', 'iis-7' ),
191
+ );
192
+
193
+ $htaccess_written = wphb_is_htaccess_written( 'caching' );
194
+ $htaccess_writable = wphb_is_htaccess_writable();
195
+ $already_enabled = $this->is_caching_fully_enabled() && ! wphb_is_htaccess_written( 'caching' );
196
+
197
+ $this->view( 'caching/enable-meta-box', array( 'snippets' => $snippets, 'htaccess_written' => $htaccess_written, 'htaccess_writable' => $htaccess_writable, 'already_enabled' => $already_enabled ) );
198
+ }
199
+
200
+ public function caching_enable_metabox_header() {
201
+ $this->view( 'caching/enable-meta-box-header', array( 'gzip_server_type' => wphb_get_server_type(), 'title' => __( 'Enable Caching', 'wphb' ) ) );
202
+ }
203
+
204
+ public function caching_enable_metabox_footer() {
205
+ $disable_enable_button = ! wphb_is_htaccess_written( 'caching' ) && $this->is_caching_fully_enabled();
206
+ $enable_link = add_query_arg( array( 'run' => 'true', 'enable' => 'true' ) );
207
+ $disable_link = add_query_arg( array( 'run' => 'true', 'disable' => 'true' ) );
208
+
209
+ $cf_active = wphb_cloudflare_is_active();
210
+
211
+ $args = array(
212
+ 'server_type' => wphb_get_server_type(),
213
+ 'enable_link' => $enable_link,
214
+ 'disable_link' => $disable_link,
215
+ 'disable_enable_button' => $disable_enable_button,
216
+ 'cloudflare_enabled' => $cf_active,
217
+ );
218
+
219
+ $this->view( 'caching/enable-meta-box-footer', $args );
220
+ }
221
+
222
+ public function is_caching_fully_enabled() {
223
+ $recommended = wphb_get_recommended_caching_values();
224
+
225
+ $results = wphb_get_caching_status();
226
+ if ( false === $results ) {
227
+ // Force only when we don't have any data yet
228
+ $results = wphb_get_caching_status( true );
229
+ }
230
+
231
+ $result_sum = 0;
232
+
233
+ foreach ( $results as $key => $result ) {
234
+ if ( $result >= $recommended[ $key ]['value'] ) {
235
+ $result_sum++;
236
+ }
237
+ }
238
+
239
+ return $result_sum === count( $results );
240
+
241
+ }
242
+
243
+ /**
244
+ * CLOUDFLARE
245
+ */
246
+ public function caching_cloudflare_metabox() {
247
+ $this->view( 'caching/cloudflare-meta-box' );
248
+ }
249
+
250
+ /**
251
+ * Display Cloudflare header
252
+ *
253
+ * @since 1.4.5
254
+ */
255
+ public function caching_cloudflare_header() {
256
+ $title = __( 'CloudFlare', 'wphb' );
257
+ $deactivate_url = add_query_arg( array(
258
+ 'type' => 'cf-deactivate',
259
+ 'run' => 'true'
260
+ ));
261
+ $deactivate_url = wp_nonce_url( $deactivate_url, 'wphb-run-caching' ) . '#wphb-box-dashboard-cloudflare';
262
+
263
+ $cf_active = wphb_cloudflare_is_active();
264
+
265
+ $this->view( 'caching/cloudflare-meta-box-header', compact( 'title', 'deactivate_url', 'cf_active' ) );
266
+ }
267
+
268
+ }
admin/class-dashboard-page.php ADDED
@@ -0,0 +1,548 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Dashboard_Page extends WP_Hummingbird_Admin_Page {
4
+
5
+ private static $current_uptime_report;
6
+
7
+
8
+ public function __construct( $slug, $page_title, $menu_title, $parent = false, $render = true ) {
9
+ parent::__construct( $slug, $page_title, $menu_title, $parent, $render );
10
+ }
11
+
12
+ public function on_load() {
13
+
14
+ if ( is_multisite() && ! is_network_admin() ) {
15
+ wphb_minification_maybe_stop_checking_files();
16
+ }
17
+
18
+ if ( isset( $_GET['wphb-clear-files'] ) && current_user_can( wphb_get_admin_capability() ) ) {
19
+ check_admin_referer( 'wphb-clear-files' );
20
+
21
+ wphb_minification_clear_files();
22
+ $url = remove_query_arg( array( 'wphb-clear-files', 'updated', '_wpnonce' ) );
23
+
24
+ if ( wphb_cloudflare_is_active() ) {
25
+ /** @var WP_Hummingbird_Module_Cloudflare $cf */
26
+ $cf = wphb_get_module( 'cloudflare' );
27
+ $cf->purge_cache();
28
+ wp_redirect( add_query_arg( 'wphb-cache-cleared-with-cloudflare', 'true', $url ) );
29
+ } else {
30
+ wp_redirect( add_query_arg( 'wphb-cache-cleared', 'true', $url ) );
31
+ }
32
+ exit;
33
+ }
34
+ }
35
+ public function render_header() {
36
+ $clear_cache_url = add_query_arg( 'wphb-clear-files', 'true' );
37
+ $clear_cache_url = wp_nonce_url( $clear_cache_url, 'wphb-clear-files' );
38
+
39
+ if ( isset( $_GET['wphb-cache-cleared'] ) ) {
40
+ $this->show_notice( 'updated', __( 'Your cache has been successfully cleared. Your assets will regenerate the next time someone visits your website.', 'wphb' ), 'success', true );
41
+ }
42
+
43
+ if ( isset( $_GET['wphb-cache-cleared-with-cloudflare'] ) ) {
44
+ $this->show_notice( 'updated', __( 'Your local and CloudFlare caches have been successfully cleared. Your assets will regenerate the next time someone visits your website.', 'wphb' ), 'success', true );
45
+ }
46
+ ?>
47
+ <section id="header">
48
+ <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
49
+ <div class="actions">
50
+ <?php if ( true === WP_Hummingbird_Module_Performance::can_run_test() ) : ?>
51
+ <?php
52
+ $scan_link = add_query_arg(
53
+ array(
54
+ 'run' => 'true',
55
+ 'type' => 'performance',
56
+ ),
57
+ wphb_get_admin_menu_url( '' )
58
+ );
59
+ $scan_link = wp_nonce_url( $scan_link, 'wphb-run-dashboard' ) . '#wphb-box-dashboard-performance-running-test';
60
+ ?>
61
+ <a href="<?php echo esc_url( $scan_link ); ?>" class="button"><?php esc_html_e( 'Run Test', 'wphb' ); ?></a>
62
+ <?php endif; ?>
63
+ <a href="<?php echo esc_url( $clear_cache_url ); ?>" class="button button-ghost"><?php esc_html_e( 'Clear Cache', 'wphb' ); ?></a>
64
+ </div>
65
+ </section><!-- end header -->
66
+ <?php
67
+ }
68
+
69
+ /**
70
+ * Run Performance, Minification, Uptime...
71
+ *
72
+ * @param string $type
73
+ */
74
+ private function run_actions( $type ) {
75
+
76
+ // Check if Uptime is active in the server.
77
+ if ( wphb_is_uptime_remotely_enabled() ) {
78
+ wphb_uptime_enable_locally();
79
+ } else {
80
+ wphb_uptime_disable_locally();
81
+ }
82
+
83
+ check_admin_referer( 'wphb-run-dashboard' );
84
+
85
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
86
+ return;
87
+
88
+ if ( 'performance' === $type ) {
89
+ // Start performance test
90
+ wphb_performance_init_scan();
91
+ wp_redirect( remove_query_arg( array( 'run', '_wpnonce' ) ) );
92
+ exit;
93
+ }
94
+
95
+ if ( 'minification' === $type ) {
96
+ // Minification scan
97
+ wphb_minification_init_scan();
98
+ wp_redirect( remove_query_arg( array( 'run', '_wpnonce' ), wphb_get_admin_menu_url( 'minification' ) ) );
99
+ exit;
100
+ }
101
+
102
+ if ( 'uptime' === $type ) {
103
+ // Minification scan
104
+ wphb_uptime_get_last_report( 'week', true );
105
+ wp_redirect( remove_query_arg( array( 'run', '_wpnonce' ) ) );
106
+ exit;
107
+ }
108
+
109
+ }
110
+
111
+ /**
112
+ * Register available metaboxes on the Dashboard page.
113
+ */
114
+ public function register_meta_boxes() {
115
+
116
+ if ( isset( $_GET['run'] ) && isset( $_GET['type'] ) ) {
117
+ $this->run_actions( $_GET['type'] );
118
+ }
119
+
120
+ $this->add_meta_box( 'dashboard/welcome', null , array( $this, 'dashboard_welcome_metabox' ), null, null, 'main', array( 'box_class' => 'dev-box content-box content-box-two-cols-image-left' ) );
121
+
122
+ /* Performance */
123
+ $last_report = wphb_performance_get_last_report();
124
+ if ( wphb_performance_is_doing_report() ) {
125
+ $this->add_meta_box( 'dashboard/performance/running-test', __( 'Performance test in progress', 'wphb' ), null, null, null, 'box-dashboard-left' );
126
+ }
127
+ elseif ( ! wphb_performance_is_doing_report() && $last_report && ! is_wp_error( $last_report ) ) {
128
+ $this->add_meta_box( 'dashboard-performance-module', __( 'Performance Report', 'wphb' ), array( $this, 'dashboard_performance_module_metabox' ), array( $this, 'dashboard_performance_module_metabox_header' ), null, 'box-dashboard-left', array( 'box_class' => 'dev-box content-box content-box-one-col-center', 'box_footer_class' => 'box-footer buttons' ) );
129
+ }
130
+ elseif ( is_wp_error( $last_report ) ) {
131
+ $this->add_meta_box( 'dashboard-performance-module-error', __( 'Performance Report', 'wphb' ), array( $this, 'dashboard_performance_module_error_metabox' ), null, null, 'box-dashboard-left', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
132
+ }
133
+ else {
134
+ $this->add_meta_box( 'dashboard-performance-disabled', __( 'Performance Report', 'wphb' ), array( $this, 'dashboard_performance_disabled_metabox' ), null, null, 'box-dashboard-left', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
135
+ }
136
+
137
+ /* Caching */
138
+ $caching_status = wphb_get_caching_status();
139
+ if ( false === $caching_status ) {
140
+ // Force only when we don't have any data yet
141
+ $caching_status = wphb_get_caching_status( true );
142
+ }
143
+ $this->add_meta_box( 'dashboard-caching-module', __( 'Browser Caching', 'wphb' ), array( $this, 'dashboard_caching_module_metabox' ), array( $this, 'dashboard_caching_module_metabox_header' ), null, 'box-dashboard-right' );
144
+
145
+ /* GZIP */
146
+ $this->add_meta_box( 'dashboard-gzip-module', __( 'GZIP Compression', 'wphb' ), array( $this, 'dashboard_gzip_module_metabox' ), array( $this, 'dashboard_gzip_module_metabox_header' ), null, 'box-dashboard-left' );
147
+
148
+ /* Minification */
149
+ $collection = wphb_minification_get_resources_collection();
150
+ $module = wphb_get_module( 'minify' );
151
+
152
+ if ( ! $module->can_execute_php() ) {
153
+ $this->add_meta_box( 'dashboard/minification/cant-execute-php', __( 'Minification', 'wphb' ), null, null, null, 'box-dashboard-right', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
154
+ }
155
+ elseif ( is_multisite() && is_network_admin() ) {
156
+ // Minification metabox is different on network admin
157
+ $this->add_meta_box( 'dashboard/minification/network-module', __( 'Minification', 'wphb' ), array( $this, 'dashboard_minification_network_module_metabox' ), null, null, 'box-dashboard-right', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
158
+ }
159
+ else {
160
+ if ( ( ! empty( $collection['styles'] ) || ! empty( $collection['scripts'] ) ) && ( $module->is_active() ) ) {
161
+ $this->add_meta_box( 'dashboard/minification-module', __( 'Minification', 'wphb' ), array( $this, 'dashboard_minification_module_metabox' ), array( $this, 'dashboard_minification_module_metabox_header' ), null, 'box-dashboard-right' );
162
+ }
163
+ else {
164
+ $this->add_meta_box( 'dashboard/minification-disabled', __( 'Minification', 'wphb' ), array( $this, 'dashboard_minification_disabled_metabox' ), null, null, 'box-dashboard-right', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
165
+ }
166
+ }
167
+
168
+ /* Smush */
169
+ $smush_id = wphb_is_member() ? 'dashboard-smush' : 'dashboard/smush/no-membership';
170
+ $this->add_meta_box( $smush_id, __( 'Image Optimization', 'wphb' ), array( $this, 'dashboard_smush_metabox' ), array( $this, 'dashboard_smush_metabox_header' ), null, 'box-dashboard-left', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
171
+
172
+ /* Become Pro Member Callout */
173
+ if ( ! wphb_is_member() ) {
174
+ $this->add_meta_box( 'dashboard-pro-membership', null, array( $this, 'dashboard_membership_metabox' ), null, null, 'box-dashboard-left', array( 'box_class' => 'dev-box callout-box content-box content-box-one-col-center' ) );
175
+ }
176
+
177
+ /* Uptime */
178
+ $uptime_module = wphb_get_module( 'uptime' );
179
+ $is_active = $uptime_module->is_active();
180
+ $report = wphb_uptime_get_last_report( 'week' );
181
+
182
+ if ( ! wphb_is_member() ) {
183
+ $this->add_meta_box( 'dashboard/uptime/no-membership', __( 'Uptime Monitoring', 'wphb' ), null, array( $this, 'dashboard_uptime_module_metabox_header' ), null, 'box-dashboard-right', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
184
+ }
185
+ elseif ( is_wp_error( $report ) && $is_active ) {
186
+ $this->add_meta_box( 'uptime-error', __( 'Uptime', 'wphb' ), array( $this, 'dashboard_uptime_error_metabox' ), null, null, 'box-dashboard-right', null );
187
+ }
188
+ elseif ( ! $is_active ) {
189
+ $this->add_meta_box( 'uptime-disabled', __( 'Uptime', 'wphb' ), array( $this, 'dashboard_uptime_disabled_metabox' ), null, null, 'box-dashboard-right', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
190
+ }
191
+ else {
192
+ $this->add_meta_box( 'dashboard-uptime', __( 'Uptime', 'wphb' ), array( $this, 'dashboard_uptime_metabox' ), array( $this, 'dashboard_uptime_module_metabox_header' ), null, 'box-dashboard-right', null );
193
+ }
194
+
195
+ /* Reports */
196
+ if ( ! wphb_is_member() ) {
197
+ $this->add_meta_box( 'dashboard/reports/no-membership', __( 'Reporting', 'wphb' ), null, array( $this, 'dashboard_reports_module_metabox_header' ), null, 'box-dashboard-right', array( 'box_class' => 'dev-box content-box content-box-one-col-center' ) );
198
+ }
199
+
200
+ }
201
+
202
+ public function dashboard_welcome_metabox() {
203
+ $caching_status = wphb_get_caching_status();
204
+ if ( false === $caching_status ) {
205
+ // Force only when we don't have any data yet
206
+ $caching_status = wphb_get_caching_status( true );
207
+ }
208
+ $caching_issues = wphb_get_number_of_issues( 'caching' );
209
+
210
+ $gzip_status = wphb_get_gzip_status();
211
+ if ( false === $gzip_status ) {
212
+ // Force only when we don't have any data yet
213
+ $gzip_status = wphb_get_gzip_status( true );
214
+ }
215
+ $gzip_issues = wphb_get_number_of_issues( 'gzip' );
216
+
217
+ $uptime_module = wphb_get_module( 'uptime' );
218
+ $uptime_active = $uptime_module->is_active();
219
+ $uptime_report = wphb_uptime_get_last_report( 'week' );
220
+ $site_date = '';
221
+ if ( wphb_is_member() && $uptime_report ) {
222
+ $gmt_date = date( 'Y-m-d H:i:s', $uptime_report->up_since );
223
+ $site_date = get_date_from_gmt( $gmt_date, get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
224
+ }
225
+
226
+ $last_report = wphb_performance_get_last_report();
227
+ /** @var WP_Hummingbird_Module_Cloudflare $cf_module */
228
+ $cf_module = wphb_get_module( 'cloudflare' );
229
+ $cf_active = false;
230
+
231
+ $cf_current = '';
232
+ if ( $cf_module->is_active() && $cf_module->is_connected() && $cf_module->is_zone_selected() ) {
233
+ $cf_active = true;
234
+ $cf_current = $cf_module->get_caching_expiration();
235
+ if ( is_wp_error( $cf_current ) ) {
236
+ $cf_current = '';
237
+ }
238
+ }
239
+
240
+ $args = compact(
241
+ 'caching_status',
242
+ 'caching_issues',
243
+ 'gzip_status',
244
+ 'gzip_issues',
245
+ 'uptime_active',
246
+ 'uptime_report',
247
+ 'last_report',
248
+ 'cf_active',
249
+ 'cf_current',
250
+ 'site_date'
251
+ );
252
+ $this->view( 'dashboard/welcome/meta-box', $args );
253
+ }
254
+
255
+ public function dashboard_welcome_metabox_header() {
256
+ $user = wphb_get_current_user_info();
257
+ $this->view( 'dashboard/welcome/meta-box-header', array( 'title' => sprintf( __( 'Welcome %s', 'wphb' ), $user) ) );
258
+ }
259
+
260
+ /**
261
+ * Display pro membership metabox
262
+ *
263
+ * @since 1.4.5
264
+ */
265
+ public function dashboard_membership_metabox() {
266
+ $this->view( 'dashboard/welcome/pro-membership-meta-box', array() );
267
+ }
268
+
269
+ /*******************
270
+ * CACHING *
271
+ *******************/
272
+ public function dashboard_caching_module_metabox() {
273
+ $caching_status = wphb_get_caching_status();
274
+ $human_results = array_map( 'wphb_human_read_time_diff', $caching_status );
275
+ $recommended = wphb_get_recommended_caching_values();
276
+
277
+ /** @var WP_Hummingbird_Module_Cloudflare $cf_module */
278
+ $cf_module = wphb_get_module( 'cloudflare' );
279
+ $cf_active = false;
280
+ $cf_current_human = '';
281
+ $cf_tooltip = '';
282
+ $cf_current = '';
283
+ if ( $cf_module->is_active() && $cf_module->is_connected() && $cf_module->is_zone_selected() ) {
284
+ $cf_active = true;
285
+ $cf_current = $cf_module->get_caching_expiration();
286
+ if ( is_wp_error( $cf_current ) ) {
287
+ $cf_current = '';
288
+ }
289
+
290
+ $cf_tooltip = $cf_current == 691200 ? __('Caching is enabled', 'wphb') : __('Caching is enabled but you aren\'t using our recommended value', 'wphb');
291
+ $cf_current_human = wphb_human_read_time_diff( $cf_current );
292
+ }
293
+
294
+ $args = array(
295
+ 'results' => $caching_status,
296
+ 'recommended' => $recommended,
297
+ 'human_results' => $human_results,
298
+ 'cf_tooltip' => $cf_tooltip,
299
+ 'cf_current' => $cf_current,
300
+ 'cf_current_human' => $cf_current_human,
301
+ 'cf_active' => $cf_active,
302
+ 'caching_url' => wphb_get_admin_menu_url( 'caching' ),
303
+ );
304
+ $this->view( 'dashboard/caching/module-meta-box', $args );
305
+ }
306
+
307
+ public function dashboard_caching_module_metabox_header() {
308
+ $title = __( 'Browser Caching', 'wphb' );
309
+ $issues = wphb_get_number_of_issues( 'caching' );
310
+
311
+ /** @var WP_Hummingbird_Module_Cloudflare $cf_module */
312
+ $cf_module = wphb_get_module( 'cloudflare' );
313
+ $cf_active = false;
314
+
315
+ $cf_current = '';
316
+ if ( $cf_module->is_active() && $cf_module->is_connected() && $cf_module->is_zone_selected() ) {
317
+ $cf_active = true;
318
+ $cf_current = $cf_module->get_caching_expiration();
319
+ if ( is_wp_error( $cf_current ) ) {
320
+ $cf_current = '';
321
+ }
322
+ }
323
+
324
+ $args = compact( 'title', 'issues', 'cf_active', 'cf_current' );
325
+ $this->view( 'dashboard/caching/module-meta-box-header', $args );
326
+ }
327
+
328
+ /*******************
329
+ * UPTIME *
330
+ *******************/
331
+ public function dashboard_uptime_module_metabox_header() {
332
+ $this->view( 'dashboard/uptime/module-meta-box-header', array( 'title' => __( 'Uptime Monitoring', 'wphb' ) ) );
333
+ }
334
+ public function dashboard_uptime_metabox() {
335
+ $uptime_stats = wphb_uptime_get_last_report( 'week' );
336
+ $this->view( 'dashboard/uptime/module-meta-box', array( 'uptime_stats' => $uptime_stats ) );
337
+ }
338
+ public function dashboard_uptime_disabled_metabox() {
339
+ $enable_url = add_query_arg( 'action', 'enable', wphb_get_admin_menu_url( 'uptime' ) );
340
+ $enable_url = wp_nonce_url( $enable_url, 'wphb-toggle-uptime' );
341
+ $this->view( 'dashboard/uptime/disabled-meta-box', array( 'enable_url' => $enable_url ) );
342
+ }
343
+ public function dashboard_uptime_error_metabox() {
344
+ $report = wphb_uptime_get_last_report();
345
+ $retry_url = add_query_arg(
346
+ array(
347
+ 'run' => 'true',
348
+ 'type' => 'uptime'
349
+ ),
350
+ wphb_get_admin_menu_url( '' )
351
+ );
352
+ $retry_url = wp_nonce_url( $retry_url, 'wphb-run-dashboard' ) . '#wphb-box-dashboard-uptime-module';
353
+ $support_url = wphb_support_link();
354
+ $error = $report->get_error_message();
355
+
356
+ $this->view( 'dashboard/uptime/error-meta-box', array( 'retry_url' => $retry_url, 'support_url' => $support_url, 'error' => $error ) );
357
+ }
358
+
359
+ /*******************
360
+ * MINIFICATION *
361
+ *******************/
362
+ public function dashboard_minification_module_metabox() {
363
+ $collection = wphb_minification_get_resources_collection();
364
+ // Remove those assets that we don't want to display
365
+ foreach ( $collection['styles'] as $key => $item ) {
366
+ if ( ! apply_filters( 'wphb_minification_display_enqueued_file', true, $item, 'styles' ) ) {
367
+ unset( $collection['styles'][ $key ] );
368
+ }
369
+ }
370
+ foreach ( $collection['scripts'] as $key => $item ) {
371
+ if ( ! apply_filters( 'wphb_minification_display_enqueued_file', true, $item, 'scripts' ) ) {
372
+ unset( $collection['scripts'][ $key ] );
373
+ }
374
+ }
375
+
376
+ $enqueued_files = count( $collection['scripts'] ) + count( $collection['styles'] );
377
+
378
+ $original_size_styles = array_sum( wp_list_pluck( $collection['styles'], 'original_size' ) );
379
+ $original_size_scripts = array_sum( wp_list_pluck( $collection['scripts'], 'original_size' ) );
380
+ $original_size = $original_size_scripts + $original_size_styles;
381
+
382
+ $compressed_size_styles = array_sum( wp_list_pluck( $collection['styles'], 'compressed_size' ) );
383
+ $compressed_size_scripts = array_sum( wp_list_pluck( $collection['scripts'], 'compressed_size' ) );
384
+ $compressed_size = $compressed_size_scripts + $compressed_size_styles;
385
+
386
+ if ( ( $original_size_scripts + $original_size_styles ) <= 0 ) {
387
+ $percentage = 0;
388
+ }
389
+ else {
390
+ $percentage = 100 - (int) $compressed_size * 100 / (int) $original_size;
391
+ }
392
+ $percentage = number_format_i18n( $percentage, 2 );
393
+
394
+ $compressed_size_styles = number_format( $original_size_styles - $compressed_size_styles, 1 );
395
+ $compressed_size_scripts = number_format( $original_size_scripts - $compressed_size_scripts, 1 );
396
+
397
+ $minification_url = wphb_get_admin_menu_url( 'minification' );
398
+
399
+ // Internalization numbers.
400
+ $original_size = number_format_i18n( $original_size, 1 );
401
+ $compressed_size = number_format_i18n( $compressed_size, 1 );
402
+
403
+ $args = compact( 'enqueued_files', 'original_size', 'compressed_size', 'compressed_size_scripts', 'compressed_size_styles', 'percentage', 'minification_url' );
404
+ $this->view( 'dashboard/minification/module-meta-box', $args );
405
+ }
406
+
407
+ public function dashboard_minification_network_module_metabox() {
408
+ $minify = wphb_get_setting( 'minify' );
409
+ $args = array(
410
+ 'use_cdn' => wphb_get_cdn_status(),
411
+ 'use_cdn_disabled' => ! wphb_is_member() || ! $minify,
412
+ );
413
+ $this->view( 'dashboard/minification/network-module-meta-box', $args );
414
+ }
415
+
416
+ public function dashboard_minification_module_metabox_header() {
417
+ $this->view( 'dashboard/minification/module-meta-box-header', array( 'title' => __( 'Minification', 'wphb' ) ) );
418
+ }
419
+
420
+ public function dashboard_minification_disabled_metabox() {
421
+ $minification_url = add_query_arg(
422
+ array(
423
+ 'run' => 'true',
424
+ 'type' => 'minification'
425
+ ),
426
+ wphb_get_admin_menu_url( '' )
427
+ );
428
+ $minification_url = wp_nonce_url( $minification_url, 'wphb-run-dashboard' ) . '#wphb-box-dashboard-minification-checking-files';
429
+ $this->view( 'dashboard/minification/disabled-meta-box', array( 'minification_url' => $minification_url ) );
430
+ }
431
+
432
+ /*******************
433
+ * GZIP *
434
+ *******************/
435
+ public function dashboard_gzip_module_metabox() {
436
+ $status = wphb_get_gzip_status();
437
+ $gzip_url = wphb_get_admin_menu_url( 'gzip' );
438
+ $this->view( 'dashboard/gzip/module-meta-box', array( 'status' => $status, 'gzip_url' => $gzip_url ) );
439
+ }
440
+
441
+ public function dashboard_gzip_module_metabox_header() {
442
+ $issues = wphb_get_number_of_issues( 'gzip' );
443
+ $this->view( 'dashboard/gzip/module-meta-box-header', array( 'issues' => $issues, 'title' => __( 'GZIP Compression', 'wphb' ) ) );
444
+ }
445
+
446
+ /********************
447
+ * PERFORMANCE *
448
+ ********************/
449
+ public function dashboard_performance_disabled_metabox() {
450
+ $run_url = add_query_arg(
451
+ array(
452
+ 'run' => 'true',
453
+ 'type' => 'performance'
454
+ ),
455
+ wphb_get_admin_menu_url( '' )
456
+ );
457
+ $run_url = wp_nonce_url( $run_url, 'wphb-run-dashboard' ) . '#wphb-box-dashboard-performance-running-test';
458
+
459
+ $this->view( 'dashboard/performance/disabled-meta-box', array( 'run_url' => $run_url ) );
460
+ }
461
+
462
+ public function dashboard_performance_module_metabox() {
463
+ $report = wphb_performance_get_last_report();
464
+ $report = $report->data;
465
+ $viewreport_link = wphb_get_admin_menu_url( 'performance' );
466
+
467
+ $settings = wphb_get_settings();
468
+ if ( wphb_is_member() ) {
469
+ $notifications = $settings['email-notifications'];
470
+ } else {
471
+ $notifications = false;
472
+ }
473
+
474
+
475
+ $args = compact( 'report', 'viewreport_link', 'notifications' );
476
+ $this->view( 'dashboard/performance/module-meta-box', $args );
477
+ }
478
+
479
+ public function dashboard_performance_module_metabox_header() {
480
+ $title = __( 'Performance Report', 'wphb' );
481
+ $last_report = wphb_performance_get_last_report();
482
+ if ( $last_report && ! is_wp_error( $last_report ) ) {
483
+ $last_report = $last_report->data;
484
+ }
485
+
486
+ $this->view( 'dashboard/performance/module-meta-box-header', array( 'title' => $title, 'last_report' => $last_report ) );
487
+ }
488
+
489
+ public function dashboard_performance_module_error_metabox() {
490
+ /** @var WP_Error $last_report */
491
+ $last_report = wphb_performance_get_last_report();
492
+ $retry_url = add_query_arg( array(
493
+ 'run' => 'true',
494
+ 'type' => 'performance'
495
+ ),
496
+ wphb_get_admin_menu_url( '' )
497
+ );
498
+ $retry_url = wp_nonce_url( $retry_url, 'wphb-run-dashboard' ) . '#wphb-box-dashboard-performance-running-test';
499
+
500
+ $support_url = wphb_support_link();
501
+ $error = $last_report->get_error_message();
502
+ $this->view( 'dashboard/performance/module-error-meta-box', compact( 'error', 'retry_url', 'support_url' ) );
503
+ }
504
+
505
+ /*********************************
506
+ /** SMUSH *
507
+ *********************************/
508
+ public function dashboard_smush_metabox() {
509
+ global $wpsmushit_admin, $wpsmush_db;
510
+
511
+ $smush_data = array( 'human' => '', 'percent' => 0 );
512
+ $unsmushed_images = 0;
513
+ if ( is_a( $wpsmushit_admin, 'WpSmushitAdmin' ) ) {
514
+ $smush_data = $wpsmushit_admin->global_stats();
515
+ $unsmushed_images = count( $wpsmush_db->get_unsmushed_attachments() );
516
+ }
517
+ $this->view(
518
+ 'dashboard/smush/meta-box',
519
+ array(
520
+ 'activate_url' => wp_nonce_url( 'plugins.php?action=activate&amp;plugin=wp-smushit/wp-smush.php', 'activate-plugin_wp-smushit/wp-smush.php' ),
521
+ 'activate_pro_url' => wp_nonce_url( 'plugins.php?action=activate&amp;plugin=wp-smush-pro/wp-smush.php', 'activate-plugin_wp-smush-pro/wp-smush.php' ),
522
+ 'is_active' => wphb_smush_is_smush_active(),
523
+ 'is_installed' => wphb_smush_is_smush_installed(),
524
+ 'smush_data' => $smush_data,
525
+ 'is_pro' => WP_Hummingbird_Module_Smush::$is_smush_pro,
526
+ 'unsmushed' => $unsmushed_images,
527
+ )
528
+ );
529
+ }
530
+ public function dashboard_smush_metabox_header() {
531
+ $title = __( 'Image Optimization', 'wphb' );
532
+ $this->view( 'dashboard/smush/meta-box-header', array( 'title' => $title ) );
533
+ }
534
+
535
+ /*********************************
536
+ /** REPORTS *
537
+ *********************************/
538
+ /**
539
+ * Reports header meta box
540
+ *
541
+ * @since 1.4.5
542
+ */
543
+ public function dashboard_reports_module_metabox_header() {
544
+ $title = __( 'Reports', 'wphb' );
545
+ $this->view( 'dashboard/reports/meta-box-header', compact( 'title' ) );
546
+ }
547
+
548
+ }
admin/class-gzip-page.php ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_GZIP_Page extends WP_Hummingbird_Admin_Page {
4
+
5
+ public function render_header() {
6
+
7
+ if ( isset( $_GET['htaccess-error'] ) ) {
8
+ $this->show_notice( 'error', __( 'Hummingbird could not update or write your .htaccess file. Please, make .htaccess writable or paste the code yourself.', 'wphb' ), 'error', true );
9
+ }
10
+
11
+ if ( isset( $_GET['gzip-enabled'] ) ) {
12
+ $this->show_notice( 'updated', __( 'Gzip enabled. Your .htaccess file has been updated', 'wphb' ), 'success', true );
13
+ }
14
+
15
+ if ( isset( $_GET['gzip-disabled'] ) ) {
16
+ $this->show_notice( 'updated', __( 'Gzip disabled. Your .htaccess file has been updated', 'wphb' ), 'error', true );
17
+ }
18
+
19
+ parent::render_header(); // TODO: Change the autogenerated stub
20
+ }
21
+
22
+ public function register_meta_boxes() {
23
+ $redirect = false;
24
+ $enabled = false;
25
+ $disabled = false;
26
+
27
+ if ( isset( $_GET['enable'] ) && current_user_can( wphb_get_admin_capability() ) ) {
28
+ // Enable caching in htaccess (only for apache servers)
29
+ $result = wphb_save_htaccess( 'gzip' );
30
+ if ( $result ) {
31
+ $redirect = true;
32
+ $enabled = true;
33
+ }
34
+ else {
35
+ $redirect_to = remove_query_arg( array( 'run', 'enable', 'disable' ) );
36
+ $redirect_to = add_query_arg( 'htaccess-error', true, $redirect_to );
37
+ wp_redirect( $redirect_to );
38
+ exit;
39
+ }
40
+ }
41
+
42
+ if ( isset( $_GET['disable'] ) && current_user_can( wphb_get_admin_capability() ) ) {
43
+ // Disable caching in htaccess (only for apache servers)
44
+ $result = wphb_unsave_htaccess( 'gzip' );
45
+ if ( $result ) {
46
+ $redirect = true;
47
+ $disabled = true;
48
+ }
49
+ else {
50
+ $redirect_to = remove_query_arg( array( 'run', 'enable', 'disable' ) );
51
+ $redirect_to = add_query_arg( 'htaccess-error', true, $redirect_to );
52
+ wp_redirect( $redirect_to );
53
+ exit;
54
+ }
55
+ }
56
+
57
+ if ( isset( $_GET['run'] ) && current_user_can( wphb_get_admin_capability() ) ) {
58
+ // Force a refresh of the data
59
+ wphb_get_gzip_status( true );
60
+ $redirect = true;
61
+ }
62
+
63
+ if ( $redirect ) {
64
+ $redirect_to = remove_query_arg( array( 'run', 'enable', 'disable', 'htaccess-error', 'gzip-enabled', 'gzip-disabled' ) );
65
+ if ( $enabled ) {
66
+ $redirect_to = add_query_arg( 'gzip-enabled', true, $redirect_to );
67
+ }
68
+ elseif ( $disabled ) {
69
+ $redirect_to = add_query_arg( 'gzip-disabled', true, $redirect_to );
70
+ }
71
+ wp_redirect( $redirect_to );
72
+ exit;
73
+ }
74
+
75
+ $show_enable_button = ! $this->_gzip_already_activated_in_server();
76
+ $footer_class = ! $show_enable_button ? '' : 'box-footer buttons buttons-on-left';
77
+ $this->add_meta_box( 'gzip-summary', __( 'Summary', 'wphb' ), array( $this, 'gzip_summary_metabox' ), array( $this, 'gzip_summary_metabox_header' ), null, 'box-gzip-left' );
78
+ $this->add_meta_box( 'gzip-enable', __( 'Enable GZIP', 'wphb' ), array( $this, 'gzip_enable_metabox' ), array( $this, 'gzip_enable_metabox_header' ), array( $this, 'gzip_enable_metabox_footer' ) , 'box-gzip-right', array( 'box_footer_class' => $footer_class) );
79
+ }
80
+
81
+
82
+ protected function render_inner_content() {
83
+ $server_name = wphb_get_server_type();
84
+ $server_type = array_search( $server_name, wphb_get_servers() );
85
+ $this->view( $this->slug . '-page', array( 'server_type' => $server_type, 'server_name' => $server_name ) );
86
+ }
87
+
88
+
89
+ public function gzip_summary_metabox() {
90
+ $status = wphb_get_gzip_status();
91
+ if ( false === $status ) {
92
+ // Force only when we don't have any data yet
93
+ $status = wphb_get_gzip_status( true );
94
+ }
95
+
96
+ $htaccess_written = wphb_is_htaccess_written( 'gzip' );
97
+ $external_problem = false;
98
+ if ( $htaccess_written ) {
99
+ if ( ! is_array( $status ) || ( is_array( $status ) && array_sum( $status ) != 3 ) ) {
100
+ // There must be another plugin/server config that is setting its own gzip stuff
101
+ $external_problem = true;
102
+ }
103
+ }
104
+
105
+
106
+ $this->view( 'gzip/summary-meta-box', array( 'status' => $status, 'external_problem' => $external_problem ) );
107
+ }
108
+
109
+ public function gzip_summary_metabox_header() {
110
+ $recheck_url = add_query_arg( 'run', 'true' );
111
+ $recheck_url = remove_query_arg( 'htaccess-error', $recheck_url );
112
+ $this->view( 'gzip/summary-meta-box-header', array( 'recheck_url' => $recheck_url, 'title' => __( 'Summary', 'wphb' ) ) );
113
+ }
114
+
115
+ public function gzip_enable_metabox() {
116
+ $snippets = array(
117
+ 'apache' => wphb_get_code_snippet( 'gzip', 'apache' ),
118
+ 'litespeed' => wphb_get_code_snippet( 'gzip', 'LiteSpeed' ),
119
+ 'nginx' => wphb_get_code_snippet( 'gzip', 'nginx' ),
120
+ 'iis' => wphb_get_code_snippet( 'gzip', 'iis' ),
121
+ 'iis-7' => wphb_get_code_snippet( 'gzip', 'iis-7' ),
122
+ );
123
+
124
+ $htaccess_written = wphb_is_htaccess_written( 'gzip' );
125
+ $htaccess_writable = wphb_is_htaccess_writable();
126
+
127
+ $gzip_already_active = $this->_gzip_already_activated_in_server();
128
+
129
+ $status = wphb_get_gzip_status();
130
+ $full_enabled = array_sum( $status ) === 3;
131
+
132
+ $server = wphb_get_server_type();
133
+
134
+ if ( $full_enabled ) {
135
+ $this->view( 'gzip/enabled-meta-box' );
136
+ }
137
+ else {
138
+ $this->view( 'gzip/enable-meta-box',
139
+ array(
140
+ 'snippets' => $snippets,
141
+ 'htaccess_written' => $htaccess_written,
142
+ 'htaccess_writable' => $htaccess_writable,
143
+ 'gzip_already_active' => $gzip_already_active
144
+ )
145
+ );
146
+ }
147
+
148
+
149
+ }
150
+
151
+ public function gzip_enable_metabox_header() {
152
+ $status = wphb_get_gzip_status();
153
+ $full_enabled = array_sum( $status ) === 3;
154
+ $this->view( 'gzip/code-snippet-meta-box-header', array( 'gzip_server_type' => wphb_get_server_type(), 'title' => __( 'Enable GZIP', 'wphb' ), 'full_enabled' => $full_enabled ) );
155
+ }
156
+
157
+ /**
158
+ * Check if Gzip has been already activated in server by user, not by Hummingbird
159
+ *
160
+ * @return bool
161
+ */
162
+ private function _gzip_already_activated_in_server() {
163
+ $status = wphb_get_gzip_status();
164
+ if ( ! is_array( $status ) ) {
165
+ $status = array();
166
+ }
167
+
168
+ $all_types_compressed = array_sum( $status ) === 3;
169
+ $htaccess_written_by_hummingbird = wphb_is_htaccess_written( 'gzip' );
170
+
171
+ $result = false;
172
+ if ( $all_types_compressed && ! $htaccess_written_by_hummingbird ) {
173
+ // Server had already gzip activated, Hummingbird did nothing
174
+ $result = true;
175
+ }
176
+
177
+ return $result;
178
+ }
179
+
180
+ public function gzip_enable_metabox_footer() {
181
+ $show_enable_button = ! $this->_gzip_already_activated_in_server();
182
+ $enable_link = add_query_arg( array( 'run' => 'true', 'enable' => 'true' ) );
183
+ $disable_link = add_query_arg( array( 'run' => 'true', 'disable' => 'true' ) );
184
+ $this->view( 'gzip/enable-meta-box-footer', array( 'server_type' => wphb_get_server_type(), 'enable_link' => $enable_link, 'disable_link' => $disable_link, 'show_enable_button' => $show_enable_button ) );
185
+ }
186
+
187
+
188
+ }
admin/class-minification-page.php ADDED
@@ -0,0 +1,500 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class WP_Hummingbird_Minification_Page
5
+ */
6
+ class WP_Hummingbird_Minification_Page extends WP_Hummingbird_Admin_Page {
7
+
8
+ /**
9
+ * WP_Hummingbird_Minification_Page constructor.
10
+ * @param $slug
11
+ * @param $page_title
12
+ * @param $menu_title
13
+ * @param bool $parent
14
+ * @param bool $render
15
+ */
16
+ public function __construct( $slug, $page_title, $menu_title, $parent = false, $render = true ) {
17
+ parent::__construct( $slug, $page_title, $menu_title, $parent, $render );
18
+
19
+ $this->tabs = array(
20
+ 'files' => __( 'Files', 'wphb' ),
21
+ );
22
+
23
+ if ( ! is_multisite() ) {
24
+ $this->tabs['settings'] = __( 'Settings', 'wphb' );
25
+ }
26
+
27
+ add_filter( 'wphb_admin_after_tab_' . $this->get_slug(), array( $this, 'after_tab' ) );
28
+ }
29
+
30
+ public function on_load() {
31
+
32
+ wphb_minification_maybe_stop_checking_files();
33
+ if ( isset( $_POST['submit'] ) ) {
34
+ check_admin_referer( 'wphb-enqueued-files' );
35
+
36
+ $options = wphb_get_settings();
37
+
38
+ $options = $this->_sanitize_type( 'styles', $options );
39
+ $options = $this->_sanitize_type( 'scripts', $options );
40
+
41
+ wphb_update_settings( $options );
42
+
43
+ wp_redirect( add_query_arg( 'updated', 'true' ) );
44
+ exit;
45
+ }
46
+
47
+ if ( isset( $_POST['clear-cache'] ) ) {
48
+ wphb_clear_minification_cache( false );
49
+ $url = remove_query_arg( 'updated' );
50
+ wp_redirect( add_query_arg( 'wphb-cache-cleared', 'true', $url ) );
51
+ exit;
52
+ }
53
+
54
+ // If selected to enable CDN from minification scan.
55
+ if ( isset( $_POST['enable_cdn'] ) ) {
56
+ $value = wp_validate_boolean( $_POST['enable_cdn'] );
57
+ wphb_toggle_cdn( $value );
58
+ // Redirect back.
59
+ wp_safe_redirect( remove_query_arg( array(
60
+ 'enable_cdn',
61
+ 'wphb-cache-cleared',
62
+ )));
63
+ exit;
64
+ }
65
+
66
+ }
67
+
68
+ private function _sanitize_type( $type, $options ) {
69
+ $current_options = wphb_get_settings();
70
+
71
+ // We'll save what groups have changed so we reset the cache for those groups.
72
+ $changed_groups = array();
73
+
74
+ if ( ! empty( $_POST[ $type ] ) ) {
75
+ foreach ( $_POST[ $type ] as $handle => $item ) {
76
+ $key = array_search( $handle, $options['block'][ $type ] );
77
+
78
+ if ( ! isset( $item['include'] ) ) {
79
+ $options['block'][ $type ][] = $handle;
80
+ }
81
+ elseif ( $key !== false ) {
82
+ unset( $options['block'][ $type ][ $key ] );
83
+ }
84
+ $options['block'][ $type ] = array_unique( $options['block'][ $type ] );
85
+ $diff = array_merge(
86
+ array_diff( $current_options['block'][ $type ], $options['block'][ $type ] ),
87
+ array_diff( $options['block'][ $type ], $current_options['block'][ $type ] )
88
+ );
89
+ if ( $diff ) {
90
+ foreach ( $diff as $diff_handle ) {
91
+ $_groups = WP_Hummingbird_Module_Minify_Group::get_groups_from_handle( $diff_handle, $type );
92
+ if ( $_groups ) {
93
+ $changed_groups = array_merge( $changed_groups, $_groups );
94
+ }
95
+ }
96
+ }
97
+
98
+ $key = array_search( $handle, $options['dont_minify'][ $type ] );
99
+ if ( ! isset( $item['minify'] ) ) {
100
+ $options['dont_minify'][ $type ][] = $handle;
101
+ }
102
+ elseif ( $key !== false ) {
103
+ unset( $options['dont_minify'][ $type ][ $key ] );
104
+ }
105
+ $options['dont_minify'][ $type ] = array_unique( $options['dont_minify'][ $type ] );
106
+ $diff = array_merge(
107
+ array_diff( $current_options['dont_minify'][ $type ], $options['dont_minify'][ $type ] ),
108
+ array_diff( $options['dont_minify'][ $type ], $current_options['dont_minify'][ $type ] )
109
+ );
110
+ if ( $diff ) {
111
+ foreach ( $diff as $diff_handle ) {
112
+ $_groups = WP_Hummingbird_Module_Minify_Group::get_groups_from_handle( $diff_handle, $type );
113
+ if ( $_groups ) {
114
+ $changed_groups = array_merge( $changed_groups, $_groups );
115
+ }
116
+ }
117
+ }
118
+
119
+ $key = array_search( $handle, $options['combine'][ $type ] );
120
+ if ( ! isset( $item['combine'] ) && false !== $key ) {
121
+ unset( $options['combine'][ $type ][ $key ] );
122
+ }
123
+ elseif ( isset( $item['combine'] ) ) {
124
+ $options['combine'][ $type ][] = $handle;
125
+ }
126
+ $options['combine'][ $type ] = array_unique( $options['combine'][ $type ] );
127
+ $diff = array_merge(
128
+ array_diff( $current_options['combine'][ $type ], $options['combine'][ $type ] ),
129
+ array_diff( $options['combine'][ $type ], $current_options['combine'][ $type ] )
130
+ );
131
+
132
+ if ( $diff ) {
133
+ foreach ( $diff as $diff_handle ) {
134
+ $_groups = WP_Hummingbird_Module_Minify_Group::get_groups_from_handle( $diff_handle, $type );
135
+ if ( $_groups ) {
136
+ $changed_groups = array_merge( $changed_groups, $_groups );
137
+ }
138
+ }
139
+ }
140
+
141
+ if ( empty( $item['position'] ) ) {
142
+ $item['position'] = 'header';
143
+ }
144
+ $key_exists = array_key_exists( $handle, $options['position'][ $type ] );
145
+ if ( 'footer' === $item['position'] ) {
146
+ $options['position'][ $type ][ $handle ] = $item['position'];
147
+ }
148
+ elseif ( $key_exists ) {
149
+ unset( $options['position'][ $type ][ $handle ] );
150
+ }
151
+ if ( $diff = array_diff_key( $current_options['position'][ $type ], $options['position'][ $type ] ) ) {
152
+ foreach ( $diff as $diff_handle ) {
153
+ $_groups = WP_Hummingbird_Module_Minify_Group::get_groups_from_handle( $diff_handle, $type );
154
+ if ( $_groups ) {
155
+ $changed_groups = array_merge( $changed_groups, $_groups );
156
+ }
157
+ }
158
+ }
159
+ $diff = array_merge(
160
+ array_diff_key( $current_options['position'][ $type ], $options['position'][ $type ] ),
161
+ array_diff_key( $options['position'][ $type ], $current_options['position'][ $type ] )
162
+ );
163
+ if ( $diff ) {
164
+ foreach ( $diff as $diff_handle => $position) {
165
+ $_groups = WP_Hummingbird_Module_Minify_Group::get_groups_from_handle( $diff_handle, $type );
166
+ if ( $_groups ) {
167
+ $changed_groups = array_merge( $changed_groups, $_groups );
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+
174
+ // Delete those groups
175
+ foreach ( $changed_groups as $group ) {
176
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
177
+ $group->delete_file();
178
+ }
179
+
180
+
181
+ return $options;
182
+ }
183
+
184
+ /**
185
+ * Render the page
186
+ */
187
+ public function render() {
188
+ ?>
189
+
190
+ <div id="container" class="wrap wrap-wp-hummingbird wrap-wp-hummingbird-page <?php echo 'wrap-' . $this->slug; ?>">
191
+ <?php
192
+ if ( isset( $_GET['updated'] ) ) {
193
+ $this->show_notice( 'updated', __( 'Your new minify settings have been saved. Simply refresh your homepage and Hummingbird will minify and serve your newly compressed files.', 'wphb' ), 'success', false );
194
+ }
195
+
196
+ if ( isset( $_GET['wphb-cache-cleared'] ) ) {
197
+ $this->show_notice( 'updated', __( 'Your cache has been successfully cleared. Your assets will regenerate the next time someone visits your website.', 'wphb' ), 'success', true );
198
+ }
199
+
200
+ if ( isset( $_GET['wphb-cache-cleared-with-cloudflare'] ) ) {
201
+ $this->show_notice( 'updated', __( 'Your local and CloudFlare caches have been successfully cleared. Your assets will regenerate the next time someone visits your website.', 'wphb' ), 'success', true );
202
+ }
203
+ ?>
204
+ <div class="wphb-notice wphb-notice-success hidden" id="wphb-notice-minification-advanced-settings-updated">
205
+ <p><?php _e( 'Settings updated', 'wphb' ); ?></p>
206
+ </div>
207
+
208
+ <?php
209
+ $this->render_header();
210
+
211
+ $this->render_inner_content();
212
+ ?>
213
+
214
+ </div><!-- end container -->
215
+
216
+ <script>
217
+ jQuery(document).ready( function() {
218
+ WPHB_Admin.getModule( 'notices' );
219
+ });
220
+
221
+ // Avoid moving dashboard notice under h2
222
+ var wpmuDash = document.getElementById( 'wpmu-install-dashboard' );
223
+ if ( wpmuDash )
224
+ wpmuDash.className = wpmuDash.className + " inline";
225
+
226
+ jQuery( 'div.updated, div.error' ).addClass( 'inline' );
227
+ </script>
228
+ <?php
229
+ }
230
+
231
+ public function render_header() {
232
+ ?>
233
+ <section id="header">
234
+ <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
235
+ <?php
236
+ $collection = wphb_minification_get_resources_collection();
237
+ $module = wphb_get_module( 'minify' );
238
+ if ( ( ! empty( $collection['styles'] ) && ! empty( $collection['scripts'] ) ) && $module->is_active() ) : ?>
239
+ <div class="actions status">
240
+ <div class="toggle-group toggle-group-with-buttons">
241
+ <div class="tooltip-box">
242
+ <span class="toggle" tooltip="<?php _e( 'Disable Minification', 'wphb' ); ?>">
243
+ <input type="checkbox" id="wphb-disable-minification" class="toggle-checkbox" name="wphb-disable-minification" checked>
244
+ <label for="wphb-disable-minification" class="toggle-label"></label>
245
+ </span>
246
+ </div>
247
+ </div>
248
+ <span class="spinner right"></span>
249
+ </div>
250
+ <?php endif; ?>
251
+ </section>
252
+
253
+ <?php
254
+ //parent::render_header(); // TODO: Change the autogenerated stub
255
+ }
256
+
257
+ /**
258
+ * Overriden from parent class
259
+ */
260
+ protected function render_inner_content() {
261
+ $collection = wphb_minification_get_resources_collection();
262
+ $args = array(
263
+ 'instructions' => empty( $collection['styles'] ) && empty( $collection['scripts'] )
264
+ );
265
+
266
+ $this->view( $this->slug . '-page', $args );
267
+ }
268
+
269
+ public function register_meta_boxes() {
270
+ $collection = wphb_minification_get_resources_collection();
271
+ $module = wphb_get_module( 'minify' );
272
+
273
+ if ( ( empty( $collection['styles'] ) && empty( $collection['scripts'] ) ) || wphb_minification_is_checking_files() || ! $module->is_active() ) {
274
+ $this->add_meta_box( 'minification/enqueued-files-empty', __( 'Get Started', 'wphb' ), array( $this, 'enqueued_files_empty_metabox' ), null, null, 'box-enqueued-files-empty', array( 'box_class' => 'dev-box content-box content-box-one-col-center') );
275
+ }
276
+ else {
277
+ $this->add_meta_box( 'minification/summary-meta-box', null, array( $this, 'summary_metabox' ), null, null, 'summary', array( 'box_class' => 'dev-box content-box content-box-two-cols-image-left' ) );
278
+
279
+ $this->add_meta_box( 'minification/enqueued-files', __( 'Files', 'wphb' ), array( $this, 'enqueued_files_metabox' ), null, null, 'main', array( 'box_content_class' => 'box-content', 'box_footer_class' => 'box-footer') );
280
+
281
+ if ( ! is_multisite() ) {
282
+ $this->add_meta_box( 'minification/advanced-settings', __( 'Advanced Settings', 'wphb' ), array( $this, 'advanced_settings_metabox' ), array( $this, 'advanced_settings_metabox_header' ), null, 'settings', array( 'box_content_class' => 'box-content', 'box_footer_class' => 'box-footer') );
283
+ }
284
+ }
285
+ }
286
+
287
+ public function enqueued_files_empty_metabox() {
288
+ // Get current user name
289
+ $user = wphb_get_current_user_info();
290
+ $checking_files = wphb_minification_is_checking_files();
291
+ $this->view( 'minification/enqueued-files-empty-meta-box', array( 'user' => $user, 'checking_files' => $checking_files ) );
292
+ }
293
+
294
+
295
+ public function enqueued_files_metabox() {
296
+ $collection = wphb_minification_get_resources_collection();
297
+ $styles_rows = $this->_collection_rows( $collection['styles'], 'styles' );
298
+ $scripts_rows = $this->_collection_rows( $collection['scripts'], 'scripts' );
299
+
300
+ $active_plugins = get_option('active_plugins', array() );
301
+ if ( is_multisite() ) {
302
+ foreach ( get_site_option('active_sitewide_plugins', array() ) as $plugin => $item ) {
303
+ $active_plugins[] = $plugin;
304
+ }
305
+ }
306
+ $theme = wp_get_theme();
307
+
308
+ $selector_filter = array();
309
+ $selector_filter[ $theme->Name ] = $theme->Name;
310
+ foreach ( $active_plugins as $plugin ) {
311
+ if ( ! is_file( WP_PLUGIN_DIR . '/' . $plugin ) ) {
312
+ continue;
313
+ }
314
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
315
+ if ( $plugin_data['Name'] ) {
316
+ // Found plugin, add it as a filter
317
+ $selector_filter[ $plugin_data['Name'] ] = $plugin_data['Name'];
318
+ }
319
+ }
320
+
321
+ /** @var WP_Hummingbird_Module_Minify $module */
322
+ $module = wphb_get_module( 'minify' );
323
+ $is_server_error = $module->errors_controller->is_server_error();
324
+ $server_errors = $module->errors_controller->get_server_errors();
325
+ $error_time_left = $module->errors_controller->server_error_time_left();
326
+
327
+ if ( isset( $_GET['view-export-form'] ) ) {
328
+ $this->view( 'minification/export-form' );
329
+ }
330
+
331
+ $args = compact( 'collection', 'styles_rows', 'scripts_rows', 'selector_filter', 'is_server_error', 'server_errors', 'error_time_left' );
332
+ $this->view( 'minification/enqueued-files-meta-box', $args );
333
+ }
334
+
335
+
336
+ private function _collection_rows( $collection, $type ) {
337
+ $options = wphb_get_settings();
338
+
339
+ // This will be used for filtering
340
+ $theme = wp_get_theme();
341
+ $active_plugins = get_option('active_plugins', array() );
342
+ if ( is_multisite() ) {
343
+ foreach ( get_site_option('active_sitewide_plugins', array() ) as $plugin => $item ) {
344
+ $active_plugins[] = $plugin;
345
+ }
346
+ }
347
+
348
+ /**
349
+ * @var WP_Hummingbird_Module_Minify $minification_module
350
+ */
351
+ $minification_module = wphb_get_module( 'minify' );
352
+
353
+ $content = '';
354
+
355
+ foreach ( $collection as $item ) {
356
+ /**
357
+ * Filter minification enqueued files items displaying
358
+ *
359
+ * @param bool $display If set to true, display the item. Default false
360
+ * @param array $item Item data
361
+ * @param string $type Type of the current item (scripts|styles)
362
+ */
363
+ if ( ! apply_filters( 'wphb_minification_display_enqueued_file', true, $item, $type ) ) {
364
+ continue;
365
+ }
366
+
367
+ if ( ! empty( $options['position'][ $type ][ $item['handle'] ] ) && in_array( $options['position'][ $type ][ $item['handle'] ], array( 'header', 'footer' ) ) ) {
368
+ $position = $options['position'][ $type ][ $item['handle'] ];
369
+ }
370
+ else {
371
+ $position = '';
372
+ }
373
+
374
+ $original_size = false;
375
+ $compressed_size = false;
376
+
377
+ $base_name = $type . '[' . $item['handle'] . ']';
378
+
379
+ if ( isset ( $item['original_size'] ) )
380
+ $original_size = $item['original_size'];
381
+
382
+ if ( isset( $item['compressed_size'] ) )
383
+ $compressed_size = $item['compressed_size'];
384
+
385
+ $site_url = str_replace( array( 'http://', 'https://' ), '', get_option('siteurl') );
386
+ $rel_src = str_replace( array( 'http://', 'https://', $site_url ), '', $item['src'] );
387
+ $rel_src = ltrim( $rel_src, '/' );
388
+ $full_src = $item['src'];
389
+
390
+ $info = pathinfo( $full_src );
391
+ $ext = isset( $info['extension'] ) ? strtoupper( $info['extension'] ) : __( 'OTHER', 'wphb' );
392
+ if ( ! in_array( $ext, array( __( 'OTHER', 'wphb' ), 'CSS', 'JS' ) ) ) {
393
+ $ext = __( 'OTHER', 'wphb' );
394
+ }
395
+ $row_error = $minification_module->errors_controller->get_handle_error( $item['handle'], $type );
396
+ $disable_switchers = array();
397
+ if ( $row_error ) {
398
+ $disable_switchers = $row_error['disable'];
399
+ }
400
+
401
+ $filter = '';
402
+ if ( preg_match( '/wp-content\/themes\/(.*)\//', $full_src, $matches ) ) {
403
+ $filter = $theme->Name;
404
+ }
405
+ elseif ( preg_match( '/wp-content\/plugins\/([\w-_]*)\//', $full_src, $matches ) ) {
406
+ // The source comes from a plugin
407
+ foreach ( $active_plugins as $active_plugin ) {
408
+ if ( stristr( $active_plugin, $matches[1] ) ) {
409
+ // It seems that we found the plguin but let's double check
410
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $active_plugin );
411
+ if ( $plugin_data['Name'] ) {
412
+ // Found plugin, add it as a filter
413
+ $filter = $plugin_data['Name'];
414
+ }
415
+ break;
416
+ }
417
+
418
+ }
419
+ }
420
+
421
+ /**
422
+ * Allows to enable/disable switchers in minification page
423
+ *
424
+ * @param array $disable_switchers List of switchers disabled for an item ( include, minify, combine)
425
+ * @param array $item Info about the current item
426
+ * @param string $type Type of the current item (scripts|styles)
427
+ */
428
+ $disable_switchers = apply_filters( 'wphb_minification_disable_switchers', $disable_switchers, $item, $type );
429
+
430
+ $args = compact( 'item', 'options', 'type', 'position', 'base_name', 'original_size', 'compressed_size', 'rel_src', 'full_src', 'ext', 'row_error', 'disable_switchers', 'filter' );
431
+ $content .= $this->view( 'minification/enqueued-files-rows', $args, false );
432
+ }
433
+
434
+ return $content;
435
+ }
436
+
437
+ function advanced_settings_metabox() {
438
+ $args = array(
439
+ 'use_cdn' => wphb_get_cdn_status(),
440
+ 'disabled' => ! wphb_is_member(),
441
+ 'super_minify' => wphb_is_member(),
442
+ );
443
+ $this->view( 'minification/advanced-settings', $args );
444
+ }
445
+
446
+ function advanced_settings_metabox_header() {
447
+ $args = array(
448
+ 'is_member' => wphb_is_member(),
449
+ 'title' => __( 'Advanced Settings', 'wphb' )
450
+ );
451
+ $this->view( 'minification/advanced-settings-header', $args );
452
+ }
453
+
454
+ function summary_metabox() {
455
+ $collection = wphb_minification_get_resources_collection();
456
+ // Remove those assets that we don't want to display
457
+ foreach ( $collection['styles'] as $key => $item ) {
458
+ if ( ! apply_filters( 'wphb_minification_display_enqueued_file', true, $item, 'styles' ) ) {
459
+ unset( $collection['styles'][ $key ] );
460
+ }
461
+ }
462
+ foreach ( $collection['scripts'] as $key => $item ) {
463
+ if ( ! apply_filters( 'wphb_minification_display_enqueued_file', true, $item, 'scripts' ) ) {
464
+ unset( $collection['scripts'][ $key ] );
465
+ }
466
+ }
467
+
468
+ $enqueued_files = count( $collection['scripts'] ) + count( $collection['styles'] );
469
+
470
+ $original_size_styles = array_sum( @wp_list_pluck( $collection['styles'], 'original_size' ) );
471
+ $original_size_scripts = array_sum( @wp_list_pluck( $collection['scripts'], 'original_size' ) );
472
+ $original_size = $original_size_scripts + $original_size_styles;
473
+
474
+ $compressed_size_styles = array_sum( @wp_list_pluck( $collection['styles'], 'compressed_size' ) );
475
+ $compressed_size_scripts = array_sum( @wp_list_pluck( $collection['scripts'], 'compressed_size' ) );
476
+ $compressed_size = $compressed_size_scripts + $compressed_size_styles;
477
+
478
+ if ( $original_size <= 0 ) {
479
+ $percentage = 0;
480
+ }
481
+ else {
482
+ //$percentage = 100 - ( (int) $compressed_size * 100 ) / (int) $original_size;
483
+ $percentage = 100 - (int) $compressed_size * 100 / (int) $original_size;
484
+ }
485
+ $percentage = number_format_i18n( $percentage, 2 );
486
+ $compressed_size = number_format( (int) $original_size - (int) $compressed_size, 1 );
487
+
488
+ $use_cdn = wphb_get_cdn_status();
489
+ $is_member = wphb_is_member();
490
+
491
+ $args = compact( 'enqueued_files', 'compressed_size', 'percentage', 'use_cdn', 'is_member' );
492
+ $this->view( 'minification/summary-meta-box', $args );
493
+ }
494
+
495
+ public function after_tab( $tab ) {
496
+ if ( 'files' === $tab ) {
497
+ echo ' <span class="wphb-button-label wphb-button-label-light">' . wphb_minification_files_count() . '</span>';
498
+ }
499
+ }
500
+ }
admin/class-performance-page.php ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Performance_Report_Page extends WP_Hummingbird_Admin_Page {
4
+
5
+ /**
6
+ * Status of error. If true, than we have some error.
7
+ *
8
+ * @var bool $has_error True if error present.
9
+ */
10
+ public $has_error;
11
+
12
+ /**
13
+ * WP_Hummingbird_Performance_Report_Page constructor.
14
+ *
15
+ * @param $slug
16
+ * @param $page_title
17
+ * @param $menu_title
18
+ * @param bool $parent
19
+ * @param bool $render
20
+ */
21
+ public function __construct( $slug, $page_title, $menu_title, $parent = false, $render = true ) {
22
+ parent::__construct( $slug, $page_title, $menu_title, $parent, $render );
23
+
24
+ $this->tabs = array(
25
+ 'main' => __( 'Improvements', 'wphb' )
26
+ );
27
+
28
+ // We need to actually tweak these tasks
29
+ add_filter( 'wphb_admin_after_tab_' . $this->get_slug(), array( $this, 'after_tab' ) );
30
+
31
+ //$this->recommendations = wphb_get_number_of_issues( 'performance' );
32
+ //$this->get_error_status();
33
+ }
34
+
35
+ public function render_header() {
36
+ $this->get_error_status();
37
+
38
+ $last_report = wphb_performance_get_last_report();
39
+ $run_url = add_query_arg( 'run', 'true', wphb_get_admin_menu_url( 'performance' ) );
40
+ $run_url = wp_nonce_url( $run_url, 'wphb-run-performance-test' );
41
+ $next_test_on = WP_Hummingbird_Module_Performance::can_run_test();
42
+ ?>
43
+ <div class="wphb-notice wphb-notice-success hidden" id="wphb-notice-performance-report-settings-updated">
44
+ <p><?php _e( 'Settings updated', 'wphb' ); ?></p>
45
+ </div>
46
+ <section id="header">
47
+ <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
48
+ <div class="actions label-and-button">
49
+ <?php if ( $last_report && ! is_wp_error( $last_report ) ): ?>
50
+ <?php
51
+ $data_time = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $last_report->data->time ) ) );
52
+ $disabled = true !== $next_test_on;
53
+ ?>
54
+ <p class="actions-label">
55
+ <?php printf( __('Your last performance test was on <strong>%s</strong> at <strong>%s</strong>', 'wphb' ), date_i18n( get_option( 'date_format' ), $data_time ), date_i18n( get_option( 'time_format' ), $data_time ) ); ?>
56
+ <?php if ( $disabled ): ?>
57
+ <br/><?php printf( __( 'Hummingbird is just catching her breath. <strong>Run again in %d minutes</strong>', 'wphb' ), $next_test_on ) ;?>
58
+ <?php endif; ?>
59
+ </p>
60
+ <?php if ( ! $disabled ): ?>
61
+ <a href="<?php echo esc_url( $run_url ); ?>" <?php disabled( $disabled ); ?> class="button"><?php _e( 'Run Test', 'wphb' ); ?></a>
62
+ <?php endif; ?>
63
+ <?php endif; ?>
64
+ </div>
65
+ </section><!-- end header -->
66
+
67
+ <?php
68
+ }
69
+
70
+ public function register_meta_boxes() {
71
+
72
+ if ( isset( $_GET['run'] ) ) {
73
+ check_admin_referer( 'wphb-run-performance-test' );
74
+
75
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
76
+ return;
77
+
78
+ // Start the test
79
+ wphb_performance_clear_cache();
80
+ wphb_performance_init_scan();
81
+
82
+ // This will trigger the popup
83
+ wphb_performance_set_doing_report( true );
84
+
85
+ wp_redirect( remove_query_arg( array( 'run', '_wpnonce' ) ) );
86
+ exit;
87
+ }
88
+
89
+ $last_test = wphb_performance_get_last_report();
90
+
91
+ if ( ! $last_test ) {
92
+ $this->add_meta_box( 'performance-summary', __( 'Summary', 'wphb' ), array( $this, 'performance_summary_metabox' ), array( $this, 'performance_summary_metabox_header' ), null, 'main', array( 'box_class' => 'dev-box content-box-one-col-center' ) );
93
+ }
94
+ elseif ( is_wp_error( $last_test ) ) {
95
+ $this->add_meta_box( 'performance-summary', __( 'Summary', 'wphb' ), array( $this, 'performance_summary_metabox' ), array( $this, 'performance_summary_metabox_header' ), null, 'main', array( 'box_class' => 'dev-box content-box-one-col-center', 'box_content_class' => 'box-content no-side-padding' ) );
96
+ }
97
+ else {
98
+ $this->add_meta_box( 'performance-welcome', null , array( $this, 'performance_welcome_metabox' ), null, null, 'summary', array( 'box_class' => 'dev-box content-box content-box-two-cols-image-left' ) );
99
+ $this->add_meta_box( 'performance-summary', __( 'Improvements', 'wphb' ), array( $this, 'performance_summary_metabox' ), array( $this, 'performance_summary_metabox_header' ), null, 'main', array( 'box_class' => 'dev-box content-box-one-col-center', 'box_content_class' => 'box-content no-side-padding' ) );
100
+ }
101
+
102
+ }
103
+
104
+ public function performance_summary_metabox() {
105
+ $last_test = wphb_performance_get_last_report();
106
+ $doing_report = wphb_performance_is_doing_report();
107
+
108
+ $error_details = '';
109
+ $error_text = '';
110
+ if ( $last_test ) {
111
+ if ( is_wp_error( $last_test ) ) {
112
+ $error_text = $last_test->get_error_message();
113
+ $error_details = $last_test->get_error_data();
114
+ if ( is_array( $error_details ) && isset( $error_details['details'] ) ) {
115
+ $error_details = $error_details['details'];
116
+ }
117
+ else {
118
+ $error_details = '';
119
+ }
120
+
121
+ $this->has_error = true;
122
+ }
123
+ else {
124
+ $last_test = $last_test->data;
125
+ /*$this->has_error = false;*/
126
+ }
127
+
128
+ $retry_url = add_query_arg( 'run', 'true', wphb_get_admin_menu_url( 'performance' ) );
129
+ $retry_url = wp_nonce_url( $retry_url, 'wphb-run-performance-test' );
130
+
131
+ $this->view( 'performance/summary-meta-box', array( 'last_test' => $last_test, 'error' => $this->has_error, 'error_details' => $error_details, 'error_text' => $error_text, 'retry_url' => $retry_url ) );
132
+ } else {
133
+ $this->view( 'performance/empty-summary-meta-box', array( 'doing_report' => $doing_report ) );
134
+ }
135
+
136
+ }
137
+
138
+ public function performance_welcome_metabox() {
139
+ $last_report = wphb_performance_get_last_report();
140
+ $last_report = $last_report->data;
141
+
142
+ $improvement = 0;
143
+ $last_score = false;
144
+ if ( $last_report->last_score ) {
145
+ $improvement = $last_report->score - $last_report->last_score['score'];
146
+ $last_score = $last_report->last_score['score'];
147
+ }
148
+
149
+ $this->view( 'performance/module-resume-meta-box', array( 'last_report' => $last_report, 'improvement' => $improvement, 'last_score' => $last_score, 'recommendations' => wphb_get_number_of_issues( 'performance' ) ) );
150
+ }
151
+
152
+ public function performance_summary_metabox_header() {
153
+ $title = __( 'Improvements', 'wphb' );
154
+ $last_report = wphb_performance_get_last_report();
155
+ if ( $last_report && ! is_wp_error( $last_report ) ) {
156
+ $last_report = $last_report->data;
157
+ }
158
+ $this->view( 'performance/summary-meta-box-header', array( 'title' => $title, 'last_report' => $last_report ) );
159
+ }
160
+
161
+ /**
162
+ * See if there are any errors. Set the variable to true if some errors are found.
163
+ *
164
+ * @since 1.4.5
165
+ */
166
+ private function get_error_status() {
167
+ $this->has_error = false;
168
+ $last_test = wphb_performance_get_last_report();
169
+ if ( is_wp_error( $last_test ) ) {
170
+ $this->has_error = true;
171
+ }
172
+ }
173
+
174
+
175
+ /**
176
+ * We need to insert an extra label to the tabs sometimes
177
+ */
178
+ public function after_tab( $tab ) {
179
+ if ( 'main' !== $tab ) {
180
+ return;
181
+ }
182
+
183
+ $last_test = wphb_performance_get_last_report();
184
+ if ( ! $last_test ) {
185
+ return;
186
+ }
187
+
188
+ $class = '';
189
+ if ( isset( $last_test->data ) ) {
190
+ switch ( $last_test->data->score_class ) {
191
+ case 'aplus':
192
+ case 'a':
193
+ case 'b':
194
+ $class = 'green';
195
+ break;
196
+ case 'c':
197
+ case 'd':
198
+ $class = 'yellow';
199
+ break;
200
+ case 'e':
201
+ case 'f':
202
+ $class = 'red';
203
+ break;
204
+ }
205
+ }
206
+ if ( ! $this->has_error ) {
207
+ echo ' <span class="hide-on-mobile wphb-button-label wphb-button-label-' . $class . '">' . wphb_get_number_of_issues( 'performance' ) . '</span>';
208
+ }
209
+ else {
210
+ echo ' <i class="hide-on-mobile hb-wpmudev-icon-warning"></i>';
211
+ }
212
+ }
213
+
214
+ }
admin/class-uptime-page.php ADDED
@@ -0,0 +1,315 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Uptime_Page extends WP_Hummingbird_Admin_Page {
4
+
5
+ private $current_report;
6
+
7
+ public function render_header()
8
+ {
9
+
10
+ $data_ranges = $this->get_data_ranges();
11
+ $data_range_selected = isset( $_GET['data-range'] ) && array_key_exists( $_GET['data-range'], $this->get_data_ranges() ) ? $_GET['data-range'] : 'week';
12
+ ?>
13
+
14
+ <section id="header">
15
+ <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
16
+ <?php
17
+ $module = wphb_get_module( 'uptime' );
18
+ $is_active = $module->is_active();
19
+ if ( wphb_is_member() && $is_active ): ?>
20
+ <div class="actions status">
21
+ <div class="toggle-group toggle-group-with-buttons">
22
+ <div class="tooltip-box">
23
+ <span class="toggle" tooltip="<?php _e( 'Disable Uptime', 'wphb' ); ?>">
24
+ <input type="checkbox" id="wphb-disable-uptime" class="toggle-checkbox" name="wphb-disable-uptime" <?php checked( wphb_get_setting( 'uptime' ) ); ?>>
25
+ <label for="wphb-disable-uptime" class="toggle-label"></label>
26
+ </span>
27
+ </div>
28
+ </div>
29
+ <span class="spinner right"></span>
30
+ </div>
31
+ <div class="actions">
32
+ <span class="spinner left"></span>
33
+ <label for="wphb-uptime-data-range" class="inline-label"><?php _e( 'Reporting period', 'wphb' ); ?></label>
34
+ <select name="wphb-uptime-data-range" id="wphb-uptime-data-range">
35
+ <?php foreach ( $data_ranges as $range => $label ): ?>
36
+ <option
37
+ value="<?php echo esc_attr( $range ); ?>"
38
+ <?php selected( $data_range_selected, $range ); ?>
39
+ data-url="<?php echo esc_url( add_query_arg( 'data-range', $range, wphb_get_admin_menu_url( 'uptime' ) ) ); ?>">
40
+ <?php echo esc_html( $label ); ?>
41
+ </option>
42
+ <?php endforeach; ?>
43
+ </select>
44
+ </div>
45
+ <?php endif; ?>
46
+ </section><!-- end header -->
47
+
48
+ <?php
49
+ //parent::render_header(); // TODO: Change the autogenerated stub
50
+ }
51
+
52
+ public function register_meta_boxes() {
53
+
54
+ // Check if Uptime is active in the server
55
+ if ( wphb_is_uptime_remotely_enabled() ) {
56
+ wphb_uptime_enable_locally();
57
+ }
58
+ else {
59
+ wphb_uptime_disable_locally();
60
+ }
61
+
62
+ $this->run_actions();
63
+
64
+ /** @var WP_Hummingbird_Module_Uptime $module */
65
+ $module = wphb_get_module( 'uptime' );
66
+ $is_active = $module->is_active();
67
+ $uptime_report = wphb_uptime_get_last_report( $this->get_current_data_range() );
68
+
69
+ if ( ! wphb_is_member() ) {
70
+ $this->add_meta_box( 'uptime-no-membership', __( 'Uptime', 'wphb' ), array( $this, 'uptime_membership_metabox' ), null, null, 'main', null );
71
+ }
72
+ elseif ( is_wp_error( $uptime_report ) && $is_active ) {
73
+ $this->add_meta_box( 'uptime', __( 'Uptime', 'wphb' ), array( $this, 'uptime_metabox' ), null, null, 'main', null );
74
+ }
75
+ elseif ( ! $is_active && wphb_is_member() ) {
76
+ $this->add_meta_box( 'uptime-disabled', __( 'Uptime', 'wphb' ), array( $this, 'uptime_disabled_metabox' ), null, null, 'box-uptime-disabled', array( 'box_class' => 'dev-box content-box content-box-one-col-center') );
77
+ }
78
+ else {
79
+ $this->add_meta_box( 'uptime-summary', null, array( $this, 'uptime_summary_metabox' ), null, null, 'summary', array( 'box_class' => 'dev-box content-box content-box-two-cols-image-left' ) );
80
+ $this->add_meta_box( 'uptime-response-time', __( 'Response Time', 'wphb' ), array( $this, 'uptime_metabox' ), array( $this, 'uptime_metabox_header' ), null, 'main', null );
81
+ $this->add_meta_box( 'uptime-downtime', __( 'Downtime', 'wphb' ), array( $this, 'uptime_downtime_metabox' ), null, null, 'main', null );
82
+ }
83
+
84
+ }
85
+
86
+ private function run_actions() {
87
+ $action = isset( $_GET['action'] ) ? $_GET['action'] : false;
88
+
89
+ if ( 'enable' === $action ) {
90
+ check_admin_referer( 'wphb-toggle-uptime' );
91
+
92
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
93
+ return;
94
+
95
+ $result = wphb_uptime_enable();
96
+ if ( is_wp_error( $result ) ) {
97
+ $redirect_to = add_query_arg( 'error', 'true', wphb_get_admin_menu_url( 'uptime' ) );
98
+ $redirect_to = add_query_arg( array(
99
+ 'code' => $result->get_error_code(),
100
+ 'message' => urlencode( $result->get_error_message() )
101
+ ), $redirect_to );
102
+ wp_redirect( $redirect_to );
103
+ exit;
104
+ }
105
+
106
+ $redirect_to = add_query_arg( 'run', 'true', wphb_get_admin_menu_url( 'uptime' ) );
107
+ $redirect_to = add_query_arg( '_wpnonce', wp_create_nonce( 'wphb-run-uptime' ), $redirect_to );
108
+
109
+ wp_redirect( $redirect_to );
110
+ exit;
111
+ }
112
+
113
+ if ( 'disable' === $action ) {
114
+ check_admin_referer( 'wphb-toggle-uptime' );
115
+
116
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
117
+ return;
118
+
119
+ wphb_uptime_disable();
120
+
121
+ wp_redirect( wphb_get_admin_menu_url( 'uptime' ) );
122
+ }
123
+
124
+ if ( isset( $_GET['run'] ) ) {
125
+ check_admin_referer( 'wphb-run-uptime' );
126
+
127
+ if ( ! current_user_can( wphb_get_admin_capability() ) )
128
+ return;
129
+
130
+ // Start the test
131
+ wphb_uptime_clear_cache();
132
+
133
+ // Start the test
134
+ wphb_uptime_get_last_report( 'week', true );
135
+
136
+ wp_redirect( remove_query_arg( array( 'run', '_wpnonce' ) ) );
137
+ exit;
138
+ }
139
+ }
140
+
141
+ public function on_load() {
142
+ if ( isset( $_GET['activate'] ) && current_user_can( wphb_get_admin_capability() ) ) {
143
+ check_admin_referer( 'activate-uptime' );
144
+
145
+ $options = wphb_get_settings();
146
+ $options['uptime'] = true;
147
+ wphb_update_settings( $options );
148
+
149
+ wp_redirect( esc_url( wphb_get_admin_menu_url( 'uptime' ) ) );
150
+ exit;
151
+ }
152
+ }
153
+
154
+ public function enqueue_scripts( $hook ) {
155
+ parent::enqueue_scripts( $hook );
156
+ wp_enqueue_script( 'wphb-google-chart', "https://www.google.com/jsapi?autoload={'modules':[{'name':'visualization','version':'1.1','packages':['corechart']}]}", array( 'jquery' ) );
157
+ }
158
+
159
+ public function uptime_disabled_metabox() {
160
+ // Get current user name
161
+ $user = wphb_get_current_user_info();
162
+ $activate_url = add_query_arg( 'action', 'enable', wphb_get_admin_menu_url( 'uptime' ) );
163
+ $activate_url = wp_nonce_url( $activate_url, 'wphb-toggle-uptime' );
164
+ $this->view( 'uptime/disabled-meta-box', array( 'user' => $user, 'activate_url' => $activate_url ) );
165
+ }
166
+
167
+ private function get_data_ranges() {
168
+ return array(
169
+ 'day' => __( 'Last Day', 'wphb' ),
170
+ 'week' => __( 'Last Week', 'wphb' ),
171
+ 'month' => __( 'Last Month', 'wphb' )
172
+ );
173
+ }
174
+
175
+ private function get_current_data_range() {
176
+ return isset( $_GET['data-range'] ) && array_key_exists( $_GET['data-range'], $this->get_data_ranges() ) ? $_GET['data-range'] : 'week';
177
+ }
178
+
179
+ protected function render_inner_content() {
180
+ $data_ranges = $this->get_data_ranges();
181
+ $data_range = $this->get_current_data_range();
182
+
183
+ $error = false;
184
+
185
+ /** @var WP_Hummingbird_Module_Uptime $module */
186
+ $module = wphb_get_module( 'uptime' );
187
+ $is_active = $module->is_active();
188
+
189
+ if ( $is_active ) {
190
+ $uptime_stats = wphb_uptime_get_last_report( $data_range );
191
+ if ( isset( $uptime_stats->code ) && $is_active ) {
192
+ $error = $uptime_stats->message;
193
+ }
194
+ elseif ( false === $uptime_stats ) {
195
+ $is_active = false;
196
+ }
197
+ }
198
+
199
+ $retry_url = add_query_arg(
200
+ array(
201
+ '_wpnonce' => wp_create_nonce( 'wphb-toggle-uptime' ),
202
+ 'action' => 'enable'
203
+ ),
204
+ wphb_get_admin_menu_url( 'uptime' )
205
+ );
206
+
207
+
208
+ $args = array(
209
+ 'error' => $error,
210
+ 'retry_url' => $retry_url
211
+ );
212
+
213
+ $this->view( $this->slug . '-page', $args );
214
+ }
215
+
216
+ public function get_current_report() {
217
+ if ( ! is_null( $this->current_report ) ) {
218
+ return $this->current_report;
219
+ }
220
+
221
+ $data_ranges = $this->get_data_ranges();
222
+ $data_range = isset( $_GET['data-range'] ) && array_key_exists( $_GET['data-range'], $data_ranges ) ? $_GET['data-range'] : 'week';
223
+ $this->current_report = wphb_uptime_get_last_report( $data_range );
224
+ return $this->current_report;
225
+ }
226
+
227
+ public function uptime_metabox() {
228
+ $error = '';
229
+
230
+ $stats = wphb_uptime_get_last_report( $this->get_current_data_range() );
231
+ if ( is_wp_error( $stats ) ) {
232
+ $error = $stats->get_error_message();
233
+ $error_type = 'error';
234
+ }
235
+ else {
236
+ if ( isset( $_GET['error'] ) ) {
237
+ $error = urldecode($_GET['message'] );
238
+ $error_type = 'error';
239
+ }
240
+ }
241
+
242
+ $retry_url = add_query_arg( 'run', 'true' );
243
+ $retry_url = wp_nonce_url( $retry_url, 'wphb-run-uptime' );
244
+
245
+ $args = array(
246
+ 'uptime_stats' => $stats,
247
+ 'error' => $error,
248
+ 'retry_url' => $retry_url,
249
+ 'support_url' => wphb_support_link(),
250
+ );
251
+
252
+ if ( ! empty( $error_type ) ) {
253
+ $args['error_type'] = $error_type;
254
+ }
255
+
256
+ $this->view( 'uptime/meta-box', $args );
257
+ }
258
+
259
+ /**
260
+ * Uptime summary meta box.
261
+ *
262
+ * @since 1.5.0
263
+ */
264
+ public function uptime_summary_metabox() {
265
+
266
+ if ( ! wphb_is_member() ) {
267
+ return;
268
+ }
269
+
270
+ $stats = wphb_uptime_get_last_report( $this->get_current_data_range() );
271
+
272
+ $this->view( 'uptime/summary-meta-box', array( 'uptime_stats' => $stats ) );
273
+ }
274
+
275
+ /**
276
+ * Uptime header for meta box.
277
+ *
278
+ * @since 1.5.0
279
+ */
280
+ public function uptime_metabox_header() {
281
+
282
+ $this->view( 'uptime/meta-box-header', array( 'title' => __( 'Response Time', 'wphb' ) ) );
283
+
284
+ }
285
+
286
+ /**
287
+ * Uptime downtime meta box.
288
+ *
289
+ * @since 1.5.0
290
+ */
291
+ public function uptime_downtime_metabox() {
292
+
293
+ if ( ! wphb_is_member() ) {
294
+ return;
295
+ }
296
+
297
+ $stats = wphb_uptime_get_last_report( $this->get_current_data_range() );
298
+ if ( is_wp_error( $stats ) ) {
299
+ return;
300
+ }
301
+ else {
302
+ if ( isset( $_GET['error'] ) ) {
303
+ return;
304
+ }
305
+ }
306
+
307
+ $this->view( 'uptime/downtime-meta-box', array( 'uptime_stats' => $stats ) );
308
+
309
+ }
310
+
311
+ public function uptime_membership_metabox() {
312
+ $this->view( 'uptime/no-membership-meta-box', array() );
313
+ }
314
+
315
+ }
admin/views/caching/cloudflare-meta-box-header.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( $cf_active ): ?>
3
+ <div class="buttons">
4
+ <a href="<?php echo esc_url( $deactivate_url ); ?>" class="button button-ghost"><?php esc_attr_e( 'Deactivate', 'wphb' ); ?></a>
5
+ </div>
6
+ <?php endif; ?>
admin/views/caching/cloudflare-meta-box.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /** @var WP_Hummingbird_Module_Cloudflare $cf_module */
4
+ $cf_module = wphb_get_module( 'cloudflare' );
5
+ $current_step = 'credentials';
6
+ $zones = array();
7
+ if ( $cf_module->is_zone_selected() && $cf_module->is_connected() ) {
8
+ $current_step = 'final';
9
+ }
10
+ elseif ( ! $cf_module->is_zone_selected() && $cf_module->is_connected() ) {
11
+ $current_step = 'zone';
12
+ $zones = $cf_module->get_zones_list();
13
+ if ( is_wp_error( $zones ) ) {
14
+ $zones = array();
15
+ }
16
+ }
17
+
18
+
19
+ $cloudflare_js_settings = array(
20
+ 'currentStep' => $current_step,
21
+ 'email' => wphb_get_setting( 'cloudflare-email' ),
22
+ 'apiKey' => wphb_get_setting( 'cloudflare-api-key' ),
23
+ 'zone' => wphb_get_setting( 'cloudflare-zone' ),
24
+ 'zoneName' => wphb_get_setting( 'cloudflare-zone-name' ),
25
+ 'plan' => $cf_module->get_plan(),
26
+ 'zones' => $zones
27
+ );
28
+
29
+ $cloudflare_js_settings = wp_json_encode( $cloudflare_js_settings );
30
+ ?>
31
+
32
+ <script type="text/template" id="cloudflare-step-credentials">
33
+ <div class="cloudflare-step">
34
+
35
+ <p><?php _e( 'Hummingbird can control your CloudFlare Browser Cache settings from here. Simply add your CloudFlare API details and configure away.', 'wphb' ); ?></p>
36
+
37
+ <form class="wphb-border-frame with-padding" action="" method="post" id="cloudflare-credentials">
38
+ <label for="cloudflare-email"><?php _e( 'CloudFlare email', 'wphb' ); ?>
39
+ <input type="text" autocomplete="off" value="{{ data.email }}" name="cloudflare-email" id="cloudflare-email" placeholder="<?php _e( 'Your CloudFlare account email', 'wphb' ); ?>">
40
+ </label>
41
+
42
+ <label for="cloudflare-api-key"><?php _e( 'CloudFlare Global API Key', 'wphb' ); ?>
43
+ <input type="text" autocomplete="off" value="{{ data.apiKey }}" name="cloudflare-api-key" id="cloudflare-api-key" placeholder="<?php _e( 'Enter your 37 digit API key', 'wphb' ); ?>">
44
+ </label>
45
+
46
+ <p class="cloudflare-submit">
47
+ <span class="spinner cloudflare-spinner"></span>
48
+ <input type="submit" class="button" value="<?php echo esc_attr( _x( 'Connect', 'Connect to CloufFlare button text', 'wphb' ) ); ?>">
49
+ </p>
50
+ <p id="cloudflare-how-to-title"><a href="#cloudflare-how-to"><?php _e( 'Need help getting your API Key?', 'wphb' ); ?></a></p>
51
+ <div class="clear"></div>
52
+ <ol id="cloudflare-how-to" class="wphb-block-content-blue">
53
+ <li><?php printf( __( '<a target="_blank" href="%s">Log in</a> to your CloudFlare account.', 'wphb' ), 'https://www.cloudflare.com/a/login' ); ?></li>
54
+ <li><?php _e( 'Go to My Settings.', 'wphb' ); ?></li>
55
+ <li><?php _e( 'Scroll down to API Key.', 'wphb' ); ?></li>
56
+ <li><?php _e( "Click 'View API Key' button and copy your API identifier.", 'wphb' ); ?></li>
57
+ </ol>
58
+ </form>
59
+ </div>
60
+ </script>
61
+
62
+ <script type="text/template" id="cloudflare-step-zone">
63
+ <div class="cloudflare-step">
64
+ <form action="" method="post" id="cloudflare-zone">
65
+ <# if ( ! data.zones.length ) { #>
66
+ <p><?php _e( 'It appears you have no active zones available. Double check your domain has been added to CloudFlare and try again.', 'wphb' ); ?></p>
67
+ <p class="cloudflare-submit">
68
+ <a href="<?php echo esc_url( wphb_get_admin_menu_url( 'caching' ) ); ?>&reload=<?php echo time(); ?>#wphb-box-dashboard-cloudflare" class="button"><?php esc_html_e( 'Re-Check', 'wphb' ); ?></a>
69
+ </p>
70
+ <# } else { #>
71
+ <p>
72
+ <label for="cloudflare-zone"><?php _e( 'Select the domain that matches this website', 'wphb' ); ?></label>
73
+ <select name="cloudflare-zone" id="cloudflare-zone">
74
+ <option value=""><?php _e( 'Select domain', 'wphb' ); ?></option>
75
+ <# for ( i in data.zones ) { #>
76
+ <option value="{{ data.zones[i].value }}">{{{ data.zones[i].label }}}</option>
77
+ <# } #>
78
+ </select>
79
+ <p class="cloudflare-submit">
80
+ <span class="spinner cloudflare-spinner"></span>
81
+ <input type="submit" class="button" value="<?php esc_attr_e( 'Enable CloudFlare', 'wphb' ); ?>">
82
+ </p>
83
+ <# } #>
84
+ <div class="clear"></div>
85
+ </form>
86
+ </div>
87
+ </script>
88
+
89
+ <script type="text/template" id="cloudflare-step-final">
90
+ <div class="cloudflare-step">
91
+ <div class="wphb-notice wphb-notice-blue">
92
+ <p><?php _e( 'CloudFlare is active on this domain. The settings you choose here will also update CloudFlare settings.', 'wphb' ); ?></p>
93
+ </div>
94
+ <p class="cloudflare-data">
95
+ <?php if ( ! empty( wphb_get_setting( 'cloudflare-zone-name' ) ) ) : ?>
96
+ <span><strong><?php _ex( 'Zone', 'CloudFlare Zone', 'wphb' ); ?>:</strong> {{ data.zoneName }}</span>
97
+ <?php endif; ?>
98
+ <?php if ( ! empty ( $cf_module->get_plan() ) ) : ?>
99
+ <span><strong><?php _ex( 'Plan', 'CloudFlare Plan', 'wphb' ); ?>:</strong> {{ data.plan }}</span>
100
+ <?php endif; ?>
101
+ </p>
102
+ <hr>
103
+ <p class="cloudflare-clear-cache-text"><?php _e( 'Made changes to your website? Use Purge Cache button to clear CloudFlare\'s cache', 'wphb' ); ?></p class="cloudflare-clear-cache-text">
104
+ <p class="cloudflare-clear-cache">
105
+ <input type="submit" class="button button-ghost" value="<?php esc_attr_e( 'Purge Cache', 'wphb' ); ?>">
106
+ <span class="spinner cloudflare-spinner"></span>
107
+ </p>
108
+ </div>
109
+ </script>
110
+
111
+
112
+
113
+ <script>
114
+ jQuery(document).ready( function( $ ) {
115
+ WPHB_Admin.DashboardCloudFlare.init( <?php echo $cloudflare_js_settings; ?> );
116
+ });
117
+ </script>
118
+
119
+ <div class="wphb-block-entry">
120
+
121
+ <div class="wphb-block-entry-content">
122
+
123
+ <div id="cloudflare-steps"></div>
124
+ <div id="cloudflare-info"></div>
125
+
126
+
127
+ </div><!-- end wphb-block-entry-content -->
128
+
129
+ </div><!-- end wphb-block-entry -->
130
+
131
+
admin/views/caching/enable-meta-box-footer.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if( wphb_is_htaccess_writable() === true ) : ?>
2
+ <div id="enable-cache-wrap" class="<?php echo $server_type != 'apache' ? 'hidden' : ''; ?>">
3
+ <?php if( wphb_is_htaccess_written('caching') === true ) : ?>
4
+ <a href="<?php echo esc_url( $disable_link ); ?>" class="button button-ghost"><?php esc_attr_e( 'Disable caching', 'wphb' ); ?></a>
5
+ <?php elseif ( ! $disable_enable_button && ! $cloudflare_enabled ) : ?>
6
+ <a href="<?php echo esc_url( $enable_link ); ?>" class="button"><?php esc_attr_e( 'Enable caching', 'wphb' ); ?></a>
7
+ <?php elseif ( $cloudflare_enabled ) : ?>
8
+ <span class="tooltip-l" tooltip="<?php esc_attr_e('CloudFlare is already controlling your Browser Caching', 'wphb' ); ?>">
9
+ <a href="<?php echo esc_url( $enable_link ); ?>" class="button disabled"><?php esc_attr_e( 'Enable caching', 'wphb' ); ?></a>
10
+ </span>
11
+ <?php endif; ?>
12
+ </div>
13
+ <?php endif; ?>
admin/views/caching/enable-meta-box-header.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <div class="extra">
3
+ <div class="wphb-select-group">
4
+ <label for="wphb-server-type" class="inline-label"><?php _e( 'Server Type:', 'wphb' ); ?></label>
5
+ <?php wphb_get_servers_dropdown( array( 'selected' => $gzip_server_type ) ); ?>
6
+ </div>
7
+ </div>
admin/views/caching/enable-meta-box.php ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="spinner standalone hide visible"></div>
2
+ <div class="wphb-content">
3
+
4
+ <div id="wphb-server-instructions-apache" class="wphb-server-instructions hidden" data-server="apache">
5
+
6
+ <?php if ( $htaccess_writable && ! $already_enabled ): ?>
7
+ <p><?php _e( 'Hummingbird will try to write into your <strong>.htaccess</strong> file for you', 'wphb' ); ?></p>
8
+ <p><a href="#" id="toggle-apache-instructions"><?php esc_html_e( 'Want to do it manually?', 'wphb' ); ?></a></p>
9
+ <?php else: ?>
10
+ <div class="wphb-caching-success wphb-notice wphb-notice-success">
11
+ <p><?php _e( 'Your browser caching is already enabled and working well', 'wphb' ); ?></p>
12
+ </div>
13
+ <?php endif; ?>
14
+
15
+ <div class="apache-instructions <?php echo $htaccess_writable ? 'hidden' : ''; ?>">
16
+
17
+ <p><?php esc_html_e( 'For Apache servers:', 'wphb'); ?></p>
18
+
19
+ <p><?php _e( 'Copy the generated code into your <strong>.htaccess</strong> file', 'wphb'); ?></p>
20
+
21
+ <p><?php _e( 'If .htaccess does not work, and you have access to <strong>vhosts.conf</strong> or <strong>httpd.conf</strong> try this:', 'wphb' ); ?></p>
22
+ <ol class="wphb-listing wphb-listing-ordered">
23
+ <li><?php esc_html_e( 'Look for your site in the file and find the line that starts with <Directory> - add the code above into that section and save the file.', 'wphb' ); ?></li>
24
+ <li><?php _e( 'Reload Apache.', 'wphb' ); ?></li>
25
+ </ol>
26
+
27
+ <p><?php _e( 'If you don\'t know where those files are, or you aren\'t able to reload Apache, you would need to <strong>consult with your hosting provider or a system administrator who has access</strong> to change the configuration of your server', 'wphb' ); ?></p>
28
+
29
+ <?php _wphb_still_having_trouble_link(); ?>
30
+
31
+ <div id="wphb-code-snippet">
32
+ <div id="wphb-code-snippet-apache" class="wphb-code-snippet">
33
+ <div class="wphb-block-content">
34
+ <pre><?php echo htmlentities2( $snippets['apache'] ); ?></pre>
35
+ </div>
36
+
37
+ </div>
38
+ </div>
39
+
40
+ </div>
41
+ </div>
42
+
43
+ <div id="wphb-server-instructions-litespeed" class="wphb-server-instructions hidden" data-server="LiteSpeed">
44
+
45
+ <?php if ( $htaccess_writable && ! $already_enabled ): ?>
46
+ <p><?php _e( 'Hummingbird will try to write into your <strong>.htaccess</strong> file for you', 'wphb' ); ?></p>
47
+ <p><a href="#" id="toggle-litespeed-instructions"><?php esc_html_e( 'Want to do it manually?', 'wphb' ); ?></a></p>
48
+ <?php else: ?>
49
+ <div class="wphb-caching-success wphb-notice wphb-notice-success">
50
+ <p><?php _e( 'Your browser caching is already enabled and working well', 'wphb' ); ?></p>
51
+ </div>
52
+ <?php endif; ?>
53
+
54
+ <div class="litespeed-instructions <?php echo $htaccess_writable ? 'hidden' : ''; ?>">
55
+
56
+ <p><?php esc_html_e( 'For LiteSpeed servers:', 'wphb'); ?></p>
57
+
58
+ <p><?php _e( 'Copy the generated code into your <strong>.htaccess</strong> file', 'wphb'); ?></p>
59
+
60
+ <p><?php _e( 'If .htaccess does not work, and you have access to <strong>vhosts.conf</strong> or <strong>httpd.conf</strong> try this:', 'wphb' ); ?></p>
61
+ <ol class="wphb-listing wphb-listing-ordered">
62
+ <li><?php esc_html_e( 'Look for your site in the file and find the line that starts with <Directory> - add the code above into that section and save the file.', 'wphb' ); ?></li>
63
+ <li><?php _e( 'Reload LiteSpeed.', 'wphb' ); ?></li>
64
+ </ol>
65
+
66
+ <p><?php _e( 'If you don\'t know where those files are, or you aren\'t able to reload LiteSpeed, you would need to <strong>consult with your hosting provider or a system administrator who has access</strong> to change the configuration of your server', 'wphb' ); ?></p>
67
+
68
+ <?php _wphb_still_having_trouble_link(); ?>
69
+
70
+ <div id="wphb-code-snippet">
71
+ <div id="wphb-code-snippet-litespeed" class="wphb-code-snippet">
72
+ <div class="wphb-block-content">
73
+ <pre><?php echo htmlentities2( $snippets['litespeed'] ); ?></pre>
74
+ </div>
75
+
76
+ </div>
77
+ </div>
78
+
79
+ </div>
80
+ </div>
81
+
82
+ <div id="wphb-server-instructions-nginx" class="wphb-server-instructions hidden" data-server="nginx">
83
+ <?php if ( $already_enabled ): ?>
84
+ <div class="wphb-caching-success wphb-notice wphb-notice-success">
85
+ <p><?php _e( 'Your browser caching is already enabled and working well', 'wphb' ); ?></p>
86
+ </div>
87
+ <?php else: ?>
88
+ <p><?php esc_html_e( 'For NGINX servers:', 'wphb'); ?></p>
89
+
90
+ <ol class="wphb-listing wphb-listing-ordered">
91
+ <li><?php _e( 'Copy the generated code into your <strong>nginx.conf</strong> usually located at <strong>/etc/nginx/nginx.conf</strong> or <strong>/usr/local/nginx/conf/nginx.conf</strong>', 'wphb' ); ?></li>
92
+ <li><?php _e( 'Add the code above to the <strong>http</strong> or inside <strong>server</strong> section in the file.', 'wphb' ); ?></li>
93
+ <li><?php _e( 'Reload NGINX.', 'wphb' ); ?></li>
94
+ </ol>
95
+
96
+ <p><?php _e( 'If you do not have access to your NGINX config files you will need to contact your hosting provider to make these changes.', 'wphb' ); ?></p>
97
+ <?php _wphb_still_having_trouble_link(); ?>
98
+
99
+ <div id="wphb-code-snippet">
100
+ <div id="wphb-code-snippet-nginx" class="wphb-code-snippet">
101
+ <div class="wphb-block-content">
102
+ <pre><?php echo htmlentities2( $snippets['nginx'] ); ?></pre>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ <?php endif; ?>
107
+
108
+ </div>
109
+
110
+ <div id="wphb-server-instructions-iis" class="wphb-server-instructions hidden" data-server="iis">
111
+ <?php if ( $already_enabled ): ?>
112
+ <div class="wphb-caching-success wphb-notice wphb-notice-success">
113
+ <p><?php _e( 'Your browser caching is already enabled and working well', 'wphb' ); ?></p>
114
+ </div>
115
+ <?php else: ?>
116
+ <p><?php printf( __( 'For IIS servers, <a href="%s">visit Microsoft TechNet</a>', 'wphb'), 'https://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/25d2170b-09c0-45fd-8da4-898cf9a7d568.mspx?mfr=true' ); ?></p>
117
+ <?php endif; ?>
118
+ </div>
119
+
120
+ <div id="wphb-server-instructions-iis-7" class="wphb-server-instructions hidden" data-server="iis-7">
121
+ <?php if ( $already_enabled ): ?>
122
+ <div class="wphb-caching-success wphb-notice wphb-notice-success">
123
+ <p><?php _e( 'Your browser caching is already enabled and working well', 'wphb' ); ?></p>
124
+ </div>
125
+ <?php else: ?>
126
+ <p><?php printf( __( 'For IIS 7 servers, <a href="%s">visit Microsoft TechNet</a>', 'wphb'), 'https://technet.microsoft.com/en-us/library/cc771003(v=ws.10).aspx' ); ?></p>
127
+ <?php endif; ?>
128
+ </div>
129
+
130
+
131
+ </div>
admin/views/caching/summary-meta-box-header.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <div class="buttons">
3
+ <a href="<?php echo esc_url( $recheck_url ); ?>" class="button button-ghost" id="recheck-expiry" name="submit"><?php esc_attr_e( 'Re-Check Status', 'wphb' ); ?></a>
4
+ </div>
admin/views/caching/summary-meta-box.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-table-wrapper">
2
+
3
+ <?php if ( $external_problem ): ?>
4
+ <div class="wphb-caching-error wphb-notice wphb-notice-error">
5
+ <p><?php _e( 'Browser Caching is not working properly:', 'wphb' ); ?></p>
6
+ <ul>
7
+ <li>- <?php _e( 'Your server may not have the "expires" module enabled (mod_expires for Apache, ngx_http_headers_module for NGINX)', 'wphb' ); ?></li>
8
+ <li>- <?php _e( 'Another plugin may be interfering with the configuration', 'wphb' ); ?></li>
9
+ </ul>
10
+ <p><?php printf( __( 'If re-checking and restarting does not resolve, please check with your host or <a href="%s" target="_blank">open a support ticket with us</a>.', 'wphb' ), wphb_support_link() ); ?></p>
11
+ </div>
12
+ <?php endif; ?>
13
+
14
+ <div class="content">
15
+ <p><?php _e( 'Caching stores temporary data on your visitors devices so that they don\'t have to download assets twice if they don\'t have to. This results in a much faster second time around page load speed. Enabling caching will set the recommended expiry times for your content.', 'wphb' ); ?></p>
16
+ </div>
17
+
18
+ <?php if ( ! $cf_active ): ?>
19
+ <table class="list-table wphb-table stack caching-table">
20
+ <thead>
21
+ <tr class="wphb-caching-summary-item-heading">
22
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-type"><?php _e( 'File Type', 'wphb' ); ?></th>
23
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-expiry"><?php _e( 'Recommended', 'wphb' ); ?></th>
24
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-status"><?php _e( 'Current', 'wphb' ); ?></th>
25
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-set-expiry"><?php _e( 'Set Expiry', 'wphb' ); ?></th>
26
+ </tr><!-- end wphb-caching-summary-item-heading -->
27
+ </thead>
28
+
29
+ <tbody>
30
+ <?php foreach ( $human_results as $type => $result ): ?>
31
+
32
+ <?php if ( $result ) {
33
+ if ( $recommended[ $type ]['value'] <= $results[ $type ] ) {
34
+ $resultStatus = $result;
35
+ $resultStatusColor = 'green';
36
+ $tooltipText = __('Caching is enabled', 'wphb');
37
+ } else {
38
+ $resultStatus = $result;
39
+ $resultStatusColor = 'yellow';
40
+ $tooltipText = __('Caching is enabled but you aren\'t using our recommended value', 'wphb');
41
+ }
42
+
43
+ } else {
44
+ $resultStatus = __( 'Disabled', 'wphb' );
45
+ $resultStatusColor = 'yellow';
46
+ $tooltipText = __('Caching is disabled', 'wphb');
47
+ }
48
+ ?>
49
+
50
+ <tr class="wphb-caching-summary-item">
51
+ <td th-data="<?php _e( 'File Type', 'wphb' ); ?>" class="wphb-caching-summary-item-type"><?php echo $type; ?></td><!-- end wphb-dashboard-modules-item-type -->
52
+ <td th-data="<?php _e( 'Recommended', 'wphb' ); ?>" class="wphb-caching-summary-item-expiry has-button-label">
53
+ <span class="wphb-button-label wphb-button-label-light" tooltip="<?php echo sprintf( __('The recommended value for this file type is at least %s. The longer the better!', 'wphb'), $recommended[ $type ]['label'] ); ?>"><?php echo $recommended[ $type ]['label']; ?></span>
54
+ </td><!-- end wphb-caching-summary-item-expiry -->
55
+ <td th-data="<?php _e( 'Current', 'wphb' ); ?>" class="wphb-caching-summary-item-status has-button-label">
56
+ <span class="wphb-button-label wphb-button-label-<?php echo $resultStatusColor; ?>" tooltip="<?php echo $tooltipText; ?>"><?php echo $resultStatus; ?></span>
57
+ </td><!-- end wphb-caching-summary-itemm-status -->
58
+ <td th-data="<?php _e( 'Set Expiry', 'wphb' ); ?>" class="wphb-caching-summary-item-set-expiry has-select">
59
+ <?php wphb_get_caching_frequencies_dropdown( array( 'name' => 'wphb-caching-summary-set-expiry-select-css', 'class' => 'wphb-expiry-select', 'selected' => $expires[ $type ], 'data-type' => $type ) ); ?>
60
+ </td><!-- end wphb-caching-summary-item-set-expiry -->
61
+ </tr><!-- wphb-caching-summary-item -->
62
+ <?php endforeach; ?>
63
+ </tbody>
64
+ </table>
65
+ <?php elseif ( $cf_active ): ?>
66
+ <div class="wphb-caching-cloudflare-box">
67
+ <div class="wphb-caching-success wphb-notice wphb-notice-blue">
68
+ <p><?php _e( 'CloudFlare is active on this domain', 'wphb' ); ?></p>
69
+ </div>
70
+
71
+ <table class="list-table wphb-table stack caching-table">
72
+ <thead>
73
+ <tr class="wphb-caching-summary-item-heading">
74
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-expiry"><?php _e( 'File Type', 'wphb' ); ?></th>
75
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-expiry"><?php _e( 'Recommended', 'wphb' ); ?></th>
76
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-status"><?php _e( 'Current', 'wphb' ); ?></th>
77
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-set-expiry"><?php _e( 'Set Expiry', 'wphb' ); ?></th>
78
+ </tr><!-- end wphb-caching-summary-item-heading -->
79
+ </thead>
80
+ <tbody>
81
+ <tr class="wphb-caching-summary-item">
82
+ <td th-data="<?php _e( 'File Type', 'wphb' ); ?>" class="wphb-caching-summary-item-type"><?php _e( 'All files', 'wphb' ); ?></td>
83
+ <td th-data="<?php _e( 'Recommended', 'wphb' ); ?>" class="wphb-caching-summary-item-expiry has-button-label">
84
+ <span class="wphb-button-label wphb-button-label-light" tooltip="<?php esc_attr_e('The recommended value for CloudFlare settings is at least 8 days.', 'wphb' ); ?>"><?php _e( '8 days', 'wphb' ); ?></span>
85
+ </td><!-- end wphb-caching-summary-item-expiry -->
86
+ <td th-data="<?php _e( 'Current', 'wphb' ); ?>" class="wphb-caching-summary-item-status has-button-label">
87
+ <span class="wphb-button-label wphb-button-label-<?php echo $cf_current == 691200 ? 'green' : 'red'; ?>" tooltip="<?php echo esc_html( $cf_tooltip ); ?>"><?php echo $cf_current_human; ?></span>
88
+ </td><!-- end wphb-caching-summary-itemm-status -->
89
+ <td th-data="<?php _e( 'Set Expiry', 'wphb' ); ?>" class="wphb-caching-summary-item-set-expiry has-select">
90
+ <?php wphb_get_caching_cloudflare_frequencies_dropdown( array( 'name' => 'wphb-caching-cloudflare-summary-set-expiry', 'class' => 'wphb-expiry-select', 'selected' => $cf_current ) ); ?>
91
+ </td><!-- end wphb-caching-summary-item-set-expiry -->
92
+ </tr><!-- wphb-caching-summary-item -->
93
+ </tbody>
94
+ </table>
95
+ </div>
96
+ <script>
97
+ jQuery(document).ready( function() {
98
+ if ( window.WPHB_Admin ) {
99
+ window.WPHB_Admin.getModule( 'cloudflare' );
100
+ }
101
+ });
102
+
103
+ </script>
104
+ <?php endif; ?>
105
+ </div>
admin/views/dashboard/caching/module-meta-box-header.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( $issues && ! $cf_active ) : ?>
3
+ <div class="wphb-pills"><?php echo intval( $issues ); ?></div>
4
+ <?php elseif ( $cf_current !== 691200 && $cf_active ) : ?>
5
+ <div class="wphb-pills">1</div>
6
+ <?php endif; ?>
admin/views/dashboard/caching/module-meta-box.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-table-wrapper">
2
+ <div class="content">
3
+ <p><?php _e( 'Caching stores temporary data on your visitors devices so that they don’t have to download assets twice if they don’t have to.', 'wphb' ); ?></p>
4
+ </div>
5
+
6
+ <?php if ( ! $cf_active ): ?>
7
+ <table class="list-table wphb-table stack caching-table">
8
+
9
+ <thead>
10
+ <tr class="wphb-caching-summary-item-heading">
11
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-type"><?php _e( 'File Type', 'wphb' ); ?></th>
12
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-expiry"><?php _e( 'Recommended', 'wphb' ); ?></th>
13
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-status"><?php _e( 'Current', 'wphb' ); ?></th>
14
+ </tr><!-- end wphb-caching-summary-item-heading -->
15
+ </thead>
16
+
17
+ <tbody>
18
+
19
+ <?php foreach ( $human_results as $type => $result ): ?>
20
+
21
+ <?php if ( $result ) {
22
+ if ( $recommended[ $type ]['value'] <= $results[ $type ] ) {
23
+ $result_status = $result;
24
+ $result_status_color = 'green';
25
+ $tooltip_text = __('Caching is enabled', 'wphb');
26
+ } else {
27
+ $result_status = $result;
28
+ $result_status_color = 'yellow';
29
+ $tooltip_text = __('Caching is enabled but you aren\'t using our recommended value', 'wphb');
30
+ }
31
+
32
+ } else {
33
+ $result_status = __( 'Disabled', 'wphb' );
34
+ $result_status_color = 'yellow';
35
+ $tooltip_text = __('Caching is disabled', 'wphb');
36
+ }
37
+ ?>
38
+
39
+ <tr class="wphb-caching-summary-item">
40
+ <td th-data="<?php _e( 'File Type', 'wphb' ); ?>" class="wphb-caching-summary-item-type"><?php echo $type; ?></td><!-- end wphb-dashboard-modules-item-type -->
41
+ <td th-data="<?php _e( 'Recommended', 'wphb' ); ?>" tr-data="<?php _e( 'File Type', 'wphb' ); ?>" class="wphb-caching-summary-item-expiry has-button-label">
42
+ <span class="wphb-button-label wphb-button-label-light" tooltip="<?php echo sprintf( __('The recommended value for this file type is at least %s. The longer the better!', 'wphb'), $recommended[ $type ]['label'] ); ?>"><?php echo $recommended[ $type ]['label']; ?></span>
43
+ </td><!-- end wphb-caching-summary-item-expiry -->
44
+ <td th-data="<?php _e( 'Current', 'wphb' ); ?>" class="wphb-caching-summary-item-status has-button-label">
45
+ <span class="wphb-button-label wphb-button-label-<?php echo $result_status_color; ?> tooltip-right" tooltip="<?php echo $tooltip_text; ?>"><?php echo $result_status; ?></a></span>
46
+ </td><!-- end wphb-caching-summary-itemm-status -->
47
+ </tr><!-- wphb-caching-summary-item -->
48
+ <?php endforeach; ?>
49
+
50
+ </tbody>
51
+ </table>
52
+
53
+ <?php elseif ( $cf_active ): ?>
54
+ <div class="wphb-dashboard-caching-cloudflare-box">
55
+ <div class="wphb-caching-success wphb-notice wphb-notice-blue">
56
+ <p><?php _e( 'CloudFlare is active on this domain', 'wphb' ); ?></p>
57
+ </div>
58
+ <table class="list-table wphb-table stack caching-table">
59
+ <thead>
60
+ <tr class="wphb-caching-summary-item-heading">
61
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-expiry"><?php _e( 'File Type', 'wphb' ); ?></th>
62
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-expiry"><?php _e( 'Recommended', 'wphb' ); ?></th>
63
+ <th class="wphb-caching-summary-heading wphb-caching-summary-heading-status"><?php _e( 'Current', 'wphb' ); ?></th>
64
+ </tr><!-- end wphb-caching-summary-item-heading -->
65
+ </thead>
66
+ <tbody>
67
+ <tr class="wphb-caching-summary-item">
68
+ <td th-data="<?php _e( 'File Type', 'wphb' ); ?>" class="wphb-caching-summary-item-type"><?php _e( 'All files', 'wphb' ); ?></td>
69
+ <td th-data="<?php _e( 'Recommended', 'wphb' ); ?>" class="wphb-caching-summary-item-expiry has-button-label">
70
+ <span class="wphb-button-label wphb-button-label-light" tooltip="<?php esc_attr_e('The recommended value for CloudFlare settings is at least 8 days.', 'wphb' ); ?>"><?php _e( '8 days', 'wphb' ); ?></span>
71
+ </td><!-- end wphb-caching-summary-item-expiry -->
72
+ <td th-data="<?php _e( 'Current', 'wphb' ); ?>" class="wphb-caching-summary-item-status has-button-label">
73
+ <span class="wphb-button-label wphb-button-label-<?php echo $cf_current == 691200 ? 'green' : 'red'; ?> tooltip-right" tooltip="<?php echo esc_html( $cf_tooltip ); ?>"><?php echo $cf_current_human; ?></span>
74
+ </td><!-- end wphb-caching-summary-itemm-status -->
75
+ </tr><!-- wphb-caching-summary-item -->
76
+ </tbody>
77
+ </table>
78
+ </div>
79
+ <?php endif; ?>
80
+
81
+ <div class="buttons">
82
+ <a href="<?php echo esc_url( $caching_url ); ?>" class="button button-ghost" name="submit"><?php esc_attr_e( 'Configure', 'wphb' ); ?></a>
83
+ </div>
84
+ </div>
admin/views/dashboard/gzip/module-meta-box-header.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( $issues ) : ?>
3
+ <div class="wphb-pills"><?php echo intval( $issues ); ?></div>
4
+ <?php endif; ?>
admin/views/dashboard/gzip/module-meta-box.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <ul class="dev-list dev-list-stats">
2
+
3
+ <div class="content">
4
+ <p><?php _e( 'Gzip compresses your webpages and style sheets before sending them over to the browser.', 'wphb' ); ?></p>
5
+ </div>
6
+
7
+ <?php foreach ( $status as $type => $result ): ?>
8
+ <?php if ( $result == 1 ) {
9
+ $resultStatus = __( 'Enabled', 'wphb' );
10
+ $resultStatusColor = 'green';
11
+ } else {
12
+ $resultStatus = __( 'Disabled', 'wphb' );
13
+ $resultStatusColor = 'yellow';
14
+ }
15
+
16
+ switch ( $type ) {
17
+ case 'HTML':
18
+ $icon = __( 'html', 'wphb' );
19
+ break;
20
+ case 'JavaScript':
21
+ $icon = __( 'js', 'wphb' );
22
+ break;
23
+ case 'CSS':
24
+ $icon = __( 'css', 'wphb' );
25
+ break;
26
+ } ?>
27
+ <li class="dev-list-stats-item">
28
+ <div>
29
+ <span class="list-label list-label-stats list-label-stats-filename">
30
+ <span class="wphb-filename-extension wphb-filename-extension-<?php echo $icon; ?>"><?php echo $icon; ?></span>
31
+ <p><?php echo $type; ?></p>
32
+ </span>
33
+ <span class="list-detail">
34
+ <div class="tooltip-box">
35
+ <span class="wphb-button-label wphb-button-label-<?php echo $resultStatusColor; ?> tooltip-l" tooltip="<?php echo sprintf( __( 'Gzip compression is %s for %s', 'wphb' ), $resultStatus, $type ); ?>">
36
+ <?php echo $resultStatus; ?>
37
+ </span>
38
+ </div>
39
+ </span>
40
+ </div>
41
+ </li><!-- end dev-list-stats-item -->
42
+ <?php endforeach; ?>
43
+ </ul>
44
+
45
+ <div class="buttons">
46
+ <a href="<?php echo esc_url( $gzip_url ); ?>" class="button button-ghost" name="submit"><?php esc_attr_e( 'Configure', 'wphb' ); ?></a>
47
+ </div>
admin/views/dashboard/minification/cant-execute-php-meta-box.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <div class="content">
6
+ <div class="wphb-notice wphb-notice-error">
7
+ <p><?php _e( 'Hummingbird\'s minification engine requires at least <strong>PHP 5.3</strong> and above. You\'ll need to update your PHP to a newer version to use this feature.', 'wphb' ); ?></p>
8
+ </div>
9
+ </div><!-- end content -->
10
+
11
+
12
+
13
+ </div><!-- end wphb-block-entry-content -->
14
+
15
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/minification/disabled-meta-box.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+ <div class="content">
5
+ <p><?php _e( 'Compress, combine and position your assets to dramatically improve your pageload speed.', 'wphb' ); ?></p>
6
+ <a href="<?php echo esc_url( $minification_url ); ?>" class="button" id="minifiy-website"><?php _e( 'Activate', 'wphb' ); ?></a>
7
+ </div><!-- end content -->
8
+
9
+ </div><!-- end wphb-block-entry-content -->
10
+
11
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/minification/module-meta-box-header.php ADDED
@@ -0,0 +1 @@
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
admin/views/dashboard/minification/module-meta-box.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <ul class="dev-list dev-list-stats">
2
+ <div class="content">
3
+ <p><?php _e( 'Compress, combine and position your assets to dramatically improve your page load speed.', 'wphb' ); ?></p>
4
+ </div>
5
+
6
+
7
+ <li class="dev-list-stats-item">
8
+ <span class="list-label list-label-stats"><?php _e( 'Total Enqueued Files', 'wphb' ); ?></span>
9
+ <span class="list-detail list-detail-stats list-detail-stats-heading"><?php echo $enqueued_files; ?></span>
10
+ </li>
11
+
12
+ <li class="dev-list-stats-item">
13
+ <span class="list-label list-label-stats list-label-stats-pills"><?php _e( 'Total Size Reductions', 'wphb' ); ?></span>
14
+ <span class="list-detail list-detail-stats">
15
+ <div class="wphb-pills-group">
16
+ <span class="wphb-pills with-arrow right grey"><?php echo $original_size; ?>KB</span>
17
+ <span class="wphb-pills"><?php echo $compressed_size; ?>KB</span>
18
+ </div>
19
+ </span>
20
+ </li><!-- end dev-list-stats-item -->
21
+
22
+ <li class="dev-list-stats-item">
23
+ <span class="list-label list-label-stats"><?php _e( 'Total % Reductions', 'wphb' ); ?></span>
24
+ <span class="list-detail list-detail-stats list-detail-stats-heading"><?php echo $percentage; ?>%</span>
25
+ </li><!-- end dev-list-stats-item -->
26
+
27
+ <li class="dev-list-stats-item">
28
+ <span class="list-label list-label-stats list-label-stats-filename">
29
+ <span class="wphb-filename-extension wphb-filename-extension-js"><?php _e( 'JS', 'wphb' ); ?></span>
30
+ <p><?php _e( 'Scripts', 'wphb' ); ?></p>
31
+ </span>
32
+ <span class="list-detail list-detail-stats list-detail-stats-heading"><?php echo $compressed_size_scripts; ?>KB</span>
33
+ </li><!-- end dev-list-stats-item -->
34
+
35
+ <li class="dev-list-stats-item">
36
+ <span class="list-label list-label-stats list-label-stats-filename">
37
+ <span class="wphb-filename-extension wphb-filename-extension-css"><?php _e( 'CSS', 'wphb' ); ?></span>
38
+ <p><?php _e( 'Stylesheets', 'wphb' ); ?></p>
39
+ </span>
40
+ <span class="list-detail list-detail-stats list-detail-stats-heading"><?php echo $compressed_size_styles; ?>KB</span>
41
+ </li><!-- end dev-list-stats-item -->
42
+ </ul>
43
+
44
+ <div class="buttons">
45
+ <a href="<?php echo esc_url( $minification_url ); ?>" class="button button-ghost" name="submit"><?php esc_attr_e( 'Configure', 'wphb' ); ?></a>
46
+ </div>
admin/views/dashboard/minification/network-module-meta-box.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <div class="content">
6
+ <p><?php _e( 'Minification can be a bit daunting to configure for beginners, and has the potential to break the frontend of a site. You can choose here who can configure Minification options on subsites in your Multisite install.', 'wphb' ); ?></p>
7
+
8
+ <div class="wphb-notice wphb-notice-success hidden" id="wphb-notice-minification-settings-updated">
9
+ <p><?php _e( 'Minification settings updated', 'wphb' ); ?></p>
10
+ </div>
11
+
12
+ <?php if ( isset( $_GET['minify-instructions'] ) ): ?>
13
+ <div class="wphb-notice wphb-notice-warning">
14
+ <p><?php _e( 'Please, activate minification first. A new menu will appear in every site on your Network.', 'wphb' ); ?></p>
15
+ </div>
16
+ <?php endif; ?>
17
+
18
+ <label for="wphb-activate-minification"><span class="screen-reader-text"><?php _e( 'Select users that can minify in this network', 'wphb' ); ?></span></label>
19
+ <select name="wphb-activate-minification" id="wphb-activate-minification">
20
+ <option value="false" <?php selected( wphb_get_setting( 'minify' ), false ); ?>><?php _e( 'Deactivate completely', 'wphb' ); ?></option>
21
+ <option value="true" <?php selected( wphb_get_setting( 'minify' ), true ); ?>><?php _e( 'Blog Admins can minify', 'wphb' ); ?></option>
22
+ <option value="super-admins" <?php selected( wphb_get_setting( 'minify' ), 'super-admins' ); ?>><?php _e( 'Only Super Admins can minify', 'wphb' ); ?></option>
23
+ </select>
24
+ <div class="toggle-item space-top-small">
25
+ <div class="toggle-item-group">
26
+ <?php
27
+ $tooltip_msg = __( 'Enable WPMU DEV CDN', 'wphb' );
28
+ if ( $use_cdn_disabled ) {
29
+ $tooltip_msg = __( 'Enable minification to use the WPMU DEV CDN', 'wphb' );
30
+ }
31
+ ?>
32
+ <label for="use_cdn"><?php _e( 'Store my files on the WPMU DEV CDN', 'wphb' ); ?></label>
33
+ <div class="toggle-actions">
34
+ <span class="toggle tooltip-right" tooltip="<?php echo $tooltip_msg; ?>">
35
+ <input type="checkbox" class="toggle-checkbox" name="use_cdn" id="use_cdn" <?php checked( $use_cdn ); ?> <?php disabled( $use_cdn_disabled ); ?>>
36
+ <label for="use_cdn" class="toggle-label"></label>
37
+ </span>
38
+ </div><!-- end toggle-actions -->
39
+ </div>
40
+ </div>
41
+
42
+
43
+ </div><!-- end content -->
44
+
45
+
46
+
47
+ </div><!-- end wphb-block-entry-content -->
48
+
49
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/performance/disabled-meta-box.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <div class="content">
6
+ <p><?php _e( 'Hummingbird will test your website and detect what improvements you can make. We’ll give you a score out of 100 for each item, with custom recommendations on how to improve!', 'wphb' ); ?></p>
7
+ <a href="<?php echo esc_url( $run_url ); ?>" class="button" id="performance-scan-website"><?php _e( 'Run Test', 'wphb' ); ?></a>
8
+ </div><!-- end content -->
9
+
10
+ </div><!-- end wphb-block-entry-content -->
11
+
12
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/performance/module-error-meta-box.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <div class="row">
2
+ <div class="wphb-notice wphb-notice-error wphb-notice-box can-close">
3
+ <p><?php echo $error; ?></p>
4
+ <a href="<?php echo esc_url( $retry_url ); ?>" class="button button-grey"><?php _e( 'Try again', 'wphb' ); ?></a>
5
+ <a target="_blank" href="<?php echo esc_url( $support_url ); ?>" class="button button-grey"><?php _e( 'Support', 'wphb' ); ?></a>
6
+ </div>
7
+ </div>
admin/views/dashboard/performance/module-meta-box-header.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( $last_report && ! is_wp_error( $last_report ) ): ?>
3
+ <div class="test-results wphb-performance-report-overall-score hide-on-mobile">
4
+ <div class="wphb-score wphb-score-have-label">
5
+ <div class="tooltip-box">
6
+ <div class="wphb-score-result wphb-score-result-grade-<?php echo $last_report->score_class ?>" tooltip="<?php echo $last_report->score; ?>/100">
7
+ <div class="wphb-score-type wphb-score-type-circle">
8
+ <svg class="wphb-score-graph wphb-score-graph-svg" xmlns="http://www.w3.org/2000/svg" width="30" height="30">
9
+ <circle class="wphb-score-graph-circle" r="12.5" cx="15" cy="15" fill="transparent" stroke-dasharray="0" stroke-dashoffset="0"></circle>
10
+ <circle class="wphb-score-graph-circle wphb-score-graph-result" r="12.5" cx="15" cy="15" fill="transparent" stroke-dasharray="80" stroke-dashoffset="0"></circle>
11
+ </svg>
12
+ </div><!-- end wphb-score-type -->
13
+ <div class="wphb-score-result-label"><?php echo $last_report->score; ?></div>
14
+ </div><!-- end wphb-score-result -->
15
+ </div><!-- end tooltip-box -->
16
+ </div><!-- end wphb-score -->
17
+ </div><!-- end test-results -->
18
+ <?php endif; ?>
admin/views/dashboard/performance/module-meta-box.php ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <table class="list-table wphb-table stack dashboard-performance-report-table">
2
+
3
+ <div class="content">
4
+ <p><?php _e( 'Here are your latest performance test results. A score above 85 is considered a good benchmark.', 'wphb' ); ?></p>
5
+ </div>
6
+
7
+ <thead>
8
+ <tr class="wphb-performance-report-item-heading">
9
+ <th class="wphb-performance-report-heading wphb-performance-report-heading-recommendation"><?php _e( 'Recommendation', 'wphb' ); ?></th>
10
+ <th class="wphb-performance-report-heading wphb-performance-report-heading-score"><?php _e( 'Score /100', 'wphb' ); ?></th>
11
+ <th class="wphb-performance-report-heading wphb-performance-report-heading-action">&nbsp;</th>
12
+ </tr><!-- end wphb-performance-report-item-heading -->
13
+ </thead>
14
+
15
+ <tbody>
16
+ <?php foreach ( $report->rule_result as $rule => $rule_result ): ?>
17
+ <tr class="wphb-performance-report-item">
18
+ <td class="wphb-performance-report-item-recommendation">
19
+ <?php echo $rule_result->label; ?>
20
+ </td><!-- end wphb-performance-report-item-recommendation -->
21
+ <td class="wphb-performance-report-item-score">
22
+ <div class="wphb-score wphb-score-have-label">
23
+ <div class="tooltip-box">
24
+ <div class="tooltip-s wphb-score-result wphb-score-result-grade-<?php echo $rule_result->impact_score_class; ?>" tooltip="<?php echo $rule_result->impact_score; ?>/100">
25
+ <div class="wphb-score-type wphb-score-type-circle">
26
+ <svg class="wphb-score-graph wphb-score-graph-svg" xmlns="http://www.w3.org/2000/svg" width="30" height="30">
27
+ <circle class="wphb-score-graph-circle" r="12.5" cx="15" cy="15" fill="transparent" stroke-dasharray="0" stroke-dashoffset="0"></circle>
28
+ <circle class="wphb-score-graph-circle wphb-score-graph-result" r="12.5" cx="15" cy="15" fill="transparent" stroke-dasharray="80" stroke-dashoffset="0"></circle>
29
+ </svg>
30
+ </div><!-- end wphb-score-type -->
31
+ <div class="wphb-score-result-label"><?php echo $rule_result->impact_score; ?></div>
32
+ </div><!-- end wphb-score-result -->
33
+ </div><!-- end tooltip-box -->
34
+ </div><!-- end wphb-score -->
35
+ </td><!-- end wphb-performance-report-item-score -->
36
+ <td>
37
+ <?php if ( $rule_result->impact_score < 100 ) : ?>
38
+ <a href="<?php echo esc_url( wphb_get_admin_menu_url( 'performance' ) ); ?>#rule-<?php echo $rule; ?>" class="button button-ghost" name="submit"><?php _e( 'Improve', 'wphb' ); ?></a>
39
+ <?php endif; ?>
40
+ </td>
41
+ </tr>
42
+ <?php endforeach; ?>
43
+
44
+ </tbody>
45
+ </table>
46
+
47
+
48
+ <div class="buttons">
49
+ <a href="<?php echo esc_url( $viewreport_link ); ?>" class="button button-ghost alignleft"><?php _e( 'View Full Report', 'wphb' ); ?></a>
50
+ <div class="alignright">
51
+ <?php
52
+ $text = __( 'Automated performance tests are disabled', 'wphb' );
53
+ if ( $notifications ) {
54
+ $text = __( 'Automated performance tests are enabled', 'wphb' );
55
+ }
56
+ ?>
57
+ <span><?php echo $text; ?></span>
58
+ </div>
59
+ </div>
60
+ <div class="clear"></div>
admin/views/dashboard/performance/running-test-meta-box.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <p><?php _e( 'Hummingbird is running a test to measure your website performance, please wait.', 'wphb' ); ?></p>
6
+
7
+ <div class="wphb-block-test wphb-block-test-standalone">
8
+ <div class="wphb-scan-progress">
9
+ <div class="wphb-scan-progress-text">
10
+ <span>0%</span>
11
+ </div><!-- end wphb-scan-progress-text -->
12
+ <div class="wphb-scan-progress-bar">
13
+ <span style="width: 0%"></span>
14
+ </div><!-- end wphb-scan-progress-bar -->
15
+ </div><!-- end wphb-scan-progress -->
16
+ </div><!-- end wphb-block-test -->
17
+
18
+ <div class="wphb-progress-state">
19
+ <span class="wphb-progress-state-text"><?php _e( 'Analyzing your site...', 'wphb' ); ?></span>
20
+ </div><!-- end wphb-progress-state -->
21
+
22
+ </div><!-- end wphb-block-entry-content -->
23
+
24
+ </div><!-- end wphb-block-entry -->
25
+
26
+
admin/views/dashboard/reports/meta-box-header.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( ! wphb_is_member() ) : ?>
3
+ <div class="buttons">
4
+ <a class="button button-content-cta" href="#wphb-upgrade-membership-modal" id="dash-reports-update-membership" rel="dialog"><?php _e( 'Upgrade to PRO', 'wphb' ); ?></a>
5
+ </div>
6
+ <?php endif; ?>
admin/views/dashboard/reports/no-membership-meta-box.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <div class="content">
6
+ <p><?php _e( "Get tailored performance reports delivered to your inbox so you don’t have to worry about checking in.", 'wphb' ); ?></p>
7
+ </div><!-- end content -->
8
+
9
+ <div class="row">
10
+ <div class="col-half">
11
+ <a href="<?php echo wphb_get_admin_menu_url( 'performance' ); ?>">
12
+ <div class="report-status with-corner">
13
+ <i class="hb-icon-performancetest"></i>
14
+ <strong><?php _e( 'Performance Test', 'wphb' ); ?></strong>
15
+ <div class="corner">
16
+ <?php _e( 'Pro', 'wphb' ); ?>
17
+ </div>
18
+ </div>
19
+ </a>
20
+ </div>
21
+ <!--
22
+ <div class="col-half">
23
+ <a href="<?php echo wphb_get_admin_menu_url( 'uptime' ); ?>">
24
+ <div class="report-status with-corner">
25
+ <i class="hb-icon-smush"></i>
26
+ <strong><?php _e( 'Uptime Report', 'wphb' ); ?></strong>
27
+ <div class="corner">
28
+ <?php _e( 'Pro', 'wphb' ); ?>
29
+ </div>
30
+ </div>
31
+ </a>
32
+ </div>
33
+ -->
34
+ </div>
35
+
36
+ <div class="content-box content-box-two-cols-image-left">
37
+ <div class="wphb-block-entry-content wphb-upsell-free-message">
38
+ <p>
39
+ <?php printf(
40
+ __( 'Schedule automated performance tests and receive email reports direct to your inbox. Get reporting as part of a full WPMU DEV membership. &mdash; <a href="%s" rel="dialog">Try Pro for FREE today!</a>', 'wphb' ),
41
+ '#wphb-upgrade-membership-modal'
42
+ ); ?>
43
+ </p>
44
+ </div>
45
+ </div>
46
+
47
+ </div><!-- end wphb-block-entry-content -->
48
+
49
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/smush/meta-box-header.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( ! wphb_is_member() && wphb_is_dashboard_logged_in() ) : ?>
3
+ <div class="buttons">
4
+ <a class="button button-content-cta" href="#wphb-upgrade-membership-modal" id="dash-uptime-update-membership" rel="dialog"><?php _e( 'Upgrade to Pro', 'wphb' ); ?></a>
5
+ </div>
6
+ <?php endif; ?>
admin/views/dashboard/smush/meta-box.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <div class="content">
6
+ <!-- No plugin is installed -->
7
+ <?php if ( ! $is_installed ) : ?>
8
+ <p><?php _e( 'Automatically compress and optimize your images with our super popular Smush plugin.', 'wphb' ); ?></p>
9
+ <?php if ( wphb_is_member() ) : ?>
10
+ <a href="<?php echo esc_url( wphb_smush_get_install_url() ); ?>" class="button" id="smush-install"><?php _e( 'Install Smush Pro', 'wphb' ); ?></a>
11
+ <?php else : ?>
12
+ <a href="<?php echo esc_url( wphb_smush_get_install_url() ); ?>" class="button" id="smush-install"><?php _e( 'Install Smush', 'wphb' ); ?></a>
13
+ <?php endif; ?>
14
+ <!-- Plugin is installed but not active -->
15
+ <?php elseif ( $is_installed && ! $is_active ) : ?>
16
+ <p><?php _e( 'WP Smush is installed but not activated! Activate and set up now to reduce page load time.', 'wphb' ); ?></p>
17
+ <?php if ( $is_pro ) : ?>
18
+ <a href="<?php echo esc_url( $activate_pro_url ); ?>" class="button" id="smush-activate"><?php _e( 'Activate Smush Pro', 'wphb' ); ?></a>
19
+ <?php else : ?>
20
+ <a href="<?php echo esc_url( $activate_url ); ?>" class="button" id="smush-activate"><?php _e( 'Activate Smush', 'wphb' ); ?></a>
21
+ <?php endif; ?>
22
+ <!-- Plugin is installed and active -->
23
+ <?php elseif ( $is_installed && $is_active ) : ?>
24
+ <?php if ( ( $smush_data['bytes'] === 0 || $smush_data['percent'] === 0 ) && $unsmushed === 0 ) : ?>
25
+ <p><?php _e( "WP Smush is installed but no images have been smushed yet. Get in there and smush away!", 'wphb' ); ?></p>
26
+ <?php elseif ( $unsmushed > 0 ) : ?>
27
+ <p><?php _e( 'Automatically compress and optimize your images with our super popular Smush plugin.', 'wphb' ); ?></p>
28
+ <div class="wphb-notice wphb-notice-warning">
29
+ <p><?php echo sprintf( __( "There are %s images that need smushing!", 'wphb' ), $unsmushed ); ?></p>
30
+ </div>
31
+ <?php else : ?>
32
+ <p><?php _e( 'Automatically compress and optimize your images with our super popular Smush plugin.', 'wphb' ); ?></p>
33
+ <div class="wphb-notice wphb-notice-success">
34
+ <p><?php echo sprintf( __( "WP Smush is installed. So far you've saved %s of space. That's a total savings of %s. Nice one!", 'wphb' ), $smush_data['human'], number_format_i18n( $smush_data['percent'], 2 ) . '%' ); ?></p>
35
+ </div>
36
+ <?php endif; ?>
37
+ <a href="<?php echo esc_url( admin_url( 'upload.php?page=wp-smush-bulk' ) ); ?>" class="button button-ghost" id="smush-link"><?php _e( 'Configure', 'wphb' ); ?></a>
38
+ <?php endif; ?>
39
+ <!-- Regular version is installed and the user in not a PRO member -->
40
+ <?php if ( ! wphb_is_member() ) : ?>
41
+ <div class="content-box content-box-two-cols-image-left">
42
+ <div class="wphb-block-entry-content wphb-upsell-free-message">
43
+ <?php printf(
44
+ __( '<p>Did you know WP Smush Pro delivers up to 2x better compression, allows you to smush your originals and removes any bulk smushing limits? &mdash; <a href="%s" rel="dialog">Try it absolutely FREE</a></p>', 'wphb' ),
45
+ '#wphb-upgrade-membership-modal'
46
+ ); ?>
47
+ </div>
48
+ </div>
49
+ <?php endif; ?>
50
+ </div><!-- end content -->
51
+
52
+ </div><!-- end wphb-block-entry-content -->
53
+
54
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/uptime/disabled-meta-box.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <div class="content">
6
+
7
+ <p><?php _e( 'Monitor your website and get notified if/when it’s inaccessible. We’ll also watch your server response time.', 'wphb' ); ?></p>
8
+ <a class="button button-cta-green" href="<?php echo esc_url( $enable_url ); ?>" id="enable-uptime"><?php _e( 'Activate', 'wphb' ); ?></a><br>
9
+ </div><!-- end content -->
10
+
11
+ </div><!-- end wphb-block-entry-content -->
12
+
13
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/uptime/error-meta-box.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <div class="row">
2
+ <div class="wphb-notice wphb-notice-error wphb-notice-box">
3
+ <p><?php echo $error; ?></p>
4
+ <a href="<?php echo esc_url( $retry_url ); ?>" class="button button-grey"><?php _e( 'Try again', 'wphb' ); ?></a>
5
+ <a target="_blank" href="<?php echo esc_url( $support_url ); ?>" class="button button-grey"><?php _e( 'Support', 'wphb' ); ?></a>
6
+ </div>
7
+ </div>
admin/views/dashboard/uptime/module-meta-box-header.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( ! wphb_is_member() ) : ?>
3
+ <div class="buttons">
4
+ <a class="button button-content-cta" href="#wphb-upgrade-membership-modal" id="dash-uptime-update-membership" rel="dialog"><?php _e( 'Upgrade to PRO', 'wphb' ); ?></a>
5
+ </div>
6
+ <?php endif; ?>
admin/views/dashboard/uptime/module-meta-box.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <ul class="dev-list dev-list-stats">
2
+
3
+ <div class="content">
4
+ <div class="wphb-notice wphb-notice-success">
5
+ <p><?php _e( 'Your website is currently up and humming.', 'wphb' ); ?></p>
6
+ </div>
7
+ </div>
8
+
9
+ <li class="dev-list-stats-item">
10
+ <div>
11
+ <span class="list-label list-label-stats"><?php _e( 'Availability', 'wphb' ); ?></span>
12
+ <span class="list-detail list-detail-stats list-detail-stats-heading"><?php echo $uptime_stats->availability; ?></span>
13
+ </div>
14
+ </li><!-- end dev-list-stats-item -->
15
+
16
+ <li class="dev-list-stats-item">
17
+ <div>
18
+ <span class="list-label list-label-stats"><?php _e( 'Downtime', 'wphb' ); ?></span>
19
+ <span class="list-detail list-detail-stats list-detail-stats-heading"><?php echo $uptime_stats->period_downtime; ?></span>
20
+ </div>
21
+ </li><!-- end dev-list-stats-item -->
22
+
23
+ <li class="dev-list-stats-item">
24
+ <div>
25
+ <span class="list-label list-label-stats"><?php _e( 'Average Response Time', 'wphb' ); ?></span>
26
+ <span class="list-detail list-detail-stats list-detail-stats-heading"><?php echo $uptime_stats->response_time ? $uptime_stats->response_time : "Calculating..."; ?></span>
27
+ </div>
28
+ </li><!-- end dev-list-stats-item -->
29
+
30
+ <li class="dev-list-stats-item">
31
+ <div>
32
+ <span class="list-label list-label-stats"><?php _e( 'Last Down', 'wphb' ); ?></span>
33
+ <?php
34
+ $gmt_date = date( 'Y-m-d H:i:s', $uptime_stats->up_since );
35
+ $site_date = get_date_from_gmt( $gmt_date, get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
36
+ ?>
37
+ <span class="list-detail list-detail-stats"><?php echo $site_date; ?></span>
38
+ </div>
39
+ </li><!-- end dev-list-stats-item -->
40
+
41
+ <div class="buttons">
42
+ <a href="<?php echo esc_url( wphb_get_admin_menu_url( 'uptime' ) ); ?>" class="button button-ghost" name="submit"><?php esc_attr_e( 'View stats', 'wphb' ); ?></a>
43
+ <span class="status-text alignright"><?php _e( 'Downtime notifications are enabled', 'wphb' ); ?></span>
44
+ </div>
45
+ </ul>
admin/views/dashboard/uptime/no-membership-meta-box.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <div class="content">
6
+ <p><?php _e( 'Monitor your website and get notified if/when it’s inaccessible. We’ll also watch your server response time.', 'wphb' ); ?></p>
7
+ </div><!-- end content -->
8
+
9
+ <div class="content-box content-box-two-cols-image-left">
10
+ <div class="wphb-block-entry-content wphb-upsell-free-message">
11
+ <p>
12
+ <?php printf(
13
+ __( 'Performance improvements hardly matter if your website isn’t accessible. Monitor your uptime and downtime with WPMU DEV’s Uptime Monitoring website management tool. &mdash; <a href="%s" rel="dialog">Try Pro for FREE today!</a>', 'wphb' ),
14
+ '#wphb-upgrade-membership-modal'
15
+ ); ?>
16
+ </p>
17
+ </div>
18
+ </div>
19
+
20
+ </div><!-- end wphb-block-entry-content -->
21
+
22
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/welcome/meta-box.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-image wphb-block-entry-image-bottom">
4
+ <img class="wphb-image"
5
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-dash-top.png'; ?>"
6
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-dash-top@2x.png'; ?> 2x"
7
+ alt="<?php esc_attr_e( 'Hummingbird', 'wphb' ); ?>">
8
+ </div>
9
+
10
+ <div class="wphb-block-entry-third">
11
+ <span class="not-present">
12
+ <?php
13
+ if ( $last_report && ! is_wp_error( $last_report ) ) :
14
+ $error_class = ( 'aplus' === $last_report->data->score_class || 'a' === $last_report->data->score_class || 'b' === $last_report->data->score_class ) ? 'tick' : 'warning';
15
+ echo $last_report->data->score . "<i class='hb-wpmudev-icon-{$error_class}'></i><span class='score-span'>/100</span>";
16
+ elseif ( wphb_performance_is_doing_report() ) : ?>
17
+ <span class="wphb-scan-progress-text"></span>
18
+ <?php else : ?>
19
+ &mdash;
20
+ <?php endif; ?>
21
+ </span>
22
+ <p class="current-performance-score"><?php _e( 'Current performance score', 'wphb' ); ?></p>
23
+ <span>
24
+ <?php
25
+ if ( $last_report && ! is_wp_error( $last_report ) ) {
26
+ $data_time = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $last_report->data->time ) ) );
27
+ echo date_i18n( get_option( 'date_format' ), $data_time ); ?> <span class="list-detail-stats-heading-extra-info"><?php printf( _x( 'at %s', 'Time of the last performance report', 'wphb' ), date_i18n( get_option( 'time_format' ), $data_time ) );
28
+ } elseif ( wphb_performance_is_doing_report() ) {
29
+ _e( 'Running scan...', 'wphb' );
30
+ } else {
31
+ _e( 'Never', 'wphb' );
32
+ } ?>
33
+ </span>
34
+ <p><?php _e( 'Last test date', 'wphb' ); ?></p>
35
+ </div>
36
+
37
+ <div class="wphb-block-entry-third">
38
+ <ul class="dev-list">
39
+ <li>
40
+ <span class="list-label"><?php _e( 'Browser Caching', 'wphb' ); ?></span>
41
+ <span class="list-detail">
42
+ <?php if ( $cf_active ) : ?>
43
+ <?php if ( 691200 === $cf_current ) : ?>
44
+ <span class="status-ok">&nbsp;</span>
45
+ <?php else : ?>
46
+ <div class="wphb-pills">!</div>
47
+ <?php endif; ?>
48
+ <?php else : ?>
49
+ <?php if ( $caching_issues ) : ?>
50
+ <div class="wphb-pills"><?php echo intval( $caching_issues ); ?></div>
51
+ <?php else : ?>
52
+ <span class="status-ok">&nbsp;</span>
53
+ <?php endif; ?>
54
+ <?php endif; ?>
55
+ </span>
56
+ </li>
57
+ <li>
58
+ <span class="list-label"><?php _e( 'GZIP Compression', 'wphb' ); ?></span>
59
+ <span class="list-detail">
60
+ <?php if ( $gzip_issues ) : ?>
61
+ <div class="wphb-pills"><?php echo intval( $gzip_issues ); ?></div>
62
+ <?php else : ?>
63
+ <span class="status-ok">&nbsp;</span>
64
+ <?php endif; ?>
65
+ </span>
66
+ </li>
67
+ <li>
68
+ <span class="list-label"><?php _e( 'Last Down', 'wphb' ); ?></span>
69
+ <span class="list-detail">
70
+ <?php if ( ! wphb_is_member() ) : ?>
71
+ <a class="button button-content-cta button-ghost" href="#wphb-upgrade-membership-modal" id="dash-uptime-update-membership" rel="dialog"><?php _e( 'Pro Feature', 'wphb' ); ?></a>
72
+ <?php elseif ( is_wp_error( $uptime_report ) || ( ! $uptime_active ) ) : ?>
73
+ <a target="_blank" class="button button-disabled" id="dash-uptime-inactive"><?php _e( 'Uptime Inactive', 'wphb' ); ?></a>
74
+ <?php else :
75
+ echo $site_date;
76
+ endif; ?>
77
+ </span>
78
+ </li>
79
+ </ul>
80
+ </div>
81
+
82
+ </div><!-- end wphb-block-entry -->
admin/views/dashboard/welcome/pro-membership-meta-box.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-content-center">
4
+
5
+ <div class="content">
6
+ <span class="callout-title"><?php _e( 'Try pro features for free!', 'wphb' ); ?></span>
7
+ <p><?php _e( 'Upgrade to Hummingbird Pro and get access to up to 2x minify compression, automated performance tests, host your files on our blazing fast WPMU DEV CDN and monitor your website’s downtime with Uptime monitor.', 'wphb' ); ?></p>
8
+ <p><?php _e( 'Get all this as part of a WPMU DEV Membership, and the best part is you can try everything absolutely free.', 'wphb' ); ?></p>
9
+
10
+ <a class="button button-large button-content-cta" href="#wphb-upgrade-membership-modal" id="dash-uptime-update-membership" rel="dialog"><?php _e( 'Find out more', 'wphb' ); ?></a>
11
+ </div><!-- end content -->
12
+
13
+ <div class="wphb-block-entry-image wphb-block-entry-image-bottom wphb-block-entry-image-center">
14
+ <img class="wphb-image"
15
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/dev-team.png'; ?>"
16
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/dev-team@2x.png'; ?> 2x"
17
+ alt="<?php esc_attr_e( 'Try pro features for free!', 'wphb' ); ?>">
18
+ </div>
19
+
20
+ </div><!-- end wphb-block-entry-content -->
21
+
22
+ </div><!-- end wphb-block-entry -->
admin/views/gzip/code-snippet-meta-box-header.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <div class="extra">
2
+ <div class="wphb-select-group">
3
+ <label for="wphb-server-type" class="inline-label"><?php _e( 'Server Type:', 'wphb' ); ?></label>
4
+ <?php wphb_get_servers_dropdown( array( 'selected' => $gzip_server_type ) ); ?>
5
+ </div>
6
+ </div>
7
+ <h3><?php echo esc_html( $title ); ?></h3>
admin/views/gzip/enable-meta-box-footer.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if( wphb_is_htaccess_writable() === true ) : ?>
2
+ <div id="enable-cache-wrap" class="<?php echo ! in_array( $server_type, array( 'apache', 'LiteSpeed' ) ) ? 'hidden' : ''; ?>">
3
+
4
+ <?php if ( $show_enable_button ): ?>
5
+ <?php if( wphb_is_htaccess_written('gzip') === true ) : ?>
6
+ <a href="<?php echo esc_url( $disable_link ); ?>" class="button button-ghost"><?php esc_attr_e( 'Disable compression', 'wphb' ); ?></a>
7
+ <?php else : ?>
8
+ <a href="<?php echo esc_url( $enable_link ); ?>" class="button"><?php esc_attr_e( 'Enable compression', 'wphb' ); ?></a>
9
+ <?php endif; ?>
10
+ <?php endif; ?>
11
+ </div>
12
+ <?php endif; ?>
admin/views/gzip/enable-meta-box.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-content">
2
+
3
+ <div id="wphb-server-instructions-apache" class="wphb-server-instructions hidden" data-server="apache">
4
+ <?php if ( $htaccess_writable && ! $gzip_already_active ): ?>
5
+ <p><?php _e( 'Hummingbird will try to write into your <strong>.htaccess</strong> file for you', 'wphb' ); ?></p>
6
+ <p><a href="#" id="toggle-apache-instructions"><?php esc_html_e( 'Want to do it manually?', 'wphb' ); ?></a></p>
7
+ <?php endif; ?>
8
+
9
+ <div class="apache-instructions <?php echo $htaccess_writable && ! $gzip_already_active ? 'hidden' : ''; ?>">
10
+
11
+ <p><?php esc_html_e( 'For Apache servers:', 'wphb'); ?></p>
12
+
13
+ <p><?php _e( 'Copy the generated code into your <strong>.htaccess</strong> file', 'wphb'); ?></p>
14
+
15
+ <p><?php _e( 'If .htaccess does not work, and you have access to <strong>vhosts.conf</strong> or <strong>httpd.conf</strong> try this:', 'wphb' ); ?></p>
16
+ <ol class="wphb-listing wphb-listing-ordered">
17
+ <li><?php esc_html_e( 'Look for your site in the file and find the line that starts with <Directory> - add the code above into that section and save the file.', 'wphb' ); ?></li>
18
+ <li><?php _e( 'Reload Apache.', 'wphb' ); ?></li>
19
+ </ol>
20
+
21
+ <p><?php _e( 'If you don\'t know where those files are, or you aren\'t able to reload Apache, you would need to <strong>consult with your hosting provider or a system administrator who has access</strong> to change the configuration of your server', 'wphb' ); ?></p>
22
+
23
+ <?php _wphb_still_having_trouble_link(); ?>
24
+
25
+ <div id="wphb-code-snippet">
26
+ <div id="wphb-code-snippet-apache" class="wphb-code-snippet">
27
+ <div class="wphb-block-content">
28
+ <pre><?php echo htmlentities2( $snippets['apache'] ); ?></pre>
29
+ </div>
30
+
31
+ </div>
32
+ </div>
33
+
34
+ </div>
35
+ </div>
36
+
37
+ <div id="wphb-server-instructions-litespeed" class="wphb-server-instructions hidden" data-server="LiteSpeed">
38
+ <?php if ( $htaccess_writable && ! $gzip_already_active ): ?>
39
+ <p><?php _e( 'Hummingbird will try to write into your <strong>.htaccess</strong> file for you', 'wphb' ); ?></p>
40
+ <p><a href="#" id="toggle-litespeed-instructions"><?php esc_html_e( 'Want to do it manually?', 'wphb' ); ?></a></p>
41
+ <?php endif; ?>
42
+
43
+ <div class="litespeed-instructions <?php echo $htaccess_writable && ! $gzip_already_active ? 'hidden' : ''; ?>">
44
+
45
+ <p><?php esc_html_e( 'For LiteSpeed servers:', 'wphb'); ?></p>
46
+
47
+ <p><?php _e( 'Copy the generated code into your <strong>.htaccess</strong> file', 'wphb'); ?></p>
48
+
49
+ <p><?php _e( 'If .htaccess does not work, and you have access to <strong>vhosts.conf</strong> or <strong>httpd.conf</strong> try this:', 'wphb' ); ?></p>
50
+ <ol class="wphb-listing wphb-listing-ordered">
51
+ <li><?php esc_html_e( 'Look for your site in the file and find the line that starts with <Directory> - add the code above into that section and save the file.', 'wphb' ); ?></li>
52
+ <li><?php _e( 'Reload LiteSpeed.', 'wphb' ); ?></li>
53
+ </ol>
54
+
55
+ <p><?php _e( 'If you don\'t know where those files are, or you aren\'t able to reload Apache, you would need to <strong>consult with your hosting provider or a system administrator who has access</strong> to change the configuration of your server', 'wphb' ); ?></p>
56
+
57
+ <?php _wphb_still_having_trouble_link(); ?>
58
+
59
+ <div id="wphb-code-snippet">
60
+ <div id="wphb-code-snippet-litespeed" class="wphb-code-snippet">
61
+ <div class="wphb-block-content">
62
+ <pre><?php echo htmlentities2( $snippets['litespeed'] ); ?></pre>
63
+ </div>
64
+
65
+ </div>
66
+ </div>
67
+
68
+ </div>
69
+ </div>
70
+
71
+ <div id="wphb-server-instructions-nginx" class="wphb-server-instructions hidden" data-server="nginx">
72
+ <p><?php esc_html_e( 'For NGINX servers:', 'wphb'); ?></p>
73
+
74
+ <ol class="wphb-listing wphb-listing-ordered">
75
+ <li><?php _e( 'Copy the generated code into your <strong>nginx.conf</strong> usually located at <strong>/etc/nginx/nginx.conf</strong> or <strong>/usr/local/nginx/conf/nginx.conf</strong>', 'wphb' ); ?></li>
76
+ <li><?php _e( 'Add the code below to the <strong>http</strong> section in the file.', 'wphb' ); ?></li>
77
+ <li><?php _e( 'Reload NGINX.', 'wphb' ); ?></li>
78
+ </ol>
79
+
80
+ <p><?php _e( 'If you do not have access to your NGINX config files you will need to contact your hosting provider to make these changes.', 'wphb' ); ?></p>
81
+ <?php _wphb_still_having_trouble_link(); ?>
82
+
83
+ <div id="wphb-code-snippet">
84
+ <div id="wphb-code-snippet-apache" class="wphb-code-snippet">
85
+ <div class="wphb-block-content">
86
+ <pre><?php echo htmlentities2( $snippets['nginx'] ); ?></pre>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </div>
91
+
92
+ <div id="wphb-server-instructions-iis" class="wphb-server-instructions hidden" data-server="iis">
93
+ <p><?php printf( __( 'For IIS servers, <a href="%s">visit Microsoft TechNet</a>', 'wphb'), 'https://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/25d2170b-09c0-45fd-8da4-898cf9a7d568.mspx?mfr=true' ); ?></p>
94
+ </div>
95
+
96
+ <div id="wphb-server-instructions-iis-7" class="wphb-server-instructions hidden" data-server="iis-7">
97
+ <p><?php printf( __( 'For IIS 7 servers, <a href="%s">visit Microsoft TechNet</a>', 'wphb'), 'https://technet.microsoft.com/en-us/library/cc771003(v=ws.10).aspx' ); ?></p>
98
+ </div>
99
+
100
+ </div>
admin/views/gzip/enabled-meta-box.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <div class="wphb-content">
2
+ <div class="wphb-gzip-success wphb-notice wphb-notice-success">
3
+ <p><?php _e( 'Looks like gzip has been successfully setup, nice!', 'wphb' ); ?></p>
4
+ </div>
5
+ </div>
admin/views/gzip/summary-meta-box-header.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <div class="buttons">
2
+ <a href="<?php echo esc_url( $recheck_url ); ?>" class="button button-ghost" name="submit"><?php esc_attr_e( 'Re-Check Status', 'wphb' ); ?></a>
3
+ </div>
4
+ <h3><?php echo esc_html( $title ); ?></h3>
admin/views/gzip/summary-meta-box.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( $external_problem ): ?>
2
+ <div class="wphb-gzip-error wphb-notice wphb-notice-error">
3
+ <p><?php _e( 'gzip is not working properly:', 'wphb' ); ?></p>
4
+ <ul>
5
+ <li>- <?php _e( 'Your server may not have the "deflate" module enabled (mod_deflate for Apache, ngx_http_gzip_module for NGINX)', 'wphb' ); ?></li>
6
+ <li>- <?php _e( 'Another plugin may be interfering with the configuration', 'wphb' ); ?></li>
7
+ </ul>
8
+ <p><?php printf( __( 'If re-checking and restarting does not resolve, please check with your host or <a href="%s" target="_blank">open a support ticket with us</a>.', 'wphb' ), wphb_support_link() ); ?></p>
9
+ </div>
10
+ <?php endif; ?>
11
+
12
+ <ul class="dev-list">
13
+
14
+ <div class="content">
15
+ <p><?php _e( "Gzip compresses your HTML, JavaScript, and Style Sheets before sending them over to the browser. This drastically reduces transfer time since the files are much smaller.", 'wphb' ); ?></p>
16
+ </div>
17
+
18
+ <?php foreach ( $status as $type => $result ): ?>
19
+ <?php if ( $result == 1 ) {
20
+ $resultStatus = __( 'Enabled', 'wphb' );
21
+ $resultStatusColor = 'green';
22
+ } else {
23
+ $resultStatus = __( 'Disabled', 'wphb' );
24
+ $resultStatusColor = 'red';
25
+ } ?>
26
+ <li>
27
+ <div>
28
+ <span class="list-label"><?php echo $type; ?></span>
29
+ <span class="list-detail">
30
+ <span class="wphb-button-label wphb-button-label-<?php echo $resultStatusColor; ?>" tooltip="<?php echo sprintf( __( 'Gzip compression is %s for %s', 'wphb' ), $resultStatus, $type ); ?>">
31
+ <?php echo $resultStatus; ?>
32
+ </span>
33
+ </span>
34
+ </div>
35
+ </li>
36
+ <?php endforeach; ?>
37
+
38
+ </ul>
admin/views/meta-box.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <section id="wphb-box-<?php echo $id; ?>" class="box-<?php echo $id; ?> <?php echo $args['box_class']; ?>">
2
+
3
+ <?php if ( is_callable( $callback_header ) ): ?>
4
+ <div class="<?php echo $args['box_header_class']; ?>">
5
+ <?php call_user_func( $callback_header ); ?>
6
+ </div><!-- end box-title -->
7
+ <?php elseif ( $this->view_exists( $orig_id . '/meta-box-header' ) ): ?>
8
+ <div class="<?php echo $args['box_header_class']; ?>">
9
+ <?php $this->view( $orig_id . '/meta-box-header', array( 'title' => $title ) ); ?>
10
+ </div><!-- end box-title -->
11
+ <?php elseif ( $this->view_exists( $orig_id . '-meta-box-header' ) ): ?>
12
+ <div class="<?php echo $args['box_header_class']; ?>">
13
+ <?php $this->view( $orig_id . '-meta-box-header', array( 'title' => $title ) ); ?>
14
+ </div><!-- end box-title -->
15
+ <?php elseif ( $title ) : ?>
16
+ <div class="<?php echo $args['box_header_class']; ?>">
17
+ <h3><?php echo esc_html( $title ); ?></h3>
18
+ </div><!-- end box-title -->
19
+ <?php endif; ?>
20
+
21
+ <div class="<?php echo $args['box_content_class']; ?>">
22
+ <?php if ( is_callable( $callback ) ): ?>
23
+ <?php call_user_func( $callback ); ?>
24
+ <?php else: ?>
25
+ <?php $this->view( $orig_id . '-meta-box' ); ?>
26
+ <?php endif; ?>
27
+ </div><!-- end box-content -->
28
+
29
+ <?php if ( is_callable( $callback_footer ) ): ?>
30
+ <div class="<?php echo $args['box_footer_class']; ?>">
31
+ <?php call_user_func( $callback_footer ); ?>
32
+ </div><!-- end box-footer -->
33
+ <?php elseif ( $this->view_exists( $orig_id . '/meta-box-footer' ) ): ?>
34
+ <div class="<?php echo $args['box_footer_class']; ?>">
35
+ <?php $this->view( $orig_id . '/meta-box-footer' ); ?>
36
+ </div><!-- end box-footer -->
37
+ <?php elseif ( $this->view_exists( $orig_id . '-meta-box-footer' ) ): ?>
38
+ <div class="<?php echo $args['box_footer_class']; ?>">
39
+ <?php $this->view( $orig_id . '-meta-box-footer' ); ?>
40
+ </div><!-- end box-footer -->
41
+ <?php endif; ?>
42
+
43
+ </section><!-- end box-<?php echo $id; ?> -->
admin/views/minification/advanced-settings-header.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( ! $is_member ): ?>
3
+ <div class="buttons">
4
+ <a class="button button-content-cta" href="#wphb-upgrade-membership-modal" id="dash-uptime-update-membership" rel="dialog"><?php _e( 'Try Pro Features free', 'wphb' ); ?></a>
5
+ </div>
6
+ <?php endif; ?>
admin/views/minification/advanced-settings.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-notice wphb-notice-success hidden" id="wphb-notice-minification-advanced-settings-updated">
2
+ <p><?php _e( 'Settings updated', 'wphb' ); ?></p>
3
+ </div>
4
+
5
+ <div class="toggle-item">
6
+
7
+ <div class="toggle-item-group">
8
+ <div class="toggle-item-info">
9
+ <p class="toggle-item-title"><?php _e( 'Super-minify my files', 'wphb' ); ?></p>
10
+ <p class="toggle-item-description"><?php _e( 'Compress your files up to 2x more than regular optimization and reduce your page load speed even further.', 'wphb' ); ?></p>
11
+ </div><!-- end toggle-item-info -->
12
+
13
+ <div class="toggle-actions">
14
+ <?php if ( $super_minify ): ?>
15
+ <span class="wphb-label wphb-label-disabled"><?php _e( 'Auto Enabled', 'wphb' ); ?></span>
16
+ <?php else: ?>
17
+ <span class="toggle tooltip-right" tooltip="<?php _e( 'Enable Super-minify my files', 'wphb' ); ?>">
18
+ <input type="checkbox" class="toggle-checkbox" name="super_minify_files" id="super_minify_files" <?php checked( $use_cdn ); ?> <?php disabled( $disabled ); ?>>
19
+ <label for="super_minify_files" class="toggle-label"></label>
20
+ </span>
21
+ <?php endif; ?>
22
+ </div><!-- end toggle-actions -->
23
+ </div><!-- end toggle-item-group -->
24
+
25
+ </div><!-- end toggle-item -->
26
+
27
+ <div class="toggle-item bordered space-top">
28
+
29
+ <div class="toggle-item-group">
30
+ <div class="toggle-item-info">
31
+ <p class="toggle-item-title"><?php _e( 'Store my files on the WPMU DEV CDN', 'wphb' ); ?></p>
32
+ <p class="toggle-item-description"><?php _e( 'By default we minify your files via our API and then send back to your server. With this setting enabled we will host your files on WPMU DEV\'s secure and hyper fast CDN which will mean less load on your server and a fast visitor experience.', 'wphb' ); ?></p>
33
+ </div><!-- end toggle-item-info -->
34
+
35
+ <div class="toggle-actions">
36
+ <span class="toggle tooltip-right" tooltip="<?php _e( 'Enable WPMU DEV CDN', 'wphb' ); ?>">
37
+ <input type="checkbox" class="toggle-checkbox" name="use_cdn" id="use_cdn" <?php checked( $use_cdn ); ?> <?php disabled( $disabled ); ?>>
38
+ <label for="use_cdn" class="toggle-label"></label>
39
+ </span>
40
+ </div><!-- end toggle-actions -->
41
+ </div><!-- end toggle-item-group -->
42
+
43
+ </div><!-- end toggle-item -->
44
+
45
+ <?php if ( $disabled ) : ?>
46
+ <div class="wphb-block-entry with-bottom-border">
47
+ <div class="wphb-block-entry-content">
48
+ <div class="content">
49
+ <div class="content-box content-box-two-cols-image-left">
50
+ <div class="wphb-block-entry-image wphb-block-entry-image-bottom">
51
+ <img class="wphb-image"
52
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hummingbird-upsell-minify.png'; ?>"
53
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/hummingbird-upsell-minify@2x.png'; ?> 2x"
54
+ alt="<?php esc_attr_e( 'WP Smush free installed', 'wphb' ); ?>">
55
+ </div>
56
+ <div class="wphb-block-entry-content wphb-upsell-free-message">
57
+ <p>
58
+ <?php printf(
59
+ __( "With our pro version of Hummingbird you can super-minify your files and then host them on our blazing fast CDN. You'll get Hummingbird PRO plus 100+ WPMU DEV plugins, themes & 24/7 WP support. <a href='%s' rel='dialog'>Try it free for 14 days</a>!", 'wphb' ),
60
+ '#wphb-upgrade-membership-modal'
61
+ ); ?>
62
+ </p>
63
+ </div>
64
+ </div>
65
+ </div><!-- end content -->
66
+ </div><!-- end wphb-block-entry-content -->
67
+ </div><!-- end wphb-block-entry -->
68
+ <?php wphb_membership_modal(); ?>
69
+ <?php endif; ?>
70
+
71
+ <div class="wphb-block-entry <?php echo ( ! $disabled ) ? 'bordered space-top' : '' ?>">
72
+ <div class="wphb-block-entry-content">
73
+ <div class="content">
74
+ <strong><?php _e( 'Deactivate', 'wphb' ); ?></strong>
75
+ <p><?php _e( "If you no longer wish to use Hummingbird’s Minification feature you can turn it off completely.", 'wphb' ); ?></p>
76
+ <div class="buttons">
77
+ <a href="<?php echo esc_url( add_query_arg( 'wphb-clear', 'true' ) ); ?>" class="button button-ghost button-large"><?php _e( 'Deactivate', 'wphb' ); ?></a>
78
+ </div>
79
+ </div><!-- end content -->
80
+ </div><!-- end wphb-block-entry-content -->
81
+ </div><!-- end wphb-block-entry -->
admin/views/minification/enqueued-files-empty-meta-box.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+ <div class="wphb-block-entry-content wphb-block-content-center">
3
+
4
+ <img class="wphb-image wphb-image-center wphb-image-icon-content-top"
5
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-reports-disabled@1x.png'; ?>"
6
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-reports-disabled@2x.png'; ?> 2x"
7
+ alt="<?php esc_attr_e( 'Reduce your page load time!', 'wphb' ); ?>">
8
+
9
+ <div class="content">
10
+ <p><?php echo sprintf( __( "Hummingbird's Minification engine can combine and minify the files your website outputs when a <br> user visits your website. The less requests your visitors have to make to your server, the <br> better. Let's check to see what we can optimise, %s!", 'wphb' ), $user ); ?></p>
11
+ <a id="check-files" class="button button-large" href="#check-files-modal" rel="dialog"><?php _e( 'Activate Minification', 'wphb' ); ?></a>
12
+ </div><!-- end content -->
13
+
14
+ </div><!-- end wphb-block-entry-content -->
15
+
16
+ </div><!-- end wphb-block-entry -->
17
+
18
+ <script>
19
+ jQuery('#enable-cdn').on('click', function(e) {
20
+ e.preventDefault();
21
+ WDP.showOverlay( '#enable-cdn-modal', { class: 'wphb-modal small wphb-progress-modal no-close' } );
22
+ })
23
+ </script>
24
+
25
+ <?php
26
+ wphb_check_files_modal();
27
+
28
+ if ( ! is_multisite() ) {
29
+ wphb_enable_cdn_modal();
30
+ }
31
+
32
+ if ( $checking_files || isset( $_GET['wphb-cache-cleared'] ) ): // Show the progress bar if we are still checking files ?>
33
+ <script>
34
+ jQuery(document).ready( function() {
35
+ var module = WPHB_Admin.getModule( 'minification' );
36
+ jQuery('#check-files').trigger('click');
37
+ });
38
+ </script>
39
+ <?php endif; ?>
admin/views/minification/enqueued-files-meta-box-footer.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <span>
2
+ <?php _e( 'Saving changes will regenerate any necessary assets, this may take a few seconds to run.', 'wphb' ); ?>
3
+ </span>
admin/views/minification/enqueued-files-meta-box-header.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <div class="buttons buttons-group">
3
+ <p class="wphb-label-notice-inline hide-to-mobile"><?php _e( 'Not seeing all your files in this list?', 'wphb' ); ?></p>
4
+ <input type="submit" class="button button-ghost" name="clear-cache" value="<?php esc_attr_e( 'Re-Check Files', 'wphb' ); ?>"/>
5
+ <a href="<?php echo esc_url( add_query_arg( 'wphb-clear', 'true' ) ); ?>" class="button button-ghost"><?php _e( 'Start over', 'wphb' ); ?></a>
6
+ </div>
admin/views/minification/enqueued-files-meta-box.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!--<div class="wphb-table-wrapper complex">-->
2
+
3
+ <?php if ( $is_server_error ): ?>
4
+ <div class="wphb-notice wphb-notice-error wphb-notice-box can-close">
5
+ <span class="close"></span>
6
+ <p><?php printf( __( 'It seems that we are having problems in our servers. Minification will be turned off for %d minutes', 'wphb' ), $error_time_left ); ?></p>
7
+ <p><?php echo $server_errors[0]->get_error_message(); ?></p></p>
8
+ </div>
9
+ <?php endif; ?>
10
+
11
+ <p><?php _e( 'Choose what files to minify, combine and where to position them in the page.', 'wphb' ); ?></p>
12
+
13
+ <div class="alignleft">
14
+ <a href="#bulk-update-modal" class="button button-notice disabled" id="bulk-update" rel="dialog"><?php _e( 'Bulk Update', 'wphb' ); ?></a>
15
+ </div>
16
+ <div class="buttons alignright">
17
+ <a href="#" class="button button-ghost" id="wphb-minification-filter-button"><?php _e( 'Filter', 'wphb' ); ?></a>
18
+ </div>
19
+ <div class="clear"></div>
20
+
21
+ <div id="wphb-minification-filter" class="wphb-border-frame hidden">
22
+ <div class="wphb-minification-filter-block" id="wphb-minification-filter-block-search">
23
+ <h3 class="wphb-block-title"><?php _e( 'Filter', 'wphb' ); ?></h3>
24
+
25
+ <div class="wphb-filters-data">
26
+
27
+ <div class="wphb-minification-filter-field wphb-minification-filter-field-select">
28
+ <label for="wphb-secondary-filter" class="screen-reader-text"><?php _e( 'Filter plugin or theme.', 'wphb' ); ?></label>
29
+ <select name="wphb-secondary-filter" id="wphb-secondary-filter">
30
+ <option value=""><?php esc_html_e( 'Choose Plugin or Theme', 'wphb' ); ?></option>
31
+ <option value="other"><?php esc_html_e( 'Others', 'wphb' ); ?></option>
32
+ <?php foreach ( $selector_filter as $secondary_filter ): ?>
33
+ <option value="<?php echo esc_attr( $secondary_filter ); ?>"><?php echo esc_html( $secondary_filter ); ?></option>
34
+ <?php endforeach; ?>
35
+ </select>
36
+ </div>
37
+
38
+ <div class="wphb-minification-filter-field wphb-minification-filter-field-search">
39
+ <label for="wphb-s" class="screen-reader-text"><?php _e( 'Search by name or extension', 'wphb' ); ?></label>
40
+ <input type="text" id="wphb-s" name="s" placeholder="<?php esc_attr_e( 'Search by name or extension', 'wphb' ); ?>" autocomplete="off">
41
+ </div>
42
+
43
+ </div>
44
+
45
+ </div>
46
+ </div>
47
+
48
+ <div class="wphb-enqueued-files">
49
+ <div class="wphb-border-row-header">
50
+ <div class="wphb-minification-file-select">
51
+ <label for="minification-bulk-file" class="screen-reader-text"><?php _e( 'Hello', 'wphb' ); ?></label>
52
+ <input type="checkbox" id="minification-bulk-file" name="minification-bulk-files" class="wphb-minification-bulk-file-selector">
53
+ </div>
54
+ <div class="wphb-minification-file-details"><?php _e( 'File Details', 'wphb' ); ?></div>
55
+ <div class="wphb-minification-exclude">&nbsp;</div>
56
+ <div class="wphb-minification-row-details">
57
+ <span><?php _e( 'Configuration', 'wphb' ); ?></span>
58
+ <span><?php _e( 'Filesize', 'wphb' ); ?></span>
59
+ </div>
60
+ </div>
61
+ <?php echo $styles_rows; ?>
62
+ <?php echo $scripts_rows; ?>
63
+ <div class="buttons alignright">
64
+ <button type="submit" class="button button-grey button-large wphb-discard hidden"><?php esc_html_e( 'Discard Changes', 'wphb' ); ?></button>
65
+ <input type="submit" class="button button-large" name="submit" value="<?php esc_attr_e( 'Save Changes', 'wphb' ); ?>"/>
66
+ </div>
67
+ <div class="clear"></div>
68
+ </div>
69
+
70
+ <!--</div>-->
71
+
72
+ <?php wp_nonce_field( 'wphb-enqueued-files' ); ?>
73
+ <?php wphb_bulk_update_modal(); ?>
74
+
75
+ <script type="text/javascript">
76
+ jQuery(document).ready(function() {
77
+ jQuery( trackChanges );
78
+
79
+ // track changes made to the form
80
+ function trackChanges(){
81
+ jQuery('.wphb-discard').hide();
82
+
83
+ jQuery(':input').on('change', function( objEvent ) {
84
+
85
+ jQuery( this ).toggleClass('changed');
86
+ var $changed = jQuery('.wphb-enqueued-files').find('input.changed');
87
+ if ( $changed.length === 0 ) {
88
+ jQuery('.wphb-discard').hide();
89
+ jQuery('#bulk-update').removeClass('button-grey');
90
+ jQuery('#bulk-update').addClass('button-notice disabled');
91
+ } else {
92
+ jQuery('.wphb-discard').show();
93
+ jQuery('#bulk-update').removeClass('button-notice disabled');
94
+ jQuery('#bulk-update').addClass('button-grey');
95
+ }
96
+ });
97
+ }
98
+
99
+ // toggle checkboxes
100
+ jQuery('#minification-bulk-file').on('click', function() {
101
+ const checkBoxes = jQuery('input[class=wphb-minification-file-selector]');
102
+ checkBoxes.prop('checked', !checkBoxes.prop('checked'));
103
+ });
104
+ })
105
+ </script>
admin/views/minification/enqueued-files-rows.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <input type="hidden" name="<?php echo $base_name; ?>[handle]" value="<?php echo $item['handle']; ?>"/>
2
+ <div class="wphb-border-row
3
+ <?php echo ( in_array( $item['handle'], $options['block'][ $type ] ) ) ? 'disabled' : ''; ?>"
4
+ id="wphb-file-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>"
5
+ data-filter="<?php echo $item['handle'] . ' ' . strtolower( $ext ); ?>"
6
+ data-filter-secondary="<?php echo esc_attr( $filter ); echo 'OTHER' === $ext ? 'other' : ''?>">
7
+
8
+ <div class="wphb-minification-file-select">
9
+ <label for="minification-file-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>" class="screen-reader-text"><?php _e( 'Hello', 'wphb' ); ?></label>
10
+ <input type="checkbox" data-type="<?php echo strtolower( $ext ); ?>" data-handle="<?php echo $item['handle']; ?>" id="minification-file-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>" name="minification-file[]" class="wphb-minification-file-selector">
11
+ </div>
12
+ <div class="wphb-minification-file-details">
13
+ <span class="wphb-filename-extension wphb-filename-extension-<?php echo strtolower( $ext ); ?>"><?php echo substr( $ext, 0, 3 ); ?></span>
14
+ <div class="wphb-filename-info">
15
+ <span class="wphb-filename-info-name"><?php echo $item['handle']; ?></span>
16
+ <a class="wphb-filename-info-url" target="_blank" href="<?php echo esc_url( $full_src ); ?>"><?php echo $rel_src; ?></a>
17
+ <?php if ( $row_error ): ?>
18
+ <p class="wphb-label wphb-label-error"><?php printf( __( '<strong>Error:</strong> %s', 'wphb' ), $row_error['error'] ); ?></p>
19
+ <?php endif; ?>
20
+ </div>
21
+ </div>
22
+
23
+ <div class="wphb-minification-exclude">
24
+ <div class="tooltip-box">
25
+ <span class="toggle tooltip-s tooltip-right" tooltip="<?php _e( 'Include/Exclude file', 'wphb' ); ?>">
26
+ <label for="wphb-minification-include-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>"
27
+ class="toggle-cross"
28
+ data-type="<?php echo strtolower( $ext ); ?>"
29
+ data-handle="<?php echo $item['handle']; ?>">
30
+ <input type="checkbox"
31
+ <?php disabled( in_array( 'include', $disable_switchers ) ); ?>
32
+ id="wphb-minification-include-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>"
33
+ class="toggle-checkbox toggle-include"
34
+ name="<?php echo $base_name; ?>[include]"
35
+ <?php checked( in_array( $item['handle'], $options['block'][ $type ] ), false ); ?>
36
+ value="1">
37
+ <i class="<?php echo ( in_array( $item['handle'], $options['block'][ $type ] ) ) ? 'wdv-icon wdv-icon-refresh' : 'dev-icon dev-icon-cross'; ?>"></i>
38
+ </label>
39
+ </span>
40
+ </div>
41
+ </div>
42
+
43
+ <div class="wphb-minification-row-details">
44
+ <div class="wphb-minification-configuration">
45
+ <strong><?php _e( 'Configuration', 'wphb' ); ?></strong>
46
+ <div class="tooltip-box">
47
+ <div class="checkbox-group">
48
+ <?php
49
+ $tooltip = __( "Compress this file to reduce it’s filesize", 'wphb' );
50
+ if ( in_array( 'minify', $disable_switchers ) && ! in_array( $item['handle'], $options['block'][ $type ] ) ) {
51
+ $tooltip = __( "Hummingbird can't compress this file", 'wphb' );
52
+ $dont_minify = true;
53
+ } ?>
54
+ <input type="checkbox" <?php disabled( in_array( 'minify', $disable_switchers ) || in_array( $item['handle'], $options['block'][ $type ] ) ); ?> id="wphb-minification-minify-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>" class="toggle-checkbox toggle-minify" name="<?php echo $base_name; ?>[minify]" <?php checked( in_array( $item['handle'], $options['dont_minify'][ $type ] ), false ); ?>>
55
+ <label for="wphb-minification-minify-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>" class="toggle-label">
56
+ <span class="toggle tooltip-l" tooltip="<?php echo $tooltip; ?>"></span>
57
+ <i class="hb-icon-minify"></i>
58
+ <span><?php _e( 'Minify', 'wphb' ); ?></span>
59
+ </label>
60
+ <?php
61
+ $tooltip = __( 'Combine this file with others if possible', 'wphb' );
62
+ if ( in_array( 'combine', $disable_switchers ) && ! in_array( $item['handle'], $options['block'][ $type ] ) ) {
63
+ $tooltip = __( "Hummingbird can't combine this file with others", 'wphb' );
64
+ $dont_combine = true;
65
+ } ?>
66
+ <input type="checkbox" <?php disabled( in_array( 'combine', $disable_switchers ) || in_array( $item['handle'], $options['block'][ $type ] ) ); ?> class="toggle-checkbox toggle-combine" name="<?php echo $base_name; ?>[combine]" id="wphb-minification-combine-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>" <?php checked( in_array( $item['handle'], $options['combine'][ $type ] ) ); ?>>
67
+ <label for="wphb-minification-combine-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>" class="toggle-label">
68
+ <span class="toggle tooltip-l" tooltip="<?php echo $tooltip; ?>"></span>
69
+ <i class="hb-icon-minify-combine"></i>
70
+ <span><?php _e( 'Combine', 'wphb' ); ?></span>
71
+ </label>
72
+ <input type="checkbox" <?php disabled( in_array( 'position', $disable_switchers ) || in_array( $item['handle'], $options['block'][ $type ] ) ); ?> class="toggle-checkbox toggle-position-footer" name="<?php echo $base_name; ?>[position]" id="wphb-minification-position-footer-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>" <?php checked( $position, 'footer' ); ?> value="footer">
73
+ <label for="wphb-minification-position-footer-<?php echo strtolower( $ext ) . '-' . $item['handle']; ?>" class="toggle-label">
74
+ <span class="toggle tooltip-l" tooltip="<?php _e( 'Load this file in the footer of the page', 'wphb' ); ?>"></span>
75
+ <i class="hb-icon-minify-footer"></i>
76
+ <span><?php _e( 'Footer', 'wphb' ); ?></span>
77
+ </label>
78
+ </div>
79
+ </div>
80
+ </div><!-- end wphb-minification-configuration -->
81
+
82
+ <div class="wphb-minification-file-size">
83
+ <strong><?php _e( 'File size', 'wphb' ); ?></strong>
84
+ <?php if ( $original_size && $compressed_size ): ?>
85
+ <div>
86
+ <span class=""><?php echo $original_size; ?>KB</span>
87
+ <span class="dev-icon dev-icon-caret_down"></span>
88
+ <span class=""><?php echo $compressed_size; ?>KB</span>
89
+ </div>
90
+ <div class="wphb-scan-progress">
91
+ <div class="wphb-scan-progress-bar">
92
+ <span style="width: 80%"></span>
93
+ </div>
94
+ </div>
95
+ <?php elseif ( isset( $dont_minify ) && isset( $dont_combine ) && ! in_array( $item['handle'], $options['block'][ $type ] ) ): ?>
96
+ <span class="tooltip tooltip-s" tooltip="<?php _e( 'This file type cannot be minified and will be left alone', 'wphb' ); ?>"><?php _e( 'Ignored', 'wphb' ); ?></span>
97
+ <?php elseif ( in_array( $item['handle'], $options['block'][ $type ] ) ): ?>
98
+ <span class="tooltip tooltip-s" tooltip="<?php _e( 'Excluded from processing', 'wphb' ); ?>"><?php _e( 'Excluded', 'wphb' ); ?></span>
99
+ <?php else: ?>
100
+ <span class="tooltip tooltip-s" tooltip="<?php _e( 'Waiting for a visitor to visit your homepage', 'wphb' ); ?>"><?php _e( 'Pending', 'wphb' ); ?></span>
101
+ <?php endif; ?>
102
+ </div><!-- end wphb-minification-file-size -->
103
+ </div><!-- end wphb-minification-row-details -->
104
+ </div><!-- end wphb-border-row -->
admin/views/minification/export-form.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $settings = wphb_get_settings();
4
+
5
+ $minification_options = array(
6
+ 'blocked' => $settings['block'],
7
+ 'dont_minify' => $settings['dont_minify'],
8
+ 'combine' => $settings['combine'],
9
+ 'position' => $settings['position'],
10
+ 'plugins' => get_option( 'active_plugins' ),
11
+ 'network_plugins' => get_site_option( 'active_sitewide_plugins' ),
12
+ 'theme' => get_stylesheet()
13
+ );
14
+ ?>
15
+
16
+ <p>Copy this and paste into your development site</p>
17
+ <pre style="width:70%">
18
+ <?php echo wp_json_encode( $minification_options ); ?>
19
+ </pre>
20
+
21
+ <?php if ( defined( 'WPHB_IMPORT_MINIFICATION' ) && WPHB_IMPORT_MINIFICATION ): ?>
22
+ <?php
23
+ if ( isset( $_POST['action'] ) && $_POST['action'] === 'import-minification' ) {
24
+ check_admin_referer( 'import-minification' );
25
+ $json = json_decode( $_POST['json'] );
26
+ if ( is_array( $json ) ) {
27
+
28
+ }
29
+ }
30
+ ?>
31
+ <form action="" method="post">
32
+ <p>Paste your JSON here</p>
33
+ <?php wp_nonce_field( 'check-minification' ); ?>
34
+ <input type="hidden" name="action" value="check-minification">
35
+ <textarea name="json" id="" cols="30" rows="10">
36
+
37
+ </textarea>
38
+ <?php submit_button( 'Submit', 'primary', 'submit-minification-import' ); ?>
39
+ </form>
40
+ <?php else: ?>
41
+ <p>Want to import settings? Use <code>define( 'WPHB_IMPORT_MINIFICATION', true );</code> in your wp-config.php file</p>
42
+ <?php endif; ?>
admin/views/minification/summary-meta-box.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-image wphb-block-entry-image-bottom">
4
+ <img class="wphb-image"
5
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/graphic-hb-minify-summary.png'; ?>"
6
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/graphic-hb-minify-summary@2x.png'; ?> 2x"
7
+ alt="<?php _e('Hummingbird', 'wphb'); ?>">
8
+ </div>
9
+
10
+ <div class="wphb-block-entry-third">
11
+ <span class="not-present">
12
+ <?php if ( ! $percentage ) : ?>
13
+ -
14
+ <?php else : ?>
15
+ <?php echo intval( $percentage ); ?>%
16
+ <?php endif; ?>
17
+ </span>
18
+ <p><?php _e( 'Total minified file savings', 'wphb' ); ?></p>
19
+ </div>
20
+
21
+ <div class="wphb-block-entry-third">
22
+ <ul class="dev-list">
23
+ <li>
24
+ <span class="list-label"><?php _e( 'Files found', 'wphb' ); ?></span>
25
+ <span class="list-detail">
26
+ <div class="wphb-dash-numbers"><?php echo intval( $enqueued_files ); ?></div>
27
+ </span>
28
+ </li>
29
+ <li>
30
+ <span class="list-label"><?php _e( 'Size reductions', 'wphb' ); ?></span>
31
+ <span class="list-detail">
32
+ <div class="wphb-dash-numbers"><?php echo intval( $compressed_size ); ?>kb</div>
33
+ </span>
34
+ </li>
35
+
36
+ <?php if ( ! is_multisite() ): ?>
37
+ <?php if ( wphb_is_member() ): ?>
38
+ <li>
39
+ <span class="list-label"><?php _e( 'WPMU DEV CDN', 'wphb' ); ?></span>
40
+ <span class="list-detail">
41
+ <div class="toggle-actions">
42
+ <span class="toggle tooltip-right" tooltip="<?php _e( 'Enable WPMU DEV CDN', 'wphb' ); ?>">
43
+ <input type="checkbox" class="toggle-checkbox" name="use_cdn" id="use_cdn" <?php checked( $use_cdn ); ?> <?php disabled( ! $is_member ); ?>>
44
+ <label for="use_cdn" class="toggle-label"></label>
45
+ </span>
46
+ </div><!-- end toggle-actions -->
47
+ </span>
48
+ </li>
49
+ <?php else: ?>
50
+ <li>
51
+ <span class="list-label"><?php _e( 'WPMU DEV CDN', 'wphb' ); ?></span>
52
+ <span class="list-detail">
53
+ <div><a class="button button-content-cta button-ghost" href="#wphb-upgrade-membership-modal" id="dash-uptime-update-membership" rel="dialog"><?php _e( 'Pro Feature', 'wphb' ); ?></a></div>
54
+ </span>
55
+ </li>
56
+ <?php endif; ?>
57
+ <?php endif; ?>
58
+ </ul>
59
+ </div>
60
+
61
+ </div><!-- end wphb-block-entry -->
admin/views/modals/bulk-update-modal.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <dialog class="wphb-modal small wphb-progress-modal" id="bulk-update-modal" title="<?php esc_attr_e( 'Bulk update', 'wphb' ); ?>">
2
+ <div class="wphb-dialog-content">
3
+ <p><?php esc_html_e( 'Choose what bulk update actions you wish to apply.', 'wphb' ); ?></p>
4
+
5
+ <script type="text/javascript">
6
+ jQuery('label[for^="filter-"]').on('click', function() {
7
+ jQuery(this).toggleClass('toggle-label-background');
8
+ });
9
+
10
+ jQuery('.save-batch').on('click', function() {
11
+ const filesCollection = WPHB_Admin.minification.rowsCollection;
12
+
13
+ const modal = jQuery( '#bulk-update-modal' );
14
+ // Get the selected batch status
15
+ let minify = modal.find( 'input.filter-minify' ).prop( 'checked' ),
16
+ combine = modal.find( 'input.filter-combine').prop('checked'),
17
+ footer = modal.find( 'input.filter-position-footer' ).prop( 'checked' ),
18
+ selectedFiles = filesCollection.getSelectedItems();
19
+
20
+ for ( let i in selectedFiles ) {
21
+ selectedFiles[i].change( 'minify', minify );
22
+ selectedFiles[i].change( 'combine', combine );
23
+ selectedFiles[i].change( 'footer', footer );
24
+ }
25
+
26
+ // Unset all the values in bulk update checkboxes
27
+ modal.find('input.filter-minify').prop('checked', false);
28
+ modal.find('input.filter-combine').prop('checked', false);
29
+ modal.find('input.filter-position-footer').prop('checked', false);
30
+ });
31
+ </script>
32
+
33
+ <div class="tooltip-box">
34
+ <span class="checkbox-group">
35
+ <input type="checkbox" class="toggle-checkbox filter-toggles filter-minify" name="filter-minify" id="filter-minify">
36
+ <label for="filter-minify" class="toggle-label">
37
+ <span class="toggle tooltip-l tooltip-left" tooltip="<?php esc_attr_e( 'Compress this file to reduce it’s filesize', 'wphb' ); ?>"></span>
38
+ <i class="hb-icon-minify"></i>
39
+ <span><?php esc_html_e( 'Minify', 'wphb' ); ?></span>
40
+ </label>
41
+
42
+ <input type="checkbox" class="toggle-checkbox filter-toggles filter-combine" name="filter-combine" id="filter-combine">
43
+ <label for="filter-combine" class="toggle-label">
44
+ <span class="toggle tooltip-l" tooltip="<?php esc_attr_e( 'Combine this file with others if possible', 'wphb' ); ?>"></span>
45
+ <i class="hb-icon-minify-combine"></i>
46
+ <span><?php esc_html_e( 'Combine', 'wphb' ); ?></span>
47
+ </label>
48
+
49
+ <input type="checkbox" class="toggle-checkbox filter-toggles filter-position-footer" name="filter-position" id="filter-position-footer">
50
+ <label for="filter-position-footer" class="toggle-label">
51
+ <span class="toggle tooltip-l tooltip-right" tooltip="<?php esc_attr_e( 'Load this file in the footer of the page', 'wphb' ); ?>"></span>
52
+ <i class="hb-icon-minify-footer"></i>
53
+ <span><?php esc_html_e( 'Footer', 'wphb' ); ?></span>
54
+ </label>
55
+ </span>
56
+ </div><!-- end tooltip-box -->
57
+
58
+ <div class="wphb-progress-state">
59
+ <span class="wphb-progress-state-text"><?php esc_html_e( 'Hummingbird will set this configuration for all chosen files. You will still need to set the changes live by clicking Save Changes on the next screen.', 'wphb' ); ?></span>
60
+ </div><!-- end wphb-progress-state -->
61
+
62
+ </div><!-- end wphb-dialog-content -->
63
+
64
+ <div class="wphb-dialog-footer">
65
+ <div class="alignleft">
66
+ <div class="close button button-ghost button-large"><?php esc_html_e( 'Cancel', 'wphb' ); ?></div>
67
+ </div>
68
+ <div class="alignright">
69
+ <div class="close button button-large save-batch"><?php esc_html_e( 'Apply', 'wphb' ); ?></div>
70
+ </div>
71
+ </div>
72
+ </dialog><!-- end check-files-modal -->
admin/views/modals/check-files-modal.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <dialog class="wphb-modal small wphb-progress-modal no-close" id="check-files-modal" title="<?php esc_attr_e( 'Checking files', 'wphb' ); ?>">
2
+ <div class="title-action">
3
+ <input type="button" class="button button-ghost" id="cancel-minification-check" value="<?php esc_attr_e( 'Cancel', 'wphb' ); ?>" onclick="WPHB_Admin.minification.cancelScan()">
4
+ </div>
5
+ <div class="wphb-dialog-content">
6
+ <p><?php esc_html_e( 'Hummingbird will combine your files as best it can, however, depending on your settings, combining all your files might not be possible. What you see here is the best output Hummingbird can muster!', 'wphb' ); ?></p>
7
+ <?php $progress = get_option( 'wphb-minification-check-files-progress' ); ?>
8
+
9
+ <div class="wphb-block-test" id="check-files-modal-content">
10
+ <div class="wphb-scan-progress">
11
+ <div class="wphb-scan-progress-text">
12
+ <span><?php echo $progress; ?>%</span>
13
+ </div><!-- end wphb-scan-progress-text -->
14
+ <div class="wphb-scan-progress-bar">
15
+ <span style="width: <?php echo $progress; ?>%"></span>
16
+ </div><!-- end wphb-scan-progress-bar -->
17
+ </div><!-- end wphb-scan-progress -->
18
+ </div><!-- end wphb-block-test -->
19
+
20
+ <div class="wphb-progress-state">
21
+ <span class="wphb-progress-state-text"><?php esc_html_e( 'Check Files is running in the background, you can check back anytime to see progress...', 'wphb' ); ?></span>
22
+ </div><!-- end wphb-progress-state -->
23
+
24
+ <div class="wphb-notice wphb-notice-warning wphb-notice-box">
25
+ <p><?php esc_html_e( 'Note: Moving files between the header and footer of your page can break your website. We recommend tweaking and checking each file as you go and if a setting causes errors then revert the setting here.', 'wphb' ); ?></p>
26
+ </div>
27
+
28
+ <img class="wphb-image wphb-image-center wphb-modal-image-bottom"
29
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/graphic-hb-minify-summary.png'; ?>"
30
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/graphic-hb-minify-summary@2x.png'; ?> 2x"
31
+ alt="<?php esc_attr_e( 'Reduce your page load time!', 'wphb' ); ?>">
32
+ </div><!-- end wphb-dialog-content -->
33
+ </dialog><!-- end check-files-modal -->
admin/views/modals/check-performance-modal.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <dialog class="wphb-modal small wphb-progress-modal no-close" id="run-performance-test-modal" title="<?php _e( 'Test in progress', 'wphb' ); ?>">
2
+ <div class="wphb-dialog-content">
3
+ <p><?php _e( 'Hummingbird is running a test to measure your website performance, please wait.', 'wphb' ); ?></p>
4
+ <?php $progress = get_option( 'wphb-minification-check-files-progress' ); ?>
5
+
6
+ <div class="wphb-block-test" id="run-performance-test-modal-modal-content">
7
+ <div class="wphb-scan-progress">
8
+ <div class="wphb-scan-progress-text">
9
+ <span>0%</span>
10
+ </div><!-- end wphb-scan-progress-text -->
11
+ <div class="wphb-scan-progress-bar">
12
+ <span style="width: 0%"></span>
13
+ </div><!-- end wphb-scan-progress-bar -->
14
+ </div><!-- end wphb-scan-progress -->
15
+ </div><!-- end wphb-block-test -->
16
+
17
+ <div class="wphb-progress-state">
18
+ <span class="wphb-progress-state-text"><?php _e( 'Performance test in progress...', 'wphb' ); ?></span>
19
+ </div><!-- end wphb-progress-state -->
20
+
21
+ <img class="wphb-image wphb-image-center wphb-modal-image-bottom"
22
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hummingbird-modal-quicksetup.png'; ?>"
23
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/hummingbird-modal-quicksetup@2x.png'; ?> 2x"
24
+ alt="<?php esc_attr_e( 'Reduce your page load time!', 'wphb' ); ?>">
25
+ </div><!-- end wphb-dialog-content -->
26
+ </dialog><!-- end run-performance-test-modal-modal -->
admin/views/modals/enable-cdn-modal.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <dialog class="wphb-modal small wphb-progress-modal no-close" id="enable-cdn-modal" title="<?php _e( 'Activate CDN', 'wphb' ); ?>">
2
+ <script type="text/javascript">
3
+ jQuery('label[for="enable_cdn"]').on('click', function(e) {
4
+ e.preventDefault();
5
+ var checkbox = jQuery('input[name="enable_cdn"]');
6
+ checkbox.prop('checked', !checkbox.prop('checked') );
7
+ });
8
+ </script>
9
+ <div class="title-action">
10
+ <?php _e( 'File check complete.' , 'wphb' ); ?>
11
+ </div>
12
+ <div class="wphb-dialog-content">
13
+ <p><?php _e( 'Do you want to store your minified files on WPMU DEV’s super-fast CDN? It’s absolutely free for WPMU DEV members!', 'wphb' ); ?></p>
14
+
15
+ <form method="post">
16
+ <div class="wphb-block-test" id="check-files-modal-content">
17
+ <span class="toggle">
18
+ <input type="hidden" name="enable_cdn" value="0">
19
+ <input type="checkbox" class="toggle-checkbox" name="enable_cdn" id="enable_cdn" value="1" checked="checked">
20
+ <label class="toggle-label" for="enable_cdn"></label>
21
+ </span>
22
+ <label><?php _e( 'Host my files on the WPMU DEV CDN', 'wphb' ); ?></label>
23
+ </div>
24
+ <div>
25
+ <a href="<?php echo wphb_cdn_link(); ?>" target="_blank"><?php _e( 'What is a CDN?', 'wphb' ); ?></a>
26
+ <button type="submit" class="button button-large alignright"><?php _e( 'Continue', 'wphb' ); ?></button>
27
+ </div>
28
+ </form>
29
+
30
+ <img class="wphb-image wphb-image-center wphb-modal-image-bottom"
31
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/graphic-hb-minify-summary.png'; ?>"
32
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/graphic-hb-minify-summary@2x.png'; ?> 2x"
33
+ alt="<?php esc_attr_e( 'Reduce your page load time!', 'wphb' ); ?>">
34
+ </div>
35
+ </dialog>
admin/views/modals/membership-modal.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <dialog id="wphb-upgrade-membership-modal" class="small wphb-modal" title="<?php esc_attr_e( 'Upgrade Membership', 'wphb' ); ?>">
2
+ <div class="wphb-dialog-content dialog-upgrade">
3
+
4
+ <p><?php esc_html_e( "Here's what you'll get by upgrading to Hummingbird Pro.", 'wphb' ); ?></p>
5
+
6
+ <ul class="listing wphb-listing">
7
+ <li>
8
+ <strong><?php esc_html_e( 'Automation', 'wphb' ); ?></strong>
9
+ <p><?php esc_html_e( 'Schedule Hummingbird to run regular performance tests daily, weekly or monthly and get email reports delivered straight to your inbox.', 'wphb' ); ?></p>
10
+ </li>
11
+ <li>
12
+ <strong><?php esc_html_e( 'Enhanced Minify Compression', 'wphb' ); ?></strong>
13
+ <p><?php esc_html_e( 'Compress your minified files up to 2x more than regular optimization and reuce your page load speed even further.', 'wphb' ); ?></p>
14
+ </li>
15
+ <li>
16
+ <strong><?php esc_html_e( 'WPMU DEV CDN', 'wphb' ); ?></strong>
17
+ <p><?php esc_html_e( 'By default we minify your files via our API and send them back to your server. Pro users can host their files on WPMU DEV’s secure and hyper fast CDN, which will mean less load on your server and a fast visitor experience.', 'wphb' ); ?></p>
18
+ </li>
19
+ <li>
20
+ <strong><?php esc_html_e( 'Smush Pro', 'wphb' ); ?></strong>
21
+ <p><?php esc_html_e( 'A membership for Hummingbird Pro also gets you the award winning Smush Pro with unlimited advanced lossy compression that’ll give image heavy websites a speed boost.', 'wphb' ); ?></p>
22
+ </li>
23
+ </ul>
24
+
25
+ <p class="wphb-block-content-center"><?php esc_html_e( 'Get all of this, plus heaps more as part of a WPMU DEV membership.', 'wphb' ); ?></p>
26
+
27
+ <div class="wphb-block-content-center">
28
+ <a target="_blank" href="<?php echo wphb_plugin_page_link(); ?>" class="button button-content-cta button-large"><?php esc_html_e( 'Upgrade Membership', 'wphb' ); ?></a>
29
+ </div>
30
+
31
+ <div class="wphb-modal-image wphb-modal-image-bottom dev-man">
32
+ <img class="wphb-image wphb-image-center"
33
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/dev-team.png'; ?>"
34
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/dev-team@2x.png'; ?> 2x"
35
+ alt="<?php esc_attr_e( 'Hummingbird','wphb' ); ?>">
36
+ </div>
37
+
38
+ </div>
39
+ </dialog><!-- end wphb-upgrade-membership-modal -->
admin/views/modals/quick-setup-modal.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <dialog id="wphb-quick-setup-modal" class="small wphb-modal wphb-quick-setup-modal no-close" title="<?php esc_attr_e( 'Quick Setup', 'wphb' ); ?>">
2
+ <div class="title-action">
3
+ <input type="button" class="button button-ghost" id="skip-quick-setup" value="<?php esc_attr_e( 'Skip', 'wphb' ); ?>" onclick="WPHB_Admin.dashboard.skipSetup()">
4
+ </div>
5
+ <div class="wphb-dialog-content">
6
+ <p><?php esc_html_e( 'Welcome to Hummingbird, the hottest Performance plugin for WordPress! We recommend running a quick performance test before you start tweaking things. Alternatively you can skip this step if you’d prefer to start customizing.', 'wphb' ); ?></p>
7
+ <div class="wphb-block-test" id="check-files-modal-content">
8
+ <p><?php esc_html_e( 'This is only a performance test. Once you know what to fix you can get started in the next steps.', 'wphb' ); ?></p>
9
+ <input type="button" class="button button-large" value="<?php esc_attr_e( 'Test my website', 'wphb' ); ?>" onclick="WPHB_Admin.dashboard.runPerformanceTest()">
10
+ </div>
11
+ <img class="wphb-image wphb-image-center wphb-modal-image-bottom"
12
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hummingbird-modal-quicksetup.png'; ?>"
13
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/hummingbird-modal-quicksetup@2x.png'; ?> 2x"
14
+ alt="<?php esc_attr_e( 'Reduce your page load time!', 'wphb' ); ?>">
15
+ </div>
16
+ </dialog><!-- end wphb-upgrade-membership-modal -->
admin/views/notice.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-notice wphb-notice-<?php echo $class; ?> can-close">
2
+ <div class="close"></div>
3
+ <p><?php echo $message; ?></p>
4
+ </div>
5
+
6
+ <?php if ( $dismissable ): ?>
7
+ <script type="text/javascript">
8
+ jQuery('.wphb-notice:not(.notice)').delay(3000).slideUp('slow');
9
+ </script>
10
+ <?php endif; ?>
admin/views/performance/empty-summary-meta-box.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content wphb-block-content-center">
4
+
5
+ <div class="content">
6
+ <img class="wphb-image wphb-image-center wphb-image-icon-content-top"
7
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hummingbird-circle@1x.jpg'; ?>"
8
+ alt="<?php esc_attr_e( "Let's see what we can improve!", 'wphb' ); ?>">
9
+
10
+ <p><?php _e( 'For us to know what to improve we need to test your website. All testing is done in the background via our <br> secure servers. Once complete, we\'ll give you a list of things to improve, and how to do it.', 'wphb' ); ?></p>
11
+ <a href="#run-performance-test-modal" class="button button-large" id="run-performance-test" rel="dialog"><?php _e( 'Test my website', 'wphb' ); ?></a>
12
+
13
+ </div><!-- end content -->
14
+
15
+ </div><!-- end wphb-block-entry-content -->
16
+
17
+ </div><!-- end wphb-block-entry -->
18
+
19
+ <?php wphb_check_performance_modal(); ?>
20
+
21
+ <?php if ( $doing_report ): // Show the progress bar if we are still checking files ?>
22
+ <script>
23
+ jQuery( document).ready( function() {
24
+ var module = WPHB_Admin.getModule( 'performance' );
25
+ jQuery('#run-performance-test').trigger('click');
26
+ });
27
+ </script>
28
+ <?php endif; ?>
admin/views/performance/module-resume-meta-box.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-image wphb-block-entry-image-bottom">
4
+ <img class="wphb-image"
5
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/graphic-hb-minify-summary.png'; ?>"
6
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/graphic-hb-minify-summary@2x.png'; ?> 2x"
7
+ alt="<?php _e('Hummingbird', 'wphb'); ?>">
8
+ </div>
9
+
10
+ <div class="wphb-block-entry-third">
11
+ <span class="not-present">
12
+ <?php
13
+ if ( $last_report && ! is_wp_error( $last_report ) ) {
14
+ $error_class = ( 'aplus' === $last_report->score_class || 'a' === $last_report->score_class || 'b' === $last_report->score_class ) ? 'tick' : 'warning';
15
+ echo $last_report->score . "<i class='hb-wpmudev-icon-{$error_class}'></i><span class='score-span'>/100</span>";
16
+ } else {
17
+ echo '-';
18
+ } ?>
19
+ </span>
20
+ <p class="current-performance-score"><?php _e( 'Current performance score', 'wphb' ); ?></p>
21
+ <?php $data_time = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $last_report->time ) ) ); ?>
22
+ <span>
23
+ <?php
24
+ if ( $last_report && ! is_wp_error( $last_report ) ) {
25
+ echo date_i18n( get_option( 'date_format' ), $data_time ); ?> <span class="list-detail-stats-heading-extra-info"><?php printf( _x( 'at %s', 'Time of the last performance report', 'wphb' ), date_i18n( get_option( 'time_format' ), $data_time ) );
26
+ } else {
27
+ _e( 'Never', 'wphb' );
28
+ } ?>
29
+ </span>
30
+ <p><?php _e( 'Last test date', 'wphb' ); ?></p>
31
+ </div>
32
+
33
+ <div class="wphb-block-entry-third">
34
+ <ul class="dev-list">
35
+ <li>
36
+ <span class="list-label"><?php _e( 'Previous score', 'wphb' ); ?></span>
37
+ <span class="list-detail">
38
+ <?php if ( intval( $last_score ) > 0 ) : ?>
39
+ <div class="wphb-dash-numbers"><?php echo intval( $last_score ); ?></div>
40
+ <?php else : ?>
41
+ <p><?php _e( 'Available after next test', 'wphb' ); ?></p>
42
+ <?php endif; ?>
43
+ </span>
44
+ </li>
45
+ <li>
46
+ <span class="list-label"><?php _e( 'Improvement', 'wphb' ); ?></span>
47
+ <span class="list-detail">
48
+ <?php if ( intval( $improvement ) === 0 && intval( $last_score ) === 0 ) : ?>
49
+ <p><?php _e( 'Available after next test', 'wphb' ); ?></p>
50
+ <?php elseif ( intval( $improvement ) > 0 ) : ?>
51
+ <div class="wphb-pills green">+<?php echo intval( $improvement ); ?></div>
52
+ <?php elseif ( intval( $improvement ) === 0 ) : ?>
53
+ <div class="wphb-pills grey">0</div>
54
+ <?php else : ?>
55
+ <div class="wphb-pills"><?php echo intval( $improvement ); ?></div>
56
+ <?php endif; ?>
57
+ </span>
58
+ </li>
59
+ <li>
60
+ <span class="list-label"><?php _e( 'Recommendations', 'wphb' ); ?></span>
61
+ <span class="list-detail">
62
+ <div class="wphb-dash-numbers"><?php echo intval( $recommendations ); ?></div>
63
+ </span>
64
+ </li>
65
+ </ul>
66
+ </div>
67
+
68
+ </div><!-- end wphb-block-entry -->
admin/views/performance/running-test-meta-box.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <p><?php _e( 'Testing your website for performance improvements', 'wphb' ); ?></p>
6
+ <p><?php _e( 'This test is running in the background, you can check back anytime to see progress', 'wphb' ); ?></p>
7
+
8
+ <div class="wphb-block-test wphb-block-test-standalone">
9
+ <div class="wphb-scan-progress">
10
+ <div class="wphb-scan-progress-text">
11
+ <span>0%</span>
12
+ </div><!-- end wphb-scan-progress-text -->
13
+ <div class="wphb-scan-progress-bar">
14
+ <span style="width: 0%"></span>
15
+ </div><!-- end wphb-scan-progress-bar -->
16
+ </div><!-- end wphb-scan-progress -->
17
+ </div><!-- end wphb-block-test -->
18
+
19
+ <div class="wphb-progress-state">
20
+ <span class="wphb-progress-state-text"><?php _e( 'Analyzing your site...', 'wphb' ); ?></span>
21
+ </div><!-- end wphb-progress-state -->
22
+
23
+ </div><!-- end wphb-block-entry-content -->
24
+
25
+ </div><!-- end wphb-block-entry -->
admin/views/performance/summary-membership-meta-box.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content">
4
+
5
+ <div class="content">
6
+ <a id="wphb-upgrade-membership-modal-link" class="hidden" href="#wphb-upgrade-membership-modal" rel="dialog"><?php _e( 'Upgrade Membership', 'wphb') ;?></a>
7
+ </div><!-- end content -->
8
+
9
+ </div><!-- end wphb-block-entry-content -->
10
+
11
+ </div><!-- end wphb-block-entry -->
12
+
13
+ <?php
14
+ wphb_membership_modal();
15
+ ?>
16
+
17
+ <script>
18
+ jQuery( document).ready( function() {
19
+ WPHB_Admin.utils.membershipModal.open();
20
+ });
21
+ </script>
admin/views/performance/summary-meta-box-header.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h3><?php echo esc_html( $title ); ?></h3>
2
+ <?php if ( $last_report && ! is_wp_error( $last_report ) ): ?>
3
+ <div class="test-results wphb-performance-report-overall-score hide-on-mobile">
4
+ <span class="test-results-label"><?php _e( 'Overall Score', 'wphb' ); ?></span>
5
+ <div class="wphb-score wphb-score-have-label">
6
+ <div class="tooltip-box">
7
+ <div class="wphb-score-result wphb-score-result-grade-<?php echo $last_report->score_class ?>" tooltip="<?php echo $last_report->score; ?>/100">
8
+ <div class="wphb-score-type wphb-score-type-circle">
9
+ <svg class="wphb-score-graph wphb-score-graph-svg" xmlns="http://www.w3.org/2000/svg" width="30" height="30">
10
+ <circle class="wphb-score-graph-circle" r="12.5" cx="15" cy="15" fill="transparent" stroke-dasharray="0" stroke-dashoffset="0"></circle>
11
+ <circle class="wphb-score-graph-circle wphb-score-graph-result" r="12.5" cx="15" cy="15" fill="transparent" stroke-dasharray="80" stroke-dashoffset="0"></circle>
12
+ </svg>
13
+ </div><!-- end wphb-score-type -->
14
+ <div class="wphb-score-result-label"><?php echo $last_report->score; ?></div>
15
+ </div><!-- end wphb-score-result -->
16
+ </div><!-- end tooltip-box -->
17
+ </div><!-- end wphb-score -->
18
+ </div><!-- end test-results -->
19
+ <?php endif; ?>
admin/views/performance/summary-meta-box.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( $error ): ?>
2
+ <div class="wphb-table-wrapper complex add-side-padding">
3
+ <div class="row">
4
+ <div class="wphb-notice wphb-notice-error wphb-notice-box">
5
+ <p><?php echo $error_text; ?></p>
6
+ <div id="wphb-error-details">
7
+ <p><code style="background:white;"><?php echo $error_details; ?></code></p>
8
+ </div>
9
+ <a href="<?php echo esc_url( $retry_url ); ?>" class="button button-notice"><?php _e( 'Try again', 'wphb' ); ?></a>
10
+ <a target="_blank" href="<?php echo esc_url( wphb_support_link() ); ?>" class="button button-notice"><?php _e( 'Support', 'wphb' ); ?></a>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ <script>
15
+ var pressedKeys = [],
16
+ timer;
17
+
18
+ function wphbSetInterval() {
19
+ timer = window.setInterval(function(){
20
+ // Clean pressedKeys every 1sec
21
+ pressedKeys = [];
22
+ }, 1000);
23
+ }
24
+
25
+ wphbSetInterval();
26
+
27
+ document.onkeyup = function( e ) {
28
+ clearInterval( timer );
29
+ wphbSetInterval();
30
+ e = e || event;
31
+ pressedKeys.push( e.keyCode );
32
+ var count = pressedKeys.length;
33
+ if ( count >= 2 ) {
34
+ // Get the previous key pressed. If they are H+B, we'll display the error
35
+ if ( pressedKeys[ count - 1 ] == 66 && pressedKeys[ count - 2 ] == 72 ) {
36
+ var errorDetails = document.getElementById('wphb-error-details');
37
+ errorDetails.style.display = 'block';
38
+ }
39
+ }
40
+
41
+ };
42
+ </script>
43
+ <?php else: ?>
44
+
45
+ <div class="box-content no-vertical-padding">
46
+ <div class="content">
47
+ <p><?php _e( 'Here are your latest performance test results. Action as many fixes as possible, however you can always ignore warnings if you are unable to fix them.', 'wphb' ); ?></p>
48
+ </div>
49
+ </div>
50
+
51
+
52
+ <div class="wphb-table-wrapper complex">
53
+
54
+ <table class="list-table hover-effect wphb-table performance-report-table">
55
+
56
+ <thead>
57
+ <tr class="wphb-performance-report-item-heading">
58
+ <th class="wphb-performance-report-heading wphb-performance-report-heading-recommendation"><?php _e( 'Recommendation', 'wphb' ); ?></th>
59
+ <th class="wphb-performance-report-heading wphb-performance-report-heading-score"><?php _e( 'Score /100', 'wphb' ); ?></th>
60
+ <th class="wphb-performance-report-heading wphb-performance-report-heading-type"><?php _e( 'Type', 'wphb' ); ?></th>
61
+ <th class="wphb-performance-report-heading wphb-performance-report-heading-cta"></th>
62
+ </tr><!-- end wphb-performance-report-item-heading -->
63
+ </thead>
64
+
65
+ <tbody>
66
+ <?php foreach ( $last_test->rule_result as $rule => $rule_result ): ?>
67
+
68
+ <?php
69
+ $class = '';
70
+ switch ( $rule_result->impact_score_class ) {
71
+ case 'aplus':
72
+ case 'a':
73
+ case 'b':
74
+ $class = 'success';
75
+ break;
76
+ case 'c':
77
+ case 'd':
78
+ $class = 'warning';
79
+ break;
80
+ case 'e':
81
+ case 'f':
82
+ $class = 'error';
83
+ break;
84
+ }
85
+ ?>
86
+
87
+ <?php $has_url_blocks = ! empty( $rule_result->urlblocks ) && is_array( $rule_result->urlblocks ) && ! empty( $rule_result->urlblocks[0] ); ?>
88
+ <tr class="wphb-performance-report-item wphb-table-score-<?php echo $class; ?>" id="rule-<?php echo esc_attr( $rule ); ?>">
89
+ <td class="wphb-performance-report-item-recommendation">
90
+ <?php echo $rule_result->label; ?>
91
+ </td><!-- end wphb-performance-report-item-recommendation -->
92
+ <td class="wphb-performance-report-item-score">
93
+ <div class="wphb-score wphb-score-have-label">
94
+ <div class="tooltip-box">
95
+ <div class="wphb-score-result wphb-score-result-grade-<?php echo $rule_result->impact_score_class; ?> tooltip-s" tooltip="<?php echo $rule_result->impact_score; ?>/100">
96
+ <div class="wphb-score-type wphb-score-type-circle">
97
+ <svg class="wphb-score-graph wphb-score-graph-svg" xmlns="http://www.w3.org/2000/svg" width="30" height="30">
98
+ <circle class="wphb-score-graph-circle" r="12.5" cx="15" cy="15" fill="transparent" stroke-dasharray="0" stroke-dashoffset="0"></circle>
99
+ <circle class="wphb-score-graph-circle wphb-score-graph-result" r="12.5" cx="15" cy="15" fill="transparent" stroke-dasharray="80" stroke-dashoffset="0"></circle>
100
+ </svg>
101
+ </div><!-- end wphb-score-type -->
102
+ <div class="wphb-score-result-label"><?php echo $rule_result->impact_score; ?></div>
103
+ </div><!-- end wphb-score-result -->
104
+ </div><!-- end tooltip-box -->
105
+ </div><!-- end wphb-score -->
106
+ </td><!-- end wphb-performance-report-item-score -->
107
+ <td class="wphb-performance-report-item-type">
108
+ <?php echo $rule_result->type; ?>
109
+ </td><!-- end wphb-performance-report-item-type -->
110
+
111
+ <td class="wphb-performance-report-item-cta">
112
+ <?php if ( ! empty( $rule_result->summary ) || ! empty ( $rule_result->tip ) ): ?>
113
+ <?php if ( $rule_result->impact_score != 100 ): ?>
114
+ <button class="button button-ghost additional-content-opener"><?php _e( 'Improve', 'wphb' ); ?></button>
115
+ <?php endif; ?>
116
+ <span class="additional-content-opener trigger-additional-content"><i class="dev-icon dev-icon-caret_down"></i></span>
117
+ <?php endif; ?>
118
+ </td><!-- end wphb-performance-report-item-cta -->
119
+
120
+ </tr><!-- end wphb-performance-report-item -->
121
+
122
+ <tr class="wphb-performance-report-item-additional-content wphb-table-additional-<?php echo $class; ?>">
123
+ <td colspan="4">
124
+ <div class="wphb-performance-report-item-additional-content-inner">
125
+
126
+ <div class="row">
127
+ <div class="dev-box">
128
+ <?php if ( ! empty( $rule_result->summary ) ): ?>
129
+ <div class="dev-box-performance-report-additional-content dev-box-performance-report-additional-content-overview">
130
+ <div class="box-content">
131
+ <h4 class="wphb-performance-report-additional-title"><?php _e('Overview', 'wphb'); ?></h4>
132
+ <p><?php echo $rule_result->summary; ?></p>
133
+ </div>
134
+ </div>
135
+ <?php endif; ?>
136
+
137
+ <?php if ( $has_url_blocks ): ?>
138
+ <div class="dev-box-performance-report-additional-content dev-box-performance-report-additional-content-benchmarks">
139
+ <div class="box-content">
140
+ <h4 class="wphb-performance-report-additional-title"><?php _e('Benchmarks', 'wphb'); ?></h4>
141
+
142
+ <ol>
143
+ <?php foreach( $rule_result->urlblocks as $url_block ): ?>
144
+ <?php if ( empty( $url_block ) )
145
+ continue; ?>
146
+
147
+ <p><?php echo $url_block->header; ?></p>
148
+
149
+ <?php if ( ! empty( $url_block->urls ) && is_array( $url_block->urls ) ): ?>
150
+ <?php foreach ( $url_block->urls as $url ): ?>
151
+ <li><?php echo make_clickable( $url ); ?></li>
152
+ <?php endforeach; ?>
153
+ <?php endif; ?>
154
+ <?php endforeach; ?>
155
+ </ol>
156
+ </div>
157
+ </div>
158
+ <?php endif; ?>
159
+
160
+ <?php if ( ! empty( $rule_result->tip ) ): ?>
161
+ <div class="dev-box-performance-report-additional-content dev-box-performance-report-additional-content-how-to-fix">
162
+ <div class="box-content">
163
+ <h4 class="wphb-performance-report-additional-title"><?php _e('How to improve', 'wphb'); ?></h4>
164
+ <?php echo $rule_result->tip; ?>
165
+ </div>
166
+ </div>
167
+ <?php endif; ?>
168
+ </div><!-- end dev-box -->
169
+ </div><!-- end row -->
170
+
171
+ </div><!-- end wphb-performance-report-item-additional-content-inner -->
172
+ </td>
173
+ </tr><!-- end wphb-performance-report-item-additional-content -->
174
+ <?php endforeach; ?>
175
+
176
+ </tbody>
177
+
178
+ </table><!-- end list-table-performance-report -->
179
+ </div>
180
+ <?php endif; ?>
admin/views/tabs.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <ul class="wphb-tabs hide-on-mobile">
2
+ <?php foreach ( $this->get_tabs() as $tab => $name ): ?>
3
+ <li class="wphb-tab <?php echo ( $tab === $this->get_current_tab() ) ? 'current' : null ?>">
4
+ <a href="<?php echo esc_url( $this->get_tab_url( $tab ) ) ?>">
5
+ <?php echo $name; ?>
6
+ </a>
7
+ <?php do_action( 'wphb_admin_after_tab_' . $this->get_slug(), $tab ); ?>
8
+ </li>
9
+ <?php endforeach; ?>
10
+ </ul>
11
+
12
+ <div class="mline hide-on-large">
13
+ <div class="select-container mobile-nav">
14
+ <span class="dropdown-handle"><i class="wdv-icon wdv-icon-reorder"></i></span>
15
+ <select class="mobile-nav wdev-styled" style="display: none;">
16
+ <?php foreach ( $this->get_tabs() as $tab => $name ): ?>
17
+ <option value="#<?php echo $tab; ?>" <?php selected( $this->get_current_tab(), $tab ); ?>><?php echo $name; ?></option>
18
+ <?php endforeach; ?>
19
+ </select>
20
+ <div class="select-list-container">
21
+ <div class="list-value">
22
+ <?php echo $this->get_tab_name( $this->get_current_tab() ); ?>
23
+ </div>
24
+ <ul class="list-results wphb-tabs">
25
+ <?php foreach ( $this->get_tabs() as $tab => $name ): ?>
26
+ <li class="wphb-tab <?php echo ( $tab === $this->get_current_tab() ) ? 'current' : null ?>">
27
+ <a href="<?php echo esc_url( $this->get_tab_url( $tab ) ) ?>" data-tab="#<?php echo $tab; ?>"><?php echo $name; ?></a>
28
+ </li>
29
+ <?php endforeach; ?>
30
+ </ul>
31
+ </div>
32
+ </div>
33
+ </div><!-- end mline -->
admin/views/uptime/disabled-meta-box.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content wphb-block-content-center">
4
+
5
+ <img class="wphb-image wphb-image-center wphb-image-icon-content-top"
6
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/icon-uptime-small.png'; ?>"
7
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/icon-uptime.png'; ?> 2x"
8
+ alt="<?php esc_attr_e( 'Monitor your website', 'wphb' ); ?>">
9
+
10
+ <h2 class="title"><?php _e( 'Monitor your website', 'wphb' ); ?></h2>
11
+
12
+ <div class="content">
13
+ <p><?php echo sprintf( __( 'We can monitor your website\'s response time and let you know when you experience downtime. It\'s included with your WPMU DEV Membership and all <br> you have to do is flick a switch. What are you waiting for, %s?', 'wphb' ), $user); ?></p>
14
+ <a href="<?php echo esc_url( $activate_url ); ?>" class="button button-large" id="activate-uptime"><?php _e( 'Activate Uptime Monitoring', 'wphb' ); ?></a>
15
+ </div><!-- end content -->
16
+
17
+ </div><!-- end wphb-block-entry-content -->
18
+
19
+ </div><!-- end wphb-block-entry -->
admin/views/uptime/downtime-meta-box.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="row row-space-large">
2
+
3
+ <div class="wphb-block wphb-block-uptime-downtime">
4
+
5
+ <div class="wphb-block-header">
6
+ <p class="wphb-block-description"><?php _e( 'Here\'s a log of when your website was inaccessible for visitors.', 'wphb' ); ?></p>
7
+ </div>
8
+ <div class="wphb-block-content">
9
+ <ul class="dev-list dev-list-stats dev-list-stats-standalone dev-list-stats-border">
10
+ <?php if ( ! count( $uptime_stats->events ) ): ?>
11
+ <div class="wphb-caching-success wphb-notice wphb-notice-blue">
12
+ <p><strong><?php _e( 'No events in the chosen date range', 'wphb' ); ?></strong></p>
13
+ </div>
14
+ <?php else: ?>
15
+ <?php foreach ( $uptime_stats->events as $event ): ?>
16
+ <li class="dev-list-stats-item">
17
+ <div>
18
+ <span class="list-label list-label-stats">
19
+ <?php if ( ! empty( $event->down ) && ! empty( $event->up ) ): ?>
20
+ <?php $down = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $event->down ) ) ); ?>
21
+ <?php $up = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $event->up ) ) ); ?>
22
+ <div class="wphb-pills-group">
23
+ <span class="wphb-pills red" tooltip="<?php echo esc_attr( $event->details ); ?>"><i class="dev-icon dev-icon-caret_down"></i> <?php echo date_i18n( 'M j, Y g:ia', $down ); ?></span>
24
+ <span class="wphb-pills green"><i class="dev-icon dev-icon-caret_up"></i> <?php echo date_i18n( 'M j, Y g:ia', $up ); ?></span>
25
+ </div>
26
+ <?php else : ?>
27
+ <?php if ( ! empty( $event->down ) ): ?>
28
+ <?php $down = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $event->down ) ) ); ?>
29
+ <span class="wphb-pills red" tooltip="<?php echo esc_attr( $event->details ); ?>"><i class="dev-icon dev-icon-caret_down"></i> <?php echo date_i18n( 'M j, Y g:ia', $down ); ?></span>
30
+ <?php endif; ?>
31
+ <?php if ( ! empty( $event->up ) ): ?>
32
+ <?php $up = strtotime( get_date_from_gmt( date( 'Y-m-d H:i:s', $event->up ) ) ); ?>
33
+ <span class="wphb-pills green"><i class="dev-icon dev-icon-caret_up"></i> <?php echo date_i18n( 'M j, Y g:ia', $up ); ?></span>
34
+ <?php endif; ?>
35
+ <?php endif; ?>
36
+ </span>
37
+ <?php if ( $event->downtime ): ?>
38
+ <span class="list-detail list-detail-stats list-detail-stats-heading tooltip-right" tooltip="<?php echo esc_attr( $event->details ); ?>"><?php echo $event->downtime; ?></span>
39
+ <?php elseif ( ! $event->up && $uptime_stats->downtime ): ?>
40
+ <span class="list-detail list-detail-stats list-detail-stats-heading tooltip-right" tooltip="<?php echo esc_attr( $event->details ); ?>"><?php echo $uptime_stats->downtime; ?></span>
41
+ <?php endif; ?>
42
+ </div>
43
+ </li><!-- end dev-list-stats-item -->
44
+ <?php endforeach; ?>
45
+ <?php endif; ?>
46
+ </ul>
47
+ </div>
48
+
49
+ </div><!-- end wphb-block-uptime-downtime -->
50
+
51
+ </div>
admin/views/uptime/meta-box-header.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <h3><?php echo $title; ?></h3>
2
+ <div class="buttons">
3
+ <p class="wphb-label-notice-inline hide-to-mobile"><?php _e( 'Tip: A lower response time is better! Google recommends less than 200ms', 'wphb' ); ?></p>
4
+ </div>
admin/views/uptime/meta-box.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( $error && ( ! strpos( $error, 'down for maintenance' ) ) ): ?>
2
+ <div class="row">
3
+ <div class="wphb-notice wphb-notice-<?php echo $error_type; ?> wphb-notice-box can-close">
4
+ <span class="close"></span>
5
+ <p><?php echo $error; ?></p>
6
+ <a href="<?php echo esc_url( $retry_url ); ?>" class="button button-notice"><?php _e( 'Try again', 'wphb' ); ?></a>
7
+ <a target="_blank" href="<?php echo esc_url( $support_url ); ?>" class="button button-notice"><?php _e( 'Support', 'wphb' ); ?></a>
8
+ </div>
9
+ </div>
10
+ <?php elseif ( strpos( $error, 'down for maintenance' ) ) : ?>
11
+ <div class="wphb-block-entry">
12
+
13
+ <div class="wphb-block-entry-content wphb-block-content-center">
14
+
15
+ <div class="content">
16
+ <img class="wphb-image-icon-content wphb-image-icon-content-top wphb-image-icon-content-center wphb-uptime-icon"
17
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-uptime-disabled@1x.png'; ?>"
18
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-uptime-disabled@2x.png'; ?> 2x">
19
+
20
+ <p><?php _e( 'Uptime monitors your server response time and lets you know when your website is down or<br> too slow for your visitors. This service is currently under maintenance as we build a brand<br> new monitoring service. Check back soon!', 'wphb' ); ?></p>
21
+ </div><!-- end content -->
22
+
23
+ </div><!-- end wphb-block-entry-content -->
24
+
25
+ </div><!-- end wphb-block-entry -->
26
+ <?php else: ?>
27
+
28
+ <div class="row row-space-large">
29
+ <div class="wphb-block wphb-block-uptime-average-responsive-time">
30
+ <div class="wphb-block-header">
31
+ <p class="wphb-block-description"><?php _e( 'Server response time is the amount of time it takes for a web server to respond to a request from a browser. The longer it takes, the longer your visitors wait for the page to start loading.', 'wphb' ); ?></p>
32
+ </div>
33
+ <div class="wphb-block-content">
34
+ <input type="hidden" id="uptime-chart-json" value="<?php echo $uptime_stats->chart_json; ?>">
35
+ <div class="uptime-chart" id="uptime-chart" style="height:400px">
36
+ <span class="loader i-wpmu-dev-loader"></span>
37
+ </div>
38
+ </div>
39
+ </div><!-- end wphb-block-uptime-average-responsive-time -->
40
+ </div>
41
+
42
+ <script>
43
+ jQuery(document).ready( function() {
44
+ WPHB_Admin.getModule( 'uptime' );
45
+ });
46
+ </script>
47
+ <?php endif; ?>
48
+
admin/views/uptime/no-membership-meta-box.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-content wphb-block-content-center">
4
+
5
+ <img class="wphb-image wphb-image-center wphb-image-icon-content-top"
6
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-uptime-disabled@1x.png'; ?>"
7
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-uptime-disabled@2x.png'; ?> 2x"
8
+ alt="<?php esc_attr_e( 'Monitor your website', 'wphb' ); ?>">
9
+
10
+ <div class="content">
11
+ <p><?php _e( 'Uptime monitors your server response time and lets you know when your website is down or too slow for your visitors. Get Uptime monitoring as part of a WPMU DEV membership.', 'wphb' ); ?></p>
12
+
13
+ <div class="buttons">
14
+ <a id="wphb-upgrade-membership-modal-link" class="button button-large button-content-cta" href="#wphb-upgrade-membership-modal" rel="dialog"><?php _e( 'Upgrade to Pro', 'wphb') ;?></a>
15
+ </div>
16
+ </div><!-- end content -->
17
+
18
+ </div><!-- end wphb-block-entry-content -->
19
+
20
+ </div><!-- end wphb-block-entry -->
21
+
22
+ <?php
23
+ wphb_membership_modal();
24
+ ?>
admin/views/uptime/summary-meta-box.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wphb-block-entry">
2
+
3
+ <div class="wphb-block-entry-image wphb-block-entry-image-bottom">
4
+ <img class="wphb-image"
5
+ src="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-uptime-up.png'; ?>"
6
+ srcset="<?php echo wphb_plugin_url() . 'admin/assets/image/hb-graphic-uptime-up@2x.png'; ?> 2x"
7
+ alt="<?php _e('Hummingbird', 'wphb'); ?>">
8
+ </div>
9
+
10
+ <div class="wphb-block-entry-third">
11
+ <span class="not-present">
12
+ <?php if ( $uptime_stats && ! is_wp_error( $uptime_stats ) ):
13
+ echo round( $uptime_stats->availability, 1 ) . '%';
14
+ endif; ?>
15
+ </span>
16
+ <p class="current-performance-score"><?php _e( 'Website availability during the reporting period', 'wphb' ); ?></p>
17
+ <span>
18
+ <span class="list-detail-stats-heading-extra-info">
19
+ <?php if ( $uptime_stats && ! is_wp_error( $uptime_stats ) ):
20
+ echo $uptime_stats->response_time ? $uptime_stats->response_time : "Calculating...";
21
+ endif; ?>
22
+ </span>
23
+ </span>
24
+ <p><?php _e( 'Average server response time during the reporting period', 'wphb' ); ?></p>
25
+ </div>
26
+
27
+ <div class="wphb-block-entry-third">
28
+ <ul class="dev-list">
29
+ <li>
30
+ <span class="list-label"><?php _e( 'Outages', 'wphb' ); ?></span>
31
+ <span class="list-detail">
32
+ <?php if ( intval( $uptime_stats->outages ) > 0 ) : ?>
33
+ <div class="wphb-dash-numbers"><?php echo intval( $uptime_stats->outages ); ?></div>
34
+ <?php else : ?>
35
+ <p><?php _e( 'None', 'wphb' ); ?></p>
36
+ <?php endif; ?>
37
+ </span>
38
+ </li>
39
+ <li>
40
+ <span class="list-label"><?php _e( 'Downtime', 'wphb' ); ?></span>
41
+ <span class="list-detail">
42
+ <?php if ( isset( $uptime_stats->period_downtime ) ) : ?>
43
+ <div class="wphb-dash-numbers"><?php echo $uptime_stats->period_downtime; ?></div>
44
+ <?php else : ?>
45
+ <p><?php _e( 'None', 'wphb' ); ?></p>
46
+ <?php endif; ?>
47
+ </span>
48
+ </li>
49
+ <li>
50
+ <span class="list-label"><?php _e( 'Up Since', 'wphb' ); ?></span>
51
+ <span class="list-detail">
52
+ <?php
53
+ $gmt_date = date( 'Y-m-d H:i:s', $uptime_stats->up_since );
54
+ $site_date = get_date_from_gmt( $gmt_date, get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
55
+ ?>
56
+ <div class="wphb-dash-numbers"><?php echo $site_date; ?></div>
57
+ </span>
58
+ </li>
59
+ </ul>
60
+ </div>
61
+
62
+ </div><!-- end wphb-block-entry -->
admin/views/wphb-caching-page.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( $this->has_meta_boxes( 'box-caching' ) ) : ?>
2
+ <div class="row">
3
+ <?php $this->do_meta_boxes( 'box-caching' ); ?>
4
+ </div>
5
+ <?php endif; ?>
6
+
7
+ <div class="row">
8
+ <div class="col-half"><?php $this->do_meta_boxes( 'box-caching-left' ); ?></div>
9
+ <div class="col-half"><?php $this->do_meta_boxes( 'box-caching-right' ); ?></div>
10
+ </div>
11
+
12
+ <script>
13
+ jQuery(document).ready( function() {
14
+ if ( window.WPHB_Admin ) {
15
+ window.WPHB_Admin.getModule( 'caching' );
16
+ }
17
+ });
18
+
19
+ </script>
admin/views/wphb-gzip-page.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="row">
2
+ <div class="col-half"><?php $this->do_meta_boxes( 'box-gzip-left' ); ?></div>
3
+ <div class="col-half"><?php $this->do_meta_boxes( 'box-gzip-right' ); ?></div>
4
+ </div>
5
+
6
+ <script>
7
+ jQuery(document).ready( function() {
8
+ if ( window.WPHB_Admin ) {
9
+ window.WPHB_Admin.getModule( 'gzip' );
10
+ }
11
+ });
12
+
13
+ </script>
admin/views/wphb-minification-page.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( $this->has_meta_boxes( 'box-enqueued-files-empty' ) ) : ?>
2
+ <div class="row">
3
+ <?php $this->do_meta_boxes( 'box-enqueued-files-empty' ); ?>
4
+ </div>
5
+ <?php endif; ?>
6
+
7
+ <div class="row">
8
+ <?php $this->do_meta_boxes( 'summary' ); ?>
9
+ </div>
10
+
11
+ <?php if ( ! $this->has_meta_boxes( 'box-enqueued-files-empty' ) ) : ?>
12
+ <div class="row">
13
+ <div class="col-fifth">
14
+ <?php $this->show_tabs(); ?>
15
+ </div><!-- end col-sixth -->
16
+
17
+ <div class="col-four-fifths">
18
+ <form action="" method="post" id="wphb-minification-form">
19
+ <?php if ( 'files' === $this->get_current_tab() ) : ?>
20
+ <div class="minification-main-screen">
21
+ <?php $this->do_meta_boxes( 'main' ); ?>
22
+
23
+ <?php if ( $this->has_meta_boxes( 'main-2' ) ): ?>
24
+ <div class="wphb-notice wphb-notice-box no-top-space">
25
+ <p><?php _e( 'Hummingbird will combine your files as best it can, however, depending on your settings, combining all your files might not be possible. What you see here is the best output Hummingbird can muster!', 'wphb' ); ?></p>
26
+ </div>
27
+ <?php $this->do_meta_boxes( 'main-2' ); ?>
28
+ <?php endif; ?>
29
+ </div>
30
+ <?php endif; ?>
31
+
32
+ <?php if ( 'settings' === $this->get_current_tab() ) : ?>
33
+ <div class="minification-settings-screen">
34
+ <?php $this->do_meta_boxes( 'settings' ); ?>
35
+ </div>
36
+ <?php endif; ?>
37
+ </form>
38
+ </div><!-- end col-five-sixths -->
39
+
40
+ </div><!-- end row -->
41
+ <?php endif; ?>
42
+
43
+ <?php
44
+ wphb_membership_modal();
45
+ ?>
46
+
47
+ <script>
48
+ jQuery(document).ready( function() {
49
+ var module = WPHB_Admin.getModule( 'minification' );
50
+ <?php if ( isset( $_GET['run'] ) ): ?>
51
+ module.$checkFilesButton.trigger( 'click' );
52
+ <?php endif; ?>
53
+ });
54
+ </script>
admin/views/wphb-page.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="row">
2
+ <?php $this->do_meta_boxes( 'main' ); ?>
3
+ </div>
4
+
5
+ <div class="row">
6
+ <div class="col-half"><?php $this->do_meta_boxes( 'box-dashboard-left' ); ?></div>
7
+ <div class="col-half"><?php $this->do_meta_boxes( 'box-dashboard-right' ); ?></div>
8
+ </div>
9
+
10
+ <?php
11
+ wphb_membership_modal();
12
+ ?>
13
+
14
+ <script>
15
+ jQuery( document).ready( function () {
16
+ WPHB_Admin.getModule( 'dashboard' );
17
+ });
18
+ </script>
admin/views/wphb-performance-page.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /** @var WP_Hummingbird_Performance_Report_Page $this */
3
+ $last_test = wphb_performance_get_last_report();
4
+ ?>
5
+
6
+ <?php if ( $this->has_meta_boxes( 'summary' ) ) : ?>
7
+ <div class="row">
8
+ <?php $this->do_meta_boxes( 'summary' ); ?>
9
+ </div>
10
+ <?php endif; ?>
11
+
12
+ <div class="row">
13
+ <?php if ( $last_test ) : ?>
14
+ <div class="col-fifth">
15
+ <?php $this->show_tabs(); ?>
16
+ </div><!-- end col-sixth -->
17
+
18
+ <div class="col-four-fifths">
19
+ <?php $this->do_meta_boxes( $this->get_current_tab() ); ?>
20
+ </div>
21
+ <?php else : ?>
22
+ <?php $this->do_meta_boxes( 'main' ); ?>
23
+ <?php endif; ?>
24
+ </div><!-- end row -->
25
+
26
+ <script>
27
+ jQuery(document).ready( function() {
28
+ WPHB_Admin.getModule( 'performance' );
29
+ });
30
+ </script>
admin/views/wphb-uptime-page.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ( $this->has_meta_boxes( 'box-uptime-disabled' ) ) : ?>
2
+ <div class="row">
3
+ <?php $this->do_meta_boxes( 'box-uptime-disabled' ); ?>
4
+ </div>
5
+ <?php endif; ?>
6
+
7
+ <?php if ( $this->has_meta_boxes( 'summary' ) ) : ?>
8
+ <div class="row">
9
+ <?php $this->do_meta_boxes( 'summary' ); ?>
10
+ </div>
11
+ <?php endif; ?>
12
+
13
+ <?php if ( $error ): ?>
14
+ <div class="row">
15
+ <div class="wphb-notice-box wphb-notice-box-error can-close">
16
+ <span class="close"></span>
17
+ <span class="wphb-icon wphb-icon-left"><i class="wdv-icon wdv-icon-fw wdv-icon-warning-sign"></i></span>
18
+ <?php $support_link = '#'; ?>
19
+ <p><?php echo $error; ?></p>
20
+ <a href="<?php echo esc_url( $retry_url ); ?>" class="button button-notice-box button-notice-box-error"><?php _e( 'Try again', 'wphb' ); ?></a>
21
+ </div>
22
+ </div>
23
+ <?php else: ?>
24
+ <div class="row">
25
+ <?php $this->do_meta_boxes( 'main' ); ?>
26
+ </div>
27
+ <?php endif; ?>
core/api/class-api.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_API {
4
+
5
+ public function __construct() {
6
+ spl_autoload_register( array( $this, 'autoload' ) );
7
+ $this->uptime = new WP_Hummingbird_API_Service_Uptime();
8
+ $this->performance = new WP_Hummingbird_API_Service_Performance();
9
+ $this->cloudflare = new WP_Hummingbird_API_Service_Cloudflare();
10
+ $this->minify = new WP_Hummingbird_API_Service_Minify();
11
+ }
12
+
13
+ /**
14
+ * Hummingbird API autoloader
15
+ */
16
+ public function autoload( $classname ) {
17
+ if ( strpos( $classname, 'WP_Hummingbird_API_' ) !== 0 ) {
18
+ return;
19
+ }
20
+
21
+ $base_dir = wphb_plugin_dir() . 'core/api';
22
+
23
+ $classname = str_replace( 'WP_Hummingbird_API_', '', $classname );
24
+ $class_parts = explode( '_', $classname );
25
+
26
+ if ( ! $class_parts ) {
27
+ return;
28
+ }
29
+
30
+ $folder = strtolower( $class_parts[0] );
31
+ if ( ! isset( $class_parts[1] ) ) {
32
+ $file = "$base_dir/$folder/$folder.php";
33
+ }
34
+ else {
35
+ $file_slug = strtolower( $class_parts[1] );
36
+ $file = "$base_dir/$folder/$file_slug.php";
37
+ }
38
+
39
+ if ( is_readable( $file ) ) {
40
+ include_once( $file );
41
+ }
42
+ }
43
+
44
+ }
core/api/exception/exception.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_API_Exception extends Exception {
4
+
5
+ public function __construct( $message = "", $code = 0, Exception $previous = null ) {
6
+ if ( ! is_numeric( $code ) ) {
7
+ switch( $code ) {
8
+ default: {
9
+ $code = 500;
10
+ }
11
+ }
12
+ }
13
+
14
+ parent::__construct( $message, $code );
15
+ }
16
+ }
core/api/request/cloudflare.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_API_Request_Cloudflare extends WP_Hummingbird_API_Request {
4
+
5
+ private $auth_email = '';
6
+ private $auth_key = '';
7
+ private $zone = '';
8
+
9
+ public function get_api_key() {
10
+ return '';
11
+ }
12
+
13
+ public function get_api_url( $path = '' ) {
14
+ $url = 'https://api.cloudflare.com/client/v4/' . $path;
15
+ return str_replace( '%ZONE%', $this->zone, $url );
16
+ }
17
+
18
+ protected function sign_request() {
19
+ $this->add_header_argument( 'X-Auth-Key', $this->auth_key );
20
+ $this->add_header_argument( 'X-Auth-Email', $this->auth_email );
21
+ }
22
+
23
+ public function set_zone( $zone ) {
24
+ $this->zone = $zone;
25
+ }
26
+
27
+ public function set_auth_email( $email ) {
28
+ $this->auth_email = $email;
29
+ }
30
+
31
+ public function set_auth_key( $key ) {
32
+ $this->auth_key = $key;
33
+ }
34
+
35
+ /**
36
+ * @inheritdoc
37
+ */
38
+ public function request( $path, $data = array(), $method = 'post' ) {
39
+ $this->add_header_argument( 'Content-Type', 'application/json' );
40
+
41
+ $response = parent::request( $path, $data, $method );
42
+
43
+ if ( is_wp_error( $response ) ) {
44
+ throw new WP_Hummingbird_API_Exception( $response->get_error_message(), $response->get_error_code() );
45
+ }
46
+
47
+ $code = wp_remote_retrieve_response_code( $response );
48
+ $body = wp_remote_retrieve_body( $response );
49
+ $body = json_decode( $body );
50
+ if ( $body && $code != 200 ) {
51
+ throw new WP_Hummingbird_API_Exception( sprintf( __( 'Cloudflare error: %s', 'wphb' ), $body->errors[0]->message ), $code );
52
+ }
53
+ elseif ( false === $body ) {
54
+ throw new WP_Hummingbird_API_Exception( __( 'Cloudflare unknown error', 'wphb' ), $code );
55
+ }
56
+
57
+ return $body;
58
+
59
+ }
60
+
61
+
62
+ }
core/api/request/minify.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @author: WPMUDEV, Ignacio Cruz (igmoweb)
4
+ * @version:
5
+ */
6
+
7
+ if ( ! defined( 'ABSPATH' ) ) {
8
+ exit;
9
+ }
10
+
11
+ class WP_Hummingbird_API_Request_Minify extends WP_Hummingbird_API_Request {
12
+
13
+ public function get_api_key() {
14
+ global $wpmudev_un;
15
+
16
+ if ( ! is_object( $wpmudev_un ) && class_exists( 'WPMUDEV_Dashboard' ) && method_exists( 'WPMUDEV_Dashboard', 'instance' ) ) {
17
+ $wpmudev_un = WPMUDEV_Dashboard::instance();
18
+ }
19
+
20
+ if ( defined( 'WPHB_API_KEY' ) ) {
21
+ $api_key = WPHB_API_KEY;
22
+ }
23
+ elseif ( is_object( $wpmudev_un ) && method_exists( $wpmudev_un, 'get_apikey' ) ) {
24
+ $api_key = $wpmudev_un->get_apikey();
25
+ }
26
+ elseif ( class_exists( 'WPMUDEV_Dashboard' ) && is_object( WPMUDEV_Dashboard::$api ) && method_exists( WPMUDEV_Dashboard::$api, 'get_key' ) ) {
27
+ $api_key = WPMUDEV_Dashboard::$api->get_key();
28
+ }
29
+ else {
30
+ $api_key = '';
31
+ }
32
+
33
+ return $api_key;
34
+ }
35
+
36
+ public function get_api_url( $path = '' ) {
37
+ $url = 'https://m9gnuc7j4d.execute-api.us-east-1.amazonaws.com/hummingbird/';
38
+ return trailingslashit( $url . $path );
39
+
40
+ }
41
+
42
+ protected function sign_request() {
43
+ if ( $this->get_api_key() ) {
44
+ $this->add_header_argument( 'Authorization', 'Basic ' . $this->get_api_key() );
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Get the current Site URL
50
+ *
51
+ * @return string
52
+ */
53
+ public function get_this_site() {
54
+ if ( defined( 'WPHB_API_DOMAIN' ) ) {
55
+ $domain = WPHB_API_DOMAIN;
56
+ } else {
57
+ $domain = network_site_url();
58
+ }
59
+
60
+ return $domain;
61
+ }
62
+
63
+ }
core/api/request/request.php ADDED
@@ -0,0 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class WP_Hummingbird_API_Request {
4
+
5
+ /**
6
+ * API Key
7
+ *
8
+ * @var string
9
+ */
10
+ private $api_key = '';
11
+
12
+ /**
13
+ * Module action path
14
+ *
15
+ * @var string
16
+ */
17
+ private $path = '';
18
+
19
+ /**
20
+ * @var null|WP_Hummingbird_API_Service
21
+ */
22
+ private $service = null;
23
+
24
+ /**
25
+ * Request Method
26
+ *
27
+ * @var string
28
+ */
29
+ private $method = 'POST';
30
+
31
+ /**
32
+ * Request max timeout
33
+ *
34
+ * @var int
35
+ */
36
+ private $timeout = 15;
37
+
38
+ /**
39
+ * Header arguments
40
+ *
41
+ * @var array
42
+ */
43
+ private $headers = array();
44
+
45
+ /**
46
+ * POST arguments
47
+ *
48
+ * @var array
49
+ */
50
+ private $post_args = array();
51
+
52
+ /**
53
+ * GET arguments
54
+ *
55
+ * @var array
56
+ */
57
+ private $get_args = array();
58
+
59
+ /**
60
+ * WP_Hummingbird_API_Request constructor.
61
+ *
62
+ * @param WP_Hummingbird_API_Service $service
63
+ *
64
+ * @throws WP_Hummingbird_API_Exception
65
+ */
66
+ public function __construct( $service ) {
67
+ if ( ! $service instanceof WP_Hummingbird_API_Service ) {
68
+ throw new WP_Hummingbird_API_Exception( __( 'Wrong Service. $service must be an instance of WP_Hummingbird_API_Service', 'wphb' ), 404 );
69
+ }
70
+
71
+ $this->service = $service;
72
+ }
73
+
74
+ public function get_service() {
75
+ return $this->service;
76
+ }
77
+
78
+ /**
79
+ * Set the Request API Key
80
+ *
81
+ * @param string $api_key
82
+ */
83
+ public function set_api_key( $api_key ) {
84
+ $this->api_key = $api_key;
85
+ }
86
+
87
+
88
+ public function set_timeout( $timeout ) {
89
+ $this->timeout = $timeout;
90
+ }
91
+
92
+ /**
93
+ * Add a new request argument for POST requests
94
+ *
95
+ * @param string $name
96
+ * @param string $value
97
+ */
98
+ public function add_post_argument( $name, $value ) {
99
+ $this->post_args[ $name ] = $value;
100
+ }
101
+
102
+ /**
103
+ * Add a new request argument for GET requests
104
+ *
105
+ * @param string $name
106
+ * @param string $value
107
+ */
108
+ public function add_get_argument( $name, $value ) {
109
+ $this->get_args[ $name ] = $value;
110
+ }
111
+
112
+ /**
113
+ * Add a new request argument for GET requests
114
+ *
115
+ * @param string $name
116
+ * @param string $value
117
+ */
118
+ public function add_header_argument( $name, $value ) {
119
+ $this->headers[ $name ] = $value;
120
+ }
121
+
122
+
123
+ /**
124
+ * Get the Request URL
125
+ *
126
+ * @return mixed
127
+ */
128
+ abstract public function get_api_url( $path = '' );
129
+
130
+
131
+ /**
132
+ * Make a GET API Call
133
+ *
134
+ * @param string $path Endpoint route
135
+ * @param array() $data
136
+ *
137
+ * @return mixed
138
+ */
139
+ public function get( $path, $data = array() ) {
140
+ try {
141
+ $result = $this->request( $path, $data, 'get' );
142
+ return $result;
143
+ }
144
+ catch ( WP_Hummingbird_API_Exception $e ) {
145
+ return new WP_Error( $e->getCode(), $e->getMessage() );
146
+ }
147
+
148
+ }
149
+
150
+ /**
151
+ * Make a GET API Call
152
+ *
153
+ * @param string $path Endpoint route
154
+ * @param array() $data
155
+ *
156
+ * @return mixed
157
+ */
158
+ public function post( $path, $data = array() ) {
159
+ try {
160
+ $result = $this->request( $path, $data, 'post' );
161
+ return $result;
162
+ }
163
+ catch ( WP_Hummingbird_API_Exception $e ) {
164
+ return new WP_Error( $e->getCode(), $e->getMessage() );
165
+ }
166
+ }
167
+
168
+ public function patch( $path, $data = array() ) {
169
+ try {
170
+ $result = $this->request( $path, $data, 'patch' );
171
+ return $result;
172
+ }
173
+ catch ( WP_Hummingbird_API_Exception $e ) {
174
+ return new WP_Error( $e->getCode(), $e->getMessage() );
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Make a GET API Call
180
+ *
181
+ * @param string $path Endpoint route
182
+ * @param array() $data
183
+ *
184
+ * @return mixed
185
+ */
186
+ public function head( $path, $data = array() ) {
187
+ try {
188
+ $result = $this->request( $path, $data, 'head' );
189
+ return $result;
190
+ }
191
+ catch ( WP_Hummingbird_API_Exception $e ) {
192
+ return new WP_Error( $e->getCode(), $e->getMessage() );
193
+ }
194
+
195
+ }
196
+
197
+ /**
198
+ * Make a GET API Call
199
+ *
200
+ * @param string $path Endpoint route
201
+ * @param array() $data
202
+ *
203
+ * @return mixed
204
+ */
205
+ public function delete( $path, $data = array() ) {
206
+ try {
207
+ $result = $this->request( $path, $data, 'delete' );
208
+ return $result;
209
+ }
210
+ catch ( WP_Hummingbird_API_Exception $e ) {
211
+ return new WP_Error( $e->getCode(), $e->getMessage() );
212
+ }
213
+
214
+ }
215
+
216
+
217
+ /**
218
+ * Make an API Request
219
+ *
220
+ * @param $path
221
+ * @param array $data
222
+ * @param string $method
223
+ *
224
+ * @return array|mixed|object
225
+ * @throws WP_Hummingbird_API_Exception
226
+ */
227
+ public function request( $path, $data = array(), $method = 'post' ) {
228
+ $url = $this->get_api_url( $path );
229
+
230
+ $this->sign_request();
231
+
232
+ $url = add_query_arg( $this->get_args, $url );
233
+ if ( 'post' != $method && 'patch' != $method && 'delete' != $method ) {
234
+ $url = add_query_arg( $data, $url );
235
+ }
236
+
237
+ $args = array(
238
+ 'headers' => $this->headers,
239
+ 'sslverify' => false,
240
+ 'method' => strtoupper( $method ),
241
+ 'timeout' => $this->timeout,
242
+ );
243
+
244
+ if ( ! $args['timeout'] || 0.1 === $args['timeout'] ) {
245
+ $args['blocking'] = false;
246
+ }
247
+
248
+ $this->log( "WPHB API: Sending request to $url" );
249
+ $this->log( "WPHB API: Arguments:" );
250
+ $this->log( $args );
251
+
252
+ switch ( strtolower( $method ) ) {
253
+ case 'patch':
254
+ case 'delete':
255
+ case 'post': {
256
+ if ( is_array( $data ) ) {
257
+ $args['body'] = array_merge( $data, $this->post_args );
258
+ }
259
+ else {
260
+ $args['body'] = $data;
261
+ }
262
+
263
+ $response = wp_remote_post( $url, $args );
264
+ break;
265
+ }
266
+ case 'head': {
267
+ $response = wp_remote_head( $url, $args );
268
+ break;
269
+ }
270
+ case 'get': {
271
+ $response = wp_remote_get( $url, $args );
272
+ break;
273
+ }
274
+ default: {
275
+ $response = wp_remote_request( $url, $args );
276
+ }
277
+ }
278
+
279
+ $this->log( "WPHB API: Response:" );
280
+ $this->log( $response );
281
+
282
+ return $response;
283
+
284
+ }
285
+
286
+ protected function sign_request() {}
287
+
288
+ private function log( $message ) {
289
+ if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
290
+ $date = current_time( 'mysql' );
291
+ if ( ! is_string( $message ) ) {
292
+ $message = print_r( $message, true );
293
+ }
294
+ error_log( '[' . $date . '] - ' . $message );
295
+ }
296
+ }
297
+ }
core/api/request/wpmudev.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_API_Request_WPMUDEV extends WP_Hummingbird_API_Request {
4
+
5
+ public function get_api_key() {
6
+ global $wpmudev_un;
7
+
8
+ if ( ! is_object( $wpmudev_un ) && class_exists( 'WPMUDEV_Dashboard' ) && method_exists( 'WPMUDEV_Dashboard', 'instance' ) ) {
9
+ $wpmudev_un = WPMUDEV_Dashboard::instance();
10
+ }
11
+
12
+ if ( defined( 'WPHB_API_KEY' ) ) {
13
+ $api_key = WPHB_API_KEY;
14
+ }
15
+ elseif ( is_object( $wpmudev_un ) && method_exists( $wpmudev_un, 'get_apikey' ) ) {
16
+ $api_key = $wpmudev_un->get_apikey();
17
+ }
18
+ elseif ( class_exists( 'WPMUDEV_Dashboard' ) && is_object( WPMUDEV_Dashboard::$api ) && method_exists( WPMUDEV_Dashboard::$api, 'get_key' ) ) {
19
+ $api_key = WPMUDEV_Dashboard::$api->get_key();
20
+ }
21
+ else {
22
+ $api_key = '';
23
+ }
24
+
25
+ return $api_key;
26
+ }
27
+
28
+ public function get_api_url( $path = '' ) {
29
+ if ( defined( 'WPHB_TEST_API_URL' ) && WPHB_TEST_API_URL ) {
30
+ $url = WPHB_TEST_API_URL;
31
+ } else {
32
+ /** @var WP_Hummingbird_API_Service_Performance|WP_Hummingbird_API_Service_Uptime $service */
33
+ $service = $this->get_service();
34
+ $url = 'https://premium.wpmudev.org/api/' . $this->get_service()->get_name() . '/' . $service->get_version() . '/';
35
+ }
36
+
37
+ $url = trailingslashit( $url . $path );
38
+
39
+ return $url;
40
+ }
41
+
42
+ /**
43
+ * Get the current Site URL
44
+ *
45
+ * The network_site_url() of the WP installation. (Or network_home_url if not passing an API key).
46
+ *
47
+ * @return string
48
+ */
49
+ public function get_this_site() {
50
+ if ( defined( 'WPHB_API_DOMAIN' ) ) {
51
+ $domain = WPHB_API_DOMAIN;
52
+ } else {
53
+ $key = $this->get_api_key();
54
+ if ( ! empty( $key ) ) {
55
+ $domain = network_site_url();
56
+ } else {
57
+ $domain = network_home_url();
58
+ }
59
+ }
60
+
61
+ return $domain;
62
+ }
63
+
64
+ protected function sign_request() {
65
+ $key = $this->get_api_key();
66
+ if ( ! empty( $key ) ) {
67
+ $this->add_header_argument( 'Authorization', 'Basic ' . $this->get_api_key() );
68
+ }
69
+ }
70
+
71
+
72
+ /**
73
+ * @inheritdoc
74
+ */
75
+ public function request( $path, $data = array(), $method = 'post', $extra = array() ) {
76
+ $response = parent::request( $path, $data, $method, $extra );
77
+
78
+ if ( is_wp_error( $response ) ) {
79
+ throw new WP_Hummingbird_API_Exception( $response->get_error_message(), $response->get_error_code() );
80
+ }
81
+
82
+ $code = wp_remote_retrieve_response_code( $response );
83
+ $body = json_decode( wp_remote_retrieve_body( $response ) );
84
+ $message = isset( $body->message ) ? $body->message : sprintf( __( 'Unknown Error. Code: %s', 'wphb' ), $code );
85
+
86
+ if ( 200 != $code ) {
87
+ throw new WP_Hummingbird_API_Exception( $message, $code );
88
+ }
89
+ else {
90
+ if ( is_object( $body ) && isset( $body->error ) && $body->error ) {
91
+ throw new WP_Hummingbird_API_Exception( $message, $code );
92
+ }
93
+ return $body;
94
+ }
95
+
96
+ }
97
+
98
+
99
+ }
core/api/service/cloudflare.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_API_Service_Cloudflare extends WP_Hummingbird_API_Service {
4
+
5
+ protected $name = 'cloudflare';
6
+
7
+ public function __construct() {
8
+ $this->request = new WP_Hummingbird_API_Request_Cloudflare( $this );
9
+ }
10
+
11
+ public function set_auth_email( $email ) {
12
+ $this->request->set_auth_email( $email );
13
+ }
14
+
15
+ public function set_auth_key( $key ) {
16
+ $this->request->set_auth_key( $key );
17
+ }
18
+
19
+ public function get_zones_list( $page = 1, $per_page = 20 ) {
20
+ return $this->request->get( "zones", array( 'per_page' => $per_page, 'page' => $page ) );
21
+ }
22
+
23
+ public function get_page_rules_list( $zone ) {
24
+ return $this->request->get( "zones/$zone/pagerules" );
25
+ }
26
+
27
+ public function add_page_rule( $targets, $actions, $zone, $status = 'active', $priority = null ) {
28
+ $data = array(
29
+ 'targets' => $targets,
30
+ 'actions' => $actions,
31
+ 'priority' => $priority,
32
+ 'status' => $status
33
+ );
34
+
35
+ return $this->request->post( "zones/$zone/pagerules", json_encode($data) );
36
+ }
37
+
38
+ public function update_page_rule( $id, $targets, $actions, $zone, $status = 'active', $priority = null ) {
39
+ $data = array(
40
+ 'targets' => $targets,
41
+ 'actions' => $actions,
42
+ 'priority' => $priority,
43
+ 'status' => $status
44
+ );
45
+
46
+ return $this->request->patch( "zones/$zone/pagerules/$id", json_encode($data) );
47
+ }
48
+
49
+ public function delete_page_rule( $id, $zone ) {
50
+ return $this->request->delete( "zones/$zone/pagerules/$id" );
51
+ }
52
+
53
+ public function set_caching_expiration( $zone, $value ) {
54
+ $data = array(
55
+ 'value' => $value
56
+ );
57
+ return $this->request->patch( "zones/$zone/settings/browser_cache_ttl", json_encode( $data ) );
58
+ }
59
+
60
+ public function get_caching_expiration( $zone ) {
61
+ return $this->request->get( "zones/$zone/settings/browser_cache_ttl" );
62
+ }
63
+
64
+ public function purge_cache( $zone ) {
65
+ return $this->request->delete( "/zones/$zone/purge_cache", wp_json_encode( array( 'purge_everything' => true ) ) );
66
+ }
67
+
68
+ }
core/api/service/minify.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_API_Service_Minify extends WP_Hummingbird_API_Service {
4
+
5
+ public $name = 'minify';
6
+
7
+ public function __construct() {
8
+ $this->request = new WP_Hummingbird_API_Request_Minify( $this );
9
+ }
10
+
11
+ /**
12
+ * Check if performance test has finished on server
13
+ *
14
+ * @return array|mixed|object|WP_Error
15
+ */
16
+ public function process_files( $files = array() ) {
17
+ $args = array(
18
+ 'domain' => $this->request->get_this_site(),
19
+ );
20
+
21
+ $args['path'] = '';
22
+ if ( is_multisite() && ! is_subdomain_install() ) {
23
+ $blog_details = get_blog_details( get_current_blog_id() );
24
+ $args['path'] = $blog_details->path;
25
+ }
26
+ elseif ( is_multisite() && is_subdomain_install() ) {
27
+ global $current_site;
28
+ $blog_details = get_blog_details( get_current_blog_id() );
29
+ $pattern = '/(https?\:\/\/)?(.*)\.' . $current_site->domain . '(.*)/';
30
+ if ( preg_match_all( $pattern, home_url(), $matches ) ) {
31
+ $args['path'] = $matches[2][0];
32
+ }
33
+ }
34
+
35
+ $args['files'] = $files;
36
+
37
+ $args = wp_json_encode( $args );
38
+
39
+ $this->request->add_header_argument( 'content-type', 'application/json' );
40
+
41
+ $result = $this->request->post( 'minify', $args );
42
+ if ( is_wp_error( $result ) ) {
43
+ return $result;
44
+ }
45
+
46
+ return json_decode( wp_remote_retrieve_body( $result ) );
47
+ }
48
+
49
+ }
core/api/service/performance.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_API_Service_Performance extends WP_Hummingbird_API_Service {
4
+
5
+ public $name = 'performance';
6
+
7
+ private $version = 'v1';
8
+
9
+ public function __construct() {
10
+ $this->request = new WP_Hummingbird_API_Request_WPMUDEV( $this );
11
+ }
12
+
13
+ public function get_version() {
14
+ return $this->version;
15
+ }
16
+
17
+ /**
18
+ * Check if performance test has finished on server
19
+ *
20
+ * @return array|mixed|object|WP_Error
21
+ */
22
+ public function check() {
23
+ return $this->request->post( 'site/check/', array( 'domain' => $this->request->get_this_site() ) );
24
+ }
25
+
26
+ /**
27
+ * Ping to Performance Module so it starts to gather data
28
+ *
29
+ * @return array|mixed|object|WP_Error
30
+ */
31
+ public function ping() {
32
+ $this->request->set_timeout( 0.1 );
33
+ return $this->request->post( 'site/check/', array( 'domain' => $this->request->get_this_site() ) );
34
+ }
35
+
36
+ /**
37
+ * Get the latest performance test results
38
+ *
39
+ * @return array|mixed|object|WP_Error
40
+ */
41
+ public function results() {
42
+ return $this->request->get( 'site/result/latest/', array( 'domain' => $this->request->get_this_site() ) );
43
+ }
44
+
45
+
46
+ }
core/api/service/service.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class WP_Hummingbird_API_Service {
4
+
5
+ protected $name = '';
6
+
7
+ /**
8
+ * @var null|WP_Hummingbird_API_Request
9
+ */
10
+ protected $request = null;
11
+
12
+ /**
13
+ * Get the Service Name
14
+ *
15
+ * @return string
16
+ */
17
+ public function get_name() {
18
+ return $this->name;
19
+ }
20
+
21
+ }
core/api/service/uptime.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_API_Service_Uptime extends WP_Hummingbird_API_Service {
4
+
5
+ protected $name = 'uptime';
6
+
7
+ private $version = 'v1';
8
+
9
+ public function __construct() {
10
+ $this->request = new WP_Hummingbird_API_Request_WPMUDEV( $this );
11
+ }
12
+
13
+ public function get_version() {
14
+ return $this->version;
15
+ }
16
+
17
+ /**
18
+ * Get Uptime data for a given segment of time
19
+ *
20
+ * @param string $time day|week|month
21
+ *
22
+ * @return mixed
23
+ */
24
+ public function check( $time = 'day' ) {
25
+ $this->request->set_timeout( 20 );
26
+ return $this->request->get( 'stats/' . $time, array( 'domain' => $this->request->get_this_site() ) );
27
+ }
28
+
29
+ /**
30
+ * Check if Uptime is enabled remotely
31
+ *
32
+ * @return mixed|WP_Error
33
+ */
34
+ public function is_enabled() {
35
+ $this->request->set_timeout( 30 );
36
+ $results = $this->request->get( 'stats/week/', array( 'domain' => $this->request->get_this_site() ) );
37
+
38
+ if ( is_wp_error( $results ) ) {
39
+ return false;
40
+ }
41
+
42
+ return true;
43
+ }
44
+
45
+ /**
46
+ * Enable Uptime remotely
47
+ *
48
+ * @return mixed|WP_Error
49
+ */
50
+ public function enable() {
51
+ $this->request->set_timeout( 30 );
52
+ $results = $this->request->post( 'monitoring', array( 'domain' => $this->request->get_this_site() ) );
53
+
54
+ if ( $results !== true ) {
55
+ return new WP_Error( 500, __( 'Unknown Error', 'wphb' ) );
56
+ }
57
+
58
+ return $results;
59
+ }
60
+
61
+ /**
62
+ * Disable Uptime remotely
63
+ *
64
+ * @return mixed|WP_Error
65
+ */
66
+ public function disable() {
67
+ $this->request->set_timeout( 30 );
68
+ $results = $this->request->delete( 'monitoring', array( 'domain' => $this->request->get_this_site() ) );
69
+
70
+ if ( $results !== true ) {
71
+ return new WP_Error( 500, __( 'Unknown Error', 'wphb' ) );
72
+ }
73
+
74
+ return $results;
75
+ }
76
+ }
core/class-abstract-module-server.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class WP_Hummingbird_Module_Server
5
+ *
6
+ * A parent class for those modules that offers a piece of code to
7
+ * setup the server (gzip and caching)
8
+ */
9
+ abstract class WP_Hummingbird_Module_Server extends WP_Hummingbird_Module {
10
+
11
+ protected $transient_slug = false;
12
+
13
+ public function run() {}
14
+ public function init() {}
15
+
16
+ /**
17
+ * Return the analized data for the module
18
+ *
19
+ * @param bool $force If set to true, cache will be cleared before getting the data
20
+ *
21
+ * @return mixed Analysis data
22
+ */
23
+ public function get_analysis_data( $force = false ) {
24
+ if ( ! $this->transient_slug )
25
+ return false;
26
+
27
+ $transient = 'wphb-' . $this->transient_slug . '-data';
28
+ $results = get_site_option( $transient );
29
+
30
+ if ( $force ) {
31
+
32
+ $this->clear_analysis_data();
33
+
34
+ $results = $this->analize_data();
35
+
36
+ update_site_option( $transient, $results );
37
+
38
+ }
39
+
40
+ return $results;
41
+ }
42
+
43
+ /**
44
+ * Analize the data
45
+ *
46
+ * @return mixed
47
+ */
48
+ protected abstract function analize_data();
49
+
50
+ /**
51
+ * Clear the module cache
52
+ */
53
+ public function clear_analysis_data() {
54
+ delete_site_option( 'wphb-' . $this->transient_slug . '-data' );
55
+ }
56
+
57
+ /**
58
+ * Get the server code snippet
59
+ *
60
+ * @param string $server Server name (nginx,apache...)
61
+ *
62
+ * @return string
63
+ */
64
+ public function get_server_code_snippet( $server ) {
65
+ $method = 'get_' . str_replace( array( '-', ' ' ), '', strtolower( $server ) ) . '_code';
66
+ if ( ! method_exists( $this, $method ) )
67
+ return '';
68
+
69
+ return call_user_func( array( $this, $method ) );
70
+ }
71
+ }
core/class-abstract-module.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class WP_Hummingbird_Module
5
+ *
6
+ * Abstract class that define every module in WP Hummingbird
7
+ */
8
+ abstract class WP_Hummingbird_Module {
9
+
10
+ /**
11
+ * Module slug name
12
+ *
13
+ * @var string
14
+ */
15
+ protected $slug = '';
16
+
17
+ /**
18
+ * Module name
19
+ *
20
+ * @var string
21
+ */
22
+ protected $name = '';
23
+
24
+ public function __construct( $slug, $name ) {
25
+ $this->slug = $slug;
26
+ $this->name = $name;
27
+ $this->init();
28
+ }
29
+
30
+ /**
31
+ * Return true if the module is activated
32
+ *
33
+ * @return Boolean
34
+ */
35
+ public function is_active() {
36
+ $slug = $this->get_slug();
37
+
38
+ /**
39
+ * Filters the activation of a module
40
+ *
41
+ * @usedby wphb_caching_module_status()
42
+ * @usedby wphb_uptime_module_status()
43
+ * @usedby wphb_minify_module_status()
44
+ *
45
+ * @param boolean $active if the module is active or not
46
+ */
47
+ return apply_filters( "wp_hummingbird_is_active_module_$slug", true );
48
+ }
49
+
50
+ /**
51
+ * Return the module slug name
52
+ *
53
+ * @return string
54
+ */
55
+ public function get_slug() {
56
+ return $this->slug;
57
+ }
58
+
59
+
60
+ /**
61
+ * Return the module name
62
+ *
63
+ * @return string
64
+ */
65
+ public function get_name() {
66
+ return $this->name;
67
+ }
68
+
69
+ /**
70
+ * Initializes the module. Always executed even if the module is deactivated.
71
+ *
72
+ * Do not use __construct in subclasses, use init() instead
73
+ */
74
+ public abstract function init();
75
+
76
+ /**
77
+ * Execute the module actions. It must be defined in subclasses.
78
+ */
79
+ public abstract function run();
80
+
81
+ /**
82
+ * Return the options array for this module
83
+ *
84
+ * @return array List of options
85
+ */
86
+ public function options() {
87
+ return array();
88
+ }
89
+
90
+ }
core/class-core.php ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class WP_Hummingbird_Core
5
+ */
6
+ class WP_Hummingbird_Core {
7
+
8
+ /**
9
+ * Saves the modules object instances
10
+ *
11
+ * @var array
12
+ */
13
+ public $modules = array();
14
+
15
+ public function __construct() {
16
+ $this->includes();
17
+
18
+ // Init the API
19
+ /** @noinspection PhpIncludeInspection */
20
+ include_once( wphb_plugin_dir() . 'core/api/class-api.php' );
21
+ $this->api = new WP_Hummingbird_API();
22
+
23
+ $this->load_modules();
24
+
25
+ $minify = wphb_get_setting( 'minify' );
26
+ if ( ( is_multisite() && ( ( 'super-admins' === $minify && is_super_admin() ) || ( true === $minify ) ) )
27
+ || ( ! is_multisite() && current_user_can( wphb_get_admin_capability() ) ) ) {
28
+ add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 );
29
+ }
30
+
31
+ }
32
+
33
+ private function includes() {
34
+ /** @noinspection PhpIncludeInspection */
35
+ include_once( wphb_plugin_dir() . 'core/settings-hooks.php' );
36
+ /** @noinspection PhpIncludeInspection */
37
+ include_once( wphb_plugin_dir() . 'core/modules-hooks.php' );
38
+ }
39
+
40
+ /**
41
+ * Load WP Hummingbird modules
42
+ */
43
+ private function load_modules() {
44
+ /**
45
+ * Filters the modules slugs list
46
+ */
47
+ $modules = apply_filters( 'wp_hummingbird_modules', array(
48
+ 'minify' => __( 'Minify', 'wphb' ),
49
+ 'minifynew' => __( 'Minify New', 'wphb' ),
50
+ 'gzip' => __( 'Gzip', 'wphb' ),
51
+ 'caching' => __( 'Caching', 'wphb' ),
52
+ 'performance' => __( 'Performance', 'wphb' ),
53
+ 'uptime' => __( 'Uptime', 'wphb' ),
54
+ 'smush' => __( 'Smush', 'wphb' ),
55
+ 'cloudflare' => __( 'Cloudflare', 'wphb' )
56
+ ) );
57
+
58
+ /** @noinspection PhpIncludeInspection */
59
+ include_once wphb_plugin_dir() . 'core/class-abstract-module.php';
60
+ include_once wphb_plugin_dir() . 'core/class-abstract-module-server.php';
61
+
62
+ array_walk( $modules, array( $this, 'load_module' ) );
63
+ }
64
+
65
+ /**
66
+ * Load a single module
67
+ *
68
+ * @param string $name Module Name
69
+ * @param string $module Module slug
70
+ */
71
+ public function load_module( $name, $module ) {
72
+ $class_name = 'WP_Hummingbird_Module_' . ucfirst( $module );
73
+
74
+ // Default modules files
75
+ $filename = wphb_plugin_dir() . 'core/modules/class-module-' . $module . '.php';;
76
+ if ( file_exists( $filename ) ) {
77
+ include_once $filename;
78
+ }
79
+
80
+ if ( class_exists( $class_name ) ) {
81
+ $module_obj = new $class_name( $module, $name );
82
+
83
+ /** @var WP_Hummingbird_Module $module_obj */
84
+ if ( $module_obj->is_active() ) {
85
+ $module_obj->run();
86
+ }
87
+
88
+ $this->modules[ $module ] = $module_obj;
89
+ }
90
+ }
91
+
92
+
93
+
94
+ /**
95
+ * Add a HB menu to the admin bar
96
+ *
97
+ * @param WP_Admin_Bar $admin_bar
98
+ */
99
+ public function admin_bar_menu( $admin_bar ) {
100
+ /** @var WP_Hummingbird_Module_Minify $minification_module */
101
+ $minification_module = wphb_get_module( 'minify' );
102
+
103
+ $menu_args = array(
104
+ 'id' => 'wphb',
105
+ 'title' => 'Hummingbird',
106
+ 'href' => admin_url( 'admin.php?page=wphb-minification' )
107
+ );
108
+
109
+ if ( $minification_module->is_active() ) {
110
+ if ( ! is_admin() && ! isset( $_GET['avoid-minify'] ) ) {
111
+ $admin_bar->add_menu( $menu_args );
112
+ $admin_bar->add_menu( array(
113
+ 'id' => 'wphb-page-minify',
114
+ 'title' => __( 'See this page unminified', 'wphb' ),
115
+ 'href' => add_query_arg( 'avoid-minify', 'true' ),
116
+ 'parent' => 'wphb'
117
+ ));
118
+ }
119
+ }
120
+ else {
121
+ if ( ! is_admin() && isset( $_GET['avoid-minify'] ) ) {
122
+ $admin_bar->add_menu( $menu_args );
123
+ $admin_bar->add_menu( array(
124
+ 'id' => 'wphb-page-minify',
125
+ 'title' => __( 'See this page minified', 'wphb' ),
126
+ 'href' => remove_query_arg( 'avoid-minify' ),
127
+ 'parent' => 'wphb'
128
+ ));
129
+ }
130
+ }
131
+ }
132
+
133
+
134
+
135
+ }
core/class-installer.php ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @author: WPMUDEV, Ignacio Cruz (igmoweb)
4
+ * @version:
5
+ */
6
+
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit;
10
+ }
11
+
12
+ if ( ! class_exists( 'WP_Hummingbird_Installer' ) ) {
13
+ /**
14
+ * Class WP_Hummingbird_Installer
15
+ *
16
+ * Manages activation/deactivation and upgrades of Hummingbird
17
+ */
18
+ class WP_Hummingbird_Installer {
19
+
20
+ /**
21
+ * Plugin activation
22
+ */
23
+ public static function activate() {
24
+ if ( ! defined( 'WPHB_ACTIVATING' ) ) {
25
+ define( 'WPHB_ACTIVATING', true );
26
+ }
27
+
28
+ /** @noinspection PhpIncludeInspection */
29
+ include_once( wphb_plugin_dir() . 'helpers/wp-hummingbird-helpers-core.php' );
30
+ /** @noinspection PhpIncludeInspection */
31
+ include_once( wphb_plugin_dir() . 'helpers/wp-hummingbird-helpers-settings.php' );
32
+ /** @noinspection PhpIncludeInspection */
33
+ include_once( wphb_plugin_dir() . 'helpers/wp-hummingbird-helpers-cache.php' );
34
+ /** @noinspection PhpIncludeInspection */
35
+ include_once( wphb_plugin_dir() . 'helpers/wp-hummingbird-helpers-modules.php' );
36
+ /** @noinspection PhpIncludeInspection */
37
+ include_once( wphb_plugin_dir() . 'core/class-abstract-module.php' );
38
+ /** @noinspection PhpIncludeInspection */
39
+ include_once( wphb_plugin_dir() . 'core/modules/class-module-uptime.php' );
40
+ /** @noinspection PhpIncludeInspection */
41
+ include_once( wphb_plugin_dir() . 'core/modules/class-module-cloudflare.php' );
42
+
43
+ // Check if Uptime is active in the server
44
+ if ( wphb_is_uptime_remotely_enabled() ) {
45
+ wphb_uptime_enable_locally();
46
+ }
47
+ else {
48
+ wphb_uptime_disable_locally();
49
+ }
50
+
51
+ update_site_option( 'wphb_version', WPHB_VERSION );
52
+
53
+ wphb_has_cloudflare( true );
54
+
55
+ do_action( 'wphb_activate' );
56
+ }
57
+
58
+ /**
59
+ * Plugin activation in a blog (if the site is a multisite)
60
+ */
61
+ public static function activate_blog() {
62
+ /** @noinspection PhpIncludeInspection */
63
+ include_once( wphb_plugin_dir() . 'helpers/wp-hummingbird-helpers-core.php' );
64
+ /** @noinspection PhpIncludeInspection */
65
+ include_once( wphb_plugin_dir() . 'helpers/wp-hummingbird-helpers-cache.php' );
66
+
67
+ update_option( 'wphb_version', WPHB_VERSION );
68
+
69
+ do_action( 'wphb_deactivate' );
70
+ }
71
+
72
+ /**
73
+ * Plugin deactivation
74
+ */
75
+ public static function deactivate() {
76
+ wphb_flush_cache( false );
77
+ delete_site_option( 'wphb_version' );
78
+ delete_option( 'wphb_cache_folder_error' );
79
+ delete_option( 'wphb-minification-check-files' );
80
+ delete_site_option( 'wphb-last-report' );
81
+ delete_site_option( 'wphb-last-report-score' );
82
+ delete_site_option( 'wphb-server-type' );
83
+ delete_site_transient( 'wphb-uptime-last-report' );
84
+ delete_site_transient( 'wphb-uptime-remotely-enabled' );
85
+ delete_site_option( 'wphb-is-cloudflare' );
86
+ wphb_cloudflare_disconnect();
87
+ delete_site_option( 'wphb-notice-free-deactivated-dismissed' );
88
+
89
+ if ( wp_next_scheduled( 'wphb_minify_clear_files' ) ) {
90
+ wp_clear_scheduled_hook( 'wphb_minify_clear_files' );
91
+ }
92
+
93
+ do_action( 'wphb_deactivate' );
94
+ }
95
+
96
+ /**
97
+ * Plugin upgrades
98
+ */
99
+ public static function maybe_upgrade() {
100
+ if ( defined( 'WPHB_ACTIVATING' ) ) {
101
+ // Avoid to execute this over an over in same thread execution
102
+ return;
103
+ }
104
+
105
+ if ( defined( 'WPHB_UPGRADING' ) && WPHB_UPGRADING ) {
106
+ return;
107
+ }
108
+
109
+ self::upgrade();
110
+ }
111
+
112
+ public static function upgrade() {
113
+ $version = get_site_option( 'wphb_version' );
114
+
115
+ if ( false === $version ) {
116
+ self::activate();
117
+ if ( ! is_multisite() ) {
118
+ self::activate_blog();
119
+ }
120
+ }
121
+
122
+ if ( is_multisite() ) {
123
+ $blog_version = get_option( 'wphb_version' );
124
+ if ( false === $blog_version ) {
125
+ self::activate_blog();
126
+ }
127
+ }
128
+
129
+ if ( $version != WPHB_VERSION ) {
130
+
131
+ define( 'WPHB_UPGRADING', true );
132
+
133
+ if ( version_compare( $version, '1.0-RC-7', '<' ) ) {
134
+ delete_site_option( 'wphb-server-type' );
135
+ }
136
+
137
+ if ( version_compare( $version, '1.1', '<' ) ) {
138
+ $options = wphb_get_settings();
139
+ $defaults = wphb_get_default_settings();
140
+
141
+ if ( isset ( $options['caching_expiry_css/javascript'] ) ) {
142
+ $options['caching_expiry_css'] = $options['caching_expiry_css/javascript'];
143
+ $options['caching_expiry_javascript'] = $options['caching_expiry_css/javascript'];
144
+ unset( $options['caching_expiry_css/javascript'] );
145
+ }
146
+ else {
147
+ $options['caching_expiry_css'] = $defaults['caching_expiry_css'];
148
+ $options['caching_expiry_javascript'] = $defaults['caching_expiry_javascript'];
149
+ }
150
+
151
+ wphb_update_settings( $options );
152
+ $module = new WP_Hummingbird_Module_Caching( 'caching', 'caching' );
153
+ $module->get_analysis_data( true );
154
+ }
155
+
156
+ if ( version_compare( $version, '1.1.1', '<' ) ) {
157
+ $options = wphb_get_setting( 'network_version' );
158
+ if ( empty( $options ) ) {
159
+ wphb_update_settings( wphb_get_default_settings() );
160
+ }
161
+ }
162
+
163
+ if ( version_compare( $version, '1.3', '<' ) ) {
164
+ wphb_has_cloudflare( true );
165
+ }
166
+
167
+ if ( version_compare( $version, '1.4', '<' ) ) {
168
+ self::upgrade_1_4();
169
+ }
170
+
171
+ if ( version_compare( $version, '1.5', '<' ) ) {
172
+ self::upgrade_1_5();
173
+ }
174
+
175
+ if ( version_compare( $version, '1.5.1-beta2', '<' ) ) {
176
+ self::upgrade_1_5_1_beta_2();
177
+ }
178
+
179
+ if ( version_compare( $version, '1.5.3', '<' ) ) {
180
+ self::upgrade_1_5_3();
181
+ }
182
+
183
+ update_site_option( 'wphb_version', WPHB_VERSION );
184
+ } // End if().
185
+ }
186
+
187
+ /**
188
+ * Upgrades a single blog in a multisite
189
+ */
190
+ public static function maybe_upgrade_blog() {
191
+ // 1.3.9 is the first version when blog upgrades are executed
192
+ $version = get_option( 'wphb_version', '1.3.9' );
193
+
194
+ if ( WPHB_VERSION === $version ) {
195
+ return;
196
+ }
197
+
198
+ if ( version_compare( $version, '1.4', '<' ) ) {
199
+ self::upgrade_1_4();
200
+ }
201
+
202
+ if ( version_compare( $version, '1.5', '<' ) ) {
203
+ self::upgrade_1_5();
204
+ }
205
+
206
+ update_option( 'wphb_version', WPHB_VERSION );
207
+ }
208
+
209
+ private static function upgrade_1_4() {
210
+ global $wpdb;
211
+
212
+ //Drop chart table
213
+ $chart_table = $wpdb->prefix . 'minification_chart';
214
+ $wpdb->query( "DROP TABLE $chart_table" );
215
+ if ( ! function_exists( 'wphb_clear_minification_cache' ) ) {
216
+ include_once wphb_plugin_dir() . 'helpers/wp-hummingbird-helpers-cache.php';
217
+ }
218
+
219
+ wphb_clear_minification_cache();
220
+
221
+ // Move all those assets in header to default position
222
+ $options = wphb_get_settings();
223
+ $options['position'];
224
+
225
+ unset( $options['max_files_in_group'] );
226
+
227
+ wphb_update_settings( $options );
228
+
229
+ delete_option( 'wphb_cache_folder_error' );
230
+ }
231
+
232
+ private static function upgrade_1_5() {
233
+ // Move dont_combine list to a new combine list instead
234
+
235
+ $options = wphb_get_settings();
236
+ if ( ! isset( $options['dont_combine'] ) ) {
237
+ return;
238
+ }
239
+
240
+ $dont_combine = $options['dont_combine'];
241
+ unset( $options['dont_combine'] );
242
+
243
+ $collection = wphb_minification_get_resources_collection();
244
+
245
+ $options['combine'] = array( 'styles' => array(), 'scripts' => array() );
246
+ foreach ( $dont_combine as $type => $handles ) {
247
+ $options['combine'][ $type ] = array();
248
+ $type_collection = wp_list_pluck( $collection[ $type ], 'handle' );
249
+ foreach ( $type_collection as $type_handle ) {
250
+ if ( ! in_array( $type_handle, $handles ) ) {
251
+ $options['combine'][ $type ][] = $type_handle;
252
+ }
253
+ }
254
+ }
255
+
256
+ wphb_update_settings( $options );
257
+ }
258
+
259
+ private static function upgrade_1_5_1_beta_2() {
260
+ // Transform recipient user IDs to email/names array
261
+ $recipients = wphb_get_setting( 'email-recipients' );
262
+ $new_recipients = array();
263
+ foreach ( $recipients as $recipient ) {
264
+ if ( is_array( $recipient ) ) {
265
+ $new_recipients[] = $recipient;
266
+ continue;
267
+ }
268
+ elseif ( is_int( $recipient ) ) {
269
+ $user = get_user_by( 'id', $recipient );
270
+ if ( ! $user ) {
271
+ continue;
272
+ }
273
+
274
+ $new_recipients[] = array(
275
+ 'name' => wphb_get_display_name( $user->ID ),
276
+ 'email' => $user->user_email
277
+ );
278
+ }
279
+ }
280
+
281
+ wphb_update_setting( 'email-recipients', $new_recipients );
282
+ }
283
+
284
+ /**
285
+ * Upgrade to version 1.5.3.
286
+ *
287
+ * @since 1.5.3
288
+ */
289
+ private static function upgrade_1_5_3() {
290
+ // Welcome box deprecated since 1.5.0.
291
+ delete_metadata( 'user', '', 'wphb-hide-welcome-box', '', true );
292
+ }
293
+
294
+ }
295
+ }
core/integration.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+
3
+ include_once( 'integration/divi.php' );
core/integration/divi.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ function wphb_et_divi_theme_active() {
4
+ $theme = wp_get_theme();
5
+ return ( 'divi' === strtolower( $theme ) || 'divi' === strtolower( $theme->get_template() ) );
6
+ }
7
+
8
+ if ( ! function_exists( 'wphb_divi_after_init' ) ):
9
+ function wphb_divi_after_init() {
10
+ if ( wphb_et_divi_theme_active() ) {
11
+ remove_action( 'wp_head', 'et_add_custom_css', 100 );
12
+ add_action( 'wp_head', 'et_add_custom_css', 9999 );
13
+
14
+ remove_action( 'wp_head', 'et_divi_add_customizer_css' );
15
+ add_action( 'wp_head', 'et_divi_add_customizer_css', 9998 );
16
+ }
17
+
18
+ if ( wphb_et_visual_builder_active() || wphb_et_divi_builder_active() ) {
19
+ add_filter( 'wp_hummingbird_is_active_module_minify', '__return_false', 500 );
20
+ }
21
+ }
22
+ endif;
23
+
24
+ function wphb_et_visual_builder_active() {
25
+ return false !== strpos( $_SERVER['REQUEST_URI'], '?et_fb=1' );
26
+ }
27
+
28
+ function wphb_et_divi_builder_active() {
29
+ return is_admin() && function_exists( 'et_builder_should_load_framework' ) && et_builder_should_load_framework();
30
+ }
31
+
32
+ function wphb_et_divi_essential_scripts() {
33
+ return array(
34
+ 'et-builder-modules-global-functions-script',
35
+ 'et-builder-modules-script',
36
+ 'divi-custom-script',
37
+ 'et-frontend-builder', // This is already handled by `wphb_divi_after_init()` , including it here to hide it in HB dashboard.
38
+ );
39
+ }
40
+
41
+ function wphb_et_maybe_exclude_divi_essential_scripts( $action, $handle, $type ) {
42
+ if ( is_array( $handle ) && isset( $handle['handle'] ) ) {
43
+ $handle = $handle['handle'];
44
+ }
45
+
46
+ if ( 'scripts' === $type && in_array( $handle, wphb_et_divi_essential_scripts() ) ) {
47
+ return false;
48
+ }
49
+
50
+ return $action;
51
+ }
52
+
53
+ if ( wphb_et_divi_theme_active() || class_exists( 'ET_Builder_Plugin' ) ) {
54
+ add_action( 'init', 'wphb_divi_after_init', 1 );
55
+ add_filter( 'wphb_minify_resource', 'wphb_et_maybe_exclude_divi_essential_scripts', 10, 3 );
56
+ add_filter( 'wphb_combine_resource', 'wphb_et_maybe_exclude_divi_essential_scripts', 10, 3 );
57
+ add_filter( 'wphb_minification_display_enqueued_file', 'wphb_et_maybe_exclude_divi_essential_scripts', 10, 3 );
58
+ }
core/modules-hooks.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Manage tweaks for modules
4
+ */
5
+
6
+ /**
7
+ * We check for current screen, because on the Dashboard page we need to ignore files without original_size
8
+ * parameter. If we include them there are two notices in the error log.
9
+ * On the Minification dedicated page we include files without sizes.
10
+ */
11
+ add_filter( 'wphb_minification_display_enqueued_file', 'wphb_minification_hooks_hide_jquery_switchers', 10, 3 );
12
+ function wphb_minification_hooks_hide_jquery_switchers( $display, $handle, $type ) {
13
+
14
+ if ( 'toplevel_page_wphb' === get_current_screen()->id ) {
15
+ if ( ( 'scripts' === $type && 'jquery' === $handle['handle'] ) || ( ! isset( $handle['original_size'] ) ) ) {
16
+ return false;
17
+ }
18
+ } else {
19
+ if ( 'scripts' === $type && 'jquery' === $handle['handle'] ) {
20
+ return false;
21
+ }
22
+ }
23
+
24
+
25
+ return $display;
26
+ }
core/modules/class-module-caching.php ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Module_Caching extends WP_Hummingbird_Module_Server {
4
+
5
+ protected $transient_slug = 'caching';
6
+
7
+ public function analize_data() {
8
+
9
+ $files = array(
10
+ 'javascript' => wphb_plugin_url() . 'core/modules/dummy/dummy-js.js',
11
+ 'css' => wphb_plugin_url() . 'core/modules/dummy/dummy-style.css',
12
+ 'media' => wphb_plugin_url() . 'core/modules/dummy/dummy-media.mp3',
13
+ 'images' => wphb_plugin_url() . 'core/modules/dummy/dummy-image.png',
14
+ );
15
+
16
+ $results = array();
17
+ foreach ( $files as $type => $file ) {
18
+
19
+ $cookies = array();
20
+ foreach ( $_COOKIE as $name => $value ) {
21
+ if ( strpos( $name, 'wordpress_' ) > -1 ) {
22
+ $cookies[] = new WP_Http_Cookie( array( 'name' => $name, 'value' => $value ) );
23
+ }
24
+ }
25
+
26
+ $args = array(
27
+ 'cookies' => $cookies,
28
+ 'sslverify' => false
29
+ );
30
+
31
+ $result = wp_remote_head( $file, $args );
32
+
33
+ wphb_log( '----- analyzing headers for ' . $file, 'caching' );
34
+ wphb_log( 'args: ', 'caching' );
35
+ if ( isset( $args['cookies'] ) ) {
36
+ unset( $args['cookies'] );
37
+ }
38
+ wphb_log( $args, 'caching' );
39
+ wphb_log( 'result: ', 'caching' );
40
+ wphb_log( $result, 'caching' );
41
+
42
+ $cache_control = wp_remote_retrieve_header( $result, 'cache-control' );
43
+ $results[ $type ] = false;
44
+ if ( $cache_control ) {
45
+ if ( is_array( $cache_control ) ) {
46
+ // Join the cache control header into a single string
47
+ $cache_control = join( ' ', $cache_control );
48
+ }
49
+ if ( preg_match( '/max\-age=([0-9]*)/', $cache_control, $matches ) ) {
50
+ if ( isset( $matches[1] ) ) {
51
+ $seconds = absint( $matches[1] );
52
+ $results[ $type ] = $seconds;
53
+ }
54
+ }
55
+ }
56
+
57
+ }
58
+
59
+ do_action( 'wphb_caching_analize_data', $results );
60
+
61
+ return $results;
62
+ }
63
+
64
+ public static function apache_modules_loaded() {
65
+ $sapi_name = '';
66
+ $apache_modules = array();
67
+ if ( function_exists( 'php_sapi_name' ) ) {
68
+ $sapi_name = php_sapi_name();
69
+ }
70
+
71
+ if ( function_exists( 'php_sapi_name' ) ) {
72
+ $apache_modules = apache_get_modules();
73
+ }
74
+
75
+ return in_array( 'mod_expires', $apache_modules );
76
+
77
+ }
78
+
79
+ public function get_nginx_code() {
80
+ $options = wphb_get_settings();
81
+
82
+ $assets_expiration = explode( '/', $options['caching_expiry_javascript'] );
83
+ $assets_expiration = $assets_expiration[0];
84
+ $css_expiration = explode( '/', $options['caching_expiry_css'] );
85
+ $css_expiration = $css_expiration[0];
86
+ $media_expiration = explode( '/', $options['caching_expiry_media'] );
87
+ $media_expiration = $media_expiration [0];
88
+ $images_expiration = explode( '/', $options['caching_expiry_images'] );
89
+ $images_expiration = $images_expiration[0];
90
+
91
+ $code = '
92
+ location ~* \.(txt|xml|js)$ {
93
+ expires %%ASSETS%%;
94
+ }
95
+
96
+ location ~* \.(css)$ {
97
+ expires %%CSS%%;
98
+ }
99
+
100
+ location ~* \.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav|mp4|m4v|ogg|webm|aac)$ {
101
+ expires %%MEDIA%%;
102
+ }
103
+
104
+ location ~* \.(jpg|jpeg|png|gif|swf|webp)$ {
105
+ expires %%IMAGES%%;
106
+ }';
107
+
108
+ $code = str_replace( '%%MEDIA%%', $media_expiration, $code );
109
+ $code = str_replace( '%%IMAGES%%', $images_expiration, $code );
110
+ $code = str_replace( '%%ASSETS%%', $assets_expiration, $code );
111
+ $code = str_replace( '%%CSS%%', $css_expiration, $code );
112
+
113
+ return $code;
114
+ }
115
+
116
+
117
+
118
+ public function get_apache_code() {
119
+
120
+ $options = wphb_get_settings();
121
+
122
+ $assets_expiration = explode( '/', $options['caching_expiry_javascript'] );
123
+ $assets_expiration = $assets_expiration[1];
124
+ $css_expiration = explode( '/', $options['caching_expiry_css'] );
125
+ $css_expiration = $css_expiration[1];
126
+ $media_expiration = explode( '/', $options['caching_expiry_media'] );
127
+ $media_expiration = $media_expiration [1];
128
+ $images_expiration = explode( '/', $options['caching_expiry_images'] );
129
+ $images_expiration = $images_expiration[1];
130
+
131
+ $code = '
132
+ <IfModule mod_expires.c>
133
+ ExpiresActive On
134
+ ExpiresDefault A0
135
+
136
+ <FilesMatch "\.(txt|xml|js)$">
137
+ ExpiresDefault %%ASSETS%%
138
+ </FilesMatch>
139
+
140
+ <FilesMatch "\.(css)$">
141
+ ExpiresDefault %%CSS%%
142
+ </FilesMatch>
143
+
144
+ <FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav|mp4|m4v|ogg|webm|aac)$">
145
+ ExpiresDefault %%MEDIA%%
146
+ </FilesMatch>
147
+
148
+ <FilesMatch "\.(jpg|jpeg|png|gif|swf|webp)$">
149
+ ExpiresDefault %%IMAGES%%
150
+ </FilesMatch>
151
+ </IfModule>
152
+
153
+ <IfModule mod_headers.c>
154
+ <FilesMatch "\.(txt|xml|js)$">
155
+ Header set Cache-Control "max-age=%%ASSETS_HEAD%%"
156
+ </FilesMatch>
157
+
158
+ <FilesMatch "\.(css)$">
159
+ Header set Cache-Control "max-age=%%CSS_HEAD%%"
160
+ </FilesMatch>
161
+
162
+ <FilesMatch "\.(flv|ico|pdf|avi|mov|ppt|doc|mp3|wmv|wav|mp4|m4v|ogg|webm|aac)$">
163
+ Header set Cache-Control "max-age=%%MEDIA_HEAD%%"
164
+ </FilesMatch>
165
+
166
+ <FilesMatch "\.(jpg|jpeg|png|gif|swf|webp)$">
167
+ Header set Cache-Control "max-age=%%IMAGES_HEAD%%"
168
+ </FilesMatch>
169
+ </IfModule>';
170
+
171
+ $code = str_replace( '%%MEDIA%%', $media_expiration, $code );
172
+ $code = str_replace( '%%IMAGES%%', $images_expiration, $code );
173
+ $code = str_replace( '%%ASSETS%%', $assets_expiration, $code );
174
+ $code = str_replace( '%%CSS%%', $css_expiration, $code );
175
+
176
+ $code = str_replace( '%%MEDIA_HEAD%%', ltrim( $media_expiration, 'A' ), $code );
177
+ $code = str_replace( '%%IMAGES_HEAD%%', ltrim( $images_expiration, 'A' ), $code );
178
+ $code = str_replace( '%%ASSETS_HEAD%%', ltrim( $assets_expiration, 'A' ), $code );
179
+ $code = str_replace( '%%CSS_HEAD%%', ltrim( $css_expiration, 'A' ), $code );
180
+
181
+ return $code;
182
+ }
183
+
184
+ public function get_litespeed_code() {
185
+ return $this->get_apache_code();
186
+ }
187
+
188
+ public function get_iis_code() {
189
+ return '';
190
+ }
191
+
192
+ public function get_iis_7_code() {
193
+ return '';
194
+ }
195
+
196
+ }
core/modules/class-module-cloudflare.php ADDED
@@ -0,0 +1,371 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Module_Cloudflare extends WP_Hummingbird_Module {
4
+
5
+ /**
6
+ * Module slug name
7
+ *
8
+ * @var string
9
+ */
10
+ protected $slug = 'cloudflare';
11
+
12
+ /**
13
+ * Module name
14
+ *
15
+ * @var string
16
+ */
17
+ protected $name = 'Cloudflare';
18
+
19
+
20
+ /**
21
+ * Initializes Minify module
22
+ */
23
+ public function init() {
24
+ if ( self::has_cloudflare() ) {
25
+ add_filter( 'wp_hummingbird_is_active_module_' . $this->get_slug(), '__return_true' );
26
+ }
27
+ else {
28
+ add_filter( 'wp_hummingbird_is_active_module_' . $this->get_slug(), '__return_false' );
29
+ }
30
+ }
31
+
32
+ public function run() {}
33
+
34
+ /**
35
+ * Detect if site is using Cloudflare
36
+ *
37
+ * @param bool $force If set to true it will check again
38
+ *
39
+ * @return bool
40
+ */
41
+ public static function has_cloudflare( $force = false ) {
42
+ if ( isset( $_GET['wphb-check-cf'] ) ) {
43
+ // If we're checking do not try to check again or it will return a timeout
44
+ return (bool) get_site_option( 'wphb-is-cloudflare' );
45
+ }
46
+ if ( $force ) {
47
+ delete_site_option( 'wphb-is-cloudflare' );
48
+ }
49
+
50
+ $is_cloudflare = get_site_option( 'wphb-is-cloudflare' );
51
+
52
+ if ( ! is_numeric( $is_cloudflare ) || $force ) {
53
+ $url = add_query_arg( 'wphb-check-cf', 'true', home_url() );
54
+ $head = wp_remote_head( $url, array( 'sslverify' => false ) );
55
+ if ( is_wp_error( $head ) ) {
56
+ // Something weird happened
57
+ $is_cloudflare = false;
58
+ }
59
+ else {
60
+ $headers = wp_remote_retrieve_headers( $head );
61
+ if ( isset( $headers['server'] ) && strpos( $headers['server'], 'cloudflare' ) > -1 ) {
62
+ $is_cloudflare = true;
63
+ update_site_option( 'wphb-is-cloudflare', 1 );
64
+ }
65
+ else {
66
+ $is_cloudflare = false;
67
+ update_site_option( 'wphb-is-cloudflare', 0 );
68
+ }
69
+ }
70
+ }
71
+
72
+ $is_cloudflare = (bool) $is_cloudflare;
73
+ return apply_filters( 'wphb_has_cloudflare', $is_cloudflare );
74
+ }
75
+
76
+ public function is_connected() {
77
+ return wphb_get_setting( 'cloudflare-connected' );
78
+ }
79
+
80
+ public function is_zone_selected() {
81
+ $zone = wphb_get_setting( 'cloudflare-zone' );
82
+ return ! empty( $zone );
83
+ }
84
+
85
+ public function get_plan() {
86
+ return wphb_get_setting( 'cloudflare-plan' );
87
+ }
88
+
89
+
90
+
91
+ /**
92
+ * Tries to set the same caching rules in CF
93
+ */
94
+ public function set_caching_rules() {
95
+ if ( ! $this->is_connected() || ! $this->is_zone_selected() ) {
96
+ return;
97
+ }
98
+
99
+ $this->clear_caching_page_rules();
100
+
101
+ $expirations = self::get_filetypes_expirations();
102
+
103
+ foreach ( $expirations as $filetype => $expiration ) {
104
+ $this->add_caching_page_rule( $filetype );
105
+ }
106
+ }
107
+
108
+ public function clear_caching_page_rules() {
109
+ $rules = $this->get_registered_caching_page_rules();
110
+
111
+ foreach ( $rules as $filetype => $id ) {
112
+ $this->delete_caching_page_rule( $filetype );
113
+ }
114
+ }
115
+
116
+ public function delete_caching_page_rule( $filetype ) {
117
+ $id = $this->get_registered_caching_page_rule_id( $filetype );
118
+ $this->unregister_caching_page_rule( $filetype );
119
+
120
+ if ( ! $this->is_connected() || ! $this->is_zone_selected() ) {
121
+ return;
122
+ }
123
+
124
+ $zone = wphb_get_setting( 'cloudflare-zone' );
125
+ $api = wphb_get_api();
126
+ $api->cloudflare->set_auth_email( wphb_get_setting( 'cloudflare-email' ) );
127
+ $api->cloudflare->set_auth_key( wphb_get_setting( 'cloudflare-api-key' ) );
128
+
129
+ $api->cloudflare->delete_page_rule( $id, $zone );
130
+ }
131
+
132
+ public function update_caching_page_rule( $filetype ) {
133
+ // Check if the rule exists already
134
+ $id = $this->get_registered_caching_page_rule_id( $filetype );
135
+
136
+ if ( $id ) {
137
+ // Delete the rule and add it a new one
138
+ $this->delete_caching_page_rule( $filetype );
139
+ }
140
+
141
+ return $this->add_caching_page_rule( $filetype );
142
+ }
143
+
144
+ public function add_caching_page_rule( $filetype ) {
145
+ // If exists, delete it
146
+ $this->delete_caching_page_rule( $filetype );
147
+
148
+ if ( ! $this->is_connected() || ! $this->is_zone_selected() ) {
149
+ return false;
150
+ }
151
+
152
+ $expirations = self::get_filetypes_expirations();
153
+
154
+ if ( ! isset( $expirations[ $filetype ] ) ) {
155
+ return false;
156
+ }
157
+
158
+ if ( ! $expirations[ $filetype ] ) {
159
+ return false;
160
+ }
161
+
162
+ $targets = self::page_rule_targets( $filetype );
163
+ $actions = self::page_rule_actions( $expirations[ $filetype ] );
164
+
165
+ $zone = wphb_get_setting( 'cloudflare-zone' );
166
+ $api = wphb_get_api();
167
+ $api->cloudflare->set_auth_email( wphb_get_setting( 'cloudflare-email' ) );
168
+ $api->cloudflare->set_auth_key( wphb_get_setting( 'cloudflare-api-key' ) );
169
+
170
+ $result = $api->cloudflare->add_page_rule( $targets, $actions, $zone );
171
+
172
+ if ( is_wp_error( $result ) ) {
173
+ return false;
174
+ }
175
+
176
+ $this->register_caching_page_rule( $result->result->id, $filetype );
177
+ return $result->result->id;
178
+
179
+ }
180
+
181
+ public static function get_filetypes_expirations() {
182
+ $settings = wphb_get_settings();
183
+ $expirations = array();
184
+ $_expirations = array(
185
+ 'css' => $settings['caching_expiry_css'],
186
+ 'js' => $settings['caching_expiry_javascript'],
187
+ 'jpg' => $settings['caching_expiry_images'],
188
+ 'png' => $settings['caching_expiry_images'],
189
+ 'jpeg' => $settings['caching_expiry_images'],
190
+ 'gif' => $settings['caching_expiry_images'],
191
+ 'mp3' => $settings['caching_expiry_media'],
192
+ 'mp4' => $settings['caching_expiry_media'],
193
+ 'ico' => $settings['caching_expiry_media']
194
+ );
195
+
196
+ foreach ( $_expirations as $filetype => $time ) {
197
+ if ( ! $time ) {
198
+ $expirations[ $filetype ] = false;
199
+ continue;
200
+ }
201
+
202
+ $time = explode( '/', $time );
203
+ if ( count( $time ) != 2 ) {
204
+ $expirations[ $filetype ] = false;
205
+ continue;
206
+ }
207
+
208
+ $time = absint( ltrim( $time[1], 'A' ) );
209
+
210
+ if ( ! $time ) {
211
+ $expirations[ $filetype ] = false;
212
+ continue;
213
+ }
214
+
215
+ $expirations[ $filetype ] = $time;
216
+ }
217
+
218
+ return $expirations;
219
+ }
220
+
221
+ public static function page_rule_targets( $filetype ) {
222
+ return array(
223
+ array(
224
+ 'target' => 'url',
225
+ 'constraint' => array(
226
+ 'operator' => 'matches',
227
+ 'value' => '*caninomag.es*.' . $filetype
228
+ )
229
+ )
230
+ );
231
+ }
232
+
233
+ public static function page_rule_actions( $time ) {
234
+ return array(
235
+ array(
236
+ 'id' => 'browser_cache_ttl',
237
+ 'value' => $time
238
+ )
239
+ );
240
+ }
241
+
242
+ /**
243
+ * Register a rule added to CF so they can be listed them later
244
+ *
245
+ * @param $id
246
+ * @param $filetype
247
+ */
248
+ public function register_caching_page_rule( $id, $filetype ) {
249
+ $current_rules = wphb_get_setting( 'cloudflare-page-rules' );
250
+ $current_rules[ $filetype ] = $id;
251
+ wphb_update_setting( 'cloudflare-page-rules', $current_rules );
252
+ }
253
+
254
+ /**
255
+ * Register a rule added to CF so they can be listed them later
256
+ *
257
+ * @param $id
258
+ * @param $filetype
259
+ */
260
+ public function unregister_caching_page_rule( $filetype ) {
261
+ $current_rules = wphb_get_setting( 'cloudflare-page-rules' );
262
+ if ( isset( $current_rules[ $filetype ] ) ) {
263
+ unset( $current_rules[ $filetype ] );
264
+ wphb_update_setting( 'cloudflare-page-rules', $current_rules );
265
+ }
266
+
267
+ }
268
+
269
+ public function get_registered_caching_page_rule_id( $filetype ) {
270
+ $current_rules = wphb_get_setting( 'cloudflare-page-rules' );
271
+ return ( isset( $current_rules[ $filetype ] ) ) ? $current_rules[ $filetype ] : false;
272
+ }
273
+
274
+ public function get_registered_caching_page_rules() {
275
+ return wphb_get_setting( 'cloudflare-page-rules' );
276
+ }
277
+
278
+ /**
279
+ * Get a list of CloudFlare zones
280
+ *
281
+ * @return WP_Error|array
282
+ */
283
+ public function get_zones_list( $page = 1, $zones = array() ) {
284
+ if ( is_wp_error( $zones ) ) {
285
+ return $zones;
286
+ }
287
+ $api = wphb_get_api();
288
+ $api->cloudflare->set_auth_email( wphb_get_setting( 'cloudflare-email' ) );
289
+ $api->cloudflare->set_auth_key( wphb_get_setting( 'cloudflare-api-key' ) );
290
+ $result = $api->cloudflare->get_zones_list( $page );
291
+ if ( is_wp_error( $result ) ) {
292
+ return $result;
293
+ }
294
+
295
+ $_zones = $result->result;
296
+ foreach ( $_zones as $zone ) {
297
+ $zones[] = array(
298
+ 'value' => $zone->id,
299
+ 'label' => $zone->name,
300
+ 'plan' => $zone->plan->legacy_id
301
+ );
302
+ }
303
+
304
+ if ( $result->result_info->total_pages > $page ) {
305
+ // Get the next page
306
+ return $this->get_zones_list( ++$page, $zones );
307
+ }
308
+
309
+
310
+ return $zones;
311
+ }
312
+
313
+ /**
314
+ * Get a list of all page rules in CF
315
+ *
316
+ * @return WP_Error|array
317
+ */
318
+ public function get_page_rules_list() {
319
+ $zone = wphb_get_setting( 'cloudflare-zone' );
320
+ $api = wphb_get_api();
321
+ $api->cloudflare->set_auth_email( wphb_get_setting( 'cloudflare-email' ) );
322
+ $api->cloudflare->set_auth_key( wphb_get_setting( 'cloudflare-api-key' ) );
323
+
324
+ $result = $api->cloudflare->get_page_rules_list( $zone );
325
+ if ( is_wp_error( $result ) ) {
326
+ return $result;
327
+ }
328
+
329
+ return $result->result;
330
+ }
331
+
332
+ public function set_caching_expiration( $value ) {
333
+ $zone = wphb_get_setting( 'cloudflare-zone' );
334
+ $api = wphb_get_api();
335
+ $api->cloudflare->set_auth_email( wphb_get_setting( 'cloudflare-email' ) );
336
+ $api->cloudflare->set_auth_key( wphb_get_setting( 'cloudflare-api-key' ) );
337
+
338
+ $value = absint( $value );
339
+ $freqs = wphb_get_caching_cloudflare_frequencies();
340
+ if ( ! $value || ! array_key_exists( $value, $freqs ) ) {
341
+ return new WP_Error( 'cf_invalid_value', __( 'Invalid CloudFlare expiration value', 'wphb' ) );
342
+ }
343
+
344
+ return $api->cloudflare->set_caching_expiration( $zone, $value );
345
+ }
346
+
347
+ public function get_caching_expiration() {
348
+ $zone = wphb_get_setting( 'cloudflare-zone' );
349
+ $api = wphb_get_api();
350
+ $api->cloudflare->set_auth_email( wphb_get_setting( 'cloudflare-email' ) );
351
+ $api->cloudflare->set_auth_key( wphb_get_setting( 'cloudflare-api-key' ) );
352
+ $result = $api->cloudflare->get_caching_expiration( $zone );
353
+ if ( is_wp_error( $result ) ) {
354
+ return $result;
355
+ }
356
+
357
+ return $result->result->value;
358
+ }
359
+
360
+ public function purge_cache() {
361
+ $zone = wphb_get_setting( 'cloudflare-zone' );
362
+ $api = wphb_get_api();
363
+ $api->cloudflare->set_auth_email( wphb_get_setting( 'cloudflare-email' ) );
364
+ $api->cloudflare->set_auth_key( wphb_get_setting( 'cloudflare-api-key' ) );
365
+ $result = $api->cloudflare->purge_cache( $zone );
366
+ return $result->result;
367
+ }
368
+
369
+
370
+ }
371
+
core/modules/class-module-gzip.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Module_GZip extends WP_Hummingbird_Module_Server {
4
+
5
+ protected $transient_slug = 'gzip';
6
+
7
+ public function analize_data() {
8
+ $files = array(
9
+ 'HTML' => add_query_arg( 'avoid-minify', 'true', get_home_url() ),
10
+ 'JavaScript' => wphb_plugin_url() . 'core/modules/dummy/dummy-js.js',
11
+ 'CSS' => wphb_plugin_url() . 'core/modules/dummy/dummy-style.css',
12
+ );
13
+
14
+ $results = array();
15
+ foreach ( $files as $type => $file ) {
16
+
17
+ // We don't use wp_remote, getting the content-encoding is not working
18
+ if ( ! class_exists('SimplePie') )
19
+ require_once( ABSPATH . WPINC . '/class-simplepie.php' );
20
+
21
+ $result = new SimplePie_File( $file, 10, 5, null, $_SERVER['HTTP_USER_AGENT'] );
22
+
23
+ $headers = $result->headers;
24
+ if ( empty( $headers ) ) {
25
+ $results[ $type ] = false;
26
+ }
27
+ elseif ( isset( $headers['content-encoding'] ) && $headers['content-encoding'] == 'gzip' ) {
28
+ $results[ $type ] = true;
29
+ }
30
+ else {
31
+ $results[ $type ] = false;
32
+ }
33
+
34
+
35
+ }
36
+
37
+ return $results;
38
+ }
39
+
40
+
41
+ public function get_nginx_code() {
42
+ return '
43
+ # Enable Gzip compression
44
+ gzip on;
45
+
46
+ # Compression level (1-9)
47
+ gzip_comp_level 5;
48
+
49
+ # Don\'t compress anything under 256 bytes
50
+ gzip_min_length 256;
51
+
52
+ # Compress output of these MIME-types
53
+ gzip_types
54
+ application/atom+xml
55
+ application/javascript
56
+ application/json
57
+ application/rss+xml
58
+ application/vnd.ms-fontobject
59
+ application/x-font-ttf
60
+ application/x-javascript
61
+ application/x-web-app-manifest+json
62
+ application/xhtml+xml
63
+ application/xml
64
+ font/opentype
65
+ image/svg+xml
66
+ image/x-icon
67
+ text/css
68
+ text/plain
69
+ text/javascript
70
+ text/x-component;
71
+
72
+ # Disable gzip for bad browsers
73
+ gzip_disable "MSIE [1-6]\.(?!.*SV1)";';
74
+ }
75
+
76
+ public function get_apache_code() {
77
+ return '
78
+ <IfModule mod_deflate.c>
79
+ <IfModule mod_setenvif.c>
80
+ <IfModule mod_headers.c>
81
+ SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
82
+ RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
83
+ </IfModule>
84
+ </IfModule>
85
+ <IfModule mod_filter.c>
86
+ AddOutputFilterByType DEFLATE "application/atom+xml" \
87
+ "application/javascript" \
88
+ "application/json" \
89
+ "application/ld+json" \
90
+ "application/manifest+json" \
91
+ "application/rdf+xml" \
92
+ "application/rss+xml" \
93
+ "application/schema+json" \
94
+ "application/vnd.geo+json" \
95
+ "application/vnd.ms-fontobject" \
96
+ "application/x-font-ttf" \
97
+ "application/x-javascript" \
98
+ "application/x-web-app-manifest+json" \
99
+ "application/xhtml+xml" \
100
+ "application/xml" \
101
+ "font/eot" \
102
+ "font/opentype" \
103
+ "image/bmp" \
104
+ "image/svg+xml" \
105
+ "image/vnd.microsoft.icon" \
106
+ "image/x-icon" \
107
+ "text/cache-manifest" \
108
+ "text/css" \
109
+ "text/html" \
110
+ "text/javascript" \
111
+ "text/plain" \
112
+ "text/vcard" \
113
+ "text/vnd.rim.location.xloc" \
114
+ "text/vtt" \
115
+ "text/x-component" \
116
+ "text/x-cross-domain-policy" \
117
+ "text/xml"
118
+
119
+ </IfModule>
120
+ <IfModule mod_mime.c>
121
+ AddEncoding gzip svgz
122
+ </IfModule>
123
+
124
+ </IfModule>';
125
+ }
126
+
127
+ public function get_litespeed_code() {
128
+ return $this->get_apache_code();
129
+ }
130
+
131
+ public function get_iis_code() {
132
+ return '';
133
+ }
134
+
135
+ public function get_iis_7_code() {
136
+ return '';
137
+ }
138
+
139
+ }
core/modules/class-module-minify.php ADDED
@@ -0,0 +1,915 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once( 'minify/class-uri-rewriter.php' );
4
+ require_once( 'minify/class-errors-controller.php' );
5
+ require_once( 'minify/class-minify-sources-collector.php' );
6
+
7
+ // New files
8
+ include_once( 'minify/class-minify-group.php' );
9
+ include_once( 'minify/class-minify-groups-list.php' );
10
+ include_once( 'minify/class-minify-housekeeper.php' );
11
+
12
+ class WP_Hummingbird_Module_Minify extends WP_Hummingbird_Module {
13
+
14
+ /**
15
+ * List of groups to be processed at the end of the request
16
+ *
17
+ * @var array
18
+ */
19
+ private $group_queue = array();
20
+
21
+ /**
22
+ * @var WP_Hummingbird_Sources_Collector
23
+ */
24
+ public $sources_collector;
25
+
26
+ /**
27
+ * @var WP_Hummingbird_Minification_Errors_Controller
28
+ */
29
+ public $errors_controller;
30
+
31
+ /**
32
+ * @var WP_Hummingbird_Module_Minify_Housekeeper
33
+ */
34
+ public $housekeeper;
35
+
36
+ /**
37
+ * Counter that will name scripts/styles slugs
38
+ *
39
+ * @var int
40
+ */
41
+ private static $counter = 0;
42
+
43
+ public $done = array(
44
+ 'scripts' => array(),
45
+ 'styles' => array()
46
+ );
47
+
48
+ public $to_footer = array(
49
+ 'styles' => array(),
50
+ 'scripts' => array()
51
+ );
52
+
53
+
54
+ public function __construct( $slug, $name ) {
55
+ parent::__construct( $slug, $name );
56
+ $this->housekeeper = new WP_Hummingbird_Module_Minify_Housekeeper();
57
+ $this->housekeeper->init();
58
+ self::$counter = 0;
59
+ }
60
+
61
+ /**
62
+ * Initializes Minify module
63
+ */
64
+ public function init() {
65
+ global $pagenow;
66
+
67
+ $this->errors_controller = new WP_Hummingbird_Minification_Errors_Controller();
68
+ $this->sources_collector = new WP_Hummingbird_Sources_Collector();
69
+
70
+ if ( isset( $_GET['avoid-minify'] ) || 'wp-login.php' === $pagenow ) {
71
+ add_filter( 'wp_hummingbird_is_active_module_' . $this->get_slug(), '__return_false' );
72
+ }
73
+
74
+ add_filter( 'wp_hummingbird_is_active_module_' . $this->get_slug(), array( $this, 'should_be_active' ), 20 );
75
+
76
+ add_action( 'before_delete_post', array( $this, 'on_delete_post' ), 10 );
77
+
78
+ // Process the queue through ajax
79
+ add_action( 'wphb_minify_process_queue', array( $this, 'process_queue' ) );
80
+ }
81
+
82
+ /**
83
+ * Delete files attached to a minify group
84
+ */
85
+ public function on_delete_post( $post_id ) {
86
+ $group = WP_Hummingbird_Module_Minify_Group::get_instance_by_post_id( $post_id );
87
+
88
+ if ( is_a( $group, 'WP_Hummingbird_Module_Minify_Group' ) && $group->file_id ) {
89
+ if ( $group->get_file_path() ) {
90
+ wp_delete_file( $group->get_file_path() );
91
+ }
92
+ wp_cache_delete( 'wphb_minify_groups' );
93
+ }
94
+ }
95
+
96
+ public function should_be_active( $is_active ) {
97
+ if ( ! $this->can_execute_php() ) {
98
+ return false;
99
+ }
100
+
101
+ return $is_active;
102
+ }
103
+
104
+ /**
105
+ * Check if Hummingbird is currently checking files
106
+ *
107
+ * @return bool
108
+ */
109
+ public static function is_checking_files() {
110
+ $checking_files = get_option( 'wphb-minification-check-files', 0 );
111
+ if ( $checking_files )
112
+ return true;
113
+
114
+ return false;
115
+ }
116
+
117
+ /**
118
+ * Check if the current PHP version is suitable for minification
119
+ */
120
+ public function can_execute_php() {
121
+ $minimun = $this->get_php_min_version();
122
+
123
+ if ( version_compare( PHP_VERSION, $minimun, '<' ) ) {
124
+ return false;
125
+ }
126
+
127
+ return true;
128
+ }
129
+
130
+ public function get_php_min_version() {
131
+ return '5.3';
132
+ }
133
+
134
+ public function run() {
135
+ global $wp_customize;
136
+
137
+ add_action( 'init', array( $this, 'register_cpts' ) );
138
+
139
+ if ( is_admin() || is_customize_preview() || is_a( $wp_customize, 'WP_Customize_Manager' ) ) {
140
+ return;
141
+ }
142
+
143
+ // Only minify on front
144
+ add_filter( 'print_styles_array', array( $this, 'filter_styles' ), 5 );
145
+ add_filter( 'print_scripts_array', array( $this, 'filter_scripts' ), 5 );
146
+ //add_action( 'wp_head', array( $this, 'print_styles' ), 900 );
147
+ //add_action( 'wp_head', array( $this, 'print_scripts' ), 900 );
148
+ //add_action( 'wp_print_footer_scripts', array( $this, 'print_late_resources' ), 900 );
149
+
150
+ add_action( 'wp_footer', array( $this, 'trigger_process_queue_cron' ), 10000 );
151
+ }
152
+
153
+ /**
154
+ * Register a new CPT for Assets groups
155
+ */
156
+ public static function register_cpts() {
157
+ $labels = array(
158
+ 'name' => 'WPHB Minify Groups',
159
+ 'singular_name' => 'WPHB Minify Group'
160
+ );
161
+
162
+ $args = array(
163
+ 'labels' => $labels,
164
+ 'description' => 'WPHB Minify Groups (internal use)',
165
+ 'public' => false,
166
+ 'publicly_queryable' => false,
167
+ 'show_ui' => false,
168
+ 'show_in_menu' => false,
169
+ 'query_var' => false,
170
+ 'rewrite' => false,
171
+ 'capability_type' => 'post',
172
+ 'has_archive' => false,
173
+ 'hierarchical' => false,
174
+ 'supports' => array()
175
+ );
176
+ register_post_type( 'wphb_minify_group', $args );
177
+ }
178
+
179
+ public function get_queue_to_process() {
180
+ return $this->group_queue;
181
+ }
182
+
183
+ /**
184
+ * Filter styles
185
+ *
186
+ * @param array $handles list of styles slugs
187
+ *
188
+ * @return array
189
+ */
190
+ function filter_styles( $handles ) {
191
+ return $this->filter_enqueues_list( $handles, 'styles' );
192
+ }
193
+
194
+ /**
195
+ * Filter scripts
196
+ *
197
+ * @param array $handles list of scripts slugs
198
+ *
199
+ * @return array
200
+ */
201
+ function filter_scripts( $handles ) {
202
+ return $this->filter_enqueues_list( $handles, 'scripts' );
203
+ }
204
+
205
+ /**
206
+ * Filter the sources
207
+ *
208
+ * We'll collect those styles/scripts that are going to be
209
+ * processed by WP Hummingbird and return those that will
210
+ * be processed by WordPress
211
+ *
212
+ * @param array $handles list of scripts/styles slugs
213
+ * @param string $type scripts|styles
214
+ *
215
+ * @return array List of handles that will be processed by WordPress
216
+ */
217
+ function filter_enqueues_list( $handles, $type ) {
218
+ if ( ! $this->is_active() ) {
219
+ // Minification not active, return the handles
220
+ return $handles;
221
+ }
222
+
223
+ if ( $this->errors_controller->is_server_error() ) {
224
+ // there seem to be an error in our severs, do not minify
225
+ return $handles;
226
+ }
227
+
228
+ if ( $type == 'styles' ) {
229
+ global $wp_styles;
230
+ $wp_dependencies = $wp_styles;
231
+ }
232
+ elseif( $type == 'scripts' ) {
233
+ global $wp_scripts;
234
+ $wp_dependencies = $wp_scripts;
235
+ }
236
+ else {
237
+ // What is this?
238
+ return $handles;
239
+ }
240
+
241
+ if ( empty( $handles ) ) {
242
+ // Nothing to do
243
+ return $handles;
244
+ }
245
+
246
+ // Collect the handles information to use in admin later
247
+ foreach ( $handles as $key => $handle ) {
248
+ if ( isset ( $wp_dependencies->registered[ $handle ] ) && ! empty( $wp_dependencies->registered[ $handle ]->src ) ) {
249
+ $this->sources_collector->add_to_collection( $wp_dependencies->registered[ $handle ], $type );
250
+ }
251
+
252
+ // If we aren't in footer, remove handles that need to go to footer
253
+ if ( ! self::is_in_footer() && isset ( $wp_dependencies->registered[ $handle ]->extra['group'] ) && $wp_dependencies->registered[ $handle ]->extra['group'] ) {
254
+ $this->to_footer[$type][] = $handle;
255
+ }
256
+ }
257
+
258
+ $return_to_wp = array();
259
+
260
+ if ( self::is_in_footer() && ! empty( $this->to_footer[ $type ] ) ) {
261
+ // Header sent us some handles to be moved to footer
262
+ $handles = array_unique( array_merge( $handles, $this->to_footer[ $type ] ) );
263
+ }
264
+
265
+ // Group dependencies by attributes like args, extra, etc
266
+ $_groups = $this->group_dependencies_by_attributes( $handles, $wp_dependencies, $type );
267
+
268
+
269
+ // Create a Groups list object
270
+ $groups_list = new WP_Hummingbird_Module_Minify_Groups_List( $type );
271
+ array_map(array( $groups_list, 'add_group' ), $_groups );
272
+
273
+ unset( $_groups );
274
+
275
+ $this->attach_inline_attribute( $groups_list, $wp_dependencies );
276
+
277
+ if ( 'scripts' === $type ) {
278
+ $this->attach_scripts_localization( $groups_list, $wp_dependencies );
279
+ }
280
+
281
+
282
+ // Time to split the groups if we're not combining some of them
283
+ foreach ( $groups_list->get_groups() as $group ) {
284
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
285
+ $dont_enqueue_list = $group->get_dont_enqueue_list();
286
+ if ( $dont_enqueue_list ) {
287
+ // There are one or more handles that should not be enqueued
288
+ $group->remove_handles( $dont_enqueue_list );
289
+ if ( 'styles' === $type ) {
290
+ wp_dequeue_style( $dont_enqueue_list );
291
+ }
292
+ else {
293
+ wp_dequeue_script( $dont_enqueue_list );
294
+ }
295
+ }
296
+
297
+ $dont_combine_list = $group->get_dont_combine_list();
298
+
299
+ if ( $dont_combine_list ) {
300
+ // There are one or more handles that should not be combined
301
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
302
+ $handles = $group->get_handles();
303
+ // Here we'll save sources that don't need to be minified/combine
304
+ // Then we'll extract those handles from the group and we'll create
305
+ // a new group for them keeping the groups order
306
+ $group_combine = array();
307
+ foreach ( $handles as $handle ) {
308
+ $combine_resource = $group->should_do_handle( $handle, 'combine' );
309
+ $group_combine[ $handle ] = $combine_resource ? 1 : 0;
310
+ }
311
+
312
+ // Now split groups if needed based on combine value
313
+ // We need to keep always the order, ALWAYS
314
+ // This will save the new splitted group structure
315
+ $splitted_group = array();
316
+
317
+ $last_status = null;
318
+ foreach ( $group_combine as $handle => $status ) {
319
+
320
+ // Last minify status will be the first one by default
321
+ if ( is_null( $last_status ) ) {
322
+ $last_status = $status;
323
+ }
324
+
325
+ // Set the splitted groups to the last element
326
+ end( $splitted_group );
327
+ if ( $last_status === $status && $status !== 0 ) {
328
+ $current_key = key( $splitted_group );
329
+ if ( ! $current_key ) {
330
+ // Current key can be NULL, set to 0
331
+ $current_key = 0;
332
+ }
333
+
334
+ if ( ! isset( $splitted_group[ $current_key ] ) || ! is_array( $splitted_group[ $current_key ] ) ) {
335
+ $splitted_group[ $current_key ] = array();
336
+ }
337
+
338
+ $splitted_group[ $current_key ][] = $handle;
339
+ }
340
+ else {
341
+ // Create a new group
342
+ $splitted_group[] = array( $handle );
343
+ }
344
+
345
+
346
+ $last_status = $status;
347
+ }
348
+
349
+ // Split the group!
350
+ $groups_list->split_group( $group->hash, $splitted_group );
351
+ }
352
+ }
353
+
354
+ // Set the groups handles, as we need all of them before processing
355
+ foreach ( $groups_list->get_groups() as $group ) {
356
+ $handles = $group->get_handles();
357
+ if ( count( $handles ) === 1 ) {
358
+ // Just one handle, let's keep the handle name as the group ID
359
+ $group->group_id = $handles[0];
360
+ }
361
+ else {
362
+ $group->group_id = 'wphb-' . ++self::$counter;
363
+ }
364
+ foreach ( $handles as $handle ) {
365
+ $this->done[ $type ][] = $handle;
366
+ }
367
+ }
368
+
369
+ // Parse dependencies, load files and mark groups as ready,process or only-handles
370
+ // Watch out! Groups must not be changed after this point
371
+ $groups_list->preprocess_groups();
372
+
373
+
374
+ foreach ( $groups_list->get_groups() as $group ) {
375
+ $group_status = $groups_list->get_group_status( $group->hash );
376
+ $deps = $groups_list->get_group_dependencies( $group->hash );
377
+
378
+ if ( 'ready' == $group_status ) {
379
+ // The group has its file and is ready to be enqueued
380
+ $group->enqueue( self::is_in_footer(), $deps );
381
+ $return_to_wp = array_merge( $return_to_wp, array( $group->group_id ) );
382
+ }
383
+ else {
384
+ // The group has not yet a file attached or it cannot be processed
385
+ // for some reason
386
+ foreach ( $group->get_handles() as $handle ) {
387
+ $new_id = $group->enqueue_one_handle( $handle, self::is_in_footer(), $deps );
388
+ $return_to_wp = array_merge( $return_to_wp, array( $new_id ) );
389
+ }
390
+
391
+ if ( 'process' == $group_status ) {
392
+ // Add the group to the queue to be processed later
393
+ if ( $group->should_process_group() ) {
394
+ $this->group_queue[] = $group;
395
+ }
396
+
397
+ }
398
+ }
399
+ }
400
+
401
+ return $return_to_wp;
402
+ }
403
+
404
+ /**
405
+ * Group dependencies by alt, title, rtl, conditional and args attributes
406
+ *
407
+ * @param $handles
408
+ * @param $wp_dependencies
409
+ *
410
+ * @return array
411
+ */
412
+ private function group_dependencies_by_attributes( $handles, $wp_dependencies, $type ) {
413
+ $groups = array();
414
+ $prev_differentiators_hash = false;
415
+
416
+ foreach ( $handles as $handle ) {
417
+ $registered_dependency = isset( $wp_dependencies->registered[ $handle ] ) ? $wp_dependencies->registered[ $handle ] : false;
418
+ if ( ! $registered_dependency ) {
419
+ continue;
420
+ }
421
+
422
+ if ( ! self::is_in_footer() ) {
423
+ /**
424
+ * Filter the resource (move to footer)
425
+ *
426
+ * @usedby wphb_filter_resource_to_footer()
427
+ *
428
+ * @var bool $send_resource_to_footer
429
+ * @var string $handle Source slug
430
+ * @var string $type scripts|styles
431
+ * @var string $source_url Source URL
432
+ */
433
+ if ( apply_filters( 'wphb_send_resource_to_footer', false, $handle, $type, $wp_dependencies->registered[ $handle ]->src ) ) {
434
+ // Move this to footer, do not take this handle in account for this iteration
435
+ $this->to_footer[ $type ][] = $handle;
436
+ continue;
437
+ }
438
+ }
439
+
440
+ // We'll group by these extras $wp_style->extras and $wp_style->args (args is no more than a string, confusing)
441
+ // If previous group has the same values, we'll add this dep it to that group
442
+ // otherwise, a new group will be created
443
+ $group_extra_differentiators = array( 'alt', 'title', 'rtl', 'conditional' );
444
+ $group_differentiators = array( 'args' );
445
+
446
+ // We'll create a hash for all differentiators
447
+ $differentiators_hash = array();
448
+ foreach ( $group_extra_differentiators as $differentiator ) {
449
+ if ( isset( $registered_dependency->extra[ $differentiator ] ) ) {
450
+ if ( is_bool( $registered_dependency->extra[ $differentiator ] ) && $registered_dependency->extra[ $differentiator ] ) {
451
+ $differentiators_hash[] = 'true';
452
+ }
453
+ elseif ( is_bool( $registered_dependency->extra[ $differentiator ] ) && ! $registered_dependency->extra[ $differentiator ] ) {
454
+ $differentiators_hash[] = 'false';
455
+ }
456
+ else {
457
+ $differentiators_hash[] = (string)$registered_dependency->extra[ $differentiator ];
458
+ }
459
+ }
460
+ else {
461
+ $differentiators_hash[] = '';
462
+ }
463
+ }
464
+
465
+ foreach ( $group_differentiators as $differentiator ) {
466
+ if ( isset( $registered_dependency->$differentiator ) ) {
467
+ if ( is_bool( $registered_dependency->$differentiator ) && $registered_dependency->$differentiator ) {
468
+ $differentiators_hash[] = 'true';
469
+ }
470
+ elseif ( is_bool( $registered_dependency->$differentiator ) && ! $registered_dependency->$differentiator ) {
471
+ $differentiators_hash[] = 'false';
472
+ }
473
+ else {
474
+ $differentiators_hash[] = (string)$registered_dependency->$differentiator;
475
+ }
476
+ }
477
+ else {
478
+ $differentiators_hash[] = '';
479
+ }
480
+ }
481
+
482
+ $differentiators_hash = implode( '-', $differentiators_hash );
483
+
484
+ // Now compare the hash with the previous one
485
+ // If they are the same, do not create a new group
486
+ if ( $differentiators_hash !== $prev_differentiators_hash ) {
487
+ $new_group = new WP_Hummingbird_Module_Minify_Group();
488
+ $new_group->set_type( $type );
489
+ foreach ( $registered_dependency->extra as $key => $value ) {
490
+ $new_group->add_extra( $key, $value );
491
+ }
492
+
493
+ // We'll treat this later
494
+ $new_group->delete_extra( 'after' );
495
+
496
+ $new_group->set_args( $registered_dependency->args );
497
+
498
+ if ( $registered_dependency->src ) {
499
+ $new_group->add_handle( $handle, $registered_dependency->src );
500
+
501
+ // Add dependencies
502
+ $new_group->add_handle_dependency( $handle, $wp_dependencies->registered[ $handle ]->deps );
503
+ }
504
+
505
+
506
+ $groups[] = $new_group;
507
+ }
508
+ else {
509
+ end( $groups );
510
+ $last_key = key( $groups );
511
+ $groups[ $last_key ]->add_handle( $handle, $registered_dependency->src );
512
+ // Add dependencies
513
+ $groups[ $last_key ]->add_handle_dependency( $handle, $registered_dependency->deps );
514
+ reset( $groups );
515
+ }
516
+
517
+ $prev_differentiators_hash = $differentiators_hash;
518
+
519
+ }
520
+
521
+ // Remove group without handles
522
+ $return = array();
523
+ foreach ( $groups as $key => $group ) {
524
+ if ( $group->get_handles() ) {
525
+ $return[ $key ] = $group;
526
+ }
527
+ }
528
+
529
+ return $return;
530
+ }
531
+
532
+ /**
533
+ * Attach inline scripts/styles to groups
534
+ *
535
+ * Extract all deps that has inline scripts/styles (added by wp_add_inline_script/style functions)
536
+ * then it will add those extras to the groups
537
+ *
538
+ * @param WP_Hummingbird_Module_Minify_Groups_List $groups_list
539
+ * @param $wp_dependencies
540
+ */
541
+ private function attach_inline_attribute( &$groups_list, $wp_dependencies ) {
542
+ $registered = $wp_dependencies->registered;
543
+ $extras = wp_list_pluck( $registered, 'extra' );
544
+ $after = wp_list_pluck( array_filter( $extras, array( $this, '_filter_after_after_attribute' ) ), 'after' );
545
+
546
+ array_map( function( $group ) use ( $groups_list, $after ) {
547
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
548
+ array_map( function( $handle ) use ( $after, $group ) {
549
+ if ( isset( $after[ $handle ] ) ) {
550
+ // Add!
551
+ $group->add_after( $after[ $handle ] );
552
+ }
553
+ }, $group->get_handles() );
554
+ }, $groups_list->get_groups() );
555
+ }
556
+
557
+ /**
558
+ * Attach localization scripts to groups
559
+ *
560
+ * @param WP_Hummingbird_Module_Minify_Groups_List $groups_list
561
+ * @param $wp_dependencies
562
+ */
563
+ private function attach_scripts_localization( &$groups_list, $wp_dependencies ) {
564
+ $registered = $wp_dependencies->registered;
565
+ $extra = wp_list_pluck( $registered, 'extra' );
566
+ $data = wp_list_pluck( array_filter( $extra, function($a) {
567
+ if ( isset ( $a['data'] ) ) {
568
+ return $a['data'];
569
+ }
570
+ return false;
571
+ } ), 'data' );
572
+
573
+ array_map( function( $group ) use ( $groups_list, $data ) {
574
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
575
+ array_map( function( $handle ) use ( $data, $group ) {
576
+ if ( isset( $data[ $handle ] ) ) {
577
+ // Add!
578
+ $group->add_data( $data[ $handle ] );
579
+ }
580
+ }, $group->get_handles() );
581
+ }, $groups_list->get_groups() );
582
+ }
583
+
584
+ /**
585
+ * Filter a list of dependencies returning their 'after' attribute inside 'extra' list
586
+ *
587
+ * @internal
588
+ */
589
+ public function _filter_after_after_attribute( $a ) {
590
+ if ( isset ( $a['after'] ) ) {
591
+ return $a['after'];
592
+ }
593
+ return false;
594
+ }
595
+
596
+
597
+ /**
598
+ * Return if we are processing the footer
599
+ *
600
+ * @return bool
601
+ */
602
+ public static function is_in_footer() {
603
+ return doing_action( 'wp_footer' );
604
+ }
605
+
606
+ /**
607
+ * Trigger the action to process the queue
608
+ */
609
+ public function trigger_process_queue_cron() {
610
+ // Trigger que the queue hrough WP CRON so we don't waste load time
611
+ $this->sources_collector->save_collection();
612
+
613
+ $queue = $this->get_queue_to_process();
614
+ $this->add_items_to_persistent_queue( $queue );
615
+ $queue = $this->get_pending_persistent_queue();
616
+ if ( empty( $queue ) ) {
617
+ return;
618
+ }
619
+
620
+ if ( defined('DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) {
621
+ $this->process_queue();
622
+ }
623
+ else {
624
+ self::schedule_process_queue_cron();
625
+ }
626
+ }
627
+
628
+ /**
629
+ * Process the queue: Minify and combine files
630
+ */
631
+ public function process_queue() {
632
+ // Process the queue
633
+ if ( get_transient( 'wphb-processing' ) ) {
634
+ // Still processing. Try again
635
+ if ( ! ( defined('DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ) {
636
+ self::schedule_process_queue_cron();
637
+ }
638
+ return;
639
+ }
640
+
641
+ $queue = $this->get_pending_persistent_queue();
642
+
643
+ set_transient( 'wphb-processing', true, 60 );
644
+ // Process 10 groups max in a request
645
+ $count = 0;
646
+
647
+ $new_queue = $queue;
648
+ foreach ( $queue as $key => $item ) {
649
+ if ( $count >= 8 ) {
650
+ break;
651
+ }
652
+ if ( ! is_a( $item, 'WP_Hummingbird_Module_Minify_Group' ) )
653
+ continue;
654
+
655
+ /** @var WP_Hummingbird_Module_Minify_Group $item */
656
+ if ( $item->should_generate_file() ) {
657
+ $result = $item->process_group();
658
+ if ( is_wp_error( $result ) ) {
659
+ $this->errors_controller->add_server_error( $result );
660
+ }
661
+ }
662
+ $this->remove_item_from_persistent_queue( $item->hash );
663
+ unset( $new_queue[ $key ] );
664
+ $count++;
665
+ }
666
+
667
+ if ( ! ( defined('DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ) {
668
+ $new_queue = array_values( $new_queue );
669
+ if ( ! empty( $new_queue ) ) {
670
+ // Still needs processing
671
+ self::schedule_process_queue_cron();
672
+ }
673
+ }
674
+
675
+ delete_transient( 'wphb-processing' );
676
+ }
677
+
678
+ public static function schedule_process_queue_cron() {
679
+ if ( ! wp_next_scheduled( 'wphb_minify_process_queue' ) ) {
680
+ wp_schedule_single_event( time(), 'wphb_minify_process_queue' );
681
+ }
682
+ }
683
+
684
+ /**
685
+ * Save a list of groups to a persistent option in database
686
+ *
687
+ * If a timeout happens during groups processing, we won't loose
688
+ * the data needed to process the rest of groups
689
+ *
690
+ * @param array $items
691
+ */
692
+ private function add_items_to_persistent_queue( $items ) {
693
+ if ( empty( $items ) ) {
694
+ // Nothing to be added
695
+ return;
696
+ }
697
+ $current_queue = $this->get_pending_persistent_queue();
698
+ if ( empty( $current_queue ) ) {
699
+ update_option( 'wphb_process_queue', $items );
700
+ } else {
701
+ $updated = false;
702
+ $current_queue_hashes = wp_list_pluck( $current_queue, 'hash' );
703
+ foreach ( $items as $item ) {
704
+ if ( ! in_array( $item->hash, $current_queue_hashes ) ) {
705
+ $updated = true;
706
+ $current_queue[] = $item;
707
+ }
708
+ }
709
+ if ( $updated ) {
710
+ update_option( 'wphb_process_queue', $current_queue );
711
+ }
712
+ }
713
+ }
714
+
715
+ /**
716
+ * Remove a group from the persistent queue
717
+ *
718
+ * @param string $hash
719
+ */
720
+ private function remove_item_from_persistent_queue( $hash ) {
721
+ $queue = $this->get_pending_persistent_queue();
722
+ $items = wp_list_filter( $queue, array( 'hash' => $hash ) );
723
+ if ( ! $items ) {
724
+ return;
725
+ }
726
+
727
+ $keys = array_keys( $items );
728
+ foreach ( $keys as $key ) {
729
+ unset( $queue[ $key ] );
730
+ }
731
+
732
+ $queue = array_values( $queue );
733
+
734
+ if ( empty( $queue ) ) {
735
+ $this->delete_pending_persistent_queue();
736
+ return;
737
+ }
738
+
739
+ update_option( 'wphb_process_queue', $queue );
740
+ }
741
+
742
+ /**
743
+ * Get the list of groups that are yet pending to be processed
744
+ */
745
+ public function get_pending_persistent_queue() {
746
+ return get_option( 'wphb_process_queue', array() );
747
+ }
748
+
749
+ /**
750
+ * Deletes the persistent queue completely
751
+ */
752
+ public function delete_pending_persistent_queue() {
753
+ delete_option( 'wphb_process_queue' );
754
+ }
755
+
756
+ /**
757
+ * Clear the module cache
758
+ */
759
+ public static function clear_cache( $reset_settings = true ) {
760
+ global $wpdb;
761
+
762
+ // Clear all the cached groups data
763
+ $option_names = $wpdb->get_col(
764
+ $wpdb->prepare(
765
+ "SELECT option_name FROM $wpdb->options
766
+ WHERE option_name LIKE %s
767
+ OR option_name LIKE %s
768
+ OR option_name LIKE %s
769
+ OR option_name LIKE %s",
770
+ '%wphb-min-scripts%',
771
+ '%wphb-scripts%',
772
+ '%wphb-min-styles%',
773
+ '%wphb-styles%'
774
+ )
775
+ );
776
+
777
+ foreach ( $option_names as $name ) {
778
+ delete_option( $name );
779
+ }
780
+
781
+ WP_Hummingbird_Sources_Collector::clear_collection();
782
+
783
+ wphb_minification_clear_files();
784
+
785
+ if ( $reset_settings ) {
786
+ // Reset the minification settings
787
+ $options = wphb_get_settings();
788
+ $default_options = wphb_get_default_settings();
789
+ $options['block'] = $default_options['block'];
790
+ $options['dont_minify'] = $default_options['dont_minify'];
791
+ $options['combine'] = $default_options['combine'];
792
+ $options['position'] = $default_options['position'];
793
+ wphb_update_settings( $options );
794
+ }
795
+
796
+ // Clear the pending process queue
797
+ self::clear_pending_process_queue();
798
+
799
+ update_option( 'wphb-minification-check-files', 0 );
800
+
801
+ WP_Hummingbird_Minification_Errors_Controller::clear_errors();
802
+ }
803
+
804
+ public static function clear_pending_process_queue() {
805
+ delete_option( 'wphb_process_queue' );
806
+ delete_transient( 'wphb-processing' );
807
+ }
808
+
809
+ /**
810
+ * Initializes the scanning process
811
+ */
812
+ public static function init_scan() {
813
+ wphb_clear_minification_cache( false );
814
+
815
+ // Activate minification if is not
816
+ wphb_toggle_minification( true );
817
+
818
+ // Calculate URLs to Check
819
+ $args = array(
820
+ 'orderby' => 'rand',
821
+ 'posts_per_page' => '1',
822
+ 'ignore_sticky_posts' => true,
823
+ 'post_status' => 'publish'
824
+ );
825
+
826
+ $urls = array();
827
+
828
+ $urls[] = home_url();
829
+
830
+ $post_types = get_post_types();
831
+ $post_types = array_diff( $post_types, array( 'attachment', 'nav_menu_item', 'revision' ) );
832
+
833
+ foreach ( $post_types as $post_type ) {
834
+ $args['post_type'] = $post_type;
835
+ $posts = get_posts( $args );
836
+ if ( $posts ) {
837
+ $urls[] = get_permalink( $posts[0] );
838
+ }
839
+
840
+ $post_type_archive_link = get_post_type_archive_link( $post_type );
841
+ if ( $post_type_archive_link )
842
+ $urls[] = $post_type_archive_link;
843
+ }
844
+
845
+ if ( get_option( 'show_on_front' ) && $post = get_post( get_option( 'page_for_posts' ) ) ) {
846
+ $urls[] = get_permalink( $post->ID );
847
+ }
848
+
849
+ $urls = array_unique( $urls );
850
+
851
+ $urls_list = array();
852
+ // Duplicate every URL 4 times. This will be enough to generate all the files for most of the sites
853
+ for ( $i = 0; $i < 4; $i++ ) {
854
+ $urls_list = array_merge( $urls_list, $urls );
855
+ }
856
+
857
+ sort( $urls_list );
858
+ $urls = $urls_list;
859
+
860
+ $args = array(
861
+ 'on' => current_time( 'timestamp' ),
862
+ 'urls_list' => $urls,
863
+ 'urls_done' => array()
864
+ );
865
+
866
+ update_option( 'wphb-minification-check-files', $args );
867
+ }
868
+
869
+ /**
870
+ * This function send a request to a URL in the site
871
+ * that will trigger the files collection
872
+ *
873
+ * Executed with AJAX
874
+ *
875
+ * @param string $url
876
+ *
877
+ * @return array
878
+ */
879
+ public static function scan( $url ) {
880
+ $cookies = array();
881
+ foreach ( $_COOKIE as $name => $value ) {
882
+ if ( strpos( $name, 'wordpress_' ) > -1 ) {
883
+ $cookies[] = new WP_Http_Cookie( array( 'name' => $name, 'value' => $value ) );
884
+ }
885
+
886
+ }
887
+
888
+ $result = array();
889
+
890
+ $args = array(
891
+ 'timeout' => 0.01,
892
+ 'cookies' => $cookies,
893
+ 'blocking' => false,
894
+ 'sslverify' => false
895
+ );
896
+ $result['cookie'] = wp_remote_get( $url, $args );
897
+
898
+ // One call logged out
899
+ $args = array(
900
+ 'timeout' => 0.01,
901
+ 'blocking' => false,
902
+ 'sslverify' => false
903
+ );
904
+
905
+ $result['no-cookie'] = wp_remote_get( $url, $args );
906
+
907
+ return $result;
908
+ }
909
+
910
+ }
911
+
912
+
913
+
914
+
915
+
core/modules/class-module-performance.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Module_Performance extends WP_Hummingbird_Module {
4
+
5
+ public function init() {}
6
+
7
+ public function run() {}
8
+
9
+ /**
10
+ * Initializes the Performance Scan
11
+ */
12
+ public static function init_scan() {
13
+ // Start the test
14
+ self::clear_cache();
15
+
16
+ // Start the test
17
+ self::set_doing_report( true );
18
+ $api = wphb_get_api();
19
+ $api->performance->ping();
20
+ }
21
+
22
+ /**
23
+ * Return the last Performance scan done data
24
+ *
25
+ * @return false|array|WP_Error Data of the last scan or false of there's not such data
26
+ */
27
+ public static function get_last_report() {
28
+
29
+ $report = get_site_option( 'wphb-last-report' );
30
+ if ( $report ) {
31
+ $last_score = get_site_option( 'wphb-last-report-score' );
32
+ if ( $last_score && ! is_wp_error( $report ) ) {
33
+ $report->data->last_score = $last_score;
34
+ }
35
+ elseif ( is_object( $report ) && ! is_wp_error( $report ) ) {
36
+ $report->data->last_score = false;
37
+ }
38
+ return $report;
39
+ }
40
+
41
+ return false;
42
+ }
43
+
44
+
45
+ /**
46
+ * Check if WP Hummingbird is currently doing a Performance Scan
47
+ *
48
+ * @return false|int Timestamp when the report started, false if there's no report being executed
49
+ */
50
+ public static function is_doing_report() {
51
+ if ( get_site_option( 'wphb-stop-report' ) ) {
52
+ return false;
53
+ }
54
+
55
+ return get_site_option( 'wphb-doing-report' );
56
+ }
57
+
58
+ /**
59
+ * Check if Performance Scan is currently halted
60
+ *
61
+ * @return bool
62
+ */
63
+ public static function stopped_report() {
64
+ return (bool)get_site_option( 'wphb-stop-report' );
65
+ }
66
+
67
+ /**
68
+ * Start a new Performance Scan
69
+ *
70
+ * It sets the new status for the report
71
+ *
72
+ * @param bool $status If set to true, it will start a new Performance Report, otherwise it will stop the current one
73
+ */
74
+ public static function set_doing_report( $status = true ) {
75
+ if ( ! $status ) {
76
+ delete_site_option( 'wphb-doing-report' );
77
+ update_site_option( 'wphb-stop-report', true );
78
+ }
79
+ else {
80
+ // Set time when we started the report
81
+ update_site_option( 'wphb-doing-report', current_time( 'timestamp' ) );
82
+ delete_site_option( 'wphb-stop-report' );
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Get latest report from server
88
+ */
89
+ public static function refresh_report() {
90
+ self::set_doing_report( false );
91
+ $api = wphb_get_api();
92
+ $results = $api->performance->results();
93
+
94
+ if ( is_wp_error( $results ) ) {
95
+ // It's an error
96
+ $results = new WP_Error(
97
+ 'performance-error',
98
+ __( "The performance test didn't return any results. This probably means you're on a local website (which we can't scan) or something went wrong trying to access WPMU DEV. Try again and if this error continues to appear please open a ticket with our support heroes", 'wphb' ),
99
+ array( 'details' => $results->get_error_message() )
100
+ );
101
+ }
102
+
103
+ update_site_option( 'wphb-last-report', $results );
104
+ }
105
+
106
+ /**
107
+ * Check if time enough has passed to make another test ( 5 minutes )
108
+ *
109
+ * @return bool|integer True if a new test is available or the time in minutes remaining for next test
110
+ */
111
+ public static function can_run_test() {
112
+ $last_report = wphb_performance_get_last_report();
113
+ $current_gmt_time = current_time( 'timestamp', true );
114
+ if ( $last_report && ! is_wp_error( $last_report ) ) {
115
+ $data_time = $last_report->data->time;
116
+ if ( ( $data_time + 300 ) < $current_gmt_time ) {
117
+ return true;
118
+ }
119
+ else {
120
+ $remaining = ceil( ( ( $data_time + 300 ) - $current_gmt_time ) / 60 );
121
+ return absint( $remaining );
122
+ }
123
+ }
124
+
125
+ return true;
126
+ }
127
+
128
+ /**
129
+ * Clear Performance Module cache
130
+ */
131
+ public static function clear_cache() {
132
+ $last_report = get_site_option( 'wphb-last-report' );
133
+ if ( $last_report && isset( $last_report->data->score ) ) {
134
+ // Save latest score
135
+ update_site_option( 'wphb-last-report-score', array( 'score' => $last_report->data->score ) );
136
+ }
137
+
138
+ delete_site_option( 'wphb-last-report' );
139
+ delete_site_option( 'wphb-doing-report' );
140
+ delete_site_option( 'wphb-stop-report' );
141
+ }
142
+
143
+ }
core/modules/class-module-smush.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_Hummingbird_Module_Smush extends WP_Hummingbird_Module {
4
+
5
+ /**
6
+ * Variable used to distinguish between versions of Smush.
7
+ * Sets true if the Pro version is installed. False in all other cases.
8
+ *
9
+ * @var bool
10
+ */
11
+ static public $is_smush_pro = false;
12
+
13
+ public function init() {}
14
+ public function run() {}
15
+
16
+ public static function is_smush_installed() {
17
+ if ( ! function_exists( 'get_plugins' ) ) {
18
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
19
+ }
20
+
21
+ $plugins = get_plugins();
22
+ if ( array_key_exists( 'wp-smush-pro/wp-smush.php', $plugins ) ) {
23
+ self::$is_smush_pro = true;
24
+ }
25
+ return array_key_exists( 'wp-smush-pro/wp-smush.php', $plugins ) || array_key_exists( 'wp-smushit/wp-smush.php', $plugins );
26
+ }
27
+
28
+ public static function is_smush_active() {
29
+ if ( ! function_exists( 'is_plugin_active' ) ) {
30
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
31
+ }
32
+
33
+ return is_plugin_active( 'wp-smush-pro/wp-smush.php' ) || is_plugin_active( 'wp-smushit/wp-smush.php' );
34
+ }
35
+
36
+ public static function get_smush_install_url() {
37
+ $url = '';
38
+ if ( wphb_is_member() ) {
39
+ // Return the pro plugin URL
40
+ $url = WPMUDEV_Dashboard::$ui->page_urls->plugins_url;
41
+ $url = $url . '#pid=912164';
42
+ }
43
+ else {
44
+ // Return the free URL
45
+ $url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=wp-smushit' ), 'install-plugin_wp-smushit' );
46
+ }
47
+
48
+ return $url;
49
+ }
50
+
51
+ public static function get_smush_activate_url() {
52
+
53
+ }
54
+ }
core/modules/class-module-uptime.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class WP_Hummingbird_Module_Uptime extends WP_Hummingbird_Module {
5
+
6
+ public function init() {}
7
+ public function run() {}
8
+
9
+ public static function get_last_report( $time, $force = false ) {
10
+
11
+ if ( ! wphb_is_member() ) {
12
+ return new WP_Error( 'uptime-membership', __( 'You need to be a WPMU DEV Member', 'wphb' ) );
13
+ }
14
+
15
+ $current_reports = get_site_transient( 'wphb-uptime-last-report' );
16
+ if ( ! isset( $current_reports[ $time ] ) || $force ) {
17
+ self::refresh_report( $time );
18
+ $current_reports = get_site_transient( 'wphb-uptime-last-report' );
19
+ }
20
+
21
+ if ( ! isset( $current_reports[ $time ] ) ) {
22
+ return false;
23
+ }
24
+
25
+ return $current_reports[ $time ];
26
+ }
27
+
28
+ /**
29
+ * Get latest report from server
30
+ */
31
+ public static function refresh_report( $time = 'day' ) {
32
+ /** @var WP_Hummingbird_API $api */
33
+ $api = wphb_get_api();
34
+ $results = $api->uptime->check( $time );
35
+
36
+ if ( is_wp_error( $results ) && 412 === $results->get_error_code() ) {
37
+ // Uptime has been deactivated
38
+ self::disable_locally();
39
+ delete_site_transient( 'wphb-uptime-last-report' );
40
+ return;
41
+ }
42
+
43
+ $current_reports = get_site_transient( 'wphb-uptime-last-report' );
44
+ if ( ! $current_reports ) {
45
+ $current_reports = array();
46
+ }
47
+
48
+ $current_reports[ $time ] = $results;
49
+ // Save for 2 minutes
50
+ set_site_transient( 'wphb-uptime-last-report', $current_reports, 120 );
51
+ }
52
+
53
+ /**
54
+ * Check if Uptime is remotely enabled
55
+ *
56
+ * @return bool
57
+ */
58
+ public static function is_remotely_enabled() {
59
+ if ( ! wphb_is_member() ) {
60
+ return false;
61
+ }
62
+
63
+ $cached = get_site_transient( 'wphb-uptime-remotely-enabled' );
64
+ if ( 'yes' === $cached ) {
65
+ return true;
66
+ }
67
+ elseif ( 'no' === $cached ) {
68
+ return false;
69
+ }
70
+
71
+ $api = wphb_get_api();
72
+ $result = $api->uptime->is_enabled();
73
+ set_site_transient( 'wphb-uptime-remotely-enabled', $result ? 'yes' : 'no', 180 ); // save for 3 minutes
74
+ return $result;
75
+ }
76
+
77
+
78
+ /**
79
+ * Enable Uptime local and remotely
80
+ */
81
+ public static function enable() {
82
+ self::clear_cache();
83
+ self::enable_locally();
84
+ return self::enable_remotely();
85
+ }
86
+
87
+ /**
88
+ * Disable Uptime local and remotely
89
+ */
90
+ public static function disable() {
91
+ self::clear_cache();
92
+ self::disable_locally();
93
+ self::disable_remotely();
94
+ }
95
+
96
+ public static function enable_locally() {
97
+ $options = wphb_get_settings();
98
+ $options['uptime'] = true;
99
+ wphb_update_settings( $options );
100
+ set_site_transient( 'wphb-uptime-remotely-enabled', 'yes', 180 ); // save for 3 minutes
101
+ }
102
+
103
+ public static function enable_remotely() {
104
+ /** @var WP_Hummingbird_API $api */
105
+ $api = wphb_get_api();
106
+ delete_site_transient( 'wphb-uptime-remotely-enabled' );
107
+ return $api->uptime->enable();
108
+ }
109
+
110
+ public static function disable_locally() {
111
+ $options = wphb_get_settings();
112
+ $options['uptime'] = false;
113
+ wphb_update_settings( $options );
114
+ set_site_transient( 'wphb-uptime-remotely-enabled', 'no', 180 ); // save for 3 minutes
115
+ }
116
+
117
+ public static function disable_remotely() {
118
+ /** @var WP_Hummingbird_API $api */
119
+ $api = wphb_get_api();
120
+ delete_site_transient( 'wphb-uptime-remotely-enabled' );
121
+ return $api->uptime->disable();
122
+ }
123
+
124
+ /**
125
+ * @param WP_Error $error
126
+ */
127
+ public static function set_error( $error ) {
128
+ set_site_transient( 'wphb-uptime-last-error', $error );
129
+ }
130
+
131
+ public static function get_error() {
132
+ return get_site_transient( 'wphb-uptime-last-error' );
133
+ }
134
+
135
+
136
+ /**
137
+ * Clear Performance Module cache
138
+ */
139
+ public static function clear_cache() {
140
+ delete_site_transient( 'wphb-uptime-last-report' );
141
+ delete_site_transient( 'wphb-uptime-last-error' );
142
+ }
143
+ }
144
+
core/modules/dummy/dummy-image.png ADDED
Binary file
core/modules/dummy/dummy-js.js ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ console.log( "Dummy WP Hummingbird" );
2
+ console.log( "Dummy WP Hummingbird" );
3
+ console.log( "Dummy WP Hummingbird" );
4
+ console.log( "Dummy WP Hummingbird" );
5
+ console.log( "Dummy WP Hummingbird" );
6
+ console.log( "Dummy WP Hummingbird" );
7
+ console.log( "Dummy WP Hummingbird" );
8
+ console.log( "Dummy WP Hummingbird" );
9
+ console.log( "Dummy WP Hummingbird" );
10
+ console.log( "Dummy WP Hummingbird" );
11
+ console.log( "Dummy WP Hummingbird" );
12
+ console.log( "Dummy WP Hummingbird" );
13
+ console.log( "Dummy WP Hummingbird" );
14
+ console.log( "Dummy WP Hummingbird" );
15
+ console.log( "Dummy WP Hummingbird" );
16
+ console.log( "Dummy WP Hummingbird" );
17
+ console.log( "Dummy WP Hummingbird" );
18
+ console.log( "Dummy WP Hummingbird" );
19
+ console.log( "Dummy WP Hummingbird" );
20
+ console.log( "Dummy WP Hummingbird" );
21
+ console.log( "Dummy WP Hummingbird" );
22
+ console.log( "Dummy WP Hummingbird" );
23
+ console.log( "Dummy WP Hummingbird" );
24
+ console.log( "Dummy WP Hummingbird" );
25
+ console.log( "Dummy WP Hummingbird" );
26
+ console.log( "Dummy WP Hummingbird" );
27
+ console.log( "Dummy WP Hummingbird" );
28
+ console.log( "Dummy WP Hummingbird" );
29
+ console.log( "Dummy WP Hummingbird" );
30
+ console.log( "Dummy WP Hummingbird" );
31
+ console.log( "Dummy WP Hummingbird" );
32
+ console.log( "Dummy WP Hummingbird" );
33
+ console.log( "Dummy WP Hummingbird" );
34
+ console.log( "Dummy WP Hummingbird" );
35
+ console.log( "Dummy WP Hummingbird" );
36
+ console.log( "Dummy WP Hummingbird" );
37
+ console.log( "Dummy WP Hummingbird" );
38
+ console.log( "Dummy WP Hummingbird" );
39
+ console.log( "Dummy WP Hummingbird" );
core/modules/dummy/dummy-media.mp3 ADDED
File without changes
core/modules/dummy/dummy-style.css ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .impossible-class {
2
+ background:black;
3
+ }
4
+ .impossible-class {
5
+ background:black;
6
+ }
7
+ .impossible-class {
8
+ background:black;
9
+ }
10
+ .impossible-class {
11
+ background:black;
12
+ }
13
+ .impossible-class {
14
+ background:black;
15
+ }
16
+ .impossible-class {
17
+ background:black;
18
+ }
19
+ .impossible-class {
20
+ background:black;
21
+ }
22
+ .impossible-class {
23
+ background:black;
24
+ }
25
+ .impossible-class {
26
+ background:black;
27
+ }
28
+ .impossible-class {
29
+ background:black;
30
+ }
31
+ .impossible-class {
32
+ background:black;
33
+ }
34
+ .impossible-class {
35
+ background:black;
36
+ }
37
+ .impossible-class {
38
+ background:black;
39
+ }
40
+ .impossible-class {
41
+ background:black;
42
+ }
43
+ .impossible-class {
44
+ background:black;
45
+ }
46
+ .impossible-class {
47
+ background:black;
48
+ }
49
+ .impossible-class {
50
+ background:black;
51
+ }
52
+ .impossible-class {
53
+ background:black;
54
+ }
55
+ .impossible-class {
56
+ background:black;
57
+ }
58
+ .impossible-class {
59
+ background:black;
60
+ }
61
+ .impossible-class {
62
+ background:black;
63
+ }
64
+ .impossible-class {
65
+ background:black;
66
+ }
67
+ .impossible-class {
68
+ background:black;
69
+ }
70
+ .impossible-class {
71
+ background:black;
72
+ }
73
+ .impossible-class {
74
+ background:black;
75
+ }
76
+ .impossible-class {
77
+ background:black;
78
+ }
79
+ .impossible-class {
80
+ background:black;
81
+ }
82
+ .impossible-class {
83
+ background:black;
84
+ }
85
+ .impossible-class {
86
+ background:black;
87
+ }
88
+ .impossible-class {
89
+ background:black;
90
+ }
91
+ .impossible-class {
92
+ background:black;
93
+ }
94
+ .impossible-class {
95
+ background:black;
96
+ }
97
+ .impossible-class {
98
+ background:black;
99
+ }
100
+ .impossible-class {
101
+ background:black;
102
+ }
103
+ .impossible-class {
104
+ background:black;
105
+ }
106
+ .impossible-class {
107
+ background:black;
108
+ }
109
+ .impossible-class {
110
+ background:black;
111
+ }
112
+ .impossible-class {
113
+ background:black;
114
+ }
115
+ .impossible-class {
116
+ background:black;
117
+ }
118
+ .impossible-class {
119
+ background:black;
120
+ }
121
+ .impossible-class {
122
+ background:black;
123
+ }
124
+ .impossible-class {
125
+ background:black;
126
+ }
127
+ .impossible-class {
128
+ background:black;
129
+ }
130
+ .impossible-class {
131
+ background:black;
132
+ }
133
+ .impossible-class {
134
+ background:black;
135
+ }
136
+ .impossible-class {
137
+ background:black;
138
+ }
139
+ .impossible-class {
140
+ background:black;
141
+ }
142
+ .impossible-class {
143
+ background:black;
144
+ }
145
+ .impossible-class {
146
+ background:black;
147
+ }
148
+ .impossible-class {
149
+ background:black;
150
+ }
151
+ .impossible-class {
152
+ background:black;
153
+ }
154
+ .impossible-class {
155
+ background:black;
156
+ }
157
+ .impossible-class {
158
+ background:black;
159
+ }
160
+ .impossible-class {
161
+ background:black;
162
+ }
core/modules/minify/class-errors-controller.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Manage the errors during minification processing
5
+ */
6
+ class WP_Hummingbird_Minification_Errors_Controller {
7
+
8
+ /**
9
+ * Minification errors list
10
+ *
11
+ * @var array|bool
12
+ */
13
+ private $errors;
14
+
15
+ /**
16
+ * Saves the errors coming from our servers
17
+ *
18
+ * @var array
19
+ */
20
+ private $server_errors = array();
21
+
22
+ public function __construct() {
23
+ $this->errors = $this->get_errors();
24
+ $this->server_errors = $this->get_server_errors();
25
+ }
26
+
27
+ /**
28
+ * Retrieve the list of errors coming from the server
29
+ *
30
+ * @return array|mixed
31
+ */
32
+ public function get_server_errors() {
33
+ $errors = get_transient( 'wphb-minify-server-errors' );
34
+ if ( ! $errors || ! is_array( $errors ) ) {
35
+ return array();
36
+ }
37
+ return $errors;
38
+ }
39
+
40
+ /**
41
+ * Add an error coming from server
42
+ *
43
+ * @param $error
44
+ */
45
+ public function add_server_error( $error ) {
46
+ $this->server_errors[] = $error;
47
+ set_transient( 'wphb-minify-server-errors', $this->server_errors, 7200 ); // save for 2 hours
48
+ }
49
+
50
+
51
+ /**
52
+ * Check if there's an error in the server
53
+ * This function should be used to stop minification
54
+ * if there have been too many errors
55
+ */
56
+ public function is_server_error() {
57
+ // More than 2 errors is too many
58
+ return ( count( $this->server_errors ) > 2 );
59
+ }
60
+
61
+ /**
62
+ * Return the server errors time left (the time to delete the transient)
63
+ * in minutes
64
+ */
65
+ public function server_error_time_left() {
66
+ if ( ! $this->is_server_error() ) {
67
+ return 0;
68
+ }
69
+ $timeout = get_option( '_transient_timeout_wphb-minify-server-errors', false );
70
+ if ( ! $timeout ) {
71
+ return 0;
72
+ }
73
+ return ceil( ( $timeout - time() ) / 60 );
74
+ }
75
+
76
+ /**
77
+ * Get all minification errors
78
+ *
79
+ * @return array|bool False if there are no errors
80
+ */
81
+ private function get_errors() {
82
+ $default = array( 'scripts' => array(), 'styles' => array() );
83
+
84
+ /**
85
+ * Filter the minification errors
86
+ */
87
+ return apply_filters( 'wphb_minification_errors', get_option( 'wphb-minification-errors', $default ) );
88
+ }
89
+
90
+ /**
91
+ * Return a single handle error
92
+ *
93
+ * @param string $handle
94
+ * @param string $type styles|scripts
95
+ *
96
+ * @return bool|array
97
+ */
98
+ public function get_handle_error( $handle, $type ) {
99
+ if ( ! isset( $this->errors[ $type ][ $handle ] ) ) {
100
+ return false;
101
+ }
102
+
103
+ $defaults = array(
104
+ 'handle' => '',
105
+ 'error' => '',
106
+ 'disable' => array()
107
+ );
108
+ return wp_parse_args( $this->errors[ $type ][ $handle ], $defaults );
109
+ }
110
+
111
+ /**
112
+ * Clear all errors
113
+ */
114
+ public static function clear_errors() {
115
+ delete_option( 'wphb-minification-errors' );
116
+ delete_option( 'wphb-minify-server-errors' );
117
+ }
118
+
119
+ /**
120
+ * Delete a single handle error
121
+ *
122
+ * @param string|array $handles
123
+ * @param string $type
124
+ */
125
+ public function clear_handle_error( $handles, $type ) {
126
+ if ( ! is_array( $handles ) ) {
127
+ $handles = array( $handles );
128
+ }
129
+
130
+ foreach ( $handles as $handle ) {
131
+ $error = $this->get_handle_error( $handle, $type );
132
+ if ( ! $error ) {
133
+ continue;
134
+ }
135
+
136
+ unset( $this->errors[ $type ][ $handle ] );
137
+ }
138
+
139
+
140
+ update_option( 'wphb-minification-errors', $this->errors );
141
+ }
142
+
143
+ /**
144
+ * Add a minification error for a list of handles
145
+ *
146
+ * @param array|string $handles Handles list or single handle
147
+ * @param string $type scripts|styles
148
+ * @param string $code Error code
149
+ * @param string $message Error message
150
+ * @param array $actions List of actions to take (don't minify, don't combine)
151
+ * @param array $disable List of switchers to disable in Minification screen (minify, combine)
152
+ */
153
+ public function add_error( $handles, $type, $code, $message, $actions = array(), $disable = array() ) {
154
+ if ( ! is_array( $handles ) ) {
155
+ $handles = array( $handles );
156
+ }
157
+
158
+ $options = wphb_get_settings();
159
+
160
+ foreach ( $handles as $handle ) {
161
+ $this->errors[ $type ][ $handle ] = array(
162
+ 'code' => $code,
163
+ 'error' => $message,
164
+ 'disable' => $disable
165
+ );
166
+
167
+ if ( ! empty( $actions ) && is_array( $actions ) ) {
168
+
169
+ if ( in_array( 'minify', $actions ) ) {
170
+ $options['dont_minify'][ $type ][] = $handle;
171
+ }
172
+
173
+ $key = in_array( $handle, $options['combine'][ $type ] );
174
+ if ( in_array( 'combine', $actions ) && false !== $key ) {
175
+ unset( $options['combine'][ $type ][ $key ] );
176
+ $options['combine'][ $type ] = array_values( $options['combine'][ $type ] );
177
+ }
178
+
179
+ }
180
+ }
181
+
182
+ wphb_update_settings( $options );
183
+ update_option( 'wphb-minification-errors', $this->errors );
184
+ }
185
+ }
core/modules/minify/class-minify-group.php ADDED
@@ -0,0 +1,1412 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @author: WPMUDEV, Ignacio Cruz (igmoweb)
4
+ * @version:
5
+ */
6
+
7
+ if ( ! defined( 'ABSPATH' ) ) {
8
+ exit;
9
+ }
10
+
11
+ class WP_Hummingbird_Module_Minify_Group {
12
+
13
+ /**
14
+ * List of handles
15
+ *
16
+ * @var array
17
+ */
18
+ private $handles = array();
19
+
20
+ /**
21
+ * List of handle URLs
22
+ *
23
+ * @var array
24
+ */
25
+ private $handle_urls = array();
26
+
27
+ /**
28
+ * List of handle version
29
+ *
30
+ * @var array
31
+ */
32
+ private $handle_versions = array();
33
+
34
+ /**
35
+ * List of extra attributes. It includes 'after' attributes
36
+ *
37
+ * @var array
38
+ */
39
+ private $extra = array();
40
+
41
+ /**
42
+ * @var string
43
+ */
44
+ private $args = '';
45
+
46
+ /**
47
+ * @var string
48
+ */
49
+ public $type = '';
50
+
51
+ /**
52
+ * What handles should not be minified|combined|enqueued
53
+ *
54
+ * @var array
55
+ */
56
+ private $dont_minify = array();
57
+ private $dont_combine = array();
58
+ private $dont_enqueue = array();
59
+
60
+ /**
61
+ * Save dependencies for each handle
62
+ *
63
+ * @var array
64
+ */
65
+ private $handle_dependencies = array();
66
+
67
+ /**
68
+ * Save original size for each handle
69
+ *
70
+ * @var array
71
+ */
72
+ private $handle_original_sizes = array();
73
+
74
+ /**
75
+ * Save compressed size for each handle
76
+ *
77
+ * @var array
78
+ */
79
+ private $handle_compressed_sizes = array();
80
+
81
+ /**
82
+ * Unique hash for this group
83
+ *
84
+ * @var string
85
+ */
86
+ public $hash;
87
+
88
+ /**
89
+ * Unique group ID
90
+ *
91
+ * Normally used for wp_enqueue_* functions
92
+ * Needs to be set if you need to get the groups list dependencies
93
+ *
94
+ * @var string
95
+ */
96
+ public $group_id = '';
97
+
98
+ /**
99
+ * The file CPT ID (see WP_Hummingbird_Module_Minifynew_File)
100
+ * @var int
101
+ */
102
+ public $file_id = 0;
103
+
104
+ public function __construct( $var_values = array() ) {
105
+ if ( $var_values ) {
106
+ foreach ( $var_values as $var_name => $var_value ) {
107
+ $this->$var_name = $var_value;
108
+ }
109
+ }
110
+
111
+ $this->refresh_hash();
112
+ }
113
+
114
+ /**
115
+ * Get an instance of WP_Hummingbird_Module_Minifynew_Group based on wphb_minify_group CPT ID
116
+ *
117
+ * @param $post_id
118
+ *
119
+ * @return WP_Hummingbird_Module_Minify_Group|false
120
+ */
121
+ public static function get_instance_by_post_id( $post_id ) {
122
+ $post = get_post( $post_id );
123
+ if ( ! $post || get_post_type( $post ) !== 'wphb_minify_group' ) {
124
+ return false;
125
+ }
126
+
127
+ $_vars = get_class_vars( 'WP_Hummingbird_Module_Minify_Group' );
128
+ $vars = array();
129
+ foreach ( $_vars as $_var_name => $_var_default ) {
130
+ $value = get_post_meta( $post_id, '_' . $_var_name, true );
131
+ if ( false !== $value ) {
132
+ $vars[ $_var_name ] = $value;
133
+ }
134
+ else {
135
+ $vars[ $_var_name ] = $_var_default;
136
+ }
137
+ }
138
+
139
+ $group = new self( $vars );
140
+ return $group;
141
+ }
142
+
143
+ /**
144
+ * Get an instance of WP_Hummingbird_Module_Minifynew_Group based on wphb_minify_group CPT ID
145
+ *
146
+ * @param string $hash
147
+ * @param string $type scripts|styles
148
+ *
149
+ * @return WP_Hummingbird_Module_Minify_Group|false
150
+ */
151
+ public static function get_instance_by_hash_and_type( $hash, $type ) {
152
+
153
+ $posts = self::get_minify_groups();
154
+
155
+ $found = false;
156
+ foreach ( $posts as $post ) {
157
+ if ( $post->post_title == $hash . '-' . $type ) {
158
+ $found = $post;
159
+ break;
160
+ }
161
+ }
162
+
163
+ if ( $found ) {
164
+ $_vars = get_class_vars( 'WP_Hummingbird_Module_Minify_Group' );
165
+ $vars = array();
166
+ foreach ( $_vars as $_var_name => $_var_default ) {
167
+ $value = get_post_meta( $found->ID, '_' . $_var_name, true );
168
+ if ( false !== $value ) {
169
+ $vars[ $_var_name ] = $value;
170
+ }
171
+ else {
172
+ $vars[ $_var_name ] = $_var_default;
173
+ }
174
+ }
175
+ return new self( $vars );
176
+ }
177
+ else {
178
+ return false;
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Return a list of WP_Posts with post_type = wphb_minify_group
184
+ *
185
+ * @return array
186
+ */
187
+ public static function get_minify_groups() {
188
+ $posts = wp_cache_get( 'wphb_minify_groups' );
189
+
190
+ if ( false === $posts ) {
191
+ $posts = get_posts(
192
+ array(
193
+ 'post_type' => 'wphb_minify_group',
194
+ 'post_status' => 'publish',
195
+ 'posts_per_page' => -1
196
+ )
197
+ );
198
+ wp_cache_set( 'wphb_minify_groups', $posts );
199
+ }
200
+
201
+ return empty( $posts ) ? array() : $posts;
202
+ }
203
+
204
+ /**
205
+ * Get the groups where a handle is
206
+ *
207
+ * @param string $handle
208
+ * @param string $type
209
+ *
210
+ * @return array list of WP_Hummingbird_Module_Minify_Group items
211
+ */
212
+ public static function get_groups_from_handle( $handle, $type ) {
213
+ $groups = array();
214
+ $posts = self::get_minify_groups();
215
+ foreach ( $posts as $post ) {
216
+ $group = self::get_instance_by_post_id( $post->ID );
217
+ if ( $group && $type === $group->type && in_array( $handle, $group->get_handles() ) ) {
218
+ $groups[] = $group;
219
+ }
220
+ }
221
+ return $groups;
222
+ }
223
+
224
+
225
+ /**
226
+ * Add a single handle to the group
227
+ *
228
+ * @param string $handle
229
+ * @param string $url
230
+ * @param string $version Source version (specified by WP)
231
+ */
232
+ public function add_handle( $handle, $url, $version = '' ) {
233
+ $this->handles[] = $handle;
234
+ $this->handle_urls[ $handle ] = $url;
235
+ $this->handle_versions[ $handle ] = $version;
236
+ $this->handle_dependencies[ $handle ] = array();
237
+ $this->handle_compressed_sizes[ $handle ] = 0;
238
+ $this->handle_original_sizes[ $handle ] = 0;
239
+
240
+ /**
241
+ * Filter the resource (blocked or not)
242
+ *
243
+ * @usedby wphb_filter_resource_block()
244
+ *
245
+ * @var bool false
246
+ * @var string $handle Source slug
247
+ * @var string $source_url Source URL
248
+ * @var string $type scripts|styles @deprecated
249
+ */
250
+ if ( apply_filters( 'wphb_block_resource', false, $handle, $this->type, $url, null ) ) {
251
+ $this->should_do_handle( $handle, 'enqueue', false );
252
+ }
253
+
254
+ /**
255
+ * Filter the resource (minify or not)
256
+ *
257
+ * @usedby wphb_filter_resource_minify()
258
+ *
259
+ * @var bool $minify_resource
260
+ * @var string $handle Source slug
261
+ * @var string $source_url Source URL
262
+ * @var string $type scripts|styles
263
+ */
264
+ if ( ! apply_filters( 'wphb_minify_resource', true, $handle, $this->type, $url ) ) {
265
+ $this->should_do_handle( $handle, 'minify', false );
266
+ }
267
+
268
+ /**
269
+ * Filter the resource (combine or not)
270
+ *
271
+ * @usedby wphb_filter_resource_combine()
272
+ *
273
+ * @var bool false
274
+ * @var string $handle Source slug
275
+ * @var string $source_url Source URL
276
+ * @var string $type scripts|styles
277
+ */
278
+ if ( ! apply_filters( 'wphb_combine_resource', false, $handle, $this->type, $url ) ) {
279
+ $this->should_do_handle( $handle, 'combine', false );
280
+ }
281
+
282
+ $this->refresh_hash();
283
+ }
284
+
285
+ /**
286
+ * Remove a single handle from the group
287
+ *
288
+ * @param string $handle
289
+ */
290
+ public function remove_handle( $handle ) {
291
+ $key = array_search( $handle, $this->handles );
292
+ if ( $key > - 1 ) {
293
+ unset( $this->handles[ $key ] );
294
+ unset( $this->handle_urls[ $handle ] );
295
+ unset( $this->handle_versions[ $handle ] );
296
+ unset( $this->handle_compressed_sizes[ $handle ] );
297
+ unset( $this->handle_original_sizes[ $handle ] );
298
+ $this->remove_handle_dependencies( $handle );
299
+ $this->should_do_handle( $handle, 'minify', true ); // This will remove the hanlde from $this->dont_minify
300
+ $this->should_do_handle( $handle, 'combine', true ); // This will remove the hanlde from $this->dont_combine
301
+ $this->should_do_handle( $handle, 'enqueue', true ); // This will remove the hanlde from $this->dont_enqueue
302
+ $this->handles = array_values( $this->handles );
303
+ $this->refresh_hash();
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Remove all handles from the group
309
+ *
310
+ * @param array $handles
311
+ */
312
+ public function remove_handles( $handles ) {
313
+ $handles = (array)$handles;
314
+ array_map( array( $this, 'remove_handle' ), $handles );
315
+ }
316
+
317
+ /**
318
+ * Add new dependencies for a given handle
319
+ *
320
+ * @param string $handle
321
+ * @param string|array $dep One or several dependencies for this handle
322
+ */
323
+ public function add_handle_dependency( $handle, $dep ) {
324
+ if ( ! isset( $this->handle_dependencies[ $handle ] ) ) {
325
+ return;
326
+ }
327
+
328
+ if ( ! is_array( $dep ) ) {
329
+ $dep = array( $dep );
330
+ }
331
+
332
+ $this->handle_dependencies[ $handle ] = array_merge( $this->handle_dependencies[ $handle ], $dep );
333
+ $this->handle_dependencies[ $handle ] = array_unique( $this->handle_dependencies[ $handle ] );
334
+ }
335
+
336
+ /**
337
+ * Remove all dependencies for a handle
338
+ *
339
+ * @param $handle
340
+ */
341
+ public function remove_handle_dependencies( $handle ) {
342
+ if ( isset( $this->handle_dependencies[ $handle ] ) ) {
343
+ unset( $this->handle_dependencies[ $handle ] );
344
+ }
345
+ }
346
+
347
+ /**
348
+ * Set the original size in Kb for a handle
349
+ *
350
+ * @param string $handle
351
+ * @param float $size Size in Kb
352
+ */
353
+ public function set_handle_original_size( $handle, $size ) {
354
+ $this->handle_original_sizes[ $handle ] = number_format_i18n( str_replace(',', '', $size ) / 1000, 1 );
355
+ }
356
+
357
+ /**
358
+ * Get the original size in Kb for a handle
359
+ *
360
+ * @param string $handle
361
+ *
362
+ * @return float Original size in Kb
363
+ */
364
+
365
+ public function get_handle_original_size( $handle ) {
366
+ return $this->handle_original_sizes[ $handle ];
367
+ }
368
+
369
+ /**
370
+ * Set the compressed size in Kb for a handle
371
+ *
372
+ * @param string $handle
373
+ * @param float $size Size in Kb
374
+ */
375
+ public function set_handle_compressed_size( $handle, $size ) {
376
+ $this->handle_compressed_sizes[ $handle ] = number_format_i18n( str_replace(',', '', $size ) / 1000, 1 );
377
+ }
378
+
379
+ /**
380
+ * Get the compressed size in Kb for a handle
381
+ *
382
+ * @param string $handle
383
+ *
384
+ * @return float Compressed size in Kb
385
+ */
386
+ public function get_handle_compressed_size( $handle ) {
387
+ return $this->handle_compressed_sizes[ $handle ];
388
+ }
389
+
390
+ /**
391
+ * Get the total original size of this group in Kb
392
+ *
393
+ * @return string
394
+ */
395
+ public function get_original_size_total() {
396
+ $sum = 0;
397
+ foreach ( $this->get_handles() as $handle ) {
398
+ $sum = $sum + $this->get_handle_original_size( $handle );
399
+ }
400
+ return number_format_i18n( $sum, 2 );
401
+ }
402
+
403
+ /**
404
+ * Get the total compressed size of this group in Kb
405
+ *
406
+ * @return string
407
+ */
408
+ public function get_compressed_size_total() {
409
+ $sum = 0;
410
+ foreach ( $this->get_handles() as $handle ) {
411
+ $sum = $sum + $this->get_handle_compressed_size( $handle );
412
+ }
413
+ return number_format_i18n( $sum, 2 );
414
+ }
415
+
416
+ /**
417
+ * Get the list of dependencies for a handle
418
+ *
419
+ * @param $handle
420
+ *
421
+ * @return array|mixed
422
+ */
423
+ public function get_handle_dependencies( $handle ) {
424
+ return isset( $this->handle_dependencies[ $handle ] ) ? $this->handle_dependencies[ $handle ] : array();
425
+ }
426
+
427
+
428
+ /**
429
+ * Return the complete list of dependencies of all handles in this group
430
+ *
431
+ * @return array
432
+ */
433
+ public function get_all_handles_dependencies() {
434
+ $all_deps = array();
435
+ foreach ( $this->handle_dependencies as $handle => $deps ) {
436
+ $all_deps = array_merge( $all_deps, $deps );
437
+ }
438
+
439
+ return array_unique( $all_deps );
440
+ }
441
+
442
+ /**
443
+ * Removes handle/s but returns a new instance of
444
+ * WP_Hummingbird_Module_Minifynew_Group with the same parameters
445
+ * but pnly with the specified handles
446
+ *
447
+ * @param array|string $handles one or more handles to remove from the group
448
+ *
449
+ * @return WP_Hummingbird_Module_Minify_Group
450
+ */
451
+ public function slice_handles( $handles ) {
452
+ if ( ! is_array( $handles ) ) {
453
+ $handles = array();
454
+ }
455
+
456
+ $new_group = clone $this;
457
+ $this->remove_handles( $handles );
458
+
459
+ // Remove those handles that we don't need in the new group
460
+ $new_group->remove_handles( $this->get_handles() );
461
+
462
+ $this->refresh_hash();
463
+
464
+ return $new_group;
465
+ }
466
+
467
+ /**
468
+ * Get the list of handles
469
+ *
470
+ * @return array
471
+ */
472
+ public function get_handles() {
473
+ return is_array( $this->handles ) ? $this->handles : array();
474
+ }
475
+
476
+ /**
477
+ * Set if a handle should be minified|combined|enqueue or not. If $value param is null, it will
478
+ * return a boolean indicating if that handle should be minified|combined|enqueue or not
479
+ *
480
+ * @param string $handle
481
+ * @param string $action minify|combine|enqueue
482
+ * @param null|bool $value
483
+ *
484
+ * @return bool|null
485
+ */
486
+ public function should_do_handle( $handle, $action, $value = null ) {
487
+ switch ( $action ) {
488
+ case 'minify': {
489
+ $should = 'dont_minify';
490
+ break;
491
+ }
492
+ case 'combine': {
493
+ $should = 'dont_combine';
494
+ break;
495
+ }
496
+ case 'enqueue': {
497
+ $should = 'dont_enqueue';
498
+ break;
499
+ }
500
+ default: {
501
+ return null;
502
+ }
503
+ }
504
+
505
+ if ( ! is_null( $value ) ) {
506
+ // Handle should or shouldn't be minified
507
+ $value = (bool) $value;
508
+ if ( ! $value && ! in_array( $handle, $this->$should ) ) {
509
+ $new_should = $this->$should;
510
+ $new_should[] = $handle;
511
+ $this->$should = $new_should;
512
+ } elseif ( $value && in_array( $handle, $this->$should ) ) {
513
+ // Remove from the array
514
+ $new_should = $this->$should;
515
+ $key = array_search( $handle, $new_should );
516
+ unset( $new_should[ $key ] );
517
+ $this->$should = array_values( $new_should );
518
+ }
519
+ } else {
520
+ // Return the value
521
+ return in_array( $handle, $this->$should ) ? false : true;
522
+ }
523
+
524
+ return null;
525
+ }
526
+
527
+ public function get_dont_combine_list() {
528
+ return $this->dont_combine;
529
+ }
530
+
531
+ public function get_dont_enqueue_list() {
532
+ return $this->dont_enqueue;
533
+ }
534
+
535
+ /**
536
+ * In some cases (when an asset is not minified and there's just one handle)
537
+ * a file should not be generated and should pick the default one instead
538
+ */
539
+ public function should_generate_file() {
540
+ $handles = $this->get_handles();
541
+ if ( count( $handles ) === 1 && ! $this->should_do_handle( $handles[0], 'minify' ) ) {
542
+ return false;
543
+ }
544
+ return true;
545
+ }
546
+
547
+ /**
548
+ * Return the URL for a given handle
549
+ *
550
+ * @param $handle
551
+ *
552
+ * @return string
553
+ */
554
+ public function get_handle_url( $handle ) {
555
+ return $this->handle_urls[ $handle ];
556
+ }
557
+
558
+ /**
559
+ * Add an extra attribute
560
+ *
561
+ * @param string $key
562
+ * @param mixed $value
563
+ */
564
+ public function add_extra( $key, $value ) {
565
+ $this->extra[ $key ] = $value;
566
+ $this->refresh_hash();
567
+ }
568
+
569
+ /**
570
+ * Return all extra attributes
571
+ *
572
+ * @return array
573
+ */
574
+ public function get_extra() {
575
+ return $this->extra;
576
+ }
577
+
578
+ /**
579
+ * Delete an extra attribute
580
+ *
581
+ * @param $key
582
+ */
583
+ public function delete_extra( $key ) {
584
+ if ( isset( $this->extra[ $key ] ) ) {
585
+ unset( $this->extra[ $key ] );
586
+ $this->refresh_hash();
587
+ }
588
+ }
589
+
590
+ /**
591
+ * Add an after attribute. Normally us by add_inline_script/style functions
592
+ *
593
+ * @param $new_after
594
+ */
595
+ public function add_after( $new_after ) {
596
+ $after = $this->get_after();
597
+
598
+ if ( ! is_array( $new_after ) ) {
599
+ $new_after = array( $new_after );
600
+ }
601
+
602
+ $after = array_merge( $new_after, $after );
603
+ $this->extra['after'] = $after;
604
+ $this->refresh_hash();
605
+ }
606
+
607
+ /**
608
+ * Add an after attribute. Normally us by add_inline_script/style functions
609
+ *
610
+ * @param $new_after
611
+ */
612
+ public function add_data( $new_data ) {
613
+ $data = $this->get_data();
614
+
615
+ if ( ! is_array( $new_data ) ) {
616
+ $new_data = array( $new_data );
617
+ }
618
+
619
+ if ( ! is_array( $data ) ) {
620
+ $data = array( $data );
621
+ }
622
+
623
+ $data = array_merge( $new_data, $data );
624
+ $this->extra['data'] = $data;
625
+ $this->refresh_hash();
626
+ }
627
+
628
+ /**
629
+ * Return after attribute
630
+ *
631
+ * @return array
632
+ */
633
+ public function get_after() {
634
+ return isset( $this->extra['after'] ) ? $this->extra['after'] : array();
635
+ }
636
+
637
+ /**
638
+ * Return data attribute
639
+ *
640
+ * @return array
641
+ */
642
+ public function get_data() {
643
+ return isset( $this->extra['data'] ) ? $this->extra['data'] : array();
644
+ }
645
+
646
+ /**
647
+ * Return the args attribute
648
+ *
649
+ * @return string
650
+ */
651
+ public function get_args() {
652
+ return $this->args;
653
+ }
654
+
655
+
656
+ /**
657
+ * Set the args attribute value
658
+ *
659
+ * @param string $value
660
+ */
661
+ public function set_args( $value ) {
662
+ $this->args = $value;
663
+ $this->refresh_hash();
664
+ }
665
+
666
+ /**
667
+ * Set the group type: scripts|styles
668
+ *
669
+ * @param string $type
670
+ */
671
+ public function set_type( $type ) {
672
+ $this->type = $type;
673
+ $this->refresh_hash();
674
+ }
675
+
676
+
677
+ /**
678
+ * Checks if the group is expired by comparing expiration time set in the file
679
+ * and handles versions hashes
680
+ *
681
+ * @return bool
682
+ */
683
+ public function is_expired() {
684
+ return ( time() > $this->expires_on() ) || ( $this->get_file_version_hash() != $this->get_versions_hash() );
685
+ }
686
+
687
+
688
+ /**
689
+ * Refresh the unique hash for this group
690
+ */
691
+ public function refresh_hash() {
692
+ $handles = $this->get_handles();
693
+ $handles_versions = $this->handle_versions;
694
+
695
+ if ( ! is_array( $handles ) ) {
696
+ $handles = array( $handles );
697
+ }
698
+
699
+ if ( ! is_array( $handles_versions ) ) {
700
+ $handles_versions = array( $handles_versions );
701
+ }
702
+
703
+ $hash = implode( '-', $handles );
704
+ $hash .= $this->args;
705
+ $hash .= $this->type;
706
+ $hash .= implode( '-', $handles_versions );
707
+ $this->hash = self::hash( $hash );
708
+ if ( $this->file_id ) {
709
+ update_post_meta( $this->file_id, '_hash', $this->hash );
710
+ }
711
+ }
712
+
713
+ public function get_versions_hash() {
714
+ return self::hash( $this->handle_versions );
715
+ }
716
+
717
+ public function get_sources_hash() {
718
+ return self::hash( $this->handle_urls );
719
+ }
720
+
721
+ /**
722
+ * General purpose function. Returns an array hashed
723
+ *
724
+ * @param array $list Array of strings
725
+ *
726
+ * @return string
727
+ */
728
+ private static function hash( $list ) {
729
+ return wp_hash( maybe_serialize( $list ) );
730
+ }
731
+
732
+
733
+ /**
734
+ * Process the group. Minifies/combine... everything
735
+ */
736
+ public function process_group() {
737
+
738
+ if ( ! $this->should_generate_file() ) {
739
+ // Nothing to process, we'll use the default handle URL instead
740
+ return false;
741
+ }
742
+
743
+ /** @var WP_Hummingbird_Module_Minify $minify_module */
744
+ $minify_module = wphb_get_module( 'minify' );
745
+
746
+ $handles = $this->get_handles();
747
+
748
+ // First file is for the header
749
+ $files_data = array();
750
+
751
+ foreach ( $handles as $handle ) {
752
+ $src = $this->get_handle_url( $handle );
753
+
754
+ if ( ! $src ) {
755
+ $minify_module->errors_controller->add_error(
756
+ $handle,
757
+ $this->type,
758
+ 'empty-url',
759
+ __( 'This file has not a linked URL, it will not be combined/minified', 'wphb' ),
760
+ array( 'minify', 'combine' ), // Disallow minification/concat
761
+ array( 'minify', 'combine' ) // Disable minification/concat switchers
762
+ );
763
+ continue;
764
+ }
765
+
766
+ $pathinfo = pathinfo( $src );
767
+ if ( ! isset( $pathinfo['extension'] ) || ( isset( $pathinfo['extension'] ) && ! in_array( $pathinfo['extension'], array( 'js', 'css' ) ) ) ) {
768
+ $minify_module->errors_controller->add_error(
769
+ $handle,
770
+ $this->type,
771
+ 'wrong-extension',
772
+ __( 'This file included in your output can\'t be minified or combined', 'wphb' ),
773
+ array( 'minify', 'combine' ), // Disallow minification/concat
774
+ array( 'minify', 'combine' ) // Disable minification/concat switchers
775
+ );
776
+ continue;
777
+ }
778
+
779
+ // @TODO Log
780
+ // WP_Hummingbird_Module_Minify::log( "locaProcessing Group : " . $this->get_cache_key() );
781
+
782
+ // Get the full URL
783
+ if ( ! preg_match( '|^(https?:)?//|', $src ) ) {
784
+ $src = site_url( $src );
785
+ }
786
+
787
+ $content = false;
788
+ $is_local = $this->is_handle_local( $handle );
789
+
790
+ if ( $is_local ) {
791
+ $path = wphb_src_to_path( $src );
792
+ if ( is_file( $path ) ) {
793
+ $content = file_get_contents( $path );
794
+ }
795
+ }
796
+
797
+ if ( false === $content ) {
798
+ // Try to get the file remotely
799
+ if ( ! preg_match( '/^https?:/', $src ) ) {
800
+ // Rooted URL
801
+ $src = 'http:' . $src;
802
+ }
803
+ $request = wp_remote_get( $src, array( 'sslverify' => false ) );
804
+ $content = wp_remote_retrieve_body( $request );
805
+ if ( is_wp_error( $request ) ) {
806
+ //WP_Hummingbird_Module_Minify::log( $request->get_error_message() );
807
+ } elseif ( wp_remote_retrieve_response_code( $request ) !== 200 ) {
808
+ //WP_Hummingbird_Module_Minify::log( "Code different from 200. Truncated content:" );
809
+ //WP_Hummingbird_Module_Minify::log( substr( $content, 0, 1000 ) );
810
+ }
811
+ }
812
+
813
+ // If nothing worked do not minify and do not combine file
814
+ if ( empty( $content ) ) {
815
+ $minify_module->errors_controller->add_error(
816
+ $handle,
817
+ $this->type,
818
+ 'empty-content',
819
+ __( 'It looks like this file is empty', 'wphb' ),
820
+ array( 'minify', 'combine' ) // Disallow minification/concat
821
+ );
822
+ continue;
823
+ }
824
+ else {
825
+ //$minification_module->errors_controller->clear_handle_error( $handle, $this->type );
826
+ }
827
+
828
+ //$this->set_handle_original_size( $handle, absint( mb_strlen( $content ) ) );
829
+
830
+ // Remove BOM
831
+ $content = preg_replace( "/^\xEF\xBB\xBF/", '', $content );
832
+
833
+ // Concatenate and minify scripts/styles!
834
+ if ( 'scripts' === $this->type ) {
835
+ //WP_Hummingbird_Module_Minify::log( "Minify script" );
836
+ }
837
+ elseif ( 'styles' === $this->type ) {
838
+ //WP_Hummingbird_Module_Minify::log( "Minify style" );
839
+ if ( $is_local ) {
840
+ //$content = self::replace_relative_urls( dirname( $path ), $content );
841
+ $content = WP_Hummingbird_CSS_UriRewriter::prepend( $content, trailingslashit( dirname($src) ) );
842
+ }
843
+
844
+ if ( preg_match_all( '/(?<fullImport>@import\s?.*?;)/', $content, $matches ) ) {
845
+ // We can't allow @import directives in files
846
+ $minify_module->errors_controller->add_error(
847
+ $handle,
848
+ $this->type,
849
+ 'import-not-allowed',
850
+ __( '@import directive is not allowed in stylesheets', 'wphb' ),
851
+ array( 'minify', 'combine' ), // Disallow minification/concat
852
+ array( 'minify', 'combine' ) // Disable minify/concat switchers
853
+ );
854
+ continue;
855
+ }
856
+ }
857
+
858
+ if ( empty( $content ) ) {
859
+ //WP_Hummingbird_Module_Minify::log( "Empty content after minification" );
860
+ // Something happened to compression
861
+ $minify_module->errors_controller->add_error(
862
+ $handle,
863
+ $this->type,
864
+ 'after-compression',
865
+ __( 'Hummingbird could not parse the content of this file', 'wphb' ),
866
+ array( 'minify', 'combine' )
867
+ );
868
+ }
869
+ else {
870
+ //$minification_module->errors_controller->clear_handle_error( $handle, $this->type );
871
+ $files_data[] = array(
872
+ 'handle' => $handle,
873
+ 'content' => $content,
874
+ 'minify' => $this->should_do_handle( $handle, 'minify' )
875
+ );
876
+ }
877
+ }
878
+
879
+ unset( $content );
880
+
881
+ if ( empty( $files_data ) ) {
882
+ return false;
883
+ }
884
+
885
+ /**
886
+ * If the files should be kept remote in CDN
887
+ */
888
+ $upload_to_cdn = wphb_get_cdn_status();
889
+
890
+ /**
891
+ * Function that will get files minified
892
+ *
893
+ * The callback should return WP_Error or array with the file details:
894
+ * {
895
+ * 'file' => absolute file path if the file is saved locally
896
+ * }
897
+ */
898
+ $minify_callback = apply_filters( 'wphb_minify_callback', array( 'WP_Hummingbird_Module_Minify_Group', 'process_remote_files' ) );
899
+
900
+ if ( ! is_callable( $minify_callback ) ) {
901
+ return new WP_Error( 'error', __( 'Minify callback does not exist', 'wphb' ) );
902
+ }
903
+
904
+
905
+ // Generate the file
906
+ $result = call_user_func_array( $minify_callback, array( $files_data, $upload_to_cdn, $this ) );
907
+
908
+ if ( is_wp_error( $result ) ) {
909
+ // Save error
910
+ return $result;
911
+ }
912
+
913
+ $result = (array)$result;
914
+ self::insert_group( $this, $result );
915
+ return true;
916
+ }
917
+
918
+ /**
919
+ * @param WP_Hummingbird_Module_Minify_Group $group
920
+ * @param array $file
921
+ *
922
+ * @return bool
923
+ */
924
+ public static function insert_group( $group, $file ) {
925
+ // Insert the new file in posts table
926
+ $post_id = wp_insert_post( array(
927
+ 'post_title' => $group->get_sources_hash() . '-' . $group->type,
928
+ 'post_status' => 'publish',
929
+ 'post_type' => 'wphb_minify_group'
930
+ ) );
931
+
932
+
933
+ if ( $post_id ) {
934
+ wp_cache_delete( 'wphb_minify_groups' );
935
+
936
+ $group->file_id = $post_id;
937
+
938
+ if ( isset( $file['atts'] ) ) {
939
+ // save information about each file
940
+ foreach ( $file['atts'] as $item ) {
941
+ $item = (array)$item;
942
+ $group->set_handle_original_size( $item['handle'], $item['original-size'] );
943
+ $group->set_handle_compressed_size( $item['handle'], $item['compressed-size'] );
944
+ }
945
+ }
946
+
947
+ $expire_on = apply_filters( 'wphb_file_expiration', 3600 * 24 * 7 ) + time() + rand( 3600, 43200 ); // 1 week + random time between 1h-12h;
948
+ $vars = get_object_vars( $group );
949
+
950
+ // Do not save this metadata
951
+ $exclude_vars = array( 'group_id' );
952
+
953
+ foreach ( $vars as $var => $value ) {
954
+ if ( in_array( $var, $exclude_vars ) ) {
955
+ continue;
956
+ }
957
+ update_post_meta( $group->file_id, '_' . $var, $value );
958
+ }
959
+
960
+ if ( 'content' === $file['type'] ) {
961
+ // Upload contents to filesystem
962
+ // Any user can upload this as is made during front request
963
+ add_filter( 'upload_mimes', array( 'WP_Hummingbird_Module_Minify_Group', '_upload_mimes' ) , 999 );
964
+ $filename = $group->hash . '.' . ( 'scripts' === $group->type ? 'js' : 'css' );
965
+ do_action( 'wp_hummingbird_before_upload_minify_group', $filename, $file['response'] );
966
+ $upload = wp_upload_bits( $filename, null, $file['response'] );
967
+ do_action( 'wp_hummingbird_after_upload_minify_group', $filename, $file['response'], $upload );
968
+ remove_filter( 'upload_mimes', array( 'WP_Hummingbird_Module_Minify_Group', '_upload_mimes' ) , 999 );
969
+
970
+ if ( is_wp_error( $upload ) ) {
971
+ // Save error and delete post
972
+ wp_delete_post( $post_id, true );
973
+ wp_cache_delete( 'wphb_minify_groups' );
974
+ return false;
975
+ }
976
+
977
+ update_post_meta( $group->file_id, '_url', $upload['url'] );
978
+ update_post_meta( $group->file_id, '_path', $upload['file'] );
979
+ }
980
+ else {
981
+ // Just save URL
982
+ update_post_meta( $group->file_id, '_url', $file['response'] );
983
+ }
984
+
985
+ update_post_meta( $group->file_id, '_expires', $expire_on );
986
+
987
+ return true;
988
+ }
989
+
990
+ return false;
991
+ }
992
+
993
+ /**
994
+ * @internal
995
+ */
996
+ public static function _upload_mimes() {
997
+ return array( 'js' => 'application/javascript', 'css' => 'text/css' );
998
+ }
999
+
1000
+ /**
1001
+ * @param $files
1002
+ * @param $upload_to_cdn
1003
+ *
1004
+ * @return array|mixed|object|WP_Error
1005
+ */
1006
+ public function process_remote_files( $files, $upload_to_cdn = true ) {
1007
+ $f = new stdClass();
1008
+ $f->contents = array();
1009
+ $f->hash = $this->hash;
1010
+ $f->type = $this->type;
1011
+ $f->expires = $this->expires_on();
1012
+ $f->cdn = $upload_to_cdn;
1013
+ foreach ( $files as $file ) {
1014
+ $c = new stdClass();
1015
+ $c->handle = $file['handle'];
1016
+ $c->content = $file['content'];
1017
+ $c->minify = $file['minify'];
1018
+ $f->contents[] = $c;
1019
+ }
1020
+
1021
+ $upload = wphb_get_api()->minify->process_files( array( $f ) );
1022
+
1023
+ if ( is_wp_error( $upload ) ) {
1024
+ return $upload;
1025
+ }
1026
+
1027
+ return $upload->files[0];
1028
+ }
1029
+
1030
+ /**
1031
+ * Delete the minified/combine file for this group
1032
+ */
1033
+ public function delete_file() {
1034
+ if ( get_post( $this->file_id ) && 'wphb_minify_group' === get_post_type( $this->file_id ) ) {
1035
+ if ( $this->get_file_path() ) {
1036
+ wp_delete_file( $this->get_file_path() );
1037
+ }
1038
+ wp_delete_post( $this->file_id, true );
1039
+ $this->file_id = 0;
1040
+ wp_cache_delete( 'wphb_minify_groups' );
1041
+ }
1042
+ }
1043
+
1044
+ /**
1045
+ * Try to find the file attached to this group and loads it into the object
1046
+ *
1047
+ * @return bool
1048
+ */
1049
+ public function maybe_load_file() {
1050
+ if ( ! $this->should_generate_file() ) {
1051
+ return false;
1052
+ }
1053
+
1054
+ $posts = self::get_minify_groups();
1055
+
1056
+ if ( empty( $posts ) ) {
1057
+ return false;
1058
+ }
1059
+
1060
+ foreach ( $posts as $post ) {
1061
+ if ( $post->post_title == $this->get_sources_hash() . '-' . $this->type ) {
1062
+ $this->file_id = $post->ID;
1063
+ return true;
1064
+ }
1065
+ }
1066
+ return false;
1067
+ }
1068
+
1069
+ public function should_process_group() {
1070
+ $handles = $this->get_handles();
1071
+ $handles_count = count( $handles );
1072
+ if ( $handles_count === 1 && ! $this->should_do_handle( $handles[0], 'minify' ) ) {
1073
+ return false;
1074
+ }
1075
+
1076
+ // Check if all handles should not be processed too
1077
+ if (
1078
+ $handles_count === count( $this->dont_minify )
1079
+ && $handles_count === count( $this->dont_combine )
1080
+ ) {
1081
+ return false;
1082
+ }
1083
+
1084
+ return true;
1085
+ }
1086
+
1087
+ public function get_group_src() {
1088
+ if ( ! $this->should_process_group() ) {
1089
+ $handles = $this->get_handles();
1090
+ return $this->get_handle_url( $handles[0] );
1091
+ }
1092
+ return get_post_meta( $this->file_id, '_url', true );
1093
+ }
1094
+
1095
+ public function get_file_path() {
1096
+ if ( ! $this->should_generate_file() ) {
1097
+ return false;
1098
+ }
1099
+ return get_post_meta( $this->file_id, '_path', true );
1100
+ }
1101
+
1102
+ public function expires_on() {
1103
+ if ( ! $this->should_generate_file() ) {
1104
+ return false;
1105
+ }
1106
+ return get_post_meta( $this->file_id, '_expires', true );
1107
+ }
1108
+
1109
+ public function get_file_version_hash() {
1110
+ if ( ! $this->should_generate_file() ) {
1111
+ return '';
1112
+ }
1113
+ $versions = get_post_meta( $this->file_id, '_handle_versions', true );
1114
+ if ( false === $versions ) {
1115
+ return '';
1116
+ }
1117
+ return self::hash( $versions );
1118
+ }
1119
+
1120
+ /**
1121
+ * Enqueue the new group (only one file)
1122
+ *
1123
+ * @param string $new_handle new dependency slug
1124
+ * @param bool $in_footer if must be enqueued on footer
1125
+ */
1126
+ public function enqueue( $in_footer, $dependencies ) {
1127
+ // Enqueue the group
1128
+ if ( 'scripts' == $this->type ) {
1129
+ $wp_sources = wp_scripts();
1130
+
1131
+ wp_dequeue_script( $this->group_id );
1132
+ wp_deregister_script( $this->group_id );
1133
+ wp_enqueue_script(
1134
+ $this->group_id,
1135
+ set_url_scheme( $this->get_group_src() ),
1136
+ $dependencies,
1137
+ null,
1138
+ $in_footer
1139
+ );
1140
+
1141
+ // Add extras to the dependency
1142
+ foreach ( $this->get_extra() as $extra_key => $extra_value ) {
1143
+ if ( 'data' === $extra_key ) {
1144
+ continue;
1145
+ }
1146
+ $wp_sources->add_data( $this->group_id, $extra_key, $extra_value );
1147
+ }
1148
+
1149
+ if ( $this->get_data() ) {
1150
+ $data = implode( ';;', $this->get_data() );
1151
+ $wp_sources->add_data( $this->group_id, 'data', $data );
1152
+ }
1153
+
1154
+ // Make sure that single handles from this group are not enqueued
1155
+ foreach ( $this->get_handles() as $handle ) {
1156
+ // The single handle
1157
+ wp_dequeue_script( $handle );
1158
+
1159
+ // But it could have been enqueued with a different ID by this group before
1160
+ // This would mostly happen during Unit Testing
1161
+ wp_dequeue_script( $this->group_id . '-' . $handle );
1162
+ }
1163
+
1164
+ $group_id = $this->group_id;
1165
+ $handles = $this->get_handles();
1166
+ // Make sure that this element is makred as done once WordPress has enqueued it
1167
+ add_action( 'wp_head', function() use ( $handles, $group_id ) {
1168
+ $wp_scripts = wp_scripts();
1169
+ if ( in_array( $group_id, $wp_scripts->done ) ) {
1170
+ // If the new ID is done it means that the handle is done too
1171
+ $wp_scripts->done = array_merge( $wp_scripts->done, $handles );
1172
+ }
1173
+ }, 999 );
1174
+
1175
+ add_action( 'wp_footer', function() use ( $handles, $group_id ) {
1176
+ $wp_scripts = wp_scripts();
1177
+ if ( in_array( $group_id, $wp_scripts->done ) ) {
1178
+ // If the new ID is done it means that the handle is done too
1179
+ $wp_scripts->done = array_merge( $wp_scripts->done, $handles );
1180
+ }
1181
+ }, 999 );
1182
+
1183
+ $wp_sources->groups[$this->group_id] = $in_footer ? 1 : 0;
1184
+ }
1185
+ elseif ( 'styles' == $this->type ) {
1186
+ $wp_sources = wp_styles();
1187
+
1188
+ wp_dequeue_style( $this->group_id );
1189
+ wp_deregister_style( $this->group_id );
1190
+ wp_enqueue_style(
1191
+ $this->group_id,
1192
+ set_url_scheme( $this->get_group_src() ),
1193
+ $dependencies,
1194
+ null,
1195
+ $this->get_args()
1196
+ );
1197
+
1198
+
1199
+ // Add extras to the dependency
1200
+ foreach ( $this->get_extra() as $extra_key => $extra_value ) {
1201
+ $wp_sources->add_data( $this->group_id, $extra_key, $extra_value );
1202
+ }
1203
+
1204
+ // Make sure that single handles from this group are not enqueued
1205
+ foreach ( $this->get_handles() as $handle ) {
1206
+ // $this->simulate_dequeue_asset( $handle );
1207
+
1208
+ // It could have been enqueued with a different ID by this group before
1209
+ // This would mostly happen during Unit Testing, we can remove it safely
1210
+ wp_dequeue_style( $this->group_id . '-' . $handle );
1211
+ }
1212
+
1213
+ $group_id = $this->group_id;
1214
+ $handles = $this->get_handles();
1215
+ // Make sure that this element is makred as done once WordPress has enqueued it
1216
+ add_action( 'wp_head', function() use ( $handles, $group_id ) {
1217
+ $wp_styles = wp_styles();
1218
+ if ( in_array( $group_id, $wp_styles->done ) ) {
1219
+ // If the new ID is done it means that the handle is done too
1220
+ $wp_styles->done = array_merge( $wp_styles->done, $handles );
1221
+ }
1222
+ }, 999 );
1223
+
1224
+ add_action( 'wp_footer', function() use ( $handles, $group_id ) {
1225
+ $wp_styles = wp_styles();
1226
+ if ( in_array( $group_id, $wp_styles->done ) ) {
1227
+ // If the new ID is done it means that the handle is done too
1228
+ $wp_styles->done = array_merge( $wp_styles->done, $handles );
1229
+ }
1230
+ }, 999 );
1231
+ }
1232
+ }
1233
+
1234
+ /**
1235
+ * Enqueue just one handle with its original URL
1236
+ * but will change the slug
1237
+ */
1238
+ public function enqueue_one_handle( $handle, $in_footer, $dependencies = array() ) {
1239
+ if ( count( $this->get_handles() ) === 1 ) {
1240
+ $new_id = $this->group_id;
1241
+ }
1242
+ else {
1243
+ $new_id = $this->group_id . '-' . $handle;
1244
+ }
1245
+
1246
+ if ( 'scripts' == $this->type ) {
1247
+ $wp_sources = wp_scripts();
1248
+
1249
+ // Just in case, we'll dequeue all possibilities
1250
+ foreach ( $this->get_handles() as $_handle ) {
1251
+ //$this->simulate_dequeue_asset( $_handle );
1252
+ }
1253
+
1254
+ wp_enqueue_script(
1255
+ $new_id,
1256
+ set_url_scheme( $this->get_handle_url( $handle ) ),
1257
+ $dependencies,
1258
+ null,
1259
+ $in_footer
1260
+ );
1261
+
1262
+ // A hack to avoid tons of warnings the first time we calculate things
1263
+ wp_scripts()->groups[ $new_id ] = $in_footer ? 1 : 0;
1264
+
1265
+ // Add extras to the dependency
1266
+ foreach ( $this->get_extra() as $extra_key => $extra_value ) {
1267
+ if ( 'data' === $extra_key ) {
1268
+ continue;
1269
+ }
1270
+ $wp_sources->add_data( $new_id, $extra_key, $extra_value );
1271
+ }
1272
+
1273
+ if ( $this->get_data() ) {
1274
+ $data = implode( ';;', $this->get_data() );
1275
+ $wp_sources->add_data( $new_id, 'data', $data );
1276
+ }
1277
+
1278
+ // Make sure that this element is makred as done once WordPress has enqueued it
1279
+ add_action( 'wp_head', function() use ( $handle, $new_id ) {
1280
+ $wp_styles = wp_scripts();
1281
+ if ( in_array( $new_id, $wp_styles->done ) ) {
1282
+ // If the new ID is done it means that the handle is done too
1283
+ $wp_styles->done[] = $handle;
1284
+ }
1285
+ }, 999 );
1286
+
1287
+ add_action( 'wp_footer', function() use ( $handle, $new_id ) {
1288
+ $wp_styles = wp_scripts();
1289
+ if ( in_array( $new_id, $wp_styles->done ) ) {
1290
+ // If the new ID is done it means that the handle is done too
1291
+ $wp_styles->done[] = $handle;
1292
+ }
1293
+ }, 999 );
1294
+ }
1295
+ elseif ( 'styles' == $this->type ) {
1296
+ $wp_sources = wp_styles();
1297
+
1298
+ // Just in case, we'll dequeue all possibilities
1299
+ foreach ( $this->get_handles() as $_handle ) {
1300
+ // $this->simulate_dequeue_asset( $_handle );
1301
+ }
1302
+
1303
+ wp_enqueue_style(
1304
+ $new_id,
1305
+ set_url_scheme( $this->get_handle_url( $handle ) ),
1306
+ $dependencies,
1307
+ null,
1308
+ $this->get_args()
1309
+ );
1310
+
1311
+ // A hack to avoid tons of warnings the first time we calculate things
1312
+ wp_styles()->groups[ $new_id ] = $in_footer ? 1 : 0;
1313
+
1314
+ // Add extras to the dependency
1315
+ foreach ( $this->get_extra() as $extra_key => $extra_value ) {
1316
+ $wp_sources->add_data( $new_id, $extra_key, $extra_value );
1317
+ }
1318
+
1319
+ // Make sure that this element is makred as done once WordPress has enqueued it
1320
+ add_action( 'wp_head', function() use ( $handle, $new_id ) {
1321
+ $wp_styles = wp_styles();
1322
+ if ( in_array( $new_id, $wp_styles->done ) ) {
1323
+ // If the new ID is done it means that the handle is done too
1324
+ $wp_styles->done[] = $handle;
1325
+ }
1326
+ }, 999 );
1327
+
1328
+ add_action( 'wp_footer', function() use ( $handle, $new_id ) {
1329
+ $wp_styles = wp_styles();
1330
+ if ( in_array( $new_id, $wp_styles->done ) ) {
1331
+ // If the new ID is done it means that the handle is done too
1332
+ $wp_styles->done[] = $handle;
1333
+ }
1334
+ }, 999 );
1335
+ }
1336
+
1337
+ return $new_id;
1338
+ }
1339
+
1340
+ /**
1341
+ * If we would have dequeued the style, wp_style_is() would stop working
1342
+ * so instead of that we'll keep the current queue but we'll remove all attributes for
1343
+ * the registered style
1344
+ *
1345
+ * @param string $handle
1346
+ */
1347
+ private function simulate_dequeue_asset( $handle ) {
1348
+ $wp_sources = 'styles' === $this->type ? wp_styles() : wp_scripts();
1349
+ if ( isset( $wp_sources->registered[ $handle ] ) ) {
1350
+ $wp_sources->registered[ $handle ]->src = false;
1351
+ $wp_sources->registered[ $handle ]->deps = array();
1352
+ $wp_sources->registered[ $handle ]->extra = array();
1353
+ }
1354
+ }
1355
+
1356
+ /**
1357
+ * Replace relative URIs in stylesheets for their absolute URIs
1358
+ *
1359
+ * @param $file_url
1360
+ * @param $css_content
1361
+ *
1362
+ * @return string
1363
+ */
1364
+ public static function replace_relative_urls( $file_url, $css_content ) {
1365
+ include_once( 'class-uri-rewriter.php' );
1366
+ return WP_Hummingbird_CSS_UriRewriter::rewrite( $css_content, $file_url );
1367
+ }
1368
+
1369
+ /**
1370
+ * Check if a handle is a local or external resource
1371
+ *
1372
+ * @param $handle
1373
+ *
1374
+ * @return bool True if the handle is a local one
1375
+ */
1376
+ private function is_handle_local( $handle ) {
1377
+ $src = $this->get_handle_url( $handle );
1378
+
1379
+ if ( ! $src ) {
1380
+ return false;
1381
+ }
1382
+ // Check if the URL is an external one
1383
+ $home_url = home_url();
1384
+
1385
+ // Add scheme to src if it does not exist
1386
+ if ( 0 === strpos( $src, '//' ) ) {
1387
+ $src = 'http:' . $src;
1388
+ }
1389
+
1390
+ $parsed_site_url = parse_url( $home_url );
1391
+ $parsed_src = parse_url( $src );
1392
+
1393
+ if ( ! $parsed_src ) {
1394
+ // Probably not local but who knows
1395
+ return false;
1396
+ }
1397
+
1398
+ // '/wp-includes/js' are locals
1399
+ if ( empty( $parsed_src['host'] ) && strpos( $parsed_src['path'], '/' ) === 0 ) {
1400
+ return true;
1401
+ }
1402
+
1403
+ // Hosts match
1404
+ if ( ! empty( $parsed_src['host'] ) && $parsed_src['host'] === $parsed_site_url['host'] ) {
1405
+ return true;
1406
+ }
1407
+
1408
+ // Not local
1409
+ return false;
1410
+
1411
+ }
1412
+ }
core/modules/minify/class-minify-groups-list.php ADDED
@@ -0,0 +1,330 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @author: WPMUDEV, Ignacio Cruz (igmoweb)
4
+ * @version:
5
+ */
6
+
7
+ if ( ! defined( 'ABSPATH' ) ) {
8
+ exit;
9
+ }
10
+
11
+ class WP_Hummingbird_Module_Minify_Groups_List {
12
+
13
+ /**
14
+ * @var array List of WP_Hummingbird_Module_Minifynew_Group objects
15
+ */
16
+ private $groups = array();
17
+
18
+ /**
19
+ * @var string styles|scripts
20
+ */
21
+ private $type = '';
22
+
23
+ private $groups_dependencies = false;
24
+
25
+ /**
26
+ * Save the status for every group
27
+ *
28
+ * A group can has status as:
29
+ * - 'process' = The group should process its file
30
+ * - 'ready' = The group has already a processed file and must be enqueued
31
+ * - 'only-handles' = The group file won't be processed and its files will be enqueued by separate
32
+ * @var array
33
+ */
34
+ private $group_statuses = array();
35
+
36
+ public function __construct( $type ) {
37
+ $this->type = $type;
38
+ }
39
+
40
+ /**
41
+ * Return the type of the sources that this list manages
42
+ *
43
+ * @return string styles|scripts
44
+ */
45
+ public function get_type() {
46
+ return $this->type;
47
+ }
48
+
49
+ public function get_groups() {
50
+ return $this->groups;
51
+ }
52
+
53
+ /**
54
+ * Return a group from the list
55
+ *
56
+ * @param int|string $key_or_hash
57
+ *
58
+ * @return bool|mixed
59
+ */
60
+ public function get_group( $key_or_hash ) {
61
+ $position = $this->get_group_position( $key_or_hash );
62
+
63
+ if ( false !== $position ) {
64
+ return $this->groups[ $position ];
65
+ }
66
+ return false;
67
+ }
68
+
69
+ /**
70
+ * Add a new group to the list
71
+ *
72
+ * @param WP_Hummingbird_Module_Minify_Group $group
73
+ *
74
+ * @return bool
75
+ */
76
+ public function add_group( $group ) {
77
+ if ( ! is_a( $group, 'WP_Hummingbird_Module_Minify_Group' ) ) {
78
+ return false;
79
+ }
80
+
81
+ $group->set_type( $this->type );
82
+ $this->groups[] = $group;
83
+ return true;
84
+ }
85
+
86
+ /**
87
+ * Remove a group from the list
88
+ *
89
+ * @param string|int $key_or_hash
90
+ *
91
+ * @return bool
92
+ */
93
+ public function remove_group( $key_or_hash ) {
94
+ $position = $this->get_group_position( $key_or_hash );
95
+ if ( false !== $position ) {
96
+ unset( $this->groups[ $position ] );
97
+ $this->groups = array_values( $this->groups );
98
+ return true;
99
+ }
100
+
101
+ return false;
102
+ }
103
+
104
+ /**
105
+ * Return a list of group hashes that are dependant of another group hash
106
+ *
107
+ * This function will search among all groups and compare if any handles of it
108
+ * has dependencies with any other group on the list. After taht, it will return
109
+ * all those group hashes
110
+ *
111
+ * IMPORTANT NOTE: All group IDs ($group->group_id) should be already set
112
+ * if you want this function to work properly. Otherwise it will return WP_Error
113
+ * and self::preprocess_groups() should has been called
114
+ *
115
+ * @param $key_or_hash
116
+ *
117
+ * @return array|WP_Error
118
+ */
119
+ public function get_group_dependencies( $key_or_hash ) {
120
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
121
+ $group = $this->get_group( $key_or_hash );
122
+ if ( ! $group ) {
123
+ return array();
124
+ }
125
+ $this->parse_groups_dependencies();
126
+ return $this->groups_dependencies[ $group->hash ];
127
+ }
128
+
129
+ /**
130
+ * @param $group_id
131
+ *
132
+ * @return bool|WP_Hummingbird_Module_Minify_Group
133
+ */
134
+ public function get_group_by_group_id( $group_id ) {
135
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
136
+ $groups = $this->get_groups();
137
+ $result = wp_list_filter( $groups, array( 'group_id' => $group_id ) );
138
+ if ( $result ) {
139
+ return $result[ key( $result ) ];
140
+ }
141
+ return false;
142
+ }
143
+
144
+ /**
145
+ * Split a group
146
+ *
147
+ * $new_handles_order is a multidimensional array that
148
+ * will tell the function how the new splitted groups must be
149
+ *
150
+ * for instance:
151
+ * Let's say that the group has the following handles:
152
+ * handle-1,
153
+ * handle-2,
154
+ * handle-3
155
+ *
156
+ * and $new_handles_order is:
157
+ * array(
158
+ * array(
159
+ * 'handle-1',
160
+ * 'handle-2'
161
+ * ),
162
+ * array(
163
+ * 'handle-3'
164
+ * )
165
+ * )
166
+ *
167
+ * This will delete hte original group and create two new groups with those handles
168
+ *
169
+ * The function will keep the groups order instead of adding them at the end of the list
170
+ *
171
+ * @param $new_handles_order
172
+ *
173
+ * @return bool
174
+ */
175
+ public function split_group( $key_or_hash, $new_handles_order ) {
176
+ $position = $this->get_group_position( $key_or_hash );
177
+ if ( false === $position ) {
178
+ return false;
179
+ }
180
+
181
+ if ( empty( $new_handles_order ) || ! is_array( $new_handles_order ) ) {
182
+ return false;
183
+ }
184
+
185
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
186
+ $group = $this->groups[ $position ];
187
+ $new_groups = array();
188
+ foreach ( $new_handles_order as $handles_order ) {
189
+ $new_groups[] = $group->slice_handles( $handles_order );
190
+ }
191
+
192
+ if ( ! empty( $new_groups ) ) {
193
+ $sliced_left = array_slice( $this->groups, 0, $position );
194
+ $sliced_right = array_slice( $this->groups, $position );
195
+ $first_key_on_right_slice = key( $sliced_right );
196
+
197
+ $sliced_left = array_merge( $sliced_left, $new_groups );
198
+
199
+ // Remove the group from the right, we don't need it anymore
200
+ unset( $sliced_right[ $first_key_on_right_slice ] );
201
+
202
+ // And merge the right side on the left too
203
+ // and we're done!
204
+ $this->groups = array_merge( $sliced_left, $sliced_right );
205
+
206
+ return true;
207
+ }
208
+
209
+ return false;
210
+ }
211
+
212
+ /**
213
+ * Return a group position based on its key (that's actually its position)
214
+ * or hash
215
+ *
216
+ * @param string|int $key_or_hash
217
+ *
218
+ * @return bool|mixed
219
+ */
220
+ public function get_group_position( $key_or_hash ) {
221
+ if ( isset( $this->groups[ $key_or_hash ] ) ) {
222
+ return $key_or_hash;
223
+ }
224
+
225
+ $group_hashes = wp_list_pluck( $this->groups, 'hash' );
226
+ $position = array_search( $key_or_hash, $group_hashes );
227
+
228
+ if ( false !== $position ) {
229
+ return $position;
230
+ }
231
+
232
+ return false;
233
+ }
234
+
235
+ public function get_group_status( $hash ) {
236
+ if ( ! isset( $this->group_statuses[ $hash ] ) ) {
237
+ return false;
238
+ }
239
+
240
+ return $this->group_statuses[ $hash ];
241
+ }
242
+
243
+ public function set_group_status( $hash, $status ) {
244
+ $this->group_statuses[ $hash ] = $status;
245
+ }
246
+
247
+ /**
248
+ * Mark the groups to be processed or not
249
+ *
250
+ */
251
+ public function preprocess_groups() {
252
+ $self = $this;
253
+ array_map( function( $group ) use ( &$self ) {
254
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
255
+ $group->maybe_load_file();
256
+ $group_src = $group->get_group_src();
257
+
258
+ if ( $group->should_process_group() && $group->file_id && $group_src && ! $group->is_expired() ) {
259
+ // The group has its file and is not expired
260
+ $self->set_group_status( $group->hash, 'ready' );
261
+ }
262
+ elseif ( ( $group->should_process_group() && ( empty( $group_src ) ) || $group->is_expired() ) ) {
263
+ // The group must be processed but it has no file yet
264
+ $self->set_group_status( $group->hash, 'process' );
265
+
266
+ // Delete file in case there's one (but is expired)
267
+ $group->delete_file();
268
+ }
269
+ else {
270
+ // The group won't be processed
271
+ // Use the original handles and their URLs instead
272
+ $self->set_group_status( $group->hash, 'only-handles' );
273
+ }
274
+ }, $this->get_groups() );
275
+
276
+ $this->parse_groups_dependencies();
277
+ }
278
+
279
+ public function parse_groups_dependencies() {
280
+ if ( false !== $this->groups_dependencies ) {
281
+ return $this->groups_dependencies;
282
+ }
283
+
284
+ $deps = array();
285
+ $self = $this;
286
+ // Now that every is marked, let's parse dependencies
287
+ // This cannot be undone, so do not change groups after this
288
+ array_map( function( $group ) use ( &$deps, $self ) {
289
+ /** @var WP_Hummingbird_Module_Minify_Group $group */
290
+ $search_group_deps = $group->get_all_handles_dependencies();
291
+ $search_group_hash = $group->hash;
292
+ $deps[ $search_group_hash ] = array();
293
+
294
+ foreach ( $self->get_groups() as $position => $g ) {
295
+ /** @var WP_Hummingbird_Module_Minify_Group $g */
296
+ $g_status = $self->get_group_status( $g->hash );
297
+ $g_hash = $g->hash;
298
+
299
+ if ( $g_hash === $search_group_hash ) {
300
+ // Don't search deps in the same group
301
+ continue;
302
+ }
303
+
304
+ $g_handles = $g->get_handles();
305
+ $intersect = array_intersect( $g_handles, $search_group_deps );
306
+ if ( ! empty( $intersect ) ) {
307
+ // We've found dependencies
308
+ if ( 'ready' != $g_status ) {
309
+ // The group is not ready, dependencies are one or more of its handles
310
+ $deps[ $search_group_hash ] = array_merge(
311
+ $deps[ $search_group_hash ],
312
+ array_map( function( $handle ) use ( $g ) {
313
+ return $g->group_id . '-' . $handle;
314
+ }, $intersect )
315
+ );
316
+
317
+ }
318
+ else {
319
+ $deps[ $search_group_hash ] = array_merge( $deps[ $search_group_hash ], array( $g->group_id ) );
320
+ }
321
+
322
+ }
323
+ }
324
+
325
+ }, $this->get_groups() );
326
+
327
+ $this->groups_dependencies = $deps;
328
+ return $deps;
329
+ }
330
+ }
core/modules/minify/class-minify-housekeeper.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ if ( ! defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
+
8
+ /**
9
+ * Class WP_Hummingbird_Module_Minify_Housekeeper
10
+ *
11
+ * Housekeeping duties to clean old minification files
12
+ */
13
+ class WP_Hummingbird_Module_Minify_Housekeeper {
14
+
15
+ function init() {
16
+ if ( ! wp_next_scheduled ( 'wphb_minify_clear_files' ) ) {
17
+ wp_schedule_event( time(), 'daily', 'wphb_minify_clear_files' );
18
+ }
19
+
20
+ add_action( 'wphb_minify_clear_files', array( $this, 'clear_expired_groups' ) );
21
+ }
22
+
23
+ /**
24
+ * Clear all minified and expired groups
25
+ *
26
+ * Sometimes minification module will not clear them by itself because they
27
+ * blong to a plugin or theme that is deactivated so minification won't get them anymore.
28
+ * This cron job will clear the expired files once a day
29
+ */
30
+ public static function clear_expired_groups() {
31
+ $groups = WP_Hummingbird_Module_Minify_Group::get_minify_groups();
32
+ foreach ( $groups as $group ) {
33
+ $instance = WP_Hummingbird_Module_Minify_Group::get_instance_by_post_id( $group->ID );
34
+ if ( is_a( $instance, 'WP_Hummingbird_Module_Minify_Group' ) && $instance->is_expired() && $instance->file_id ) {
35
+ $instance->delete_file();
36
+ wp_delete_post( $instance->file_id, true );
37
+ }
38
+ }
39
+ }
40
+
41
+ }
core/modules/minify/class-minify-sources-collector.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class WP_Hummingbird_Sources_Collector
5
+ *
6
+ * Manages the collection of all sources that WP HUmmingbird is going to compress
7
+ */
8
+ class WP_Hummingbird_Sources_Collector {
9
+
10
+ private static $styles_option = 'wphb_styles_collection';
11
+ private static $scripts_option = 'wphb_scripts_collection';
12
+
13
+ private $collection_updated = false;
14
+
15
+ private $collected = array(
16
+ 'styles' => array(),
17
+ 'scripts' => array()
18
+ );
19
+
20
+
21
+ public function __construct() {
22
+ $this->collected = self::get_collection();
23
+ }
24
+
25
+ public function save_collection() {
26
+ if ( $this->collection_updated ) {
27
+ update_option( self::$styles_option, $this->collected['styles'] );
28
+ update_option( self::$scripts_option, $this->collected['scripts'] );
29
+ }
30
+
31
+ }
32
+
33
+ public function add_to_collection( $registered, $type ) {
34
+ $registered = (array)$registered;
35
+
36
+ if ( isset( $this->collected[ $type ][ $registered['handle'] ] ) && $registered === $this->collected[ $type ][ $registered['handle'] ] )
37
+ return;
38
+
39
+ $this->collection_updated = true;
40
+ $this->collected[ $type ][ $registered['handle'] ] = $registered;
41
+ }
42
+
43
+
44
+ public static function get_collection() {
45
+ return array(
46
+ 'styles' => get_option( self::$styles_option, array() ),
47
+ 'scripts' => get_option( self::$scripts_option, array() )
48
+ );
49
+ }
50
+
51
+ public static function clear_collection() {
52
+ delete_option( self::$styles_option );
53
+ delete_option( self::$scripts_option );
54
+ }
55
+
56
+ public static function clear_handle_from_collection( $handle, $type ) {
57
+ $collection = self::get_collection();
58
+ if ( ! isset( $collection[ $type ][ $handle ] ) ) {
59
+ return;
60
+ }
61
+
62
+ unset( $collection[ $type ][ $handle ] );
63
+
64
+ update_option( self::$styles_option, $collection['styles'] );
65
+ update_option( self::$scripts_option, $collection['scripts'] );
66
+ }
67
+
68
+ /**
69
+ * @TODO Finish
70
+ * @param $plugin
71
+ */
72
+ public static function remove_sources_from_plugin( $plugin ) {
73
+ $collection = self::get_collection();
74
+ $plugin_dir = '/plugins/' . dirname( $plugin );
75
+ foreach ( $collection['styles'] as $style ) {
76
+
77
+ }
78
+ }
79
+
80
+ }
core/modules/minify/class-uri-rewriter.php ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Rewrite file-relative URIs as root-relative in CSS files
5
+ *
6
+ * @package Minify
7
+ * @author Stephen Clay <steve@mrclay.org>
8
+ */
9
+ class WP_Hummingbird_CSS_UriRewriter {
10
+
11
+ /**
12
+ * rewrite() and rewriteRelative() append debugging information here
13
+ *
14
+ * @var string
15
+ */
16
+ public static $debugText = '';
17
+
18
+ /**
19
+ * In CSS content, rewrite file relative URIs as root relative
20
+ *
21
+ * @param string $css
22
+ *
23
+ * @param string $currentDir The directory of the current CSS file.
24
+ *
25
+ * @param string $docRoot The document root of the web site in which
26
+ * the CSS file resides (default = $_SERVER['DOCUMENT_ROOT']).
27
+ *
28
+ * @param array $symlinks (default = array()) If the CSS file is stored in
29
+ * a symlink-ed directory, provide an array of link paths to
30
+ * target paths, where the link paths are within the document root. Because
31
+ * paths need to be normalized for this to work, use "//" to substitute
32
+ * the doc root in the link paths (the array keys). E.g.:
33
+ * <code>
34
+ * array('//symlink' => '/real/target/path') // unix
35
+ * array('//static' => 'D:\\staticStorage') // Windows
36
+ * </code>
37
+ *
38
+ * @return string
39
+ */
40
+ public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array())
41
+ {
42
+ self::$_docRoot = self::_realpath(
43
+ $docRoot ? $docRoot : $_SERVER['DOCUMENT_ROOT']
44
+ );
45
+ self::$_currentDir = self::_realpath($currentDir);
46
+ self::$_symlinks = array();
47
+
48
+ // normalize symlinks
49
+ foreach ($symlinks as $link => $target) {
50
+ $link = ($link === '//')
51
+ ? self::$_docRoot
52
+ : str_replace('//', self::$_docRoot . '/', $link);
53
+ $link = strtr($link, '/', DIRECTORY_SEPARATOR);
54
+ self::$_symlinks[$link] = self::_realpath($target);
55
+ }
56
+
57
+ self::$debugText .= "docRoot : " . self::$_docRoot . "\n"
58
+ . "currentDir : " . self::$_currentDir . "\n";
59
+ if (self::$_symlinks) {
60
+ self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n";
61
+ }
62
+ self::$debugText .= "\n";
63
+
64
+ $css = self::_trimUrls($css);
65
+
66
+ // rewrite
67
+ $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
68
+ ,array(self::$className, '_processUriCB'), $css);
69
+ $css = preg_replace_callback('/url\s*\\(\\s*([^\\)\\s]+)\\s*\\)/'
70
+ ,array(self::$className, '_processUriCB'), $css);
71
+
72
+ return $css;
73
+ }
74
+
75
+ /**
76
+ * In CSS content, prepend a path to relative URIs
77
+ *
78
+ * @param string $css
79
+ *
80
+ * @param string $path The path to prepend.
81
+ *
82
+ * @return string
83
+ */
84
+ public static function prepend($css, $path)
85
+ {
86
+ self::$_prependPath = $path;
87
+
88
+ $css = self::_trimUrls($css);
89
+
90
+ // append
91
+ $css = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/'
92
+ ,array(self::$className, '_processUriCB'), $css);
93
+ $css = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
94
+ ,array(self::$className, '_processUriCB'), $css);
95
+
96
+ self::$_prependPath = null;
97
+ return $css;
98
+ }
99
+
100
+ /**
101
+ * Get a root relative URI from a file relative URI
102
+ *
103
+ * <code>
104
+ * Minify_CSS_UriRewriter::rewriteRelative(
105
+ * '../img/hello.gif'
106
+ * , '/home/user/www/css' // path of CSS file
107
+ * , '/home/user/www' // doc root
108
+ * );
109
+ * // returns '/img/hello.gif'
110
+ *
111
+ * // example where static files are stored in a symlinked directory
112
+ * Minify_CSS_UriRewriter::rewriteRelative(
113
+ * 'hello.gif'
114
+ * , '/var/staticFiles/theme'
115
+ * , '/home/user/www'
116
+ * , array('/home/user/www/static' => '/var/staticFiles')
117
+ * );
118
+ * // returns '/static/theme/hello.gif'
119
+ * </code>
120
+ *
121
+ * @param string $uri file relative URI
122
+ *
123
+ * @param string $realCurrentDir realpath of the current file's directory.
124
+ *
125
+ * @param string $realDocRoot realpath of the site document root.
126
+ *
127
+ * @param array $symlinks (default = array()) If the file is stored in
128
+ * a symlink-ed directory, provide an array of link paths to
129
+ * real target paths, where the link paths "appear" to be within the document
130
+ * root. E.g.:
131
+ * <code>
132
+ * array('/home/foo/www/not/real/path' => '/real/target/path') // unix
133
+ * array('C:\\htdocs\\not\\real' => 'D:\\real\\target\\path') // Windows
134
+ * </code>
135
+ *
136
+ * @return string
137
+ */
138
+ public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array())
139
+ {
140
+ // prepend path with current dir separator (OS-independent)
141
+ $path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR)
142
+ . DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);
143
+
144
+ self::$debugText .= "file-relative URI : {$uri}\n"
145
+ . "path prepended : {$path}\n";
146
+
147
+ // "unresolve" a symlink back to doc root
148
+ foreach ($symlinks as $link => $target) {
149
+ if (0 === strpos($path, $target)) {
150
+ // replace $target with $link
151
+ $path = $link . substr($path, strlen($target));
152
+
153
+ self::$debugText .= "symlink unresolved : {$path}\n";
154
+
155
+ break;
156
+ }
157
+ }
158
+ // strip doc root
159
+ $path = substr($path, strlen($realDocRoot));
160
+
161
+ self::$debugText .= "docroot stripped : {$path}\n";
162
+
163
+ // fix to root-relative URI
164
+ $uri = strtr($path, '/\\', '//');
165
+ $uri = self::removeDots($uri);
166
+
167
+ self::$debugText .= "traversals removed : {$uri}\n\n";
168
+
169
+ return $uri;
170
+ }
171
+
172
+ /**
173
+ * Remove instances of "./" and "../" where possible from a root-relative URI
174
+ *
175
+ * @param string $uri
176
+ *
177
+ * @return string
178
+ */
179
+ public static function removeDots($uri)
180
+ {
181
+ $uri = str_replace('/./', '/', $uri);
182
+ // inspired by patch from Oleg Cherniy
183
+ do {
184
+ $uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, 1, $changed);
185
+ } while ($changed);
186
+ return $uri;
187
+ }
188
+
189
+ /**
190
+ * Defines which class to call as part of callbacks, change this
191
+ * if you extend Minify_CSS_UriRewriter
192
+ *
193
+ * @var string
194
+ */
195
+ protected static $className = 'WP_Hummingbird_CSS_UriRewriter';
196
+
197
+ /**
198
+ * Get realpath with any trailing slash removed. If realpath() fails,
199
+ * just remove the trailing slash.
200
+ *
201
+ * @param string $path
202
+ *
203
+ * @return mixed path with no trailing slash
204
+ */
205
+ protected static function _realpath($path)
206
+ {
207
+ $realPath = realpath($path);
208
+ if ($realPath !== false) {
209
+ $path = $realPath;
210
+ }
211
+ return rtrim($path, '/\\');
212
+ }
213
+
214
+ /**
215
+ * Directory of this stylesheet
216
+ *
217
+ * @var string
218
+ */
219
+ private static $_currentDir = '';
220
+
221
+ /**
222
+ * DOC_ROOT
223
+ *
224
+ * @var string
225
+ */
226
+ private static $_docRoot = '';
227
+
228
+ /**
229
+ * directory replacements to map symlink targets back to their
230
+ * source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
231
+ *
232
+ * @var array
233
+ */
234
+ private static $_symlinks = array();
235
+
236
+ /**
237
+ * Path to prepend
238
+ *
239
+ * @var string
240
+ */
241
+ private static $_prependPath = null;
242
+
243
+ /**
244
+ * @param string $css
245
+ *
246
+ * @return string
247
+ */
248
+ private static function _trimUrls($css)
249
+ {
250
+ return preg_replace('/
251
+ url\\( # url(
252
+ \\s*
253
+ ([^\\)]+?) # 1 = URI (assuming does not contain ")")
254
+ \\s*
255
+ \\) # )
256
+ /x', 'url($1)', $css);
257
+ }
258
+
259
+ /**
260
+ * @param array $m
261
+ *
262
+ * @return string
263
+ */
264
+ private static function _processUriCB($m)
265
+ {
266
+ // $m matched either '/@import\\s+([\'"])(.*?)[\'"]/' or '/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
267
+ $isImport = ($m[0][0] === '@');
268
+ // determine URI and the quote character (if any)
269
+ if ($isImport) {
270
+ $quoteChar = $m[1];
271
+ $uri = $m[2];
272
+ } else {
273
+ // $m[1] is either quoted or not
274
+ $quoteChar = ($m[1][0] === "'" || $m[1][0] === '"')
275
+ ? $m[1][0]
276
+ : '';
277
+ $uri = ($quoteChar === '')
278
+ ? $m[1]
279
+ : substr($m[1], 1, strlen($m[1]) - 2);
280
+ }
281
+ // analyze URI
282
+ if ('/' !== $uri[0] // root-relative
283
+ && false === strpos($uri, '//') // protocol (non-data)
284
+ && 0 !== strpos($uri, 'data:') // data protocol
285
+ ) {
286
+ // URI is file-relative: rewrite depending on options
287
+ if (self::$_prependPath === null) {
288
+ $uri = self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);
289
+ } else {
290
+ $uri = self::$_prependPath . $uri;
291
+ if ($uri[0] === '/') {
292
+ $root = '';
293
+ $rootRelative = $uri;
294
+ $uri = $root . self::removeDots($rootRelative);
295
+ } elseif (preg_match('@^((https?\:)?//([^/]+))/@', $uri, $m) && (false !== strpos($m[3], '.'))) {
296
+ $root = $m[1];
297
+ $rootRelative = substr($uri, strlen($root));
298
+ $uri = $root . self::removeDots($rootRelative);
299
+ }
300
+ }
301
+ }
302
+ return $isImport
303
+ ? "@import {$quoteChar}{$uri}{$quoteChar}"
304
+ : "url({$quoteChar}{$uri}{$quoteChar})";
305
+ }
306
+ }
core/settings-hooks.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ add_filter( 'wphb_block_resource', 'wphb_filter_resource_block', 10, 5 );
4
+ function wphb_filter_resource_block( $value, $handle, $type ) {
5
+ $options = wphb_get_settings();
6
+ $blocked = $options['block'][ $type ];
7
+ if ( in_array( $handle, $blocked ) ) {
8
+ return true;
9
+ }
10
+
11
+
12
+ return $value;
13
+ }
14
+
15
+ add_filter( 'wphb_minify_resource', 'wphb_filter_resource_minify', 10, 3 );
16
+ function wphb_filter_resource_minify( $value, $handle, $type ) {
17
+ $options = wphb_get_settings();
18
+ $dont_minify = $options['dont_minify'][ $type ];
19
+ if ( in_array( $handle, $dont_minify ) ) {
20
+ return false;
21
+ }
22
+
23
+ return $value;
24
+ }
25
+
26
+ add_filter( 'wphb_combine_resource', 'wphb_filter_resource_combine', 10, 3 );
27
+ function wphb_filter_resource_combine( $value, $handle, $type ) {
28
+ $options = wphb_get_settings();
29
+ $combine = $options['combine'][ $type ];
30
+ if ( ! in_array( $handle, $combine ) ) {
31
+ return $value;
32
+ }
33
+
34
+ return true;
35
+ }
36
+
37
+ add_filter( 'wphb_send_resource_to_footer', 'wphb_filter_resource_to_footer', 10, 3 );
38
+ function wphb_filter_resource_to_footer( $value, $handle, $type ) {
39
+ $options = wphb_get_settings();
40
+ $to_footer = $options['position'][ $type ];
41
+
42
+ if ( array_key_exists( $handle, $to_footer ) && $to_footer[ $handle ] === 'footer' )
43
+ return true;
44
+
45
+ return $value;
46
+ }
47
+
48
+ add_filter( 'wp_hummingbird_is_active_module_caching', 'wphb_caching_module_status' );
49
+ function wphb_caching_module_status( $current ) {
50
+ $options = wphb_get_settings();
51
+ if ( ! $options['caching'] )
52
+ return false;
53
+
54
+ return $current;
55
+ }
56
+
57
+ add_filter( 'wp_hummingbird_is_active_module_uptime', 'wphb_uptime_module_status' );
58
+ function wphb_uptime_module_status( $current ) {
59
+ $options = wphb_get_settings();
60
+ if ( ! $options['uptime'] )
61
+ return false;
62
+
63
+ return $current;
64
+ }
65
+
66
+ add_filter( 'wp_hummingbird_is_active_module_minify', 'wphb_minify_module_status' );
67
+ function wphb_minify_module_status( $current ) {
68
+ $options = wphb_get_settings();
69
+
70
+ if ( false === $options['minify'] ) {
71
+ return false;
72
+ }
73
+
74
+ if ( is_multisite() ) {
75
+ $current = $options['minify-blog'];
76
+ }
77
+ else {
78
+ $current = $options['minify'];
79
+ }
80
+
81
+ return $current;
82
+ }
83
+
84
+ add_filter( 'wphb_get_server_type', 'wphb_set_user_server_type' );
85
+ function wphb_set_user_server_type( $type ) {
86
+ $user_type = get_user_meta( get_current_user_id(), 'wphb-server-type', true );
87
+ if ( $user_type ) {
88
+ $type = $user_type;
89
+ }
90
+ return $type;
91
+ }
externals/shared-ui/contributors.txt ADDED
@@ -0,0 +1 @@
 
1
+ Philipp Stracker
externals/shared-ui/font/WPMU DEV Dashboard.json ADDED
@@ -0,0 +1,1396 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "metadata": {
3
+ "name": "WPMU DEV Dashboard",
4
+ "lastOpened": 1446220177291,
5
+ "created": 1446220144047
6
+ },
7
+ "iconSets": [
8
+ {
9
+ "selection": [
10
+ {
11
+ "order": 77,
12
+ "id": 70,
13
+ "name": "comment",
14
+ "prevSize": 32,
15
+ "code": 65,
16
+ "tempChar": ""
17
+ },
18
+ {
19
+ "order": 45,
20
+ "id": 8,
21
+ "prevSize": 32,
22
+ "code": 109,
23
+ "name": "speach",
24
+ "tempChar": ""
25
+ },
26
+ {
27
+ "id": 21,
28
+ "order": 40,
29
+ "prevSize": 32,
30
+ "code": 61,
31
+ "name": "speach_alt",
32
+ "tempChar": ""
33
+ },
34
+ {
35
+ "order": 81,
36
+ "id": 68,
37
+ "name": "download",
38
+ "prevSize": 32,
39
+ "code": 66,
40
+ "tempChar": ""
41
+ },
42
+ {
43
+ "id": 32,
44
+ "order": 10,
45
+ "prevSize": 32,
46
+ "code": 105,
47
+ "name": "download_alt",
48
+ "tempChar": ""
49
+ },
50
+ {
51
+ "order": 101,
52
+ "id": 50,
53
+ "name": "upload",
54
+ "prevSize": 32,
55
+ "code": 86,
56
+ "tempChar": ""
57
+ },
58
+ {
59
+ "order": 82,
60
+ "id": 67,
61
+ "name": "error",
62
+ "prevSize": 32,
63
+ "code": 69,
64
+ "tempChar": ""
65
+ },
66
+ {
67
+ "order": 90,
68
+ "id": 63,
69
+ "name": "archive",
70
+ "prevSize": 32,
71
+ "code": 79,
72
+ "tempChar": ""
73
+ },
74
+ {
75
+ "id": 19,
76
+ "order": 25,
77
+ "prevSize": 32,
78
+ "code": 57,
79
+ "name": "logo",
80
+ "tempChar": ""
81
+ },
82
+ {
83
+ "id": 20,
84
+ "order": 26,
85
+ "prevSize": 32,
86
+ "code": 48,
87
+ "name": "logo_alt",
88
+ "tempChar": ""
89
+ },
90
+ {
91
+ "order": 95,
92
+ "id": 48,
93
+ "name": "wordpress",
94
+ "prevSize": 32,
95
+ "code": 71,
96
+ "tempChar": ""
97
+ },
98
+ {
99
+ "order": 85,
100
+ "id": 66,
101
+ "name": "facebook",
102
+ "prevSize": 32,
103
+ "code": 70,
104
+ "tempChar": ""
105
+ },
106
+ {
107
+ "order": 88,
108
+ "id": 51,
109
+ "name": "twitter",
110
+ "prevSize": 32,
111
+ "code": 73,
112
+ "tempChar": ""
113
+ },
114
+ {
115
+ "order": 89,
116
+ "id": 64,
117
+ "name": "github",
118
+ "prevSize": 32,
119
+ "code": 74,
120
+ "tempChar": ""
121
+ },
122
+ {
123
+ "order": 83,
124
+ "id": 54,
125
+ "name": "stackoverflow",
126
+ "prevSize": 32,
127
+ "code": 75,
128
+ "tempChar": ""
129
+ },
130
+ {
131
+ "order": 94,
132
+ "id": 61,
133
+ "name": "linkedin",
134
+ "prevSize": 32,
135
+ "code": 76,
136
+ "tempChar": ""
137
+ },
138
+ {
139
+ "order": 97,
140
+ "id": 60,
141
+ "name": "medium",
142
+ "prevSize": 32,
143
+ "code": 77,
144
+ "tempChar": ""
145
+ },
146
+ {
147
+ "order": 100,
148
+ "id": 57,
149
+ "name": "quora",
150
+ "prevSize": 32,
151
+ "code": 81,
152
+ "tempChar": ""
153
+ },
154
+ {
155
+ "order": 104,
156
+ "id": 73,
157
+ "name": "seo",
158
+ "prevSize": 32,
159
+ "code": 83,
160
+ "tempChar": ""
161
+ },
162
+ {
163
+ "order": 98,
164
+ "id": 59,
165
+ "name": "minify",
166
+ "prevSize": 32,
167
+ "code": 78,
168
+ "tempChar": ""
169
+ },
170
+ {
171
+ "order": 92,
172
+ "id": 49,
173
+ "name": "uptime",
174
+ "prevSize": 32,
175
+ "code": 85,
176
+ "tempChar": ""
177
+ },
178
+ {
179
+ "order": 96,
180
+ "id": 47,
181
+ "name": "world",
182
+ "prevSize": 32,
183
+ "code": 87,
184
+ "tempChar": ""
185
+ },
186
+ {
187
+ "order": 50,
188
+ "id": 3,
189
+ "prevSize": 32,
190
+ "code": 89,
191
+ "name": "pos_footer",
192
+ "tempChar": ""
193
+ },
194
+ {
195
+ "order": 49,
196
+ "id": 4,
197
+ "prevSize": 32,
198
+ "code": 88,
199
+ "name": "pos_middle",
200
+ "tempChar": ""
201
+ },
202
+ {
203
+ "order": 48,
204
+ "id": 5,
205
+ "prevSize": 32,
206
+ "code": 67,
207
+ "name": "pos_header",
208
+ "tempChar": ""
209
+ },
210
+ {
211
+ "order": 43,
212
+ "id": 6,
213
+ "prevSize": 32,
214
+ "code": 98,
215
+ "name": "book",
216
+ "tempChar": ""
217
+ },
218
+ {
219
+ "order": 46,
220
+ "id": 9,
221
+ "prevSize": 32,
222
+ "code": 110,
223
+ "name": "support",
224
+ "tempChar": ""
225
+ },
226
+ {
227
+ "id": 33,
228
+ "order": 11,
229
+ "prevSize": 32,
230
+ "code": 106,
231
+ "name": "rocket",
232
+ "tempChar": ""
233
+ },
234
+ {
235
+ "order": 52,
236
+ "id": 7,
237
+ "prevSize": 32,
238
+ "code": 118,
239
+ "name": "rocket_alt",
240
+ "tempChar": ""
241
+ },
242
+ {
243
+ "id": 25,
244
+ "order": 3,
245
+ "prevSize": 32,
246
+ "code": 97,
247
+ "name": "lock",
248
+ "tempChar": ""
249
+ },
250
+ {
251
+ "id": 26,
252
+ "order": 4,
253
+ "prevSize": 32,
254
+ "code": 99,
255
+ "name": "unlock",
256
+ "tempChar": ""
257
+ },
258
+ {
259
+ "id": 27,
260
+ "order": 5,
261
+ "prevSize": 32,
262
+ "code": 100,
263
+ "name": "plugin",
264
+ "tempChar": ""
265
+ },
266
+ {
267
+ "id": 39,
268
+ "order": 17,
269
+ "prevSize": 32,
270
+ "code": 114,
271
+ "name": "caret_up",
272
+ "tempChar": ""
273
+ },
274
+ {
275
+ "order": 103,
276
+ "id": 71,
277
+ "name": "caret_right",
278
+ "prevSize": 32,
279
+ "code": 51,
280
+ "tempChar": ""
281
+ },
282
+ {
283
+ "id": 28,
284
+ "order": 6,
285
+ "prevSize": 32,
286
+ "code": 101,
287
+ "name": "caret_down",
288
+ "tempChar": ""
289
+ },
290
+ {
291
+ "order": 102,
292
+ "id": 72,
293
+ "name": "caret_left",
294
+ "prevSize": 32,
295
+ "code": 124,
296
+ "tempChar": ""
297
+ },
298
+ {
299
+ "id": 29,
300
+ "order": 7,
301
+ "prevSize": 32,
302
+ "code": 102,
303
+ "name": "power",
304
+ "tempChar": ""
305
+ },
306
+ {
307
+ "id": 31,
308
+ "order": 9,
309
+ "prevSize": 32,
310
+ "code": 104,
311
+ "name": "radio_default, radio",
312
+ "tempChar": ""
313
+ },
314
+ {
315
+ "id": 30,
316
+ "order": 8,
317
+ "prevSize": 32,
318
+ "code": 103,
319
+ "name": "radio_checked",
320
+ "tempChar": ""
321
+ },
322
+ {
323
+ "id": 45,
324
+ "order": 23,
325
+ "prevSize": 32,
326
+ "code": 121,
327
+ "name": "cross",
328
+ "tempChar": ""
329
+ },
330
+ {
331
+ "id": 46,
332
+ "order": 24,
333
+ "prevSize": 32,
334
+ "code": 122,
335
+ "name": "tick",
336
+ "tempChar": ""
337
+ },
338
+ {
339
+ "id": 34,
340
+ "order": 12,
341
+ "prevSize": 32,
342
+ "code": 107,
343
+ "name": "search",
344
+ "tempChar": ""
345
+ },
346
+ {
347
+ "id": 37,
348
+ "order": 15,
349
+ "prevSize": 32,
350
+ "code": 112,
351
+ "name": "info",
352
+ "tempChar": ""
353
+ },
354
+ {
355
+ "id": 10,
356
+ "order": 41,
357
+ "prevSize": 32,
358
+ "code": 49,
359
+ "name": "devman",
360
+ "tempChar": ""
361
+ },
362
+ {
363
+ "id": 16,
364
+ "order": 35,
365
+ "prevSize": 32,
366
+ "code": 55,
367
+ "name": "upfront",
368
+ "tempChar": ""
369
+ },
370
+ {
371
+ "order": 93,
372
+ "id": 62,
373
+ "name": "hummingbird",
374
+ "prevSize": 32,
375
+ "code": 72,
376
+ "tempChar": ""
377
+ },
378
+ {
379
+ "order": 80,
380
+ "id": 69,
381
+ "name": "defender",
382
+ "prevSize": 32,
383
+ "code": 68,
384
+ "tempChar": ""
385
+ },
386
+ {
387
+ "id": 35,
388
+ "order": 13,
389
+ "prevSize": 32,
390
+ "code": 108,
391
+ "name": "theme",
392
+ "tempChar": ""
393
+ },
394
+ {
395
+ "order": 99,
396
+ "id": 58,
397
+ "name": "pencil",
398
+ "prevSize": 32,
399
+ "code": 80,
400
+ "tempChar": ""
401
+ },
402
+ {
403
+ "order": 84,
404
+ "id": 53,
405
+ "name": "star",
406
+ "prevSize": 32,
407
+ "code": 90,
408
+ "tempChar": ""
409
+ },
410
+ {
411
+ "order": 87,
412
+ "id": 52,
413
+ "name": "trash",
414
+ "prevSize": 32,
415
+ "code": 84,
416
+ "tempChar": ""
417
+ },
418
+ {
419
+ "order": 78,
420
+ "id": 56,
421
+ "name": "recycle",
422
+ "prevSize": 32,
423
+ "code": 82,
424
+ "tempChar": ""
425
+ },
426
+ {
427
+ "order": 86,
428
+ "id": 65,
429
+ "name": "fix",
430
+ "prevSize": 32,
431
+ "code": 50,
432
+ "tempChar": ""
433
+ },
434
+ {
435
+ "id": 36,
436
+ "order": 14,
437
+ "prevSize": 32,
438
+ "code": 111,
439
+ "name": "edit",
440
+ "tempChar": ""
441
+ },
442
+ {
443
+ "id": 40,
444
+ "order": 18,
445
+ "prevSize": 32,
446
+ "code": 115,
447
+ "name": "options",
448
+ "tempChar": ""
449
+ },
450
+ {
451
+ "id": 41,
452
+ "order": 19,
453
+ "prevSize": 32,
454
+ "code": 116,
455
+ "name": "cog",
456
+ "tempChar": ""
457
+ },
458
+ {
459
+ "id": 38,
460
+ "order": 47,
461
+ "prevSize": 32,
462
+ "code": 113,
463
+ "name": "badge",
464
+ "tempChar": ""
465
+ },
466
+ {
467
+ "id": 42,
468
+ "order": 20,
469
+ "prevSize": 32,
470
+ "code": 117,
471
+ "name": "cylinder",
472
+ "tempChar": ""
473
+ },
474
+ {
475
+ "id": 44,
476
+ "order": 22,
477
+ "prevSize": 32,
478
+ "code": 120,
479
+ "name": "trophy",
480
+ "tempChar": ""
481
+ },
482
+ {
483
+ "id": 43,
484
+ "order": 21,
485
+ "prevSize": 32,
486
+ "code": 119,
487
+ "name": "bell",
488
+ "tempChar": ""
489
+ }
490
+ ],
491
+ "id": 3,
492
+ "metadata": {
493
+ "name": "WPMU DEV App Icons",
494
+ "importSize": {
495
+ "width": 32,
496
+ "height": 32
497
+ }
498
+ },
499
+ "height": 1024,
500
+ "prevSize": 32,
501
+ "icons": [
502
+ {
503
+ "id": 70,
504
+ "paths": [
505
+ "M0 190.573c0.213-105.296 85.621-190.573 190.947-190.573 0.066 0 0.132 0 0.198 0l666.058-0c0.056-0 0.122-0 0.188-0 105.325 0 190.734 85.277 190.947 190.552l0 492.364c0 105.354-85.406 190.76-190.76 190.76h-38.938l-60.279 149.762-146.018-149.762h-421.955c-105.17-0.107-190.385-85.388-190.385-190.572 0-0.066 0-0.132 0-0.198l-0-492.333z"
506
+ ],
507
+ "attrs": [],
508
+ "isMulticolor": false,
509
+ "width": 1048,
510
+ "grid": 0,
511
+ "tags": [
512
+ "comment"
513
+ ],
514
+ "colorPermutations": {}
515
+ },
516
+ {
517
+ "id": 8,
518
+ "paths": [
519
+ "M699.206 370.919h-345.743c-13.632 0-24.696 11.014-24.696 24.696 0 13.632 11.064 24.696 24.696 24.696h345.743c13.632 0 24.696-11.064 24.696-24.696 0-13.682-11.064-24.696-24.696-24.696z",
520
+ "M699.206 667.271h-345.743c-13.632 0-24.696 11.014-24.696 24.696 0 13.632 11.064 24.696 24.696 24.696h345.743c13.632 0 24.696-11.064 24.696-24.696 0-13.682-11.064-24.696-24.696-24.696z",
521
+ "M699.206 519.095h-345.743c-13.632 0-24.696 11.014-24.696 24.696 0 13.632 11.064 24.696 24.696 24.696h345.743c13.632 0 24.696-11.064 24.696-24.696 0-13.682-11.064-24.696-24.696-24.696z",
522
+ "M501.639 28.88c-272.742 0-493.919 221.226-493.919 493.919 0 109.897 35.908 211.447 96.611 293.437l-51.318 177.218 175.983-58.727c78.089 51.911 171.884 81.991 272.643 81.991 272.742 0 493.919-221.078 493.919-493.919 0-272.693-221.177-493.919-493.919-493.919v0zM501.639 917.935c-78.138 0-153.461-22.671-217.917-65.494-16.398-10.916-35.463-16.497-54.726-16.497-9.681 0-19.362 1.432-28.845 4.297 7.162-28.598 1.185-59.023-16.398-82.781-50.528-68.21-77.249-149.312-77.249-234.661 0-217.868 177.268-395.135 395.135-395.135s395.135 177.268 395.135 395.135c0 217.868-177.268 395.135-395.135 395.135v0z"
523
+ ],
524
+ "attrs": [],
525
+ "isMulticolor": false,
526
+ "grid": 0,
527
+ "tags": [
528
+ "speach"
529
+ ],
530
+ "colorPermutations": {}
531
+ },
532
+ {
533
+ "id": 21,
534
+ "paths": [
535
+ "M558 778c-42 14-86 22-134 22-26 0-50-2-76-8-22 20-74 52-150 58-2 2-2 2-4 2-6 0-14-4-4-8 22-14 62-40 62-80-120-52-202-156-202-276 0-174 168-314 374-314 156 0 290 80 346 194 22 2 42 8 60 14-52-148-214-258-406-258-234 0-424 164-424 364 0 120 70 232 186 298-6 6-14 10-22 14-28 16-32 42-28 60 6 20 24 42 58 42 2 0 6-2 8-2 74-6 128-32 160-54 20 2 42 4 62 4 70 0 134-16 192-40-22-8-42-18-58-32zM732 390c138 0 248 94 248 208 0 82-54 152-134 186 10 28 40 50 58 60 10 4 2 8-4 8-2 0-2 0-4-2-62-4-108-26-134-46-10 2-20 2-30 2-138 0-250-92-250-208 0-114 112-208 250-208zM732 340c-166 0-300 116-300 258s134 258 300 258c4 0 10 0 18 0 32 20 80 40 142 44 2 0 4 2 8 2 34 0 52-22 58-42 4-18 0-44-30-60-2-2-2-2-4-4 66-48 106-120 106-198 0-142-134-258-298-258z"
536
+ ],
537
+ "attrs": [],
538
+ "isMulticolor": false,
539
+ "tags": [
540
+ "speach_alt",
541
+ "comment"
542
+ ],
543
+ "defaultCode": 57345,
544
+ "grid": 0,
545
+ "colorPermutations": {}
546
+ },
547
+ {
548
+ "id": 68,
549
+ "paths": [
550
+ "M1050.836 1024h-749.992c-0.424 0.002-0.925 0.003-1.426 0.003-15.013 0-29.805-0.942-44.322-2.77-117.762-14.242-218.304-105.483-247.147-224.715-3.005-14.041-5.359-25.576-7.949-36.169v-69.208c-0.121 0.517 1.417-1.772 2.319-4.359 11.525-110.342 91.606-206.428 199.228-241.984 7.938-1.803 12.284-6.922 12.284-13.057 0-1.006-0.117-1.986-0.338-2.925 0.011-0.63 0.007-1.476 0.007-2.323 0-163.941 132.901-296.842 296.842-296.842 20.495 0 40.506 2.077 59.832 6.032-0.203 0.254 1.768 0.59 3.817 0.59 6.46 0 12.14-3.336 15.413-8.378 26.059-43.611 96.992-96.055 180.393-117.272-11.657 2.522 15.599-5.389 44.039-9.689 10.816-1.059 21.262-1.533 31.817-1.533 18.246 0 36.161 1.416 53.642 4.144 69.441 4.088 148.797 45.322 204.691 107.946 55.785 58.363 89.947 137.21 89.947 224.035 0 13.662-0.846 27.126-2.488 40.343-0.163-0.309-0.348 1.151-0.348 2.653 0 6.791 3.784 12.699 9.359 15.729 68.861 34.597 134.23 117.504 155.763 216.754-1.424-7.797 3.362 11.618 5.916 31.73 1.696 13.937 2.586 28.537 2.586 43.344s-0.889 29.407-2.618 43.748c-15.395 134.38-118.284 249.368-253.362 283.546-10.044 3.904-33.128 8.976-57.16 10.586zM780.359 317.793h-146.42c-12.397 1.14-22.314 11.010-23.532 23.433l-0.009 194.314c-0.974 12.508-10.94 22.506-23.448 23.534l-99.432 0.006c-14.36 0-48.493 0 0 48.728l195.149 196.326c6.226 6.256 14.843 10.128 24.364 10.128s18.139-3.872 24.363-10.127l195.15-194.914c49.199-49.199 11.535-48.728 0-48.728h-97.692c-13.001 0-23.54-10.539-23.54-23.54v-195.384c-0.63-13.496-11.616-24.24-25.165-24.482z"
551
+ ],
552
+ "attrs": [],
553
+ "isMulticolor": false,
554
+ "width": 1365,
555
+ "grid": 0,
556
+ "tags": [
557
+ "download"
558
+ ],
559
+ "colorPermutations": {}
560
+ },
561
+ {
562
+ "id": 32,
563
+ "paths": [
564
+ "M753.6 848c-174.4 0-318.4 0-492.8 0-16 0-27.2-1.6-28.8-1.6-80-11.2-145.6-70.4-163.2-150.4-1.6-8-3.2-14.4-4.8-22.4 0-14.4 0-30.4 0-44.8 0-1.6 1.6-1.6 1.6-3.2 12.8-78.4 57.6-131.2 132.8-160 6.4-1.6 6.4-4.8 6.4-9.6-1.6-123.2 112-217.6 233.6-193.6 6.4 1.6 9.6 0 14.4-4.8 32-38.4 72-64 120-76.8 9.6-1.6 19.2-4.8 28.8-6.4 25.6-3.2 52.8 1.6 54.4 1.6 54.4 8 99.2 30.4 136 70.4 44.8 49.6 64 105.6 57.6 172.8 0 6.4 1.6 9.6 6.4 12.8 54.4 33.6 88 81.6 102.4 144 1.6 8 3.2 12.8 3.2 20.8 3.2 28.8 0 54.4 0 56-12.8 91.2-78.4 164.8-168 188.8-12.8 3.2-27.2 6.4-40 6.4zM560 400c-32 0-73.6 0-96 0-8 0-16 8-16 16 0 43.2 0 84.8 0 128 0 9.6-8 16-16 16-27.2 0-38.4 0-64 0-9.6 0-32 0 0 32 44.8 44.8 84.8 84.8 128 128 8 8 22.4 9.6 32 0 43.2-43.2 84.8-84.8 128-128 32-32 8-32 0-32-16 0-48 0-64 0-9.6 0-16-8-16-16 0-48 0-80 0-128 0-9.6-8-16-16-16z"
565
+ ],
566
+ "attrs": [],
567
+ "isMulticolor": false,
568
+ "tags": [
569
+ "download"
570
+ ],
571
+ "defaultCode": 105,
572
+ "grid": 0,
573
+ "colorPermutations": {}
574
+ },
575
+ {
576
+ "id": 50,
577
+ "paths": [
578
+ "M1050.836 1024h-749.992c-0.424 0.002-0.925 0.003-1.426 0.003-15.013 0-29.805-0.942-44.322-2.77-117.762-14.242-218.304-105.483-247.147-224.715-3.005-14.041-5.359-25.576-7.949-36.169v-69.208c-0.121 0.517 1.417-1.772 2.319-4.359 11.525-110.342 91.606-206.428 199.228-241.984 7.938-1.803 12.284-6.922 12.284-13.057 0-1.006-0.117-1.986-0.338-2.925 0.011-0.63 0.007-1.476 0.007-2.323 0-163.941 132.901-296.842 296.842-296.842 20.495 0 40.506 2.077 59.832 6.032-0.203 0.254 1.768 0.59 3.817 0.59 6.46 0 12.14-3.336 15.413-8.378 26.059-43.611 96.992-96.055 180.393-117.272-11.657 2.522 15.599-5.389 44.039-9.689 10.816-1.059 21.262-1.533 31.817-1.533 18.246 0 36.161 1.416 53.642 4.144 69.441 4.088 148.797 45.322 204.691 107.946 55.785 58.363 89.947 137.21 89.947 224.035 0 13.662-0.846 27.126-2.488 40.343-0.163-0.309-0.348 1.151-0.348 2.653 0 6.791 3.784 12.699 9.359 15.729 68.861 34.597 134.23 117.504 155.763 216.754-1.424-7.797 3.362 11.618 5.916 31.73 1.696 13.937 2.586 28.537 2.586 43.344s-0.889 29.407-2.618 43.748c-15.395 134.38-118.284 249.368-253.362 283.546-10.044 3.904-33.128 8.976-57.16 10.586zM633.468 814.257h146.185c12.397-1.14 22.314-11.010 23.532-23.433l0.009-195.727c0.974-12.508 10.94-22.506 23.448-23.534l97.549-0.006c14.36 0 48.493 0 0-48.728l-195.149-194.913c-6.226-6.256-14.843-10.128-24.364-10.128s-18.139 3.872-24.363 10.127l-195.15 194.914c-49.199 49.199-11.535 48.728 0 48.728h97.457c13.001 0 23.54 10.539 23.54 23.54v194.913c0.741 13.575 11.929 24.302 25.623 24.302 0.592 0 1.18-0.020 1.763-0.060z"
579
+ ],
580
+ "attrs": [],
581
+ "isMulticolor": false,
582
+ "width": 1365,
583
+ "grid": 0,
584
+ "tags": [
585
+ "upload"
586
+ ],
587
+ "colorPermutations": {}
588
+ },
589
+ {
590
+ "id": 67,
591
+ "paths": [
592
+ "M1133.686 927.114l-507.668-894.818c-10.931-19.443-31.427-32.362-54.942-32.362s-44.011 12.919-54.779 32.047l-507.831 895.133c-5.349 9.287-8.504 20.423-8.504 32.295s3.155 23.008 8.673 32.615c10.799 19.015 31.273 31.902 54.762 31.976l1015.346 0c23.439-0.050 43.924-12.919 54.778-31.984 5.512-9.599 8.667-20.734 8.667-32.607s-3.155-23.008-8.673-32.615zM571.077 899.545c-47.431-2.299-85.016-41.314-85.016-89.108s37.585-86.808 84.811-89.1c47.636 2.291 85.221 41.306 85.221 89.1s-37.585 86.808-84.811 89.1zM640.985 606.523c-1.182 27.372-31.311 48.443-71.089 48.443s-67.545-21.071-68.726-48.443c-6.105-98.462-19.692-275.692-19.692-294.006 0-36.037 39.385-64.197 90.388-64.197s86.843 28.16 86.843 64.197c0.591 17.526-11.422 196.135-17.526 293.809z"
593
+ ],
594
+ "attrs": [],
595
+ "isMulticolor": false,
596
+ "width": 1142,
597
+ "grid": 0,
598
+ "tags": [
599
+ "error",
600
+ "warning"
601
+ ],
602
+ "colorPermutations": {}
603
+ },
604
+ {
605
+ "id": 63,
606
+ "paths": [
607
+ "M382.025 694.59h-238.592c-1.362 0.048-2.963 0.075-4.569 0.075-76.722 0-138.918-62.196-138.918-138.918 0-1.37 0.020-2.735 0.059-4.095q-0.005-206.441-0.005-412.734c0-76.722 62.196-138.918 138.918-138.918 161.666 0 324.026 0 486.213 0 0.971-0.025 2.113-0.040 3.26-0.040 56.17 0 104.23 34.726 123.881 83.881 14.209 31.287-1.593 54.73-34.412 54.73h-503.578c-1.857-0.176-4.014-0.277-6.195-0.277-38.361 0-69.459 31.098-69.459 69.459 0 2.237 0.106 4.45 0.313 6.633q-0.021 131.52-0.021 263.318c0 50.705 27.784 77.968 78.662 77.968h501.321c1.458-0.217 3.141-0.341 4.852-0.341 19.181 0 34.73 15.549 34.73 34.73 0 6.532-1.803 12.643-4.94 17.862-21.008 51.071-70.552 86.546-128.396 86.667l-243.122 0z",
608
+ "M451.484 746.685h208.377v121.553c25.7 0 15.802 0 40.634 0 2.535-0.441 5.797-2.794 7.78-6.017 12.82-17.355 33.139-28.447 56.049-28.447 38.361 0 69.459 31.098 69.459 69.459 0 2.169-0.099 4.314-0.294 6.432-2.734 30.281-26.005 55.449-56.157 61.132-4.598 1.004-9.383 1.54-14.293 1.54-22.154 0-41.758-10.918-53.726-27.666-2.948-4.367-7.652-7.070-12.987-7.070-0.611 0-1.215 0.036-1.807 0.105-22.676-0.007-10.694-0.007-33.268-0.007 0 29.867-28.826 86.824-105.578 86.824-1.14 0.046-2.478 0.072-3.822 0.072-50.887 0-93.019-37.48-100.298-86.34-24.726-0.555-14.828-0.555-39.833-0.555-2.535 0.441-5.797 2.794-7.78 6.017-12.746 18.188-33.546 29.892-57.081 29.892-38.361 0-69.459-31.098-69.459-69.459 0-2.741 0.159-5.444 0.468-8.102 2.724-30.229 25.995-55.398 56.147-61.080 4.598-1.004 9.383-1.54 14.293-1.54 22.154 0 41.758 10.918 53.726 27.666 2.935 4.459 7.69 7.232 13.094 7.232 0.574 0 1.14-0.031 1.698-0.092 22.679 0.006 10.697 0.006 34.661 0.006v-121.553z",
609
+ "M664.376 358.93l-217.58-80.746v-80.92l217.58 80.92v80.746z",
610
+ "M664.376 220.185l-217.58-80.92h217.58v80.92z",
611
+ "M664.376 497.674l-217.58-80.746v-80.746l217.58 80.746v80.746z",
612
+ "M446.795 555.672v-80.746l217.58 80.746h-217.58z"
613
+ ],
614
+ "attrs": [],
615
+ "isMulticolor": false,
616
+ "width": 833,
617
+ "grid": 0,
618
+ "tags": [
619
+ "gzip",
620
+ "archive"
621
+ ],
622
+ "colorPermutations": {}
623
+ },
624
+ {
625
+ "id": 19,
626
+ "paths": [
627
+ "M1004 670v-670l-108 84v586c0 34-24 62-54 62-32 0-56-28-56-62v-312c0-100-74-182-164-182s-162 82-162 182v312c0 34-26 62-56 62s-54-28-54-62v-312c0-100-74-182-164-182s-164 82-164 182v0 670l108-84v-586c0-34 26-62 56-62s56 28 56 62l-2 312c0 100 74 182 164 182s164-82 164-182v0-312c0-34 24-62 54-62 32 0 56 28 56 62v312c0 100 72 182 164 182 90 0 162-82 162-182z"
628
+ ],
629
+ "attrs": [],
630
+ "isMulticolor": false,
631
+ "tags": [
632
+ "wpmudev-logo"
633
+ ],
634
+ "defaultCode": 99,
635
+ "grid": 0,
636
+ "colorPermutations": {}
637
+ },
638
+ {
639
+ "id": 20,
640
+ "paths": [
641
+ "M514 0c-284 0-514 230-514 514s230 514 514 514c284 0 514-230 514-514s-230-514-514-514zM514 950c-242 0-436-196-436-436 0-242 194-436 436-436 240 0 436 194 436 436 0 240-196 436-436 436zM774 228l-60 48v322c0 20-14 34-30 34-18 0-32-14-32-34v-172c0-56-40-100-90-100s-90 44-90 100v172c0 20-14 34-30 34s-30-14-30-34v-172c0-56-40-100-90-100s-90 44-90 100v0 370l58-46v-324c0-18 14-34 32-34 16 0 30 16 30 34v172c0 56 40 102 90 102s90-46 90-102v0-172c0-18 14-34 30-34 18 0 32 16 32 34v172c0 56 40 102 90 102s90-46 90-102v0-370z"
642
+ ],
643
+ "attrs": [],
644
+ "isMulticolor": false,
645
+ "tags": [
646
+ "wpmudev-logo"
647
+ ],
648
+ "defaultCode": 100,
649
+ "grid": 0,
650
+ "colorPermutations": {}
651
+ },
652
+ {
653
+ "id": 48,
654
+ "paths": [
655
+ "M510.72 1024c-282.192-0.764-510.657-229.701-510.657-511.998 0-282.77 229.23-512 512-512s512 229.23 512 512c0 2.828-0.023 5.651-0.069 8.469-3.807 278.716-230.984 503.536-510.67 503.536-0.916 0-1.831-0.002-2.746-0.007zM801.829 186.331c-192-178.103-514.011-136.594-652.069 83.383 1.457 0.351 5.118 0.794 8.862 0.912l128.098-4.569c1.526-0.428 3.279-0.673 5.089-0.673 9.947 0 18.161 7.423 19.403 17.033 0.021 0.347 0.027 0.638 0.027 0.931 0 11.21-9.087 20.297-20.297 20.297-0.714 0-1.42-0.037-2.116-0.109-13.81 1.653-27.89 2.75-43.616 4.213l157.074 469.76c2.56-6.766 4.023-10.606 5.303-14.629 28.343-85.029 56.686-170.24 85.211-256 1.679-4.231 2.652-9.133 2.652-14.263s-0.973-10.032-2.745-14.532c-18.192-48.005-36.478-96.097-52.752-144.919-6.583-19.749-14.811-31.451-36.571-28.526-0.546 0.016-1.189 0.025-1.834 0.025-5.843 0-11.513-0.743-16.92-2.139-8.938-0.769-16.246-8.623-16.246-18.183 0-10.14 8.22-18.36 18.36-18.36 0.579 0 1.153 0.027 1.718 0.079 14.007-0.005 28.27 1.457 42.35 2.555 22.64 1.451 49.092 2.278 75.736 2.278 38.096 0 75.797-1.69 113.032-5-3.065-0.267-1.049-0.621 1.050-0.621 9.86 0 17.897 7.804 18.272 17.572 0.040 0.495 0.062 1.031 0.062 1.572 0 10.705-8.678 19.383-19.383 19.383-0.601 0-1.195-0.027-1.782-0.081-14.37 1.651-28.816 2.931-44.542 4.577l156.16 464.457c-2.265 4.5 0.24 0.213 1.921-4.467 22.399-75.076 45.439-149.864 66.833-224.836 5.267-17.232 8.3-37.039 8.3-57.555 0-37.519-10.143-72.669-27.837-102.857-7.891-14.4-17.765-28.845-25.994-44.571 3.982 11.641-12.885-20.218-22.608-55.057-1.764-7.159-2.529-13.298-2.529-19.616 0-39.446 29.81-71.93 68.131-76.153-2.341 0.849 2.341-0.302 6.655-2.147zM655.726 923.977l-134.766-367.177h-2.926l-128.914 374.674c36.697 11.121 78.871 17.524 122.541 17.524 51.481 0 100.884-8.898 146.754-25.239zM318.72 903.314l-206.629-566.857c-23.247 51.636-36.791 111.934-36.791 175.395 0 170.748 98.044 318.596 240.906 390.319zM899.291 310.857c0 6.217 0 9.143 0 12.069 0.474 7.029 0.745 15.236 0.745 23.506 0 43.384-7.439 85.030-21.111 123.733q-54.057 156.852-108.914 316.12l-34.743 100.571c197.303-111.726 272.823-371.383 164.571-575.817z"
656
+ ],
657
+ "attrs": [],
658
+ "isMulticolor": false,
659
+ "grid": 0,
660
+ "tags": [
661
+ "wordpress"
662
+ ],
663
+ "colorPermutations": {}
664
+ },
665
+ {
666
+ "id": 66,
667
+ "paths": [
668
+ "M109.909 1024v-512h-109.909v-176.469h109.739v-105.984c0.171-144.213 62.123-229.547 238.251-229.547h146.603v176.469h-91.648c-68.267 0-73.216 24.747-73.216 70.656v88.235h166.059l-19.627 176.64h-146.603v512h-219.648z"
669
+ ],
670
+ "attrs": [],
671
+ "isMulticolor": false,
672
+ "width": 495,
673
+ "grid": 0,
674
+ "tags": [
675
+ "facebook"
676
+ ],
677
+ "colorPermutations": {}
678
+ },
679
+ {
680
+ "id": 51,
681
+ "paths": [
682
+ "M1310.792 121.135c-14.89 10.709-81.418 32.19-151.988 40.433 39.699-16.967 91.224-72.488 115.047-140.977-5.215 8.61-82.434 44.54-166.562 61.314-53.177-49.795-122.171-81.005-198.455-81.005-0.51 0-1.019 0.001-1.529 0.004-1.417-0.031-3.181-0.048-4.948-0.048-143.894 0-260.897 115.137-263.907 258.31-0.005 0.394-0.005 0.528-0.005 0.663 0 20.801 2.555 41.005 7.367 60.315-213.432-6.91-416.518-110.697-554.535-271.859-23.725 35.825-37.265 80.55-37.265 128.437 0 0.162 0 0.324 0 0.486 0.318 89.914 47.503 169.25 118.519 214.509-40.056 0.282-83.88-11.67-122.242-32.426s1.463 2.758 1.463 3.888c1.807 126.237 93.452 231.003 213.999 253.1-19.642 6.049-44.035 9.384-69.208 9.384-17.872 0-35.351-1.681-52.289-4.894 39.032 104.987 137.304 178.977 252.959 179.717-91.27 69.137-206.805 110.743-332.057 110.743-0.661 0-1.321-0.001-1.981-0.003-21.669-0.002-43.945-1.315-65.843-3.869 119.49 73.177 261.363 116.418 413.335 116.418 0.546 0 1.091-0.001 1.636-0.002 494.626 0 765.147-393.916 765.147-735.4q0-16.724 0-33.448c-10.131 19.157 72.941-47.501 132.196-132.070z"
683
+ ],
684
+ "attrs": [],
685
+ "isMulticolor": false,
686
+ "width": 1311,
687
+ "grid": 0,
688
+ "tags": [
689
+ "twitter"
690
+ ],
691
+ "colorPermutations": {}
692
+ },
693
+ {
694
+ "id": 64,
695
+ "paths": [
696
+ "M692.495 744.47c63.126-15.876 116.235-46.872 145.341-107.73 18.195-36.716 28.841-79.951 28.841-125.673 0-26.693-3.629-52.539-10.419-77.070 1.36-8.143-14.763-42.914-38.675-70.812-2.053-2.82-3.417-6.692-3.417-10.883 0-1.408 0.154-2.78 0.446-4.1 4.58-15.767 7.227-34.023 7.227-52.897 0-24.881-4.601-48.687-12.998-70.614-0.751-4.264-5.676-8.414-11.569-8.414-0.625 0-1.24 0.047-1.84 0.137-22.795 0.222-48.918 7.221-71.926 19.338-17.97 8.815-36.87 20.344-55.77 30.361-3.497 1.961-7.675 3.117-12.123 3.117-1.324 0-2.625-0.102-3.894-0.3-37.228-9.592-80.127-15.108-124.315-15.108s-87.087 5.516-128.047 15.898c2.499-0.603 1.24-0.507-0.042-0.507-4.959 0-9.583-1.436-13.479-3.916-6.299-9.525-54.471-35.184-107.814-47.174l-8.319-1.338c-18.9-2.079-20.412-1.701-26.46 17.577-6.368 18.236-10.046 39.259-10.046 61.14 0 19.234 2.842 37.804 8.129 55.314-0.014-0.17 0.18 1.189 0.18 2.593 0 3.031-0.903 5.852-2.455 8.206-47.593 55.132-56.665 119.959-46.081 188.944-2.207 0.821 5.952 38.105 19.692 72.558 26.046 66.924 81.045 103.59 150.408 121.545 21.357 5.481 43.281 8.883 66.339 13.608-12.638 11.215-26.514 36.191-31.088 64.29-1.070 3.438-4.041 6.294-7.755 7.504-56.791 21.761-111.412 12.122-145.999-45.145-10.683-23.925-37.497-46.215-69.98-53.542-4.020-0.649-7.843-0.943-11.734-0.943-5.736 0-11.323 0.639-16.694 1.849-7.811 1.416-9.134 7.842-3.842 14.079-2.725-1.877 4.644 6.466 13.756 12.335 19.054 7.885 45.767 36.705 59.057 72.092 17.056 43.824 58.023 73.933 106.097 74.521 4.852 0.123 10.481 0.193 16.125 0.193 20.964 0 41.704-0.962 62.177-2.844-2.629 32.514-2.629 66.534-2.629 100.365 0 17.199-18.9 25.137-39.123 18.9 7.828 9.482-65.118-19.649-127.215-63.198-158.175-112.005-238.689-266.229-230.562-461.276 11.099-242.804 190.67-443.514 425.429-487.122 34.55-7.142 70.546-10.946 107.43-10.946 289.868 0 524.852 234.984 524.852 524.852 0 229.409-147.183 424.441-352.272 495.818-29.388 9.621-44.886-1.152-44.886-27.99q0-65.961 0-132.3c0.271-3.25 0.426-7.035 0.426-10.856 0-35.003-12.981-66.973-34.392-91.36 23.382-4.379 44.928-7.781 65.907-13.073z"
697
+ ],
698
+ "attrs": [],
699
+ "isMulticolor": false,
700
+ "width": 1058,
701
+ "grid": 0,
702
+ "tags": [
703
+ "github"
704
+ ],
705
+ "colorPermutations": {}
706
+ },
707
+ {
708
+ "id": 54,
709
+ "paths": [
710
+ "M750.421 379.904l-232.448-328.704 69.973-51.2c6.315 7.68 12.629 14.336 17.067 21.675 64.171 95.573 127.488 191.488 192.341 286.379 12.288 17.92 14.165 29.696-6.315 41.643 76.886-48.048 12.89-14.204-41.447 30.876zM734.72 397.824l-52.736 59.221-304.299-277.163 60.075-64.171zM270.677 345.088l34.133-63.317c9.899-17.067 21.333-6.656 31.403-0.853q140.459 80.555 280.576 161.621c59.051 34.133 59.904 41.813 11.776 97.792zM620.203 570.197c-2.56 10.581-3.072 13.312-3.925 16.213-17.067 60.587-5.461 54.784-64.683 38.059-106.667-30.208-213.333-61.269-320.341-90.112-25.088-6.827-29.525-17.067-20.992-40.448 25.429-70.656 11.947-59.221 74.923-39.765 103.253 31.744 205.995 65.365 308.736 99.157-5.62-4.303 11.983 4.578 26.432 17.021zM595.285 691.712c-1.877 49.323-2.731 51.2-48.469 46.421-117.077-11.264-233.984-23.381-351.061-34.133-21.333-2.048-27.136-9.899-23.211-31.915 10.923-63.659 9.728-62.635 75.264-53.589q158.891 22.016 318.293 40.277c25.259 2.56 35.328 11.435 29.355 32.939zM378.027 765.781c59.904 0 119.467 0 179.712 0 22.869 0 33.109 5.291 32.256 30.549-2.389 72.704 9.899 63.317-62.805 63.659-108.203 0-216.405 0-324.267 0-27.136 0.512-38.229-6.656-38.229-35.157 1.877-70.827-2.731-58.027 59.221-58.88 51.712-0.683 102.912-0.171 154.112-0.171zM91.136 930.475h576.512v-38.741c0-87.040 0-173.909 0-260.949 0-23.040 6.997-30.208 29.696-29.525 73.387 2.219 60.587-8.875 61.099 61.44 0 110.080 0 220.331 0 330.411 0 24.576-8.021 30.891-31.573 30.72q-347.819-1.024-695.808 0c-24.064 0-31.403-7.168-31.232-31.232 1.024-119.467 1.195-238.933 0-359.424 0-26.283 8.533-32.597 33.28-32.256 57.856 1.195 57.856 0 57.856 59.051v270.507z"
711
+ ],
712
+ "attrs": [],
713
+ "isMulticolor": false,
714
+ "width": 807,
715
+ "grid": 0,
716
+ "tags": [
717
+ "stackoverflow"
718
+ ],
719
+ "colorPermutations": {}
720
+ },
721
+ {
722
+ "id": 61,
723
+ "paths": [
724
+ "M378.839 1024h234.818v-380.6c-0.115-2.18-0.181-4.732-0.181-7.299 0-17.148 2.933-33.61 8.325-48.913 18.477-47.756 64.975-81.744 119.411-81.744 0.217 0 0.434 0.001 0.65 0.002 85.088-0 118.941 62.422 118.941 154.001v364.554h235.013v-391.363c0-209.379-115.843-306.633-270.431-306.633-3.397-0.176-7.375-0.276-11.377-0.276-85.454 0-160.246 45.646-201.324 113.886l0.974 1.058v-97.841h-234.818c3.131 63.596 0 681.166 0 681.166zM131.302 263.387c1.841 0.096 3.997 0.15 6.166 0.15 70.031 0 126.801-56.771 126.801-126.801 0-1.773-0.036-3.538-0.108-5.293-1.362-74.499-50.869-131.442-131.294-131.442-1.841-0.096-3.997-0.15-6.166-0.15-70.031 0-126.801 56.771-126.801 126.801 0 1.773 0.036 3.538 0.108 5.293-0.091 1.46-0.139 3.466-0.139 5.482 0 69.598 56.421 126.019 126.019 126.019 1.353 0 2.702-0.021 4.045-0.064l1.369 0.005zM248.711 1024v-681.166h-234.818v681.166h234.818z"
725
+ ],
726
+ "attrs": [],
727
+ "isMulticolor": false,
728
+ "width": 1096,
729
+ "grid": 0,
730
+ "tags": [
731
+ "linkedin"
732
+ ],
733
+ "colorPermutations": {}
734
+ },
735
+ {
736
+ "id": 60,
737
+ "paths": [
738
+ "M0 150.68v-151.349h484.806v1.783l17.832 65.087 109.667 407.906q15.603 58.177 31.206 116.354c0 2.452 2.006 3.566 4.235 2.675 0.899-0.591 1.747-1.849 2.001-3.312l111.454-414.179 48.146-176.313h483.469v151.572h-4.235c-14.934 0-29.646 0-44.58 0-4.902 0.022-10.177 1.17-14.975 3.221-4.709 0.532-16.911 9.762-25.001 21.956-5.298 7.041-8.399 15.65-8.399 24.983 0 0.233 0.002 0.465 0.006 0.697q-0 313.139-0 626.535c-0.011 0.319-0.017 0.695-0.017 1.071 0 8.082 2.868 15.495 7.641 21.275-7.498-8.847 0.66 2.521 10.991 11.442 8.277 7.432 19.135 11.92 31.042 11.92 0.409 0 0.817-0.005 1.224-0.016 13.983 0.001 28.025 0.001 41.845 0.001h4.458v3.566q0 73.111 0 146.445h-462.739c-0.034-0.533-0.053-1.156-0.053-1.783s0.019-1.25 0.057-1.868q-0.004-71.912-0.004-143.685c0-1.114 0-2.229 0-3.789h96.515v-668.698c-3.566-1.337-4.904 0-5.795 3.343q-29.2 103.871-57.285 207.296l-161.379 583.997c-2.229 8.47-4.458 16.717-6.687 25.188h-175.199s0-2.229-1.114-3.343l-60.852-222.899-160.488-588.677c-1.337-4.904-1.337-4.904-6.687-4.012v668.698h96.738v4.458q0 73.111 0 146.445h-387.845v-152.017h49.707c0.97 0.123 2.093 0.193 3.232 0.193s2.262-0.070 3.364-0.206c11.449-1.849 25.89-12 34.716-26.038 3.75-4.782 6.060-10.819 6.165-17.391q0-316.541 0-633.281c-0.021-3.62-0.924-7.669-2.528-11.342 0.243-2.833-7.367-14.032-17.619-21.991-8.527-7.722-19.721-12.387-32.005-12.387-0.551 0-1.099 0.009-1.645 0.028-14.409-0.002-28.675-0.002-43.163-0.002z"
739
+ ],
740
+ "attrs": [],
741
+ "isMulticolor": false,
742
+ "width": 1293,
743
+ "grid": 0,
744
+ "tags": [
745
+ "medium"
746
+ ],
747
+ "colorPermutations": {}
748
+ },
749
+ {
750
+ "id": 57,
751
+ "paths": [
752
+ "M695.79 853.981c3.596 15.101 23.817 39.586 50.242 54.246-40.601-22.728 2.827 5.557 50.912 24.625 9.205 2.488 13.998 8.286 13.998 15.204 0 0.382-0.015 0.761-0.043 1.136 0.003 17.605 0.003 35.261 0.003 52.916 0.257 1.013 0.404 2.177 0.404 3.375 0 7.898-6.403 14.301-14.301 14.301-0.266 0-0.531-0.007-0.794-0.022-59.108 9.182-115.605 5.828-166.805-29.129-7.085 0.7-40.335-30.641-61.431-69.534-3.148-6.217-8.387-9.67-14.433-9.67-1.336 0-2.632 0.169-3.869 0.486 2.529 0.954-45.655 7.205-94.816 9.766-3.969 0.12-5.873 0.132-7.78 0.132-94.629 0-182.061-30.815-252.809-82.957-85.845-51.128-164.078-162.048-186.131-292.088-5.712-28.702-8.77-58.662-8.77-89.337 0-116.169 43.862-222.094 115.928-302.117 45.578-64.244 143.675-127.546 256.753-147.171 27.893-5.565 56.97-8.538 86.741-8.538 104.131 0 199.769 36.366 274.906 97.090 75.283 48.643 146.935 154.036 168.449 276.688 5.832 29.094 8.949 59.458 8.949 90.549 0 103.708-34.672 199.318-93.057 275.871 16.652-8.453-41.705 60.467-114.896 108.714l-7.526 5.466zM629.407 714.505c1.236-1.766 4.237-5.473 7.062-9.534 33.173-48.522 52.973-108.474 52.973-173.049 0-0.735-0.003-1.469-0.008-2.203 0.319-11.927 0.501-26.1 0.501-40.317 0-51.28-2.361-102.009-6.982-152.083-3.832-61.431-43.719-131.186-103.212-176.534-33.71-26.441-75.921-42.117-121.793-42.117-51.63 0-98.622 19.858-133.754 52.353-59.034 54.74-96.017 132.976-96.090 219.851-1.412 44.858-0 89.878-0 134.722-0.011 0.992-0.017 2.164-0.017 3.337 0 42.177 8.042 82.475 22.677 119.446 31.895 82.723 109.754 169.41 226.985 158.817 10.417-0.883 20.657-3.708 33.368-6.003-26.659-40.96-57.732-69.385-103.283-79.095-4.557-1.173-8.784-5.253-10.387-10.481-0.912-24.477-0.030-49.017-0.030-73.382-0.027-0.266-0.043-0.574-0.043-0.886 0-5.070 4.11-9.181 9.181-9.181 0.64 0 1.265 0.065 1.868 0.19 4.087-0.251 8.936-0.389 13.818-0.389 42.722 0 82.986 10.523 118.342 29.118 29.503 15.928 57.751 37.291 89.001 57.771z"
753
+ ],
754
+ "attrs": [],
755
+ "isMulticolor": false,
756
+ "width": 911,
757
+ "grid": 0,
758
+ "tags": [
759
+ "quora"
760
+ ],
761
+ "colorPermutations": {}
762
+ },
763
+ {
764
+ "id": 73,
765
+ "paths": [
766
+ "M640 635.68h-151.52v-87.84h126.24c8.837 0 16-7.163 16-16v-66.080c0-8.837-7.163-16-16-16h-126.24v-73.6h150.72c8.837 0 16-7.163 16-16v-66.080c0-8.837-7.163-16-16-16h-249.6c-8.837 0-16 7.163-16 16v423.68c0 8.837 7.163 16 16 16h250.4c8.837 0 16-7.163 16-16v-66.080c0-8.837-7.163-16-16-16v0z",
767
+ "M295.040 510.88c-27.243-25.69-60.119-44.648-96-55.36-12.16-5.28-22.24-10.24-30.56-14.88-6.525-3.489-12.689-7.616-18.4-12.32-3.204-2.715-5.771-6.102-7.52-9.92-1.675-3.943-2.493-8.197-2.4-12.48-0.196-5.436 0.618-10.861 2.4-16 1.559-4.269 3.952-8.185 7.040-11.52 2.931-2.939 6.485-5.181 10.4-6.56 5.121-1.88 10.545-2.802 16-2.72 5.868-0.144 11.7 0.947 17.12 3.2 4.517 1.996 8.474 5.073 11.52 8.96 3.693 4.755 6.412 10.192 8 16 2.034 7.016 3.004 14.297 2.88 21.6 0 8.837 7.163 16 16 16h80c6.879 0.018 12.999-4.363 15.2-10.88v-1.76c0.51-1.55 0.78-3.169 0.8-4.8v-4c0.199-18.749-3.337-37.351-10.4-54.72-6.484-17.080-16.394-32.653-29.12-45.76-14.215-13.736-31.172-24.314-49.76-31.040-19.396-6.945-39.88-10.359-60.48-10.080-20.14-0.235-40.186 2.791-59.36 8.96-17.943 5.928-34.569 15.273-48.96 27.52-14.061 11.771-25.321 26.529-32.96 43.2-7.485 16.923-11.25 35.256-11.040 53.76-0.308 17.979 2.842 35.85 9.28 52.64 6.347 15.934 16.381 30.136 29.28 41.44 30.757 24.553 65.881 43.065 103.52 54.56 14.493 5.372 27.766 13.586 39.040 24.16 2.89 3.307 5.069 7.174 6.4 11.36 1.694 5.545 2.504 11.323 2.4 17.12 0.050 5.427-0.76 10.827-2.4 16-1.304 3.972-3.43 7.625-6.24 10.72l11.84 10.72-11.68-10.080c-2.624 2.855-5.926 5.001-9.6 6.24-5.624 1.846-11.523 2.712-17.44 2.56-8.13 0.199-16.237-0.936-24-3.36-5.492-1.716-10.487-4.736-14.56-8.8-4.135-4.554-7.1-10.045-8.64-16-2.43-9.347-3.561-18.984-3.36-28.64 0-8.837-7.163-16-16-16h-81.28c-6.879-0.018-12.999 4.363-15.2 10.88v1.76c-0.494 1.499-0.764 3.062-0.8 4.64v4.48c-0.349 21.369 3.794 42.573 12.16 62.24 8.179 18.8 20.875 35.288 36.96 48 32.617 25.906 73.234 39.653 114.88 38.88 20.378-0.054 40.622-3.293 60-9.6 17.592-5.53 33.909-14.504 48-26.4 13.909-11.625 24.873-26.373 32-43.040 7.182-17.558 10.72-36.393 10.4-55.36 0.036-17.877-2.994-35.628-8.96-52.48-5.571-16.093-14.579-30.78-26.4-43.040v0z",
768
+ "M996.96 375.36c-7.145-20.974-18.775-40.138-34.080-56.16-14.863-15.548-32.935-27.669-52.96-35.52-42.728-15.595-89.592-15.595-132.32 0-19.961 7.869-37.937 20.053-52.64 35.68-15.124 16.074-26.587 35.233-33.6 56.16-7.557 23.019-11.234 47.135-10.88 71.36v118.72c-0.368 24.279 3.309 48.449 10.88 71.52 7.046 20.853 18.568 39.912 33.76 55.84 14.748 15.457 32.721 27.475 52.64 35.2 42.865 15.442 89.775 15.442 132.64 0 19.957-7.741 37.978-19.756 52.8-35.2 15.254-15.909 26.832-34.97 33.92-55.84 7.595-23.065 11.272-47.24 10.88-71.52v-118.72c0.371-24.291-3.361-48.471-11.040-71.52v0zM794.4 445.92c-0.139-12.101 1.096-24.178 3.68-36 1.741-8.286 5.054-16.162 9.76-23.2 3.551-5.173 8.409-9.314 14.080-12 13.895-5.682 29.465-5.682 43.36 0 5.828 2.793 10.841 7.035 14.56 12.32 4.796 6.91 8.218 14.678 10.080 22.88 2.661 11.864 3.896 24.003 3.68 36.16v119.68c0.189 12.156-1.046 24.292-3.68 36.16-1.735 8.364-5.106 16.303-9.92 23.36-3.719 5.285-8.732 9.527-14.56 12.32-13.738 5.637-29.142 5.637-42.88 0-5.778-2.728-10.742-6.92-14.4-12.16-4.815-7.115-8.185-15.106-9.92-23.52-2.646-12.029-3.881-24.325-3.68-36.64v-119.36h-0.16z"
769
+ ],
770
+ "attrs": [],
771
+ "isMulticolor": false,
772
+ "grid": 0,
773
+ "tags": [
774
+ "seo"
775
+ ]
776
+ },
777
+ {
778
+ "id": 59,
779
+ "paths": [
780
+ "M244.524 887.172c3.553-5.798-0.865 3.084-6.972 10.526-35.223 35.201-68.945 69.452-103.726 103.703-14.1 13.997-33.525 22.647-54.969 22.647-11.348 0-22.131-2.422-31.859-6.778-27.618-12.237-46.878-39.882-46.878-72.026 0-22.325 9.291-42.48 24.217-56.81l101.544-101.366c-16.571 15.614-4.263 2.16 10.381-8.213-4.202-5.204-7.027-8.559-10.205-11.56l-89.335-89.512c-0.261 0.319-3.339-2.282-5.427-5.573-2.997-5.565-4.731-12.087-4.731-19.013 0-0.978 0.035-1.948 0.103-2.909 4.057-4.921 10.436-8.32 17.615-8.521 43.288-0.001 86.543-0.001 129.798-0.001h179.023c1.53-0.095 3.319-0.149 5.12-0.149s3.59 0.054 5.364 0.16c-0.168-0.013-0.077-0.014 0.013-0.014 9.751 0 17.655 7.904 17.655 17.655 0 1.061-0.094 2.1-0.273 3.11 0.016 29.907 0.016 59.921 0.016 89.758q0 112.11 0 224.221c0.66 1.778 1.041 3.831 1.041 5.974 0 7.121-4.216 13.258-10.289 16.050-2.023 0.657-4.224 1.009-6.508 1.009-7.33 0-13.812-3.632-17.744-9.194q-45.949-45.971-91.499-92.051c3.89 5.539-2.709-2.264-7.247-11.283z",
781
+ "M886.113 774.003c5.826 6.179 8.121 9.004 10.77 11.652 35.31 35.31 69.385 69.032 103.636 104.166 14.141 14.205 22.884 33.795 22.884 55.426 0 36.978-25.546 67.989-59.952 76.347-6.248 1.654-12.806 2.541-19.57 2.541-21.704 0-41.275-9.129-55.085-23.756l-104.023-103.849-7.945-7.768-9.357 8.828-89.159 89.335c0.312 0.541-3.553 4.67-8.341 7.347-4.333 2.131-9.274 3.337-14.497 3.337-1.911 0-3.784-0.161-5.606-0.471-4.663-3.855-7.749-9.78-7.749-16.426 0-0.050 0-0.1 0.001-0.15-0-73.261-0-146.53-0-219.799 0-32.662 0-65.324 0-97.986-0.459-1.497-0.723-3.218-0.723-5.001 0-9.751 7.904-17.655 17.655-17.655 1.833 0 3.6 0.279 5.262 0.797l317.668-0.034c0.522-0.060 1.127-0.093 1.74-0.093 8.971 0 16.243 7.272 16.243 16.243 0 4.019-1.46 7.697-3.878 10.533 4.384-5.383-1.42 3.319-8.937 10.174q-44.716 44.711-89.56 89.202c3.812-2.402-3.136 3.205-11.14 6.922z",
782
+ "M245.76 136.828l89.688-90.041c-6.447 6.153 4.178-6.713 17.378-16.229 5.098-3.007 10.891-4.67 17.072-4.67 1.423 0 2.826 0.088 4.203 0.259 8.486 1.396 8.31 10.4 8.31 17.638q0 157.837 0 315.498c0 18.538-4.943 23.128-24.011 23.128-104.342 0-208.861 0-313.203 0-6.749-0.104-13.125-3.133-17.643-7.932-1.432-2.499-2.269-5.477-2.269-8.651 0-5.661 2.665-10.7 6.808-13.931 15.399-15.743 31.112-31.279 46.649-46.816l57.026-57.909-9.181-9.71c-35.31-35.31-69.385-69.032-103.636-104.166-14.223-13.509-23.071-32.559-23.071-53.676 0-8.596 1.466-16.85 4.162-24.525 6.485-26.059 29.621-47.893 58.533-53.086 5.633-1.325 11.579-2.046 17.693-2.046 21.959 0 41.746 9.302 55.635 24.18l102.264 102.444c-11.027-12.493-0.547-2.233 7.359 9.861z",
783
+ "M775.062 137.534c39.901-40.077 76.623-77.33 114.052-114.052 14.357-14.968 34.522-24.269 56.859-24.269 43.488 0 78.742 35.254 78.742 78.742 0 22.645-9.559 43.057-24.861 57.421-33.94 34.29-68.191 68.188-102.266 102.263-2.825 2.825-5.65 6.003-9.534 10.24l62.323 61.263c13.418 13.418 27.189 26.483 40.077 40.43 3.281 2.891 7.111 9.74 8.444 17.445 1.443 10.097-5.443 15.394-17.625 15.57h-312.32c-23.658 0-27.719-4.061-27.719-27.895q0-154.306 0-308.789c-0.413-1.424-0.651-3.059-0.651-4.749 0-6.691 3.722-12.513 9.21-15.508 2.175-0.813 4.58-1.256 7.088-1.256 6.687 0 12.638 3.151 16.45 8.049q45.938 45.421 91.312 91.147c-15.147-17.038-0.765-3.060 10.102 13.439z"
784
+ ],
785
+ "attrs": [],
786
+ "isMulticolor": false,
787
+ "grid": 0,
788
+ "tags": [
789
+ "minify"
790
+ ],
791
+ "colorPermutations": {}
792
+ },
793
+ {
794
+ "id": 49,
795
+ "paths": [
796
+ "M57.234 569.417h217.051l164.571 418.011c8.581 21.457 29.195 36.339 53.284 36.339 28.233 0 51.692-20.443 56.381-47.334l119.455-695.199 89.966 250.149c8.129 22.356 29.192 38.034 53.918 38.034 0.009 0 0.018-0 0.026-0l264.593 0c31.711-0 57.417-25.707 57.417-57.417s-25.707-57.417-57.417-57.417h-223.817l-150.126-416.549c-8.447-21.735-29.2-36.861-53.486-36.861-27.832 0-51.024 19.866-56.17 46.191l-122.207 707.105-103.314-263.497c-8.551-21.544-29.217-36.526-53.389-36.571l-256.006-0c-31.711 0-57.417 25.707-57.417 57.417s25.707 57.417 57.417 57.417h0z"
797
+ ],
798
+ "attrs": [],
799
+ "isMulticolor": false,
800
+ "width": 1134,
801
+ "grid": 0,
802
+ "tags": [
803
+ "uptime"
804
+ ],
805
+ "colorPermutations": {}
806
+ },
807
+ {
808
+ "id": 47,
809
+ "paths": [
810
+ "M365.714 941.897c5.976 10.646 28.073 27.415 54.041 35.262 31.188 10.424 66.163 16.318 102.515 16.318 38.771 0 75.977-6.704 110.52-19.015-13.109 5.71 1.945 0.090 15.19-8.16-33.216-43.97-73.627-69.57-128.484-67.193s-103.131 25.783-153.783 42.789zM125.074 740.754c-3.508-4.984-5.606-11.179-5.606-17.865 0-9.726 4.44-18.414 11.404-24.149 7.002-8.637 15.414-15.952 21.631-24.912-4.73 9.278 15.3-15.941 28.060-45.071 11.803-37.763 8.328-48.369-17.82-67.203-1.097 0-2.011-1.829-3.109-2.56-14.538-5.499-40.503-33.064-54.492-66.844-3.657-7.945-7.497-14.527-10.423-21.659-15.909-34.194-29.989-68.206-21.577-108.434 8.298-9.68-1.302-0.041-8.378 11.33 20.448-38.773-2.988-0.547-18.783 41.421-10.326 34.045-15.799 70.328-15.799 107.889s5.474 73.844 15.667 108.095c-0.221 16.144 12.884 49.446 33.481 76.783 3.135 7.668 21.778 23.63 44.121 32.032zM454.217 98.743l1.28 2.194c8.042-10.711 0.704 0.748-8.764 10.044-18.299 15.19-36.584 30.184-54.87 45.361 59.907-40.798 9.274-11.484-33.074 26.82-1.783 2.523-3.062 6.094-3.062 9.964 0 1.683 0.242 3.309 0.693 4.846 2.261 3.854 6.823 6.973 12.148 7.552 0.898 0.057 1.861 0.085 2.832 0.085 6.38 0 12.471-1.238 18.045-3.486q91.104-35.176 180.521-71.382c2.854-1.477 5.345-4.779 6.024-8.702 0.122-0.926 0.186-1.91 0.186-2.909 0-12.725-10.315-23.040-23.040-23.040-1.615 0-3.192 0.166-4.713 0.482-0.754 0.189-1.792 0.313-2.859 0.313-6.948 0-12.673-5.237-13.443-11.979-2.099-5.094-3.315-10.939-3.315-17.068 0-0.45 0.007-0.898 0.020-1.345 0.23-0.933 0.363-2.080 0.363-3.259 0-7.25-5.023-13.327-11.779-14.94 8.614 5.016-0.37-1.021-10.353-5.127-9.261-4.806-26.68-9.694-45.095-10.962-78.148 2.53-171.621 39.469-246.413 98.904 37.597-34.161-25.949 13.059-74.639 72.857l13.606 28.078c4.925 1.539 10.588 2.426 16.458 2.426 9.768 0 18.962-2.455 27-6.781 6.459-3.32 14.452-5.354 22.919-5.354s16.46 2.034 23.515 5.639c-4.164-1.729 1.135 0.895 6.854 2.522 4.053 1.832 8.393 2.851 12.97 2.851 16.663 0 30.171-13.508 30.171-30.171 0-0.137-0.001-0.273-0.003-0.409 0.016 0.566 0.75-3.026 1.083-6.734 0.525-10.233 6.505-19.572 15.231-24.801-11.879 9.884-0.573-0.973 12.66-8.961q56.969-30.067 113.837-59.141c-6.309 2.273 3.829-2.272 14.694-4.98zM503.223 341.211c13.531-6.4 26.514-12.069 39.314-18.286 5.65-2.873 12.322-4.556 19.386-4.556 4.433 0 8.71 0.663 12.74 1.894-1.772-5.663 56.736 14.645 107.651 46.072-11.303-9.775 12.401 6.356 30.666 27.346 12.963 14.089 23.386 30.18 35.272 44.992-6.989-3.404 18.165 26.478 49.745 47.457 10.514 6.811 22.49 10.592 35.348 10.592 3.984 0 7.883-0.363 11.666-1.058 11.396-0.105 20.89-9.701 20.89-21.515 0-4.048-1.114-7.835-3.053-11.072-0.976-1.882-1.581-4.226-1.581-6.711 0-1.416 0.196-2.787 0.563-4.086 2.929-2.032 6.625-3.313 10.621-3.313 0.759 0 1.507 0.046 2.242 0.136 2.334 0.111 7.185 2.578 10.887 6.212 25.231 20.659 50.099 41.688 75.699 61.985 12.069 9.509 21.211 6.949 25.783-7.863 3.369-9.396 5.316-20.237 5.316-31.532 0-0.55-0.005-1.099-0.014-1.647-0.263-42.389-13.256-99.616-36.027-151.584 7.501 12.427-6.079-20.844-26.073-49.278 118.608 161.488 35.527 28.798-71.081-80.907 50.945 50.529 7.397 0.455-45.169-38.030-7.394-5.781-15.317-8.763-23.936-8.763-5.84 0-11.361 1.369-16.258 3.804-12.222 5.39-24.473 11.424-36.359 18.19-16.64 8.046-18.286 7.314-25.234-9.326-1.026-10.748-10.008-19.088-20.939-19.088-5.21 0-9.977 1.894-13.65 5.032-22.28 13.69-43.857 28.867-65.434 43.679-4.895 3.332-8.068 8.878-8.068 15.165 0 2.441 0.478 4.771 1.347 6.9q2.882 8.289 5.259 17.066c1.995 2.751 3.191 6.194 3.191 9.917 0 8.97-6.946 16.319-15.752 16.96-21.084 8.049-42.661 15.546-63.141 24.689 2.909-3.329-14.693 6.197-28.765 19.435-6.227 5.566-10.163 13.695-10.163 22.744 0 6.523 2.045 12.568 5.529 17.53zM593.554 397.166c-20.993-12.338-46.239-19.625-73.188-19.625-1.463 0-2.921 0.021-4.373 0.064-65.067 5.298-106.027 42.966-133.821 97.824-3.271 5.69-5.2 12.511-5.2 19.782 0 12.99 6.157 24.542 15.711 31.897-8.384-4.063 15.818 14.994 43.748 27.058-34.324-12.321 16.004 9.664 69.761 22.946 21.284 3.464 36.121 17.656 39.951 35.897-2.367-6.813 0.391 0.114 2.137 7.433 6.143 39.307 12.36 78.073 18.395 116.838-2.344-10.411 2.408 32.601 10.992 74.213 6.928 25.261 26.676 31.295 52.459 13.924-12.475 9.056 4.526-1.252 18.3-14.826-29.756 26.513 2.517 1.845 27.796-28.806 26.681-35.728 52.647-71.202 77.332-107.408 1.65-7.609 18.879-26.348 40.565-37.757 21.975-7.156 37.189-26.885 37.189-50.166 0-0.718-0.014-1.433-0.043-2.144-0.063-0.2-0.1-0.548-0.1-0.904s0.038-0.703 0.109-1.038c0.586-1.261 0.931-2.772 0.931-4.365 0-4.378-2.608-8.147-6.355-9.838 36.045 26.123 5.795 0.803-28.714-17.572-17.225-5.638-35.937-23.326-45.206-45.89 10.205 22.437 0.183-4.434-14.439-28.168 14.264 22.666 0.548-3.173-17.978-24.763-1.787-2.226-6.771-5.211-12.43-6.305-19.907-4.414-40.204-7.34-59.587-12.643 26.012 9.617-12.883-1.666-48.169-19.14-4.050-0.727-8.367-6.070-8.367-12.422 0-1.803 0.348-3.525 0.981-5.102zM539.977 1024h-55.954c2.685 0.476-3.199-1.009-9.304-1.788-65.31-1.008-144.474-24.437-212.994-64.186-120.342-57.945-225.505-193.667-253.256-355.816-4.080-22.553-5.909-42.484-8.469-62.233v-55.954c-0.579 3.095 0.961-2.979 1.785-9.279 1.727-81.753 33.964-174.177 87.408-250.693 62.601-105.24 193.094-195.584 345.686-217.516 18.059-2.695 33.601-4.341 49.144-6.17h55.954c-2.808-0.507 3.133 0.994 9.296 1.787 44.675 0.295 103.039 13.054 156.284 35.552 169.597 73.29 274.922 202.57 310.579 387.438 3.84 19.749 5.303 40.046 7.863 60.16v54.857c0.445-2.562-1.023 3.265-1.789 9.311-0.264 42.76-13.201 101.078-35.915 154.22-75.118 174.938-208.604 281.544-400.055 314.458-15.177 2.56-30.72 3.84-46.263 5.851z"
811
+ ],
812
+ "attrs": [],
813
+ "isMulticolor": false,
814
+ "grid": 0,
815
+ "tags": [
816
+ "world"
817
+ ],
818
+ "colorPermutations": {}
819
+ },
820
+ {
821
+ "id": 3,
822
+ "paths": [
823
+ "M0 575.81c0-35.241 28.456-63.81 64.056-63.81h895.888c35.377 0 64.056 28.994 64.056 63.81v384.38c0 35.241-28.456 63.81-64.056 63.81h-895.888c-35.377 0-64.056-28.994-64.056-63.81v-384.38zM0 288c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0 160c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0 32c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0 416c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32z"
824
+ ],
825
+ "attrs": [],
826
+ "isMulticolor": false,
827
+ "grid": 0,
828
+ "tags": [
829
+ "footer"
830
+ ],
831
+ "colorPermutations": {}
832
+ },
833
+ {
834
+ "id": 4,
835
+ "paths": [
836
+ "M0 704.19c0 35.241 28.456 63.81 64.056 63.81h895.888c35.377 0 64.056-28.994 64.056-63.81v-384.38c0-35.241-28.456-63.81-64.056-63.81h-895.888c-35.377 0-64.056 28.994-64.056 63.81v384.38zM0 160c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 864c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 992c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 32c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32z"
837
+ ],
838
+ "attrs": [],
839
+ "isMulticolor": false,
840
+ "grid": 0,
841
+ "tags": [
842
+ "middle",
843
+ "center"
844
+ ],
845
+ "colorPermutations": {}
846
+ },
847
+ {
848
+ "id": 5,
849
+ "paths": [
850
+ "M0 448.19c0 35.241 28.456 63.81 64.056 63.81h895.888c35.377 0 64.056-28.994 64.056-63.81v-384.38c0-35.241-28.456-63.81-64.056-63.81h-895.888c-35.377 0-64.056 28.994-64.056 63.81v384.38zM0 736c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 864c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 992c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 608c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32z"
851
+ ],
852
+ "attrs": [],
853
+ "isMulticolor": false,
854
+ "grid": 0,
855
+ "tags": [
856
+ "header"
857
+ ],
858
+ "colorPermutations": {}
859
+ },
860
+ {
861
+ "id": 6,
862
+ "paths": [
863
+ "M707.467 151.080c-2.704-9.436-9.638-16.489-18.143-19.762-0.335-0.134-0.671-0.263-1.011-0.385-0.338-0.116-0.678-0.224-1.020-0.328-3.334-1.063-6.841-1.586-10.376-1.438-0.732 0.032-1.507 0.048-2.322 0.048-4.964 0.008-11.389-0.645-18.57-2.063-12.594-2.459-27.479-7.227-42.21-13.683-11.060-4.833-22.069-10.603-32.15-16.917-7.561-4.732-14.603-9.77-20.762-14.877-4.621-3.827-8.744-7.693-12.233-11.443-5.247-5.621-9.006-11-11.161-15.356-1.087-2.179-1.496-4.090-1.911-5.683-0.417-1.597-0.265-2.865-0.265-3.929v-0.147c0-9.547-4.633-18.687-12.259-24.436-7.624-5.749-17.788-7.537-26.931-4.782l-474.675 143.044c-12.698 3.827-21.469 15.534-21.469 28.795v666.072c0 10.182 1.798 20.104 4.889 29.476 2.707 8.21 6.395 16.027 10.827 23.458 7.77 13.003 17.797 24.86 29.448 35.633 17.493 16.137 38.693 29.876 62.282 40.397 23.591 10.496 49.603 17.75 76.729 20.243 3.777 0.346 7.663-0.039 11.299-1.119 0.985-0.293 2.247-0.677 3.919-1.192 6.43-1.98 18.749-5.841 35.546-11.126 117.454-36.968 452.335-143.268 452.35-143.274 12.466-3.956 20.976-15.585 20.976-28.664v-653.767c0.633-4.15 0.433-8.495-0.798-12.795v0zM542.709 142.981c8.776 5.86 17.982 11.248 27.4 16.17-39.795 11.404-87.554 25.093-135.832 38.936-59.784 17.143-120.357 34.518-167.561 48.078-23.603 6.78-43.863 12.604-59.017 16.971-7.579 2.183-13.88 4.001-18.692 5.395-1.489 0.43-2.812 0.814-4.006 1.161-15.907-1.901-31.585-5.708-46.115-10.997-12.141-4.412-23.481-9.844-33.481-15.902-7.501-4.541-14.245-9.436-20.027-14.452-7.916-6.848-13.95-13.929-17.953-20.448l416.585-125.558c1.54 3.032 3.209 5.977 5.006 8.824 4.783 7.561 10.395 14.531 16.585 21.076 10.842 11.437 23.473 21.618 37.108 30.746v0zM105.647 913.493c-7.508-4.95-14.299-10.286-20.161-15.755-8.803-8.197-15.457-16.72-19.586-24.403-2.075-3.839-3.531-7.454-4.447-10.723-0.916-3.275-1.302-6.188-1.302-8.803v-568.871c14.659 10.516 31.171 19.49 48.965 26.74 14.961 6.078 30.833 10.922 47.275 14.275v610.805c-5.932-1.717-11.765-3.705-17.43-5.962-12.018-4.782-23.302-10.699-33.314-17.302v0zM256.541 919.698c-15.080 4.762-28.58 9.019-40 12.613v-609.125c15.947-4.6 40.601-11.481 69.172-19.743v267.943l83.133-83.765 55.211 27.922v-252.161c45.112-12.656 89.321-25.505 129.125-36.914 37.621-10.783 71.111-20.275 94.933-27.1v596.265c-42.103 13.361-141.164 44.792-237.658 75.363-56.069 17.762-111.271 35.236-153.917 48.702v0z"
864
+ ],
865
+ "attrs": [],
866
+ "isMulticolor": false,
867
+ "width": 727,
868
+ "grid": 0,
869
+ "tags": [
870
+ "book"
871
+ ],
872
+ "colorPermutations": {}
873
+ },
874
+ {
875
+ "id": 9,
876
+ "paths": [
877
+ "M504.231 955.882c22.087-9.699 42.18-20.276 60.268-31.085 39.815-23.797 69.925-48.698 90.442-68.056 1.536 0.142 3.092 0.214 4.664 0.214 27.658 0 50.078-22.421 50.078-50.078v-206.037c0-27.658-22.421-50.078-50.078-50.078s-50.078 22.421-50.078 50.078v200.346c-6.829 6.618-15.244 14.275-25.222 22.478-15.543 12.784-34.873 26.902-57.905 40.556-14.759 8.751-31.036 17.312-48.824 25.227-11.141-4.622-23.975-5.258-36.212-0.833-16.277 5.886-33.641 11.126-52.114 15.437-26.934 6.284-43.674 33.213-37.388 60.147 6.284 26.934 33.213 43.674 60.147 37.388 22.439-5.235 43.588-11.614 63.421-18.787 13.406-4.849 23.478-14.826 28.803-26.918zM101.589 702.427v-277.577c0.007-42.612 8.608-82.95 24.154-119.726 23.312-55.141 62.386-102.213 111.51-135.39 24.558-16.59 51.606-29.709 80.464-38.686 28.862-8.974 59.532-13.819 91.496-13.822 42.612 0.007 82.948 8.608 119.726 24.154 55.141 23.312 102.213 62.386 135.39 111.51 16.59 24.558 29.709 51.605 38.686 80.463 8.974 28.864 13.819 59.533 13.822 91.497v277.577c0 27.658 22.421 50.078 50.078 50.078s50.078-22.421 50.078-50.078v-277.577c0.007-56.165-11.411-109.929-32.066-158.743-30.991-73.243-82.631-135.406-147.685-179.366-32.532-21.979-68.44-39.405-106.787-51.33-38.341-11.929-79.124-18.344-121.243-18.342-56.165-0.007-109.929 11.411-158.743 32.066-73.243 30.991-135.406 82.629-179.366 147.685-21.977 32.532-39.405 68.44-51.33 106.787-11.929 38.34-18.344 79.124-18.342 121.243v277.577c0 27.658 22.421 50.078 50.078 50.078s50.078-22.421 50.078-50.078zM108.743 602.271v206.037c0 27.658 22.421 50.078 50.078 50.078s50.078-22.421 50.078-50.078v-206.037c0-27.658-22.421-50.078-50.078-50.078s-50.078 22.421-50.078 50.078z"
878
+ ],
879
+ "attrs": [],
880
+ "isMulticolor": false,
881
+ "width": 847,
882
+ "grid": 0,
883
+ "tags": [
884
+ "support"
885
+ ],
886
+ "colorPermutations": {}
887
+ },
888
+ {
889
+ "id": 33,
890
+ "paths": [
891
+ "M603.2 777.6c-36.8 36.8-148.8 36.8-184 0-19.2-19.2-35.2 0-35.2 19.2 0 33.6 0 78.4 0 112 0 19.2 17.6 36.8 36.8 19.2 11.2-11.2 24-24 36.8-36.8 11.2 27.2 25.6 64 36.8 92.8 9.6 24 27.2 24 36.8 0 9.6-25.6 27.2-70.4 36.8-92.8 9.6 9.6 17.6 17.6 36.8 36.8 17.6 17.6 36.8 0 36.8-19.2 0-32 0-78.4 0-112-1.6-19.2-19.2-38.4-38.4-19.2zM800 540.8c-19.2-19.2-80-60.8-80-80 0-168-51.2-307.2-144-400-52.8-52.8-76.8-51.2-128 0-92.8 92.8-144 232-144 400 0 17.6-62.4 62.4-80 80-36.8 36.8-32 76.8-32 96 0 56 25.6 140.8 32 160 11.2 36.8 60.8 35.2 80 16 36.8-36.8 83.2-83.2 96-96 56 56 168 56 224 0 12.8 12.8 59.2 59.2 96 96 19.2 19.2 70.4 20.8 80-16 4.8-19.2 32-104 32-160 0-19.2 4.8-59.2-32-96zM512 425.6c-52.8 0-96-43.2-96-96s43.2-96 96-96c51.2 0 96 44.8 96 96 0 49.6-43.2 96-96 96zM560 329.6c0 26.51-21.49 48-48 48s-48-21.49-48-48c0-26.51 21.49-48 48-48s48 21.49 48 48z"
892
+ ],
893
+ "attrs": [],
894
+ "isMulticolor": false,
895
+ "tags": [
896
+ "rocket"
897
+ ],
898
+ "defaultCode": 106,
899
+ "grid": 0,
900
+ "colorPermutations": {}
901
+ },
902
+ {
903
+ "id": 7,
904
+ "paths": [
905
+ "M797.496 32.018c0-3.36-0.111-5.277-0.139-5.804-0.472-8.415-4.721-16.135-11.581-21.023-6.86-4.916-15.552-6.443-23.662-4.138-5.388 1.416-162.048 47.823-387.305 306.712-98.062 16.358-160.549 52.878-197.291 97.062-38.908 46.657-47.712 98.701-47.656 135.36 0.028 31.021 6.026 52.044 6.526 53.794 3.166 10.942 12.719 18.857 24.050 19.912 11.359 1.083 22.217-4.916 27.383-15.080l0.361-0.667c2.138-4.138 14.136-26.078 30.549-45.879 2.138-2.611 4.499-4.943 6.776-7.415 0.417 0.305 0.639 0.833 1.083 1.139l91.314 63.931-14.775 56.682c-1.472 5.554 0.667 11.47 5.332 14.802 4.693 3.333 10.942 3.444 15.747 0.305l49.545-32.687 90.258 63.209c0.444 0.305 1.028 0.361 1.5 0.667-6.415 12.331-14.469 24.384-21.551 33.798-4.666 6.249-8.887 11.414-11.886 14.941l-3.471 3.971-0.861 0.972-0.167 0.194c-7.721 8.276-9.637 20.496-4.832 30.743 4.832 10.248 15.469 16.552 26.744 15.913 2.638-0.305 49.406-2.86 98.618-34.132 24.495-15.663 49.462-38.936 67.93-72.262 18.468-33.298 30.16-76.206 30.105-129.722 0-25.828-2.86-54.349-8.693-85.537 151.19-270.636 160.104-428.047 160.049-459.762v0zM636.142 135.69c43.796-32.521 78.455-52.489 102.617-64.625-10.664 80.372-58.487 276.579-265.998 579.486l-84.176-58.932 141.275-200.401c4.416-6.249 2.916-14.913-3.36-19.329s-14.941-2.944-19.357 3.333l-141.303 200.457-84.454-59.126c143.025-199.874 266.776-315.432 354.757-380.862v0zM189.877 501.583c4.666-19.94 13.636-41.213 30.299-61.181 18.774-22.467 48.323-44.379 94.841-60.709-20.94 26.244-42.296 54.155-64.097 84.065-15.774 3.583-29.466 11.164-41.186 19.968-7.248 5.499-13.719 11.609-19.857 17.857v0zM339.123 638.609l3.027-11.692 7.137 4.999-10.164 6.693zM590.596 577.317c-0.028 45.657-9.665 78.4-23.162 102.783-13.691 24.661-31.826 41.297-50.184 52.85 1.722-3.527 3.61-6.887 5.166-10.609 6.304-15.274 11.136-31.938 11.192-50.017 0-3.749-0.278-7.582-0.778-11.442 20.634-30.688 40.075-60.543 57.599-89.12 0.028 1.833 0.167 3.777 0.167 5.554zM213.4 843.065l63.681-90.953c8.804-12.581 5.749-29.882-6.804-38.686-12.581-8.804-29.882-5.749-38.686 6.832l-63.681 90.953c-8.804 12.581-5.749 29.882 6.832 38.686 12.553 8.804 29.882 5.749 38.658-6.832zM326.848 798.297l-127.417 181.989c-8.804 12.553-5.749 29.882 6.832 38.686 12.553 8.804 29.855 5.749 38.658-6.832l127.417-181.989c8.804-12.553 5.749-29.855-6.832-38.658-12.553-8.804-29.882-5.749-38.658 6.804zM171.104 680.406c-12.553-8.804-29.882-5.749-38.658 6.804l-127.417 181.989c-8.804 12.553-5.749 29.882 6.832 38.686 12.553 8.776 29.855 5.749 38.658-6.832l127.417-181.961c8.804-12.581 5.749-29.882-6.832-38.686zM543.218 346.394c7.609 5.304 16.302 7.859 24.911 7.859 13.691 0 27.161-6.443 35.631-18.524 13.775-19.69 9.026-46.768-10.664-60.543-7.582-5.332-16.274-7.887-24.884-7.887-13.719 0-27.189 6.471-35.659 18.552-13.719 19.662-8.998 46.768 10.664 60.543z"
906
+ ],
907
+ "attrs": [],
908
+ "isMulticolor": false,
909
+ "width": 800,
910
+ "grid": 0,
911
+ "tags": [
912
+ "rocket"
913
+ ],
914
+ "colorPermutations": {}
915
+ },
916
+ {
917
+ "id": 25,
918
+ "paths": [
919
+ "M568 848h-112l20.8-120c-28.8-12.8-48-41.6-48-75.2 0-46.4 36.8-83.2 83.2-83.2s83.2 36.8 83.2 83.2c0 33.6-19.2 62.4-48 75.2l20.8 120zM624 456h-224v-168c0-62.4 51.2-112 112-112s112 49.6 112 112v168zM736 456v-168c0-123.2-100.8-224-224-224s-224 100.8-224 224v168h-56c-30.4 0-56 25.6-56 56v392c0 30.4 25.6 56 56 56h560c30.4 0 56-25.6 56-56v-392c0-30.4-25.6-56-56-56h-56z"
920
+ ],
921
+ "attrs": [],
922
+ "isMulticolor": false,
923
+ "tags": [
924
+ "lock"
925
+ ],
926
+ "defaultCode": 97,
927
+ "grid": 0,
928
+ "colorPermutations": {}
929
+ },
930
+ {
931
+ "id": 26,
932
+ "paths": [
933
+ "M800 448h-64v-160c0-123.2-100.8-224-224-224s-224 100.8-224 224c0 0 0 40 0 48s8 16 16 16 72 0 80 0c8 0 16-8 16-16s0-48 0-48c0-62.4 51.2-112 112-112 62.4 0 112 49.6 112 112v160h-400c-30.4 0-48 17.6-48 48v408c0 30.4 25.6 56 56 56h560c30.4 0 56-25.6 56-56v-408c0-30.4-17.6-48-48-48zM547.2 728l20.8 120h-112l20.8-120c-28.8-12.8-48-41.6-48-75.2 0-46.4 36.8-83.2 83.2-83.2s83.2 36.8 83.2 83.2c0 32-19.2 60.8-48 75.2z"
934
+ ],
935
+ "attrs": [],
936
+ "isMulticolor": false,
937
+ "tags": [
938
+ "unlock"
939
+ ],
940
+ "defaultCode": 99,
941
+ "grid": 0,
942
+ "colorPermutations": {}
943
+ },
944
+ {
945
+ "id": 27,
946
+ "paths": [
947
+ "M272 224c16-16 544 512 528 528-65.6 65.6-160 112-272 112-75.2 0-164.8 0-224 0-12.8 0-24 4.8-32 12.8-20.8 17.6-38.4 38.4-59.2 57.6-35.2 33.6-86.4 33.6-120 0-35.2-33.6-35.2-84.8-1.6-121.6 17.6-19.2 38.4-36.8 56-57.6 8-9.6 12.8-22.4 12.8-35.2 0-67.2 0-139.2 0-224 0-112 48-208 112-272zM785.6 606.4c-16 16-128-96-112-112s139.2-137.6 176-174.4c33.6-33.6 144 80 112 110.4-59.2 59.2-116.8 116.8-176 176zM545.6 366.4c-16 16-128-96-112-112s139.2-137.6 176-174.4c33.6-33.6 144 80 112 110.4-59.2 59.2-116.8 116.8-176 176z"
948
+ ],
949
+ "attrs": [],
950
+ "isMulticolor": false,
951
+ "tags": [
952
+ "plugin"
953
+ ],
954
+ "defaultCode": 100,
955
+ "grid": 0,
956
+ "colorPermutations": {}
957
+ },
958
+ {
959
+ "id": 39,
960
+ "paths": [
961
+ "M779.2 667.2c-27.2 27.2-67.2 27.2-94.4 0l-172.8-172.8-172.8 172.8c-27.2 27.2-67.2 27.2-94.4 0s-27.2-67.2 0-94.4l204.8-204.8c14.4-14.4 32-32 62.4-32s49.6 17.6 62.4 32l204.8 204.8c27.2 27.2 27.2 67.2 0 94.4z"
962
+ ],
963
+ "attrs": [],
964
+ "isMulticolor": false,
965
+ "tags": [
966
+ "caret up"
967
+ ],
968
+ "defaultCode": 114,
969
+ "grid": 0,
970
+ "colorPermutations": {}
971
+ },
972
+ {
973
+ "id": 71,
974
+ "paths": [
975
+ "M451.2 779.2l204.8-204.8c14.4-14.4 32-32 32-62.4s-17.6-49.6-32-62.4l-204.8-204.8c-27.2-27.2-67.2-27.2-94.4 0s-27.2 67.2 0 94.4l172.8 172.8-172.8 172.8c-27.2 27.2-27.2 67.2 0 94.4s67.2 27.2 94.4 0z"
976
+ ],
977
+ "attrs": [],
978
+ "isMulticolor": false,
979
+ "tags": [
980
+ "caret right"
981
+ ],
982
+ "defaultCode": 101,
983
+ "grid": 0,
984
+ "colorPermutations": {}
985
+ },
986
+ {
987
+ "id": 28,
988
+ "paths": [
989
+ "M779.2 451.2l-204.8 204.8c-14.4 14.4-32 32-62.4 32s-49.6-17.6-62.4-32l-204.8-204.8c-27.2-27.2-27.2-67.2 0-94.4s67.2-27.2 94.4 0l172.8 172.8 172.8-172.8c27.2-27.2 67.2-27.2 94.4 0s27.2 67.2 0 94.4z"
990
+ ],
991
+ "attrs": [],
992
+ "isMulticolor": false,
993
+ "tags": [
994
+ "caret down"
995
+ ],
996
+ "defaultCode": 101,
997
+ "grid": 0,
998
+ "colorPermutations": {}
999
+ },
1000
+ {
1001
+ "id": 72,
1002
+ "paths": [
1003
+ "M572.8 779.2l-204.8-204.8c-14.4-14.4-32-32-32-62.4s17.6-49.6 32-62.4l204.8-204.8c27.2-27.2 67.2-27.2 94.4 0s27.2 67.2 0 94.4l-172.8 172.8 172.8 172.8c27.2 27.2 27.2 67.2 0 94.4s-67.2 27.2-94.4 0z"
1004
+ ],
1005
+ "attrs": [],
1006
+ "isMulticolor": false,
1007
+ "tags": [
1008
+ "caret left"
1009
+ ],
1010
+ "defaultCode": 101,
1011
+ "grid": 0,
1012
+ "colorPermutations": {}
1013
+ },
1014
+ {
1015
+ "id": 29,
1016
+ "paths": [
1017
+ "M848 233.6c-16-20.8-46.4-24-67.2-6.4-20.8 16-24 46.4-6.4 67.2v0c48 59.2 75.2 131.2 75.2 212.8 0 92.8-38.4 177.6-99.2 238.4s-145.6 99.2-238.4 99.2c-92.8 0-177.6-38.4-238.4-99.2s-99.2-145.6-99.2-238.4c0-80 27.2-153.6 75.2-212.8 16-20.8 12.8-49.6-6.4-67.2-20.8-16-49.6-12.8-67.2 6.4-60.8 75.2-96 169.6-96 272 0 118.4 48 227.2 126.4 305.6s185.6 126.4 305.6 126.4c118.4 0 227.2-48 305.6-126.4s126.4-187.2 126.4-307.2c0-102.4-35.2-196.8-96-270.4zM512 561.6c27.2 0 48-20.8 48-48v-384c0-27.2-20.8-48-48-48s-48 20.8-48 48v384c0 27.2 20.8 48 48 48z"
1018
+ ],
1019
+ "attrs": [],
1020
+ "isMulticolor": false,
1021
+ "tags": [
1022
+ "power"
1023
+ ],
1024
+ "defaultCode": 102,
1025
+ "grid": 0,
1026
+ "colorPermutations": {}
1027
+ },
1028
+ {
1029
+ "id": 31,
1030
+ "paths": [
1031
+ "M512 156.8c195.2 0 355.2 158.4 355.2 355.2s-160 355.2-355.2 355.2-355.2-160-355.2-355.2 160-355.2 355.2-355.2zM512 64c-248 0-448 200-448 448s200 448 448 448 448-200 448-448-200-448-448-448z"
1032
+ ],
1033
+ "attrs": [],
1034
+ "isMulticolor": false,
1035
+ "tags": [
1036
+ "radio_default"
1037
+ ],
1038
+ "defaultCode": 104,
1039
+ "grid": 0,
1040
+ "colorPermutations": {}
1041
+ },
1042
+ {
1043
+ "id": 30,
1044
+ "paths": [
1045
+ "M512 64c-248 0-448 200-448 448s200 448 448 448 448-200 448-448-200-448-448-448zM720 464l-176 176c-3.2 3.2-28.8 32-64 32s-60.8-28.8-64-32l-112-112c-16-16-16-48 0-64s48-14.4 64 1.6l112 110.4 176-176c16-16 48-16 64 0s16 48 0 64z"
1046
+ ],
1047
+ "attrs": [],
1048
+ "isMulticolor": false,
1049
+ "tags": [
1050
+ "radio_checked"
1051
+ ],
1052
+ "defaultCode": 103,
1053
+ "grid": 0,
1054
+ "colorPermutations": {}
1055
+ },
1056
+ {
1057
+ "id": 45,
1058
+ "paths": [
1059
+ "M608 512l208-208c28.8-28.8 28.8-67.2 0-96s-67.2-28.8-96 0l-208 208-208-208c-28.8-28.8-67.2-28.8-96 0s-28.8 67.2 0 96l208 208-208 208c-28.8 28.8-28.8 67.2 0 96s67.2 28.8 96 0l208-208 208 208c28.8 28.8 67.2 28.8 96 0s28.8-67.2 0-96l-208-208z"
1060
+ ],
1061
+ "attrs": [],
1062
+ "isMulticolor": false,
1063
+ "tags": [
1064
+ "cross"
1065
+ ],
1066
+ "defaultCode": 121,
1067
+ "grid": 0,
1068
+ "colorPermutations": {}
1069
+ },
1070
+ {
1071
+ "id": 46,
1072
+ "paths": [
1073
+ "M400 667.2l-256-256c-28.8-28.8-83.2-28.8-112 0s-28.8 83.2 0 112l304 304c14.4 14.4 32 32 64 32s49.6-17.6 64-32l528-528c28.8-28.8 28.8-83.2 0-112s-83.2-28.8-112 0l-480 480z"
1074
+ ],
1075
+ "attrs": [],
1076
+ "isMulticolor": false,
1077
+ "tags": [
1078
+ "tick"
1079
+ ],
1080
+ "defaultCode": 122,
1081
+ "grid": 0,
1082
+ "colorPermutations": {}
1083
+ },
1084
+ {
1085
+ "id": 34,
1086
+ "paths": [
1087
+ "M923.2 822.4l-228.8-230.4c33.6-52.8 52.8-112 52.8-179.2-1.6-184-150.4-332.8-334.4-332.8s-332.8 148.8-332.8 332.8 148.8 332.8 332.8 332.8c67.2 0 126.4-19.2 179.2-52.8l230.4 230.4c28.8 28.8 73.6 28.8 100.8 0s27.2-73.6 0-100.8zM174.4 412.8c0-131.2 105.6-238.4 238.4-238.4s238.4 105.6 238.4 238.4-107.2 236.8-238.4 236.8-238.4-105.6-238.4-236.8z"
1088
+ ],
1089
+ "attrs": [],
1090
+ "isMulticolor": false,
1091
+ "tags": [
1092
+ "search"
1093
+ ],
1094
+ "defaultCode": 107,
1095
+ "grid": 0,
1096
+ "colorPermutations": {}
1097
+ },
1098
+ {
1099
+ "id": 37,
1100
+ "paths": [
1101
+ "M512 160c195.2 0 352 156.8 352 352s-156.8 352-352 352-352-156.8-352-352 156.8-352 352-352zM512 64c-248 0-448 200-448 448s200 448 448 448 448-200 448-448-200-448-448-448zM523.2 563.2c0 11.2 6.4 19.2 6.4 30.4 0 14.4-11.2 28.8-27.2 28.8-27.2 0-41.6-41.6-41.6-64 0-92.8 121.6-102.4 121.6-174.4 0-33.6-24-62.4-76.8-62.4-36.8 0-65.6 14.4-88 36.8-6.4 4.8-12.8 8-20.8 8-16 0-30.4-14.4-30.4-32 0-6.4 1.6-14.4 6.4-19.2 32-38.4 84.8-59.2 139.2-59.2 88 0 142.4 51.2 142.4 116.8 1.6 110.4-131.2 120-131.2 190.4zM508.8 768c-24 0-44.8-20.8-44.8-46.4 0-24 19.2-46.4 44.8-46.4 24 0 44.8 22.4 44.8 46.4-1.6 25.6-22.4 46.4-44.8 46.4z"
1102
+ ],
1103
+ "attrs": [],
1104
+ "isMulticolor": false,
1105
+ "tags": [
1106
+ "info"
1107
+ ],
1108
+ "defaultCode": 112,
1109
+ "grid": 0,
1110
+ "colorPermutations": {}
1111
+ },
1112
+ {
1113
+ "id": 10,
1114
+ "paths": [
1115
+ "M798 468c18-10 32-30 32-52 0-32-26-58-58-58-34-120-62-230-62-230s-34-128-198-128c-164 0-198 128-198 128s-28 110-62 230c-32 0-58 26-58 58 0 22 14 42 32 52-32 118-62 224-62 224 0 10 22 22 56 28 10-40 22-98 36-146 22-76 58-120 120-142-36-12-54-58-62-110l124 66 78-74 14 198h-110c0 0 70 36 146 36 8-6 4-84 0-182l22 26 126-66c-8 48-26 94-64 106 64 26 104 70 122 142 10 48 26 106 36 146 34-6 56-18 56-28-4 0-34-106-66-224zM420 304l-90-74 150 16zM604 304l-62-58 150-16zM798 728c0 0-148 66-216 66-70 0-66-58-66-66h-8c-4 8 4 66-66 66-68 0-216-66-216-66l-44 182 330 114 332-114zM458 622h108v36h-108z"
1116
+ ],
1117
+ "attrs": [],
1118
+ "isMulticolor": false,
1119
+ "tags": [
1120
+ "wpmudev-devman"
1121
+ ],
1122
+ "defaultCode": 108,
1123
+ "grid": 0,
1124
+ "colorPermutations": {}
1125
+ },
1126
+ {
1127
+ "id": 16,
1128
+ "paths": [
1129
+ "M810 356l-18-234-122-82-112-12-180 166 228 24zM16 580l176 86 26-322-198 182zM1012 580l-496 244 210 104 302-148zM984 254l-192-132 42 546 178-88zM316 0l-274 254-22 272 538-498zM0 780l514 248 212-100-710-348z"
1130
+ ],
1131
+ "attrs": [],
1132
+ "isMulticolor": false,
1133
+ "tags": [
1134
+ "wpmudev-upfront"
1135
+ ],
1136
+ "defaultCode": 68,
1137
+ "grid": 0,
1138
+ "colorPermutations": {}
1139
+ },
1140
+ {
1141
+ "id": 62,
1142
+ "paths": [
1143
+ "M757.583 355.928c11.477-11.477 18.575-27.331 18.575-44.844 0-35.025-28.394-63.419-63.419-63.419-17.513 0-33.368 7.098-44.844 18.575-10.923 11.137-17.664 26.409-17.664 43.255 0 0.372 0.003 0.744 0.010 1.115-0.009 0.316-0.013 0.754-0.013 1.193 0 34.42 27.903 62.323 62.323 62.323 0.439 0 0.877-0.005 1.314-0.014-0.064 0.001-0.062 0.001-0.061 0.001 17.106 0 32.589-6.951 43.778-18.183zM623.051 400.772c-22.791-22.051-36.94-52.915-36.94-87.082 0-1.103 0.015-2.202 0.044-3.297-0.060-1.246-0.092-2.898-0.092-4.558 0-69.717 56.517-126.234 126.234-126.234s126.234 56.517 126.234 126.234c0 1.66-0.032 3.312-0.096 4.957 0.068 1.193 0.102 2.87 0.102 4.555 0 33.365-13.531 63.569-35.405 85.426-22.405 21.845-53.059 35.319-86.861 35.319-0.498 0-0.995-0.003-1.491-0.009-1.977 0.127-4.375 0.198-6.791 0.198-33.231 0-63.289-13.581-84.928-35.496zM784.772 776.828c0-0.098 0-0.214 0-0.33 0-28.728-2.182-56.946-6.39-84.498q-6.674-51.469 6.39-64.711c-104.163 104.549 12.74 3.697 101.875-118.677-55.039 80.477 21.701-15.244 74.999-124.498-5.498 21.297 27.966-51.503 46.666-130.027 10.199-43.067 15.641-88.167 15.687-134.53q0-74.712-23.834-97.664t-95.868-21.892c-46.070 0.004-91.085 5.603-134.153 16.159 28.939-12.216-54.196 10.331-129.672 46.343 77.853-41.806-31.522 6.241-125.255 74.477 118.509-87.564-12.674-5.057-119.168 102.027q-12.226 12.226-68.722 6.047t-80.154-6.003c-3.046-0.29-6.585-0.455-10.163-0.455-25.805 0-49.602 8.597-68.684 23.082q-27.084 23.276-41.384 37.224c27.28-35.625-31.619 25.214-72.705 97.5q-36.581 63.162-46.115 81.877c-4.572 7.318-7.283 16.205-7.283 25.726 0 13.972 5.838 26.58 15.208 35.519 10.411 14.901 29.204 26.422 50.759 28.422l107.274 0.021q54.731 0 72.386 0c0.62 55.862 25.696 107.667 65.339 143.745 34.953 38.736 86.445 64.019 143.857 65.113q1.077 17.658 0.194 72.389t0 106.99c0.871 20.401 11.99 40.168 28.77 52.832 8.854 9.49 21.208 15.327 34.926 15.327 9.675 0 18.672-2.904 26.166-7.888l78.745-45.441c-29.723 23.258 42.571-18.267 100.585-74.45q13.821-13.826 37.302-41.014c14.292-18.785 22.897-42.572 22.897-68.369 0-3.652-0.172-7.264-0.51-10.828zM378.703 814.257q-50.494 0-111.228-60.734t-60.734-111.228q0.883-27.012-17.655-28.072c-0.688-0.041-1.493-0.064-2.303-0.064-11.959 0-22.741 5.038-30.339 13.107l-105.951 105.952c-7.15 6.829-11.595 16.437-11.595 27.084 0 1.655 0.107 3.285 0.316 4.884q1.922 18.526 28.052 20.292h69.208q-10.593 26.659-24.541 58.968t-27.189 60.557c-3.134 4.806-4.999 10.688-4.999 17.006 0 6.87 2.204 13.225 5.945 18.397 4.631 3.246 10.481 5.244 16.797 5.244s12.166-1.998 16.951-5.397q24.274-11.062 61.526-26.951l59.851-25.247q0 13.065 0 27.542t0 41.49c-0.233 1.233-0.367 2.652-0.367 4.102 0 11.657 8.624 21.3 19.841 22.896 2.129 0.405 4.435 0.628 6.794 0.628 10.166 0 19.363-4.151 25.988-10.851l104.875-104.875c6.815-8.468 10.939-19.352 10.939-31.2 0-1.447-0.061-2.879-0.182-4.295q-1.4-19.060-29.471-19.060z"
1144
+ ],
1145
+ "attrs": [],
1146
+ "isMulticolor": false,
1147
+ "grid": 0,
1148
+ "tags": [
1149
+ "hummingbird"
1150
+ ],
1151
+ "colorPermutations": {}
1152
+ },
1153
+ {
1154
+ "id": 69,
1155
+ "paths": [
1156
+ "M836.149 346.571c7.483-36.21-2.216 28.877-18.984 91.063 12.733-9.516-27.719 112.534-90.884 219.586 21.638-1.365-83.817 143.882-221.683 248.702l-22.964 17.090c-4.412 2.891-9.818 4.611-15.625 4.611s-11.213-1.72-15.735-4.679l-2.538-0.815-19.421-14.654c-2.618 20.020-135.11-100.592-223.789-250.229-6.611-11.597-11.025-19.365-15.262-27.134 60.454 104.853 3.792 19.941-35.933-73.884-43.388-102.226-67.491-215.092-67.526-333.584-0-1.073-0-2.132-0-3.015 0-8.828 0-17.655 0-26.306-0.023-0.422-0.037-0.916-0.037-1.412s0.013-0.991 0.040-1.481c-0.066-0.646-0.102-1.476-0.102-2.315s0.036-1.67 0.106-2.49c0.831-7.653 6.206-15.435 13.802-19.771-1.342 0.6 1.387-0.991 4.392-1.97l0.16-0.045c8.651-3.884 17.655-7.768 25.953-11.299-68.26 26.429 17.317-13.015 109.005-37.494 71.809-19.158 147.446-29.39 225.473-29.39s153.664 10.232 225.643 29.427c-63.3-19.62 30.059 3.042 116.233 39.39q8.491 3.717 22.439 10.249c9.004 4.137 15.58 13.234 16.239 23.931l0.004 0.081c0 10.063 0 20.127 0 30.19 0 1.059 0 2.119 0 3.178 0.001 0.449 0.001 0.98 0.001 1.511 0 43.386-3.274 86.007-9.588 127.63zM732.866 444.734h-2.648l-5.297 0.883c14.98-20.528-234.445 43.985-461.092 149.267l12.474-5.2-3.178 1.412-6.532 3.001c-12.357 7.588-20.477 21.030-20.48 36.369-0.008 0.316-0.013 0.688-0.013 1.061 0 8.020 2.237 15.517 6.122 21.901l-0.105-0.187c-28.723-16.918 67.487 115.537 192.366 212.951l5.196 4.031c-2.892-1.681 0.951 0.982 5.257 2.746 3.281 1.292 6.831 1.996 10.545 1.996s7.264-0.704 10.524-1.985c-2.767 1.345 1.597-0.349 5.4-2.832l3.232-2.573c-2.954 22.686 121.104-90.887 204.65-231.368-27.53 56.203 30.813-39.564 67.65-145.403 1.709-7.759 3.121-9.701 3.827-11.82v0c0.086-0.873 0.135-1.887 0.135-2.913s-0.049-2.040-0.144-3.041c-0.085-15.408-12.554-28.001-28.034-28.297zM787.597 195.972c1.65 0.612-4.461-4.267-11.547-7.308 69.21 26.78-10.842-9.765-96.458-32.707-68.289-18.189-140.156-27.892-214.29-27.892s-146.001 9.703-214.401 27.908c65.558-19.796-21.197 1.107-101.41 34.56 6.226-3.164-1.027 0.568-6.877 5.828-2.485 1.051-8.402 8.523-11.519 17.32-1.364 3.399-2.395 8.149-2.562 13.118l-0.002 2.718c0.178 93.262 18.101 188.172 50.737 275.925l0.639 1.085c4.879 9.2 14.396 15.36 25.352 15.36 0.025 0 0.050-0 0.076-0 2.876-0.001 5.68-0.453 8.313-1.289l7.22-3.301 15.007-5.297c12.421-23.546 252.262-113.836 508.637-154.443l11.131-1.453 7.062-0.883c16.607-3.504 30.083-17.498 32.981-35.059l0.034-2.37c2.806-17.151 5.717-52.069 6.346-87.545l0.010-0.731v-3.531c-0.301-11.393-5.827-22.388-14.431-29.973zM928.839 155.012v0-3.884c-1.45-19.185-13.611-37.652-31.129-48.035l-8.595-3.871c-123.554-62.554-269.36-99.192-423.724-99.192s-300.171 36.639-429.198 101.694l-0.706 0.5c-17.981 9.809-31.053 29.183-32.476 51.721l-0.009 0.185c-2.295 22.422-3.001 45.55-3.001 68.502-0 0.347-0.001 0.758-0.001 1.168 0 132.824 27.602 259.201 77.382 373.708q15.309 34.37 35.789 72.859c0.214 48.775 134.179 221.365 308.837 337.68l13.546 8.714c8.615 4.561 18.832 7.239 29.674 7.239 0.057 0 0.115-0 0.172-0 0.27 0.004 0.6 0.007 0.93 0.007 10.76 0 20.893-2.681 29.769-7.412l9.545-6.19c170.176-91.26 341.8-313.48 402.374-578.038q10.227-46.955 15.7-88.974c4.833-36.003 7.592-77.623 7.592-119.887 0-0.245-0-0.491-0-0.736q-0.353-34.213-2.825-67.758z"
1157
+ ],
1158
+ "attrs": [],
1159
+ "isMulticolor": false,
1160
+ "width": 931,
1161
+ "grid": 0,
1162
+ "tags": [
1163
+ "defender"
1164
+ ],
1165
+ "colorPermutations": {}
1166
+ },
1167
+ {
1168
+ "id": 35,
1169
+ "paths": [
1170
+ "M336 256c113.6 113.6 224 224 336 336 16 16 16 33.6 0 48-24 24-57.6 57.6-80 80-16 16-32 16-48 0-17.6-17.6-62.4-62.4-80-80-30.4-28.8-51.2-12.8-64 0-16 16-80 128-160 208-81.6 81.6-152 104-208 48s-33.6-126.4 48-208c80-80 192-144 208-160s32-32 0-64c-19.2-19.2-60.8-60.8-80-80-16-16-16-32 0-48 24-24 56-56 80-80 16-16 32-17.6 48 0zM384 160c17.6-17.6 36.8-35.2 56-52.8 27.2-25.6 62.4-19.2 94.4-16 44.8 4.8 84.8 24 121.6 51.2 32 25.6 64 52.8 99.2 75.2 81.6 54.4 169.6 92.8 268.8 73.6-80 80-176 172.8-256 252.8-16 16-32 16-48 0-30.4-30.4-310.4-308.8-337.6-336-14.4-14.4-14.4-32 1.6-48z"
1171
+ ],
1172
+ "attrs": [],
1173
+ "isMulticolor": false,
1174
+ "tags": [
1175
+ "theme"
1176
+ ],
1177
+ "defaultCode": 108,
1178
+ "grid": 0,
1179
+ "colorPermutations": {}
1180
+ },
1181
+ {
1182
+ "id": 58,
1183
+ "paths": [
1184
+ "M1005.714 124.343l-105.874-106.057c-11.205-10.989-26.57-17.772-43.52-17.772s-32.315 6.783-43.53 17.782l-90.139 89.773c-5.001 4.942-8.098 11.801-8.098 19.383s3.097 14.441 8.095 19.38l155.066 154.883c4.933 4.946 11.755 8.006 19.291 8.006s14.358-3.060 19.291-8.005l89.418-90.332c11.28-10.805 18.29-25.989 18.29-42.81 0-0.25-0.002-0.499-0.005-0.748 0.003-0.173 0.005-0.423 0.005-0.672 0-16.821-7.010-32.005-18.269-42.79zM85.577 764.343l-6.4 4.754-1.646 4.754-75.703 219.429-1.829 5.669c-0.513 1.557-0.809 3.35-0.809 5.211s0.296 3.654 0.843 5.333c-0.303 0.398 1.78 4.222 4.722 7.195 1.212 2.436 4.596 5.222 8.667 6.372 1.411 0.533 2.92 0.826 4.497 0.826s3.085-0.294 4.474-0.829l4.669-3.263 219.429-74.24 6.4-3.291 4.754-4.754c3.012-4.003 4.823-9.059 4.823-14.537s-1.811-10.534-4.868-14.6l-146.241-146.223c-3.377-2.079-7.47-3.311-11.849-3.311-0.334 0-0.667 0.007-0.998 0.021-0.021-0.003-0.101-0.003-0.181-0.003-4.96 0-9.371 2.351-12.18 6zM141.897 727.771l154.697 154.88c4.341 4.569 10.461 7.411 17.245 7.411 0.753 0 1.497-0.035 2.232-0.103 8.182-0.993 15.802-6.995 19.227-15.186l508.222-505.218c4.805-1.237 8.299-5.531 8.299-10.641 0-0.83-0.092-1.638-0.267-2.415 0.044-0.358 0.062-0.86 0.062-1.367 0-6.796-3.142-12.858-8.052-16.813l-154.739-154.912c-4.933-4.946-11.755-8.006-19.291-8.006s-14.358 3.060-19.291 8.005l-507.612 505.783c-4.946 4.933-8.006 11.755-8.006 19.291s3.060 14.358 8.005 19.291z"
1185
+ ],
1186
+ "attrs": [],
1187
+ "isMulticolor": false,
1188
+ "grid": 0,
1189
+ "tags": [
1190
+ "pencil",
1191
+ "edit"
1192
+ ],
1193
+ "colorPermutations": {}
1194
+ },
1195
+ {
1196
+ "id": 53,
1197
+ "paths": [
1198
+ "M1061.82 351.266h-294.154c-0.215 0.002-0.468 0.003-0.722 0.003-32.971 0-61.217-20.227-73.008-48.949 2.219 5.396-0.573-0.484-2.378-6.781l-86.442-257.146-2.101-6.494c-8.374-19.126-27.135-32.245-48.96-32.245-23.194 0-42.927 14.817-50.25 35.502l-0.115 0.373-87.291 257.862c1.558-5.097-0.132 1.945-2.835 8.46-12.006 28.401-40.045 48.274-72.727 48.274-0.296 0-0.592-0.002-0.887-0.005l0.045 0h-294.727c-25.642 3.248-45.271 24.925-45.271 51.186 0 0.136 0.001 0.272 0.002 0.407 0.027 16.564 8.167 31.293 20.675 40.373l2.628 1.819 229.211 161.021c20.484 13.761 33.881 36.915 34 63.206 0 0.107 0.001 0.211 0.001 0.316 0 6.067-0.767 11.955-2.208 17.572 1.142-2.679-1.008 5.384-4.459 12.715l-86.355 256.883v1.91c-1.388 4.412-2.187 9.486-2.187 14.747 0 28.061 22.748 50.808 50.808 50.808 0.702 0 1.401-0.014 2.096-0.042-0.047 0.003 0.015 0.004 0.077 0.004 9.536 0 18.494-2.478 26.264-6.826l8.705-6.163 231.885-162.74c12.206-7.704 27.058-12.276 42.977-12.276s30.771 4.572 43.314 12.474c-7.243-4.386 0.917-0.236 7.788 5.423l-0.102-0.082 231.885 162.931c7.777 4.564 17.128 7.259 27.108 7.259 0.073 0 0.145-0 0.218-0 0.221 0.004 0.495 0.006 0.77 0.006 28.12 0 51.003-22.423 51.745-50.364-0.002-5.381-0.911-10.616-2.582-15.497l0.101-2.144-88.055-258.435c1.605 4.417-1.49-2.474-3.341-9.859-1.674-6.132-2.58-12.65-2.58-19.38 0-0.062 0-0.124 0-0.186 0.066-24.265 11.745-45.936 29.802-59.64l6.108-4.338 226.155-158.729 6.303-4.011c11.197-8.706 18.704-22.538 19.1-38.138-0.050-26.51-20.083-48.268-45.805-51.043z"
1199
+ ],
1200
+ "attrs": [],
1201
+ "isMulticolor": false,
1202
+ "width": 1108,
1203
+ "grid": 0,
1204
+ "tags": [
1205
+ "star"
1206
+ ],
1207
+ "colorPermutations": {}
1208
+ },
1209
+ {
1210
+ "id": 52,
1211
+ "paths": [
1212
+ "M57.026 56.85c-0 0-0 0-0 0 0 31.397 25.452 56.85 56.85 56.85 0.062 0 0.124-0 0.177-0h568.497c0 0 0 0 0 0 31.397 0 56.85-25.452 56.85-56.85s-25.452-56.85-56.85-56.85c-0 0-0 0-0 0l-568.506 0c-31.383 0.099-56.817 25.472-57.017 56.85zM739.585 341.274c31.286-0.099 56.641-25.392 56.84-56.673l-0-57.026c0-0 0-0.001 0-0.001 0-31.397-25.452-56.85-56.85-56.85-0.124 0-0.248 0-0.353 0.001l-681.833 0c-0.062-0-0.124-0-0.186-0-31.433 0-56.926 25.431-57.026 56.85l-0 56.85c0 31.397 25.452 56.85 56.85 56.85l0 625.523c-0 0-0 0-0 0 0 31.53 25.51 57.102 57.026 57.202l568.516-0c31.457-0.2 56.908-25.713 57.007-57.203v-625.523zM170.726 341.274h113.699v569.026h-113.699v-569.026zM341.451 341.274h113.699v569.026h-113.699v-569.026zM512.177 341.274h113.699v569.026h-113.876v-569.026z"
1213
+ ],
1214
+ "attrs": [],
1215
+ "isMulticolor": false,
1216
+ "width": 796,
1217
+ "grid": 0,
1218
+ "tags": [
1219
+ "trash"
1220
+ ],
1221
+ "colorPermutations": {}
1222
+ },
1223
+ {
1224
+ "id": 56,
1225
+ "paths": [
1226
+ "M0 719.978c3.708-17.655 6.532-35.31 11.299-51.377-7.126 8.74 11.71-43.949 40.441-89.805q27.355-46.14 55.426-93.985l5.12-9.357c-17.655-11.123-33.898-21.539-50.141-33.015 5.822 5.696-10.335-5.639-22.639-20.313-4.919-5.51-7.844-12.605-7.844-20.383 0-9.889 4.727-18.675 12.046-24.219-3.645 1.351 9.614-8.768 24.869-15.010 56.421-23.003 112.387-45.249 168.178-67.494-6.106 1.961 5.043-2.664 16.931-5.336 4.708-1.271 9.284-1.923 14.013-1.923 26.118 0 47.589 19.9 50.077 45.365 0.783 4.665 1.359 11.168 1.428 17.793 0.001 57.978 0.001 116.063 0.001 173.972-0.021 10.077-2.028 20.3-5.67 29.708-4.239 12.323-16.269 21.427-30.425 21.427-3.504 0-6.878-0.558-10.037-1.589 6.52 3.21-10.628-2.488-25.818-11.211-5.909-3.025-11.736-7.615-17.032-11.499l-19.068-12.359c8.284-9.307 1.068-2.312-4.432 5.926q-27.524 46.156-54.89 92.060c-6.004 6.006-17.172 30.182-21.757 56.615-1.298 6.087-1.965 11.997-1.965 18.063 0 36.533 24.174 67.419 57.399 77.535 13.393 5.084 32.907 9.050 53.262 9.677 47.947 1.243 95.616 0.007 143.991 0.007v127.47c-2.295 0-4.767 0-7.415 0-47.669 0-95.338 0-143.007 0-1.38 0.024-3.009 0.037-4.641 0.037-53.195 0-103.050-14.302-145.929-39.269-40.348-21.217-73.7-67.505-80.455-122.039 0.117-0.52-0.434-3.603-1.382-6.506l0.065-38.965z",
1227
+ "M529.655 0c8.121 1.766 16.066 3.354 24.011 5.473 41.158 5.964 94.925 41.852 129.257 92.078 26.639 37.158 48.531 76.529 72.365 114.664 5.473 8.651 10.417 17.655 16.066 27.189 17.655-11.652 34.251-23.305 51.553-33.721-3.028 0.505 11.386-7.634 27.317-12.175 3.654-1.177 6.994-1.751 10.469-1.751 13.188 0 24.446 8.262 28.88 19.893 3.479 7.925 5.842 18.24 6.072 29.080 0.001 59.408 0.001 118.729 0.001 178.051-0.015 8.262-1.436 16.972-4.052 25.147-9.543 30.29-39.733 43.179-73.808 30.467-39.548-14.83-78.742-30.543-118.113-45.903-19.597-7.592-39.018-15.183-58.439-23.128-15.99-3.526-29.254-17.061-32.616-34.149-0.057-0.657-0.064-1.101-0.064-1.547 0-17.183 9.899-32.055 24.305-39.223 13.319-9.295 26.737-17.77 40.332-26.774 0.441 0.988-0.304-1.449-1.462-3.635-22.196-36.972-43.382-74.754-67.040-110.948 8.017 6.546-12.692-21.384-39.313-42.065-14.667-12.194-33.179-19.41-53.376-19.41s-38.71 7.216-53.099 19.211c25.271-24.464-12.142 5.895-40.479 43.481 19.652-25.731-1.942-1.266-17.598 26.949l-100.686-59.592c35.31-60.381 75.211-113.699 141.241-141.241-34.894 12.533 6.236-4.964 49.994-15.797l38.282-0.622z",
1228
+ "M735.868 799.956c7.004 0.482 15.18 0.756 23.42 0.756 23.683 0 46.837-2.267 69.257-6.596 54.391-15.17 80.344-60.543 61.453-116.334 19.88 44.969-1.019-13.112-31.86-64.551-4.156-8.188-10.689-17.899-16.515-29.022l97.633-58.439c0.396-0.012 1.445 0.414 2.31 1.070 30.175 50.13 62.661 99.035 76.255 157.297 4.796 15.802 7.557 33.964 7.557 52.77 0 36.685-10.506 70.915-28.672 99.848-15.944 29.748-59.158 63.651-110.656 76.957-28.747 8.77-62.15 14.028-96.75 14.243-17.768 0.001-34.011 0.001-53.078 0.001 0 17.655 0 33.015 0 49.258-0.026 8.341-1.711 17.96-4.778 26.939-3.703 11.521-14.901 20.166-28.118 20.166-3.391 0-6.65-0.569-9.685-1.617 1.124 1.594-12.643-3.507-24.506-11.276q-79.804-51.514-159.605-103.774c-39.371-25.777-39.018-61.44 0-87.217l149.892-97.633c5.65-3.708 11.123-7.415 17.655-10.593 32.132-17.655 58.262-3.531 59.498 33.545-0.177 17.302-0.706 34.957-0.706 54.201z"
1229
+ ],
1230
+ "attrs": [],
1231
+ "isMulticolor": false,
1232
+ "grid": 0,
1233
+ "tags": [
1234
+ "recycle"
1235
+ ],
1236
+ "colorPermutations": {}
1237
+ },
1238
+ {
1239
+ "id": 65,
1240
+ "paths": [
1241
+ "M783.177 485.669c-0.348 0.003-0.76 0.004-1.172 0.004-24.883 0-48.442-5.667-69.457-15.781-34.513-16.040-53.896-11.103-78.582 19.617-112.823 141.166-226.926 281.6-348.526 415.086q-38.766 42.24-79.36 82.834c-20.826 22.637-50.592 36.771-83.659 36.771-16.787 0-32.724-3.643-47.062-10.181-43.521-16.596-74.586-58.691-74.992-108.094-0.292-3.121-0.458-6.69-0.458-10.298 0-32.327 13.337-61.54 34.809-82.435 53.603-52.871 106.083-106.997 162.22-157.099 107.703-95.817 217.417-189.257 325.486-283.429 27.794-24.137 33.097-44.617 18.286-79.36-9.86-21.246-15.611-46.116-15.611-72.329 0-16.558 2.295-32.579 6.584-47.764 2.76-24.535 23.467-58.079 53.097-80.421-50.767 31.77 36.317-36.676 136.106-82.067 11.91-5.812 25.84-9.77 40.592-10.707 18.593-0.016 25.908 14.796 15.485 30.887 5.996-7.73-0.822 2.75-9.657 11.122-21.063 21.792-42.091 43.186-63.303 65.129-20.488 20.262-33.176 48.375-33.176 79.451s12.688 59.189 33.166 79.441c12.262 12.993 24.696 25.793 36.582 38.227 19.129 19.681 45.853 31.893 75.429 31.893s56.3-12.212 75.405-31.868c22.515-22.333 44.458-45.373 66.584-68.048 4.73-7.707 13.111-12.77 22.674-12.77 2.874 0 5.642 0.457 8.234 1.303 6.31 4.942 10.457 12.717 10.457 21.461 0 4.495-1.096 8.735-3.035 12.465 4.698-9.518-4.469 21.077-18.839 48.518-20.039 35.263-41.616 73.298-64.29 109.32-26.735 41.843-72.942 69.187-125.535 69.187-1.574 0-3.143-0.024-4.705-0.073z"
1242
+ ],
1243
+ "attrs": [],
1244
+ "isMulticolor": false,
1245
+ "width": 999,
1246
+ "grid": 0,
1247
+ "tags": [
1248
+ "fix"
1249
+ ],
1250
+ "colorPermutations": {}
1251
+ },
1252
+ {
1253
+ "id": 36,
1254
+ "paths": [
1255
+ "M380.8 547.2l96 96c6.4 6.4 17.6 6.4 24-4.8l315.2-313.6c6.4-1.6 6.4-12.8 0-19.2l-96-96c-6.4-6.4-17.6-6.4-24 0l-315.2 313.6c-6.4 6.4-6.4 17.6 0 24zM345.6 569.6l-3.2 3.2-1.6 3.2-46.4 136-1.6 3.2c-1.6 4.8 0 8 3.2 11.2s8 4.8 11.2 3.2l3.2-1.6 136-46.4 3.2-1.6 3.2-3.2c4.8-4.8 4.8-12.8 0-17.6l-91.2-91.2c-3.2-3.2-11.2-3.2-16 1.6zM916.8 172.8l-65.6-65.6c-14.4-14.4-40-14.4-54.4 0l-56 56c-6.4 6.4-6.4 17.6 0 24l96 96c6.4 6.4 17.6 6.4 24 0l56-56c14.4-14.4 14.4-40 0-54.4zM832 432c-24 0-48 24-48 48v361.6l-592 6.4v-608h352c24 0 48-24 48-48s-24-48-48-48h-400c-24 0-48 24-48 48v704c0 24 24 48 48 48h688c25.6 0 48-22.4 48-48 0-4.8 0-416 0-416 0-24-24-48-48-48z"
1256
+ ],
1257
+ "attrs": [],
1258
+ "isMulticolor": false,
1259
+ "tags": [
1260
+ "edit"
1261
+ ],
1262
+ "defaultCode": 111,
1263
+ "grid": 0,
1264
+ "colorPermutations": {}
1265
+ },
1266
+ {
1267
+ "id": 40,
1268
+ "paths": [
1269
+ "M224 512c0 61.856-50.144 112-112 112s-112-50.144-112-112c0-61.856 50.144-112 112-112s112 50.144 112 112zM624 512c0 61.856-50.144 112-112 112s-112-50.144-112-112c0-61.856 50.144-112 112-112s112 50.144 112 112zM1024 512c0 61.856-50.144 112-112 112s-112-50.144-112-112c0-61.856 50.144-112 112-112s112 50.144 112 112z"
1270
+ ],
1271
+ "attrs": [],
1272
+ "isMulticolor": false,
1273
+ "tags": [
1274
+ "options"
1275
+ ],
1276
+ "defaultCode": 115,
1277
+ "grid": 0,
1278
+ "colorPermutations": {}
1279
+ },
1280
+ {
1281
+ "id": 41,
1282
+ "paths": [
1283
+ "M740.8 512v0c0 25.6-4.8 51.2-12.8 75.2-3.2 9.6-6.4 17.6-11.2 25.6-11.2 22.4-25.6 43.2-43.2 60.8s-38.4 32-60.8 44.8c-8 4.8-17.6 8-25.6 11.2-24 8-48 12.8-75.2 12.8v0c-25.6 0-51.2-4.8-73.6-12.8-9.6-3.2-17.6-6.4-27.2-11.2-22.4-11.2-43.2-25.6-60.8-43.2s-33.6-38.4-44.8-60.8c-4.8-8-8-17.6-11.2-27.2-8-24-12.8-48-12.8-73.6s4.8-51.2 12.8-75.2c3.2-9.6 6.4-17.6 11.2-27.2 11.2-22.4 25.6-43.2 44.8-60.8 17.6-17.6 38.4-32 60.8-43.2 8-4.8 17.6-8 27.2-11.2 24-8 48-12.8 73.6-12.8v0c25.6 0 51.2 4.8 75.2 12.8 9.6 3.2 17.6 6.4 25.6 11.2 22.4 11.2 43.2 25.6 60.8 44.8 17.6 17.6 32 38.4 43.2 60.8 4.8 8 8 17.6 11.2 25.6 8 22.4 12.8 48 12.8 73.6v0 0zM958.4 470.4v0c-1.6-17.6-16-32-33.6-33.6h-20.8c-22.4 0-41.6-12.8-49.6-30.4-1.6-4.8-3.2-9.6-4.8-14.4-4.8-11.2-9.6-22.4-14.4-33.6v0c-3.2-3.2-4.8-8-6.4-12.8v0c-1.6-6.4-3.2-12.8-3.2-19.2 0-16 6.4-28.8 16-40v0l11.2-11.2c12.8-14.4 14.4-35.2 1.6-49.6v0c-8-11.2-17.6-20.8-27.2-30.4s-20.8-19.2-30.4-28.8v0c-12.8-11.2-32-11.2-44.8-1.6l-8 8-8 9.6c-16 16-40 20.8-60.8 12.8-3.2-1.6-4.8-3.2-8-3.2-12.8-6.4-25.6-11.2-40-16-3.2 0-4.8-1.6-6.4-1.6v0c-6.4-3.2-12.8-6.4-19.2-12.8-9.6-9.6-14.4-20.8-16-32 0-4.8 0-9.6 0-14.4v-12.8c0-17.6-12.8-33.6-30.4-36.8-1.6 0-4.8 0-6.4 0v0c-11.2-1.6-24-1.6-36.8-1.6s-25.6 0-36.8 1.6v0c-1.6 0-4.8 0-6.4 0-17.6 3.2-30.4 17.6-30.4 36.8v16c0 24-14.4 44.8-36.8 52.8-1.6 0-3.2 1.6-4.8 1.6-14.4 4.8-28.8 11.2-43.2 17.6v0c-1.6 0-1.6 1.6-3.2 1.6-6.4 3.2-14.4 4.8-24 4.8-16 0-28.8-6.4-40-16v0l-11.2-11.2c-12.8-12.8-33.6-14.4-48-4.8-1.6 1.6-3.2 3.2-4.8 4.8v0c-9.6 8-19.2 16-27.2 25.6-9.6 8-17.6 17.6-25.6 27.2v0c-1.6 1.6-3.2 3.2-4.8 4.8-9.6 14.4-8 35.2 4.8 48l11.2 11.2c17.6 17.6 20.8 41.6 11.2 62.4 0 1.6-1.6 3.2-1.6 3.2-6.4 14.4-12.8 28.8-17.6 43.2 0 1.6-1.6 3.2-1.6 4.8v0c-3.2 6.4-6.4 14.4-12.8 19.2-11.2 11.2-25.6 16-40 16v0h-16c-17.6 0-33.6 12.8-36.8 30.4 0 1.6 0 4.8 0 6.4-1.6 14.4-1.6 27.2-1.6 40v0 0c0 12.8 0 24 1.6 36.8v0c0 1.6 0 4.8 0 6.4 3.2 17.6 17.6 30.4 36.8 30.4v0h16c24 0 44.8 14.4 52.8 35.2v0c0 1.6 1.6 3.2 1.6 4.8v0c4.8 14.4 11.2 28.8 17.6 43.2v0c0 1.6 1.6 1.6 1.6 3.2 3.2 6.4 4.8 14.4 4.8 24 0 16-6.4 28.8-16 40v0l-11.2 11.2c-12.8 12.8-14.4 32-4.8 46.4 1.6 1.6 3.2 3.2 4.8 6.4 8 9.6 16 19.2 25.6 27.2 8 8 17.6 17.6 27.2 25.6 1.6 1.6 3.2 3.2 6.4 4.8 12.8 8 30.4 8 43.2-1.6l16-16c17.6-17.6 41.6-20.8 62.4-11.2 1.6 0 1.6 1.6 3.2 1.6v0c14.4 6.4 28.8 12.8 43.2 17.6 1.6 0 3.2 1.6 3.2 1.6 8 3.2 14.4 6.4 20.8 12.8 11.2 11.2 16 25.6 16 40v0 16c0 19.2 14.4 35.2 33.6 36.8v0c14.4 4.8 27.2 4.8 41.6 4.8s27.2 0 41.6-1.6v0c19.2-1.6 33.6-17.6 33.6-36.8v-16c0-22.4 12.8-41.6 32-51.2 3.2-1.6 8-3.2 12.8-4.8 12.8-4.8 24-9.6 35.2-14.4 3.2-1.6 6.4-4.8 11.2-4.8 6.4-1.6 12.8-3.2 19.2-3.2 14.4 0 27.2 4.8 36.8 14.4 1.6 1.6 3.2 3.2 4.8 4.8l9.6 9.6c12.8 12.8 33.6 14.4 48 3.2v0c1.6-1.6 1.6-1.6 3.2-3.2 9.6-8 19.2-17.6 28.8-25.6 9.6-9.6 17.6-19.2 25.6-28.8 1.6-1.6 1.6-3.2 3.2-3.2 9.6-14.4 9.6-33.6-3.2-46.4v0l-3.2-3.2-9.6-12.8c-16-16-20.8-41.6-11.2-62.4 1.6-1.6 1.6-3.2 3.2-6.4 6.4-12.8 12.8-27.2 17.6-41.6 0-1.6 1.6-3.2 1.6-6.4 3.2-6.4 6.4-12.8 12.8-19.2 11.2-11.2 25.6-16 40-16v0h16c19.2 0 36.8-16 36.8-35.2v0c1.6-11.2 1.6-24 1.6-36.8 0-14.4 0-27.2-1.6-41.6z"
1284
+ ],
1285
+ "attrs": [],
1286
+ "isMulticolor": false,
1287
+ "tags": [
1288
+ "cog",
1289
+ "gear"
1290
+ ],
1291
+ "defaultCode": 116,
1292
+ "grid": 0,
1293
+ "colorPermutations": {}
1294
+ },
1295
+ {
1296
+ "id": 38,
1297
+ "paths": [
1298
+ "M683.2 683.2l-163.2-113.6-163.2 113.6 65.6-179.2-131.2-97.6h163.2l65.6-179.2 65.6 179.2h163.2l-131.2 97.6 65.6 179.2zM912 585.6c0-65.6-19.2-97.6-32-131.2-12.8-35.2-24-64-32-81.6-28.8-65.6 0-131.2 16-147.2s32-32 49.6-49.6c-19.2-20.8-62.4-59.2-81.6-81.6-33.6 16-81.6 32-147.2 32s-132.8-33.6-163.2-65.6c-33.6 35.2-116.8 67.2-180.8 67.2-67.2 0-99.2-14.4-131.2-32-17.6 17.6-54.4 54.4-81.6 81.6 12.8 12.8 30.4 30.4 49.6 49.6 16 16 44.8 97.6 16 147.2-9.6 16-32 51.2-49.6 81.6-16 32-32 65.6-32 131.2s32 168 97.6 212.8c49.6 32 131.2 32 179.2 49.6 49.6 16 113.6 81.6 131.2 113.6 16-32 83.2-97.6 131.2-113.6 49.6-17.6 131.2-16 179.2-49.6 70.4-49.6 81.6-148.8 81.6-214.4z"
1299
+ ],
1300
+ "attrs": [],
1301
+ "isMulticolor": false,
1302
+ "tags": [
1303
+ "badge"
1304
+ ],
1305
+ "defaultCode": 113,
1306
+ "grid": 0,
1307
+ "colorPermutations": {}
1308
+ },
1309
+ {
1310
+ "id": 42,
1311
+ "paths": [
1312
+ "M512 608c-212.8 0-390.4-78.4-416-160 0 20.8 0 108.8 0 108.8 0 92.8 185.6 163.2 416 163.2s416-70.4 416-163.2c0 0 0-91.2 0-108.8-25.6 81.6-203.2 160-416 160zM512 832c-212.8 0-390.4-78.4-416-160 0 27.2 0 105.6 0 105.6 0 92.8 185.6 166.4 416 166.4s416-73.6 416-166.4c0 0 0-94.4 0-105.6-25.6 81.6-203.2 160-416 160zM512 96c-230.4 0-416 73.6-416 160v80c0 91.2 185.6 160 416 160s416-68.8 416-160v-80c0-86.4-185.6-160-416-160z"
1313
+ ],
1314
+ "attrs": [],
1315
+ "isMulticolor": false,
1316
+ "tags": [
1317
+ "cylinder"
1318
+ ],
1319
+ "defaultCode": 117,
1320
+ "grid": 0,
1321
+ "colorPermutations": {}
1322
+ },
1323
+ {
1324
+ "id": 44,
1325
+ "paths": [
1326
+ "M716.8 564.8c112-75.2 259.2-168 259.2-388.8 0-32-27.2-48-48-48h-160c-25.6-48-105.6-96-256-96s-230.4 48-256 96h-160c-20.8 0-48 16-48 48 0 220.8 134.4 310.4 248 385.6 92.8 60.8 152 102.4 152 176v62.4c-81.6 8-160 54.4-160 96 0 51.2 100.8 96 224 96s224-44.8 224-96c0-41.6-81.6-86.4-160-96v-64c0-75.2 48-110.4 140.8-171.2zM784 208h112c-12.8 128-86.4 195.2-176 256 28.8-62.4 60.8-144 64-256zM128 208h112c3.2 112 35.2 193.6 64 256-89.6-60.8-163.2-128-176-256zM320 192c0-20.8 51.2-80 192-80s192 59.2 192 80-51.2 80-192 80-192-59.2-192-80z"
1327
+ ],
1328
+ "attrs": [],
1329
+ "isMulticolor": false,
1330
+ "tags": [
1331
+ "trophy"
1332
+ ],
1333
+ "defaultCode": 120,
1334
+ "grid": 0,
1335
+ "colorPermutations": {}
1336
+ },
1337
+ {
1338
+ "id": 43,
1339
+ "paths": [
1340
+ "M512 96c-307.2 0-179.2 387.2-336 544 0 0 587.2 0 672 0-148.8-148.8-30.4-544-336-544zM864 688h-704c-35.2 0-64 28.8-64 64s28.8 64 64 64h240c0 62.4 49.6 112 112 112s112-49.6 112-112h240c35.2 0 64-28.8 64-64s-28.8-64-64-64z"
1341
+ ],
1342
+ "attrs": [],
1343
+ "isMulticolor": false,
1344
+ "tags": [
1345
+ "bell"
1346
+ ],
1347
+ "defaultCode": 119,
1348
+ "grid": 0,
1349
+ "colorPermutations": {}
1350
+ }
1351
+ ],
1352
+ "invisible": false,
1353
+ "colorThemes": [],
1354
+ "colorThemeIdx": 0
1355
+ }
1356
+ ],
1357
+ "uid": -1,
1358
+ "preferences": {
1359
+ "showGlyphs": true,
1360
+ "showQuickUse": false,
1361
+ "showQuickUse2": true,
1362
+ "showSVGs": true,
1363
+ "fontPref": {
1364
+ "prefix": "dev-icon-",
1365
+ "metadata": {
1366
+ "fontFamily": "WPMU-DEV-App-Icons",
1367
+ "majorVersion": 2,
1368
+ "minorVersion": 0
1369
+ },
1370
+ "metrics": {
1371
+ "emSize": 1024,
1372
+ "baseline": 6.25,
1373
+ "whitespace": 50
1374
+ },
1375
+ "embed": false,
1376
+ "includeMetadata": false,
1377
+ "showSelector": false,
1378
+ "showMetrics": false,
1379
+ "showMetadata": false,
1380
+ "showVersion": true
1381
+ },
1382
+ "imagePref": {
1383
+ "prefix": "icon-",
1384
+ "png": true,
1385
+ "useClassSelector": true,
1386
+ "color": 4473924,
1387
+ "bgColor": 16777215,
1388
+ "classSelector": ".icon"
1389
+ },
1390
+ "historySize": 100,
1391
+ "showCodes": true,
1392
+ "gridSize": 16,
1393
+ "showGrid": false,
1394
+ "showLiga": false
1395
+ }
1396
+ }
externals/shared-ui/font/WPMU-DEV-App-Icons.eot ADDED
Binary file
externals/shared-ui/font/WPMU-DEV-App-Icons.svg ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata>Generated by IcoMoon</metadata>
5
+ <defs>
6
+ <font id="WPMU-DEV-App-Icons" horiz-adv-x="1024">
7
+ <font-face units-per-em="1024" ascent="960" descent="-64" />
8
+ <missing-glyph horiz-adv-x="1024" />
9
+ <glyph unicode="&#x20;" horiz-adv-x="512" d="" />
10
+ <glyph unicode="&#x30;" glyph-name="logo_alt" d="M514 960c-284 0-514-230-514-514s230-514 514-514c284 0 514 230 514 514s-230 514-514 514zM514 10c-242 0-436 196-436 436 0 242 194 436 436 436 240 0 436-194 436-436 0-240-196-436-436-436zM774 732l-60-48v-322c0-20-14-34-30-34-18 0-32 14-32 34v172c0 56-40 100-90 100s-90-44-90-100v-172c0-20-14-34-30-34s-30 14-30 34v172c0 56-40 100-90 100s-90-44-90-100v0-370l58 46v324c0 18 14 34 32 34 16 0 30-16 30-34v-172c0-56 40-102 90-102s90 46 90 102v0 172c0 18 14 34 30 34 18 0 32-16 32-34v-172c0-56 40-102 90-102s90 46 90 102v0 370z" />
11
+ <glyph unicode="&#x31;" glyph-name="devman" d="M798 492c18 10 32 30 32 52 0 32-26 58-58 58-34 120-62 230-62 230s-34 128-198 128c-164 0-198-128-198-128s-28-110-62-230c-32 0-58-26-58-58 0-22 14-42 32-52-32-118-62-224-62-224 0-10 22-22 56-28 10 40 22 98 36 146 22 76 58 120 120 142-36 12-54 58-62 110l124-66 78 74 14-198h-110c0 0 70-36 146-36 8 6 4 84 0 182l22-26 126 66c-8-48-26-94-64-106 64-26 104-70 122-142 10-48 26-106 36-146 34 6 56 18 56 28-4 0-34 106-66 224zM420 656l-90 74 150-16zM604 656l-62 58 150 16zM798 232c0 0-148-66-216-66-70 0-66 58-66 66h-8c-4-8 4-66-66-66-68 0-216 66-216 66l-44-182 330-114 332 114zM458 338h108v-36h-108z" />
12
+ <glyph unicode="&#x32;" glyph-name="fix" horiz-adv-x="999" d="M783.177 474.331c-0.348-0.003-0.76-0.004-1.172-0.004-24.883 0-48.442 5.667-69.457 15.781-34.513 16.040-53.896 11.103-78.582-19.617-112.823-141.166-226.926-281.6-348.526-415.086q-38.766-42.24-79.36-82.834c-20.826-22.637-50.592-36.771-83.659-36.771-16.787 0-32.724 3.643-47.062 10.181-43.521 16.596-74.586 58.691-74.992 108.094-0.292 3.121-0.458 6.69-0.458 10.298 0 32.327 13.337 61.54 34.809 82.435 53.603 52.871 106.083 106.997 162.22 157.099 107.703 95.817 217.417 189.257 325.486 283.429 27.794 24.137 33.097 44.617 18.286 79.36-9.86 21.246-15.611 46.116-15.611 72.329 0 16.558 2.295 32.579 6.584 47.764 2.76 24.535 23.467 58.079 53.097 80.421-50.767-31.77 36.317 36.676 136.106 82.067 11.91 5.812 25.84 9.77 40.592 10.707 18.593 0.016 25.908-14.796 15.485-30.887 5.996 7.73-0.822-2.75-9.657-11.122-21.063-21.792-42.091-43.186-63.303-65.129-20.488-20.262-33.176-48.375-33.176-79.451s12.688-59.189 33.166-79.441c12.262-12.993 24.696-25.793 36.582-38.227 19.129-19.681 45.853-31.893 75.429-31.893s56.3 12.212 75.405 31.868c22.515 22.333 44.458 45.373 66.584 68.048 4.73 7.707 13.111 12.77 22.674 12.77 2.874 0 5.642-0.457 8.234-1.303 6.31-4.942 10.457-12.717 10.457-21.461 0-4.495-1.096-8.735-3.035-12.465 4.698 9.518-4.469-21.077-18.839-48.518-20.039-35.263-41.616-73.298-64.29-109.32-26.735-41.843-72.942-69.187-125.535-69.187-1.574 0-3.143 0.024-4.705 0.073z" />
13
+ <glyph unicode="&#x33;" glyph-name="caret_right" d="M451.2 180.8l204.8 204.8c14.4 14.4 32 32 32 62.4s-17.6 49.6-32 62.4l-204.8 204.8c-27.2 27.2-67.2 27.2-94.4 0s-27.2-67.2 0-94.4l172.8-172.8-172.8-172.8c-27.2-27.2-27.2-67.2 0-94.4s67.2-27.2 94.4 0z" />
14
+ <glyph unicode="&#x37;" glyph-name="upfront" d="M810 604l-18 234-122 82-112 12-180-166 228-24zM16 380l176-86 26 322-198-182zM1012 380l-496-244 210-104 302 148zM984 706l-192 132 42-546 178 88zM316 960l-274-254-22-272 538 498zM0 180l514-248 212 100-710 348z" />
15
+ <glyph unicode="&#x39;" glyph-name="logo" d="M1004 290v670l-108-84v-586c0-34-24-62-54-62-32 0-56 28-56 62v312c0 100-74 182-164 182s-162-82-162-182v-312c0-34-26-62-56-62s-54 28-54 62v312c0 100-74 182-164 182s-164-82-164-182v0-670l108 84v586c0 34 26 62 56 62s56-28 56-62l-2-312c0-100 74-182 164-182s164 82 164 182v0 312c0 34 24 62 54 62 32 0 56-28 56-62v-312c0-100 72-182 164-182 90 0 162 82 162 182z" />
16
+ <glyph unicode="&#x3d;" glyph-name="speach_alt" d="M558 182c-42-14-86-22-134-22-26 0-50 2-76 8-22-20-74-52-150-58-2-2-2-2-4-2-6 0-14 4-4 8 22 14 62 40 62 80-120 52-202 156-202 276 0 174 168 314 374 314 156 0 290-80 346-194 22-2 42-8 60-14-52 148-214 258-406 258-234 0-424-164-424-364 0-120 70-232 186-298-6-6-14-10-22-14-28-16-32-42-28-60 6-20 24-42 58-42 2 0 6 2 8 2 74 6 128 32 160 54 20-2 42-4 62-4 70 0 134 16 192 40-22 8-42 18-58 32zM732 570c138 0 248-94 248-208 0-82-54-152-134-186 10-28 40-50 58-60 10-4 2-8-4-8-2 0-2 0-4 2-62 4-108 26-134 46-10-2-20-2-30-2-138 0-250 92-250 208 0 114 112 208 250 208zM732 620c-166 0-300-116-300-258s134-258 300-258c4 0 10 0 18 0 32-20 80-40 142-44 2 0 4-2 8-2 34 0 52 22 58 42 4 18 0 44-30 60-2 2-2 2-4 4 66 48 106 120 106 198 0 142-134 258-298 258z" />
17
+ <glyph unicode="&#x41;" glyph-name="comment" horiz-adv-x="1048" d="M0 769.427c0.213 105.296 85.621 190.573 190.947 190.573 0.066 0 0.132 0 0.198 0h666.058c0.056 0 0.122 0 0.188 0 105.325 0 190.734-85.277 190.947-190.552v-492.364c0-105.354-85.406-190.76-190.76-190.76h-38.938l-60.279-149.762-146.018 149.762h-421.955c-105.17 0.107-190.385 85.388-190.385 190.572 0 0.066 0 0.132 0 0.198v492.333z" />
18
+ <glyph unicode="&#x42;" glyph-name="download" horiz-adv-x="1365" d="M1050.836-64h-749.992c-0.424-0.002-0.925-0.003-1.426-0.003-15.013 0-29.805 0.942-44.322 2.77-117.762 14.242-218.304 105.483-247.147 224.715-3.005 14.041-5.359 25.576-7.949 36.169v69.208c-0.121-0.517 1.417 1.772 2.319 4.359 11.525 110.342 91.606 206.428 199.228 241.984 7.938 1.803 12.284 6.922 12.284 13.057 0 1.006-0.117 1.986-0.338 2.925 0.011 0.63 0.007 1.476 0.007 2.323 0 163.941 132.901 296.842 296.842 296.842 20.495 0 40.506-2.077 59.832-6.032-0.203-0.254 1.768-0.59 3.817-0.59 6.46 0 12.14 3.336 15.413 8.378 26.059 43.611 96.992 96.055 180.393 117.272-11.657-2.522 15.599 5.389 44.039 9.689 10.816 1.059 21.262 1.533 31.817 1.533 18.246 0 36.161-1.416 53.642-4.144 69.441-4.088 148.797-45.322 204.691-107.946 55.785-58.363 89.947-137.21 89.947-224.035 0-13.662-0.846-27.126-2.488-40.343-0.163 0.309-0.348-1.151-0.348-2.653 0-6.791 3.784-12.699 9.359-15.729 68.861-34.597 134.23-117.504 155.763-216.754-1.424 7.797 3.362-11.618 5.916-31.73 1.696-13.937 2.586-28.537 2.586-43.344s-0.889-29.407-2.618-43.748c-15.395-134.38-118.284-249.368-253.362-283.546-10.044-3.904-33.128-8.976-57.16-10.586zM780.359 642.207h-146.42c-12.397-1.14-22.314-11.010-23.532-23.433l-0.009-194.314c-0.974-12.508-10.94-22.506-23.448-23.534l-99.432-0.006c-14.36 0-48.493 0 0-48.728l195.149-196.326c6.226-6.256 14.843-10.128 24.364-10.128s18.139 3.872 24.363 10.127l195.15 194.914c49.199 49.199 11.535 48.728 0 48.728h-97.692c-13.001 0-23.54 10.539-23.54 23.54v195.384c-0.63 13.496-11.616 24.24-25.165 24.482z" />
19
+ <glyph unicode="&#x43;" glyph-name="pos_header" d="M0 511.81c0-35.241 28.456-63.81 64.056-63.81h895.888c35.377 0 64.056 28.994 64.056 63.81v384.38c0 35.241-28.456 63.81-64.056 63.81h-895.888c-35.377 0-64.056-28.994-64.056-63.81v-384.38zM0 224c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0 96c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0-32c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0 352c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32z" />
20
+ <glyph unicode="&#x44;" glyph-name="defender" horiz-adv-x="931" d="M836.149 613.429c7.483 36.21-2.216-28.877-18.984-91.063 12.733 9.516-27.719-112.534-90.884-219.586 21.638 1.365-83.817-143.882-221.683-248.702l-22.964-17.090c-4.412-2.891-9.818-4.611-15.625-4.611s-11.213 1.72-15.735 4.679l-2.538 0.815-19.421 14.654c-2.618-20.020-135.11 100.592-223.789 250.229-6.611 11.597-11.025 19.365-15.262 27.134 60.454-104.853 3.792-19.941-35.933 73.884-43.388 102.226-67.491 215.092-67.526 333.584 0 1.073 0 2.132 0 3.015 0 8.828 0 17.655 0 26.306-0.023 0.422-0.037 0.916-0.037 1.412s0.013 0.991 0.040 1.481c-0.066 0.646-0.102 1.476-0.102 2.315s0.036 1.67 0.106 2.49c0.831 7.653 6.206 15.435 13.802 19.771-1.342-0.6 1.387 0.991 4.392 1.97l0.16 0.045c8.651 3.884 17.655 7.768 25.953 11.299-68.26-26.429 17.317 13.015 109.005 37.494 71.809 19.158 147.446 29.39 225.473 29.39s153.664-10.232 225.643-29.427c-63.3 19.62 30.059-3.042 116.233-39.39q8.491-3.717 22.439-10.249c9.004-4.137 15.58-13.234 16.239-23.931l0.004-0.081c0-10.063 0-20.127 0-30.19 0-1.059 0-2.119 0-3.178 0.001-0.449 0.001-0.98 0.001-1.511 0-43.386-3.274-86.007-9.588-127.63zM732.866 515.266h-2.648l-5.297-0.883c14.98 20.528-234.445-43.985-461.092-149.267l12.474 5.2-3.178-1.412-6.532-3.001c-12.357-7.588-20.477-21.030-20.48-36.369-0.008-0.316-0.013-0.688-0.013-1.061 0-8.020 2.237-15.517 6.122-21.901l-0.105 0.187c-28.723 16.918 67.487-115.537 192.366-212.951l5.196-4.031c-2.892 1.681 0.951-0.982 5.257-2.746 3.281-1.292 6.831-1.996 10.545-1.996s7.264 0.704 10.524 1.985c-2.767-1.345 1.597 0.349 5.4 2.832l3.232 2.573c-2.954-22.686 121.104 90.887 204.65 231.368-27.53-56.203 30.813 39.564 67.65 145.403 1.709 7.759 3.121 9.701 3.827 11.82v0c0.086 0.873 0.135 1.887 0.135 2.913s-0.049 2.040-0.144 3.041c-0.085 15.408-12.554 28.001-28.034 28.297zM787.597 764.028c1.65-0.612-4.461 4.267-11.547 7.308 69.21-26.78-10.842 9.765-96.458 32.707-68.289 18.189-140.156 27.892-214.29 27.892s-146.001-9.703-214.401-27.908c65.558 19.796-21.197-1.107-101.41-34.56 6.226 3.164-1.027-0.568-6.877-5.828-2.485-1.051-8.402-8.523-11.519-17.32-1.364-3.399-2.395-8.149-2.562-13.118l-0.002-2.718c0.178-93.262 18.101-188.172 50.737-275.925l0.639-1.085c4.879-9.2 14.396-15.36 25.352-15.36 0.025 0 0.050 0 0.076 0 2.876 0.001 5.68 0.453 8.313 1.289l7.22 3.301 15.007 5.297c12.421 23.546 252.262 113.836 508.637 154.443l11.131 1.453 7.062 0.883c16.607 3.504 30.083 17.498 32.981 35.059l0.034 2.37c2.806 17.151 5.717 52.069 6.346 87.545l0.010 0.731v3.531c-0.301 11.393-5.827 22.388-14.431 29.973zM928.839 804.988v0 3.884c-1.45 19.185-13.611 37.652-31.129 48.035l-8.595 3.871c-123.554 62.554-269.36 99.192-423.724 99.192s-300.171-36.639-429.198-101.694l-0.706-0.5c-17.981-9.809-31.053-29.183-32.476-51.721l-0.009-0.185c-2.295-22.422-3.001-45.55-3.001-68.502 0-0.347-0.001-0.758-0.001-1.168 0-132.824 27.602-259.201 77.382-373.708q15.309-34.37 35.789-72.859c0.214-48.775 134.179-221.365 308.837-337.68l13.546-8.714c8.615-4.561 18.832-7.239 29.674-7.239 0.057 0 0.115 0 0.172 0 0.27-0.004 0.6-0.007 0.93-0.007 10.76 0 20.893 2.681 29.769 7.412l9.545 6.19c170.176 91.26 341.8 313.48 402.374 578.038q10.227 46.955 15.7 88.974c4.833 36.003 7.592 77.623 7.592 119.887 0 0.245 0 0.491 0 0.736q-0.353 34.213-2.825 67.758z" />
21
+ <glyph unicode="&#x45;" glyph-name="error" horiz-adv-x="1142" d="M1133.686 32.886l-507.668 894.818c-10.931 19.443-31.427 32.362-54.942 32.362s-44.011-12.919-54.779-32.047l-507.831-895.133c-5.349-9.287-8.504-20.423-8.504-32.295s3.155-23.008 8.673-32.615c10.799-19.015 31.273-31.902 54.762-31.976h1015.346c23.439 0.050 43.924 12.919 54.778 31.984 5.512 9.599 8.667 20.734 8.667 32.607s-3.155 23.008-8.673 32.615zM571.077 60.455c-47.431 2.299-85.016 41.314-85.016 89.108s37.585 86.808 84.811 89.1c47.636-2.291 85.221-41.306 85.221-89.1s-37.585-86.808-84.811-89.1zM640.985 353.477c-1.182-27.372-31.311-48.443-71.089-48.443s-67.545 21.071-68.726 48.443c-6.105 98.462-19.692 275.692-19.692 294.006 0 36.037 39.385 64.197 90.388 64.197s86.843-28.16 86.843-64.197c0.591-17.526-11.422-196.135-17.526-293.809z" />
22
+ <glyph unicode="&#x46;" glyph-name="facebook" horiz-adv-x="495" d="M109.909-64v512h-109.909v176.469h109.739v105.984c0.171 144.213 62.123 229.547 238.251 229.547h146.603v-176.469h-91.648c-68.267 0-73.216-24.747-73.216-70.656v-88.235h166.059l-19.627-176.64h-146.603v-512h-219.648z" />
23
+ <glyph unicode="&#x47;" glyph-name="wordpress" d="M510.72-64c-282.192 0.764-510.657 229.701-510.657 511.998 0 282.77 229.23 512 512 512s512-229.23 512-512c0-2.828-0.023-5.651-0.069-8.469-3.807-278.716-230.984-503.536-510.67-503.536-0.916 0-1.831 0.002-2.746 0.007zM801.829 773.669c-192 178.103-514.011 136.594-652.069-83.383 1.457-0.351 5.118-0.794 8.862-0.912l128.098 4.569c1.526 0.428 3.279 0.673 5.089 0.673 9.947 0 18.161-7.423 19.403-17.033 0.021-0.347 0.027-0.638 0.027-0.931 0-11.21-9.087-20.297-20.297-20.297-0.714 0-1.42 0.037-2.116 0.109-13.81-1.653-27.89-2.75-43.616-4.213l157.074-469.76c2.56 6.766 4.023 10.606 5.303 14.629 28.343 85.029 56.686 170.24 85.211 256 1.679 4.231 2.652 9.133 2.652 14.263s-0.973 10.032-2.745 14.532c-18.192 48.005-36.478 96.097-52.752 144.919-6.583 19.749-14.811 31.451-36.571 28.526-0.546-0.016-1.189-0.025-1.834-0.025-5.843 0-11.513 0.743-16.92 2.139-8.938 0.769-16.246 8.623-16.246 18.183 0 10.14 8.22 18.36 18.36 18.36 0.579 0 1.153-0.027 1.718-0.079 14.007 0.005 28.27-1.457 42.35-2.555 22.64-1.451 49.092-2.278 75.736-2.278 38.096 0 75.797 1.69 113.032 5-3.065 0.267-1.049 0.621 1.050 0.621 9.86 0 17.897-7.804 18.272-17.572 0.040-0.495 0.062-1.031 0.062-1.572 0-10.705-8.678-19.383-19.383-19.383-0.601 0-1.195 0.027-1.782 0.081-14.37-1.651-28.816-2.931-44.542-4.577l156.16-464.457c-2.265-4.5 0.24-0.213 1.921 4.467 22.399 75.076 45.439 149.864 66.833 224.836 5.267 17.232 8.3 37.039 8.3 57.555 0 37.519-10.143 72.669-27.837 102.857-7.891 14.4-17.765 28.845-25.994 44.571 3.982-11.641-12.885 20.218-22.608 55.057-1.764 7.159-2.529 13.298-2.529 19.616 0 39.446 29.81 71.93 68.131 76.153-2.341-0.849 2.341 0.302 6.655 2.147zM655.726 36.023l-134.766 367.177h-2.926l-128.914-374.674c36.697-11.121 78.871-17.524 122.541-17.524 51.481 0 100.884 8.898 146.754 25.239zM318.72 56.686l-206.629 566.857c-23.247-51.636-36.791-111.934-36.791-175.395 0-170.748 98.044-318.596 240.906-390.319zM899.291 649.143c0-6.217 0-9.143 0-12.069 0.474-7.029 0.745-15.236 0.745-23.506 0-43.384-7.439-85.030-21.111-123.733q-54.057-156.852-108.914-316.12l-34.743-100.571c197.303 111.726 272.823 371.383 164.571 575.817z" />
24
+ <glyph unicode="&#x48;" glyph-name="hummingbird" d="M757.583 604.072c11.477 11.477 18.575 27.331 18.575 44.844 0 35.025-28.394 63.419-63.419 63.419-17.513 0-33.368-7.098-44.844-18.575-10.923-11.137-17.664-26.409-17.664-43.255 0-0.372 0.003-0.744 0.010-1.115-0.009-0.316-0.013-0.754-0.013-1.193 0-34.42 27.903-62.323 62.323-62.323 0.439 0 0.877 0.005 1.314 0.014-0.064-0.001-0.062-0.001-0.061-0.001 17.106 0 32.589 6.951 43.778 18.183zM623.051 559.228c-22.791 22.051-36.94 52.915-36.94 87.082 0 1.103 0.015 2.202 0.044 3.297-0.060 1.246-0.092 2.898-0.092 4.558 0 69.717 56.517 126.234 126.234 126.234s126.234-56.517 126.234-126.234c0-1.66-0.032-3.312-0.096-4.957 0.068-1.193 0.102-2.87 0.102-4.555 0-33.365-13.531-63.569-35.405-85.426-22.405-21.845-53.059-35.319-86.861-35.319-0.498 0-0.995 0.003-1.491 0.009-1.977-0.127-4.375-0.198-6.791-0.198-33.231 0-63.289 13.581-84.928 35.496zM784.772 183.172c0 0.098 0 0.214 0 0.33 0 28.728-2.182 56.946-6.39 84.498q-6.674 51.469 6.39 64.711c-104.163-104.549 12.74-3.697 101.875 118.677-55.039-80.477 21.701 15.244 74.999 124.498-5.498-21.297 27.966 51.503 46.666 130.027 10.199 43.067 15.641 88.167 15.687 134.53q0 74.712-23.834 97.664t-95.868 21.892c-46.070-0.004-91.085-5.603-134.153-16.159 28.939 12.216-54.196-10.331-129.672-46.343 77.853 41.806-31.522-6.241-125.255-74.477 118.509 87.564-12.674 5.057-119.168-102.027q-12.226-12.226-68.722-6.047t-80.154 6.003c-3.046 0.29-6.585 0.455-10.163 0.455-25.805 0-49.602-8.597-68.684-23.082q-27.084-23.276-41.384-37.224c27.28 35.625-31.619-25.214-72.705-97.5q-36.581-63.162-46.115-81.877c-4.572-7.318-7.283-16.205-7.283-25.726 0-13.972 5.838-26.58 15.208-35.519 10.411-14.901 29.204-26.422 50.759-28.422l107.274-0.021q54.731 0 72.386 0c0.62-55.862 25.696-107.667 65.339-143.745 34.953-38.736 86.445-64.019 143.857-65.113q1.077-17.658 0.194-72.389t0-106.99c0.871-20.401 11.99-40.168 28.77-52.832 8.854-9.49 21.208-15.327 34.926-15.327 9.675 0 18.672 2.904 26.166 7.888l78.745 45.441c-29.723-23.258 42.571 18.267 100.585 74.45q13.821 13.826 37.302 41.014c14.292 18.785 22.897 42.572 22.897 68.369 0 3.652-0.172 7.264-0.51 10.828zM378.703 145.743q-50.494 0-111.228 60.734t-60.734 111.228q0.883 27.012-17.655 28.072c-0.688 0.041-1.493 0.064-2.303 0.064-11.959 0-22.741-5.038-30.339-13.107l-105.951-105.952c-7.15-6.829-11.595-16.437-11.595-27.084 0-1.655 0.107-3.285 0.316-4.884q1.922-18.526 28.052-20.292h69.208q-10.593-26.659-24.541-58.968t-27.189-60.557c-3.134-4.806-4.999-10.688-4.999-17.006 0-6.87 2.204-13.225 5.945-18.397 4.631-3.246 10.481-5.244 16.797-5.244s12.166 1.998 16.951 5.397q24.274 11.062 61.526 26.951l59.851 25.247q0-13.065 0-27.542t0-41.49c-0.233-1.233-0.367-2.652-0.367-4.102 0-11.657 8.624-21.3 19.841-22.896 2.129-0.405 4.435-0.628 6.794-0.628 10.166 0 19.363 4.151 25.988 10.851l104.875 104.875c6.815 8.468 10.939 19.352 10.939 31.2 0 1.447-0.061 2.879-0.182 4.295q-1.4 19.060-29.471 19.060z" />
25
+ <glyph unicode="&#x49;" glyph-name="twitter" horiz-adv-x="1311" d="M1310.792 838.865c-14.89-10.709-81.418-32.19-151.988-40.433 39.699 16.967 91.224 72.488 115.047 140.977-5.215-8.61-82.434-44.54-166.562-61.314-53.177 49.795-122.171 81.005-198.455 81.005-0.51 0-1.019-0.001-1.529-0.004-1.417 0.031-3.181 0.048-4.948 0.048-143.894 0-260.897-115.137-263.907-258.31-0.005-0.394-0.005-0.528-0.005-0.663 0-20.801 2.555-41.005 7.367-60.315-213.432 6.91-416.518 110.697-554.535 271.859-23.725-35.825-37.265-80.55-37.265-128.437 0-0.162 0-0.324 0-0.486 0.318-89.914 47.503-169.25 118.519-214.509-40.056-0.282-83.88 11.67-122.242 32.426s1.463-2.758 1.463-3.888c1.807-126.237 93.452-231.003 213.999-253.1-19.642-6.049-44.035-9.384-69.208-9.384-17.872 0-35.351 1.681-52.289 4.894 39.032-104.987 137.304-178.977 252.959-179.717-91.27-69.137-206.805-110.743-332.057-110.743-0.661 0-1.321 0.001-1.981 0.003-21.669 0.002-43.945 1.315-65.843 3.869 119.49-73.177 261.363-116.418 413.335-116.418 0.546 0 1.091 0.001 1.636 0.002 494.626 0 765.147 393.916 765.147 735.4q0 16.724 0 33.448c-10.131-19.157 72.941 47.501 132.196 132.070z" />
26
+ <glyph unicode="&#x4a;" glyph-name="github" horiz-adv-x="1058" d="M692.495 215.53c63.126 15.876 116.235 46.872 145.341 107.73 18.195 36.716 28.841 79.951 28.841 125.673 0 26.693-3.629 52.539-10.419 77.070 1.36 8.143-14.763 42.914-38.675 70.812-2.053 2.82-3.417 6.692-3.417 10.883 0 1.408 0.154 2.78 0.446 4.1 4.58 15.767 7.227 34.023 7.227 52.897 0 24.881-4.601 48.687-12.998 70.614-0.751 4.264-5.676 8.414-11.569 8.414-0.625 0-1.24-0.047-1.84-0.137-22.795-0.222-48.918-7.221-71.926-19.338-17.97-8.815-36.87-20.344-55.77-30.361-3.497-1.961-7.675-3.117-12.123-3.117-1.324 0-2.625 0.102-3.894 0.3-37.228 9.592-80.127 15.108-124.315 15.108s-87.087-5.516-128.047-15.898c2.499 0.603 1.24 0.507-0.042 0.507-4.959 0-9.583 1.436-13.479 3.916-6.299 9.525-54.471 35.184-107.814 47.174l-8.319 1.338c-18.9 2.079-20.412 1.701-26.46-17.577-6.368-18.236-10.046-39.259-10.046-61.14 0-19.234 2.842-37.804 8.129-55.314-0.014 0.17 0.18-1.189 0.18-2.593 0-3.031-0.903-5.852-2.455-8.206-47.593-55.132-56.665-119.959-46.081-188.944-2.207-0.821 5.952-38.105 19.692-72.558 26.046-66.924 81.045-103.59 150.408-121.545 21.357-5.481 43.281-8.883 66.339-13.608-12.638-11.215-26.514-36.191-31.088-64.29-1.070-3.438-4.041-6.294-7.755-7.504-56.791-21.761-111.412-12.122-145.999 45.145-10.683 23.925-37.497 46.215-69.98 53.542-4.020 0.649-7.843 0.943-11.734 0.943-5.736 0-11.323-0.639-16.694-1.849-7.811-1.416-9.134-7.842-3.842-14.079-2.725 1.877 4.644-6.466 13.756-12.335 19.054-7.885 45.767-36.705 59.057-72.092 17.056-43.824 58.023-73.933 106.097-74.521 4.852-0.123 10.481-0.193 16.125-0.193 20.964 0 41.704 0.962 62.177 2.844-2.629-32.514-2.629-66.534-2.629-100.365 0-17.199-18.9-25.137-39.123-18.9 7.828-9.482-65.118 19.649-127.215 63.198-158.175 112.005-238.689 266.229-230.562 461.276 11.099 242.804 190.67 443.514 425.429 487.122 34.55 7.142 70.546 10.946 107.43 10.946 289.868 0 524.852-234.984 524.852-524.852 0-229.409-147.183-424.441-352.272-495.818-29.388-9.621-44.886 1.152-44.886 27.99q0 65.961 0 132.3c0.271 3.25 0.426 7.035 0.426 10.856 0 35.003-12.981 66.973-34.392 91.36 23.382 4.379 44.928 7.781 65.907 13.073z" />
27
+ <glyph unicode="&#x4b;" glyph-name="stackoverflow" horiz-adv-x="807" d="M750.421 580.096l-232.448 328.704 69.973 51.2c6.315-7.68 12.629-14.336 17.067-21.675 64.171-95.573 127.488-191.488 192.341-286.379 12.288-17.92 14.165-29.696-6.315-41.643 76.886 48.048 12.89 14.204-41.447-30.876zM734.72 562.176l-52.736-59.221-304.299 277.163 60.075 64.171zM270.677 614.912l34.133 63.317c9.899 17.067 21.333 6.656 31.403 0.853q140.459-80.555 280.576-161.621c59.051-34.133 59.904-41.813 11.776-97.792zM620.203 389.803c-2.56-10.581-3.072-13.312-3.925-16.213-17.067-60.587-5.461-54.784-64.683-38.059-106.667 30.208-213.333 61.269-320.341 90.112-25.088 6.827-29.525 17.067-20.992 40.448 25.429 70.656 11.947 59.221 74.923 39.765 103.253-31.744 205.995-65.365 308.736-99.157-5.62 4.303 11.983-4.578 26.432-17.021zM595.285 268.288c-1.877-49.323-2.731-51.2-48.469-46.421-117.077 11.264-233.984 23.381-351.061 34.133-21.333 2.048-27.136 9.899-23.211 31.915 10.923 63.659 9.728 62.635 75.264 53.589q158.891-22.016 318.293-40.277c25.259-2.56 35.328-11.435 29.355-32.939zM378.027 194.219c59.904 0 119.467 0 179.712 0 22.869 0 33.109-5.291 32.256-30.549-2.389-72.704 9.899-63.317-62.805-63.659-108.203 0-216.405 0-324.267 0-27.136-0.512-38.229 6.656-38.229 35.157 1.877 70.827-2.731 58.027 59.221 58.88 51.712 0.683 102.912 0.171 154.112 0.171zM91.136 29.525h576.512v38.741c0 87.040 0 173.909 0 260.949 0 23.040 6.997 30.208 29.696 29.525 73.387-2.219 60.587 8.875 61.099-61.44 0-110.080 0-220.331 0-330.411 0-24.576-8.021-30.891-31.573-30.72q-347.819 1.024-695.808 0c-24.064 0-31.403 7.168-31.232 31.232 1.024 119.467 1.195 238.933 0 359.424 0 26.283 8.533 32.597 33.28 32.256 57.856-1.195 57.856 0 57.856-59.051v-270.507z" />
28
+ <glyph unicode="&#x4c;" glyph-name="linkedin" horiz-adv-x="1096" d="M378.839-64h234.818v380.6c-0.115 2.18-0.181 4.732-0.181 7.299 0 17.148 2.933 33.61 8.325 48.913 18.477 47.756 64.975 81.744 119.411 81.744 0.217 0 0.434-0.001 0.65-0.002 85.088 0 118.941-62.422 118.941-154.001v-364.554h235.013v391.363c0 209.379-115.843 306.633-270.431 306.633-3.397 0.176-7.375 0.276-11.377 0.276-85.454 0-160.246-45.646-201.324-113.886l0.974-1.058v97.841h-234.818c3.131-63.596 0-681.166 0-681.166zM131.302 696.613c1.841-0.096 3.997-0.15 6.166-0.15 70.031 0 126.801 56.771 126.801 126.801 0 1.773-0.036 3.538-0.108 5.293-1.362 74.499-50.869 131.442-131.294 131.442-1.841 0.096-3.997 0.15-6.166 0.15-70.031 0-126.801-56.771-126.801-126.801 0-1.773 0.036-3.538 0.108-5.293-0.091-1.46-0.139-3.466-0.139-5.482 0-69.598 56.421-126.019 126.019-126.019 1.353 0 2.702 0.021 4.045 0.064l1.369-0.005zM248.711-64v681.166h-234.818v-681.166h234.818z" />
29
+ <glyph unicode="&#x4d;" glyph-name="medium" horiz-adv-x="1293" d="M0 809.32v151.349h484.806v-1.783l17.832-65.087 109.667-407.906q15.603-58.177 31.206-116.354c0-2.452 2.006-3.566 4.235-2.675 0.899 0.591 1.747 1.849 2.001 3.312l111.454 414.179 48.146 176.313h483.469v-151.572h-4.235c-14.934 0-29.646 0-44.58 0-4.902-0.022-10.177-1.17-14.975-3.221-4.709-0.532-16.911-9.762-25.001-21.956-5.298-7.041-8.399-15.65-8.399-24.983 0-0.233 0.002-0.465 0.006-0.697q0-313.139 0-626.535c-0.011-0.319-0.017-0.695-0.017-1.071 0-8.082 2.868-15.495 7.641-21.275-7.498 8.847 0.66-2.521 10.991-11.442 8.277-7.432 19.135-11.92 31.042-11.92 0.409 0 0.817 0.005 1.224 0.016 13.983-0.001 28.025-0.001 41.845-0.001h4.458v-3.566q0-73.111 0-146.445h-462.739c-0.034 0.533-0.053 1.156-0.053 1.783s0.019 1.25 0.057 1.868q-0.004 71.912-0.004 143.685c0 1.114 0 2.229 0 3.789h96.515v668.698c-3.566 1.337-4.904 0-5.795-3.343q-29.2-103.871-57.285-207.296l-161.379-583.997c-2.229-8.47-4.458-16.717-6.687-25.188h-175.199s0 2.229-1.114 3.343l-60.852 222.899-160.488 588.677c-1.337 4.904-1.337 4.904-6.687 4.012v-668.698h96.738v-4.458q0-73.111 0-146.445h-387.845v152.017h49.707c0.97-0.123 2.093-0.193 3.232-0.193s2.262 0.070 3.364 0.206c11.449 1.849 25.89 12 34.716 26.038 3.75 4.782 6.060 10.819 6.165 17.391q0 316.541 0 633.281c-0.021 3.62-0.924 7.669-2.528 11.342 0.243 2.833-7.367 14.032-17.619 21.991-8.527 7.722-19.721 12.387-32.005 12.387-0.551 0-1.099-0.009-1.645-0.028-14.409 0.002-28.675 0.002-43.163 0.002z" />
30
+ <glyph unicode="&#x4e;" glyph-name="minify" d="M244.524 72.828c3.553 5.798-0.865-3.084-6.972-10.526-35.223-35.201-68.945-69.452-103.726-103.703-14.1-13.997-33.525-22.647-54.969-22.647-11.348 0-22.131 2.422-31.859 6.778-27.618 12.237-46.878 39.882-46.878 72.026 0 22.325 9.291 42.48 24.217 56.81l101.544 101.366c-16.571-15.614-4.263-2.16 10.381 8.213-4.202 5.204-7.027 8.559-10.205 11.56l-89.335 89.512c-0.261-0.319-3.339 2.282-5.427 5.573-2.997 5.565-4.731 12.087-4.731 19.013 0 0.978 0.035 1.948 0.103 2.909 4.057 4.921 10.436 8.32 17.615 8.521 43.288 0.001 86.543 0.001 129.798 0.001h179.023c1.53 0.095 3.319 0.149 5.12 0.149s3.59-0.054 5.364-0.16c-0.168 0.013-0.077 0.014 0.013 0.014 9.751 0 17.655-7.904 17.655-17.655 0-1.061-0.094-2.1-0.273-3.11 0.016-29.907 0.016-59.921 0.016-89.758q0-112.11 0-224.221c0.66-1.778 1.041-3.831 1.041-5.974 0-7.121-4.216-13.258-10.289-16.050-2.023-0.657-4.224-1.009-6.508-1.009-7.33 0-13.812 3.632-17.744 9.194q-45.949 45.971-91.499 92.051c3.89-5.539-2.709 2.264-7.247 11.283zM886.113 185.997c5.826-6.179 8.121-9.004 10.77-11.652 35.31-35.31 69.385-69.032 103.636-104.166 14.141-14.205 22.884-33.795 22.884-55.426 0-36.978-25.546-67.989-59.952-76.347-6.248-1.654-12.806-2.541-19.57-2.541-21.704 0-41.275 9.129-55.085 23.756l-104.023 103.849-7.945 7.768-9.357-8.828-89.159-89.335c0.312-0.541-3.553-4.67-8.341-7.347-4.333-2.131-9.274-3.337-14.497-3.337-1.911 0-3.784 0.161-5.606 0.471-4.663 3.855-7.749 9.78-7.749 16.426 0 0.050 0 0.1 0.001 0.15 0 73.261 0 146.53 0 219.799 0 32.662 0 65.324 0 97.986-0.459 1.497-0.723 3.218-0.723 5.001 0 9.751 7.904 17.655 17.655 17.655 1.833 0 3.6-0.279 5.262-0.797l317.668 0.034c0.522 0.060 1.127 0.093 1.74 0.093 8.971 0 16.243-7.272 16.243-16.243 0-4.019-1.46-7.697-3.878-10.533 4.384 5.383-1.42-3.319-8.937-10.174q-44.716-44.711-89.56-89.202c3.812 2.402-3.136-3.205-11.14-6.922zM245.76 823.172l89.688 90.041c-6.447-6.153 4.178 6.713 17.378 16.229 5.098 3.007 10.891 4.67 17.072 4.67 1.423 0 2.826-0.088 4.203-0.259 8.486-1.396 8.31-10.4 8.31-17.638q0-157.837 0-315.498c0-18.538-4.943-23.128-24.011-23.128-104.342 0-208.861 0-313.203 0-6.749 0.104-13.125 3.133-17.643 7.932-1.432 2.499-2.269 5.477-2.269 8.651 0 5.661 2.665 10.7 6.808 13.931 15.399 15.743 31.112 31.279 46.649 46.816l57.026 57.909-9.181 9.71c-35.31 35.31-69.385 69.032-103.636 104.166-14.223 13.509-23.071 32.559-23.071 53.676 0 8.596 1.466 16.85 4.162 24.525 6.485 26.059 29.621 47.893 58.533 53.086 5.633 1.325 11.579 2.046 17.693 2.046 21.959 0 41.746-9.302 55.635-24.18l102.264-102.444c-11.027 12.493-0.547 2.233 7.359-9.861zM775.062 822.466c39.901 40.077 76.623 77.33 114.052 114.052 14.357 14.968 34.522 24.269 56.859 24.269 43.488 0 78.742-35.254 78.742-78.742 0-22.645-9.559-43.057-24.861-57.421-33.94-34.29-68.191-68.188-102.266-102.263-2.825-2.825-5.65-6.003-9.534-10.24l62.323-61.263c13.418-13.418 27.189-26.483 40.077-40.43 3.281-2.891 7.111-9.74 8.444-17.445 1.443-10.097-5.443-15.394-17.625-15.57h-312.32c-23.658 0-27.719 4.061-27.719 27.895q0 154.306 0 308.789c-0.413 1.424-0.651 3.059-0.651 4.749 0 6.691 3.722 12.513 9.21 15.508 2.175 0.813 4.58 1.256 7.088 1.256 6.687 0 12.638-3.151 16.45-8.049q45.938-45.421 91.312-91.147c-15.147 17.038-0.765 3.060 10.102-13.439z" />
31
+ <glyph unicode="&#x4f;" glyph-name="archive" horiz-adv-x="833" d="M382.025 265.41h-238.592c-1.362-0.048-2.963-0.075-4.569-0.075-76.722 0-138.918 62.196-138.918 138.918 0 1.37 0.020 2.735 0.059 4.095q-0.005 206.441-0.005 412.734c0 76.722 62.196 138.918 138.918 138.918 161.666 0 324.026 0 486.213 0 0.971 0.025 2.113 0.040 3.26 0.040 56.17 0 104.23-34.726 123.881-83.881 14.209-31.287-1.593-54.73-34.412-54.73h-503.578c-1.857 0.176-4.014 0.277-6.195 0.277-38.361 0-69.459-31.098-69.459-69.459 0-2.237 0.106-4.45 0.313-6.633q-0.021-131.52-0.021-263.318c0-50.705 27.784-77.968 78.662-77.968h501.321c1.458 0.217 3.141 0.341 4.852 0.341 19.181 0 34.73-15.549 34.73-34.73 0-6.532-1.803-12.643-4.94-17.862-21.008-51.071-70.552-86.546-128.396-86.667h-243.122zM451.484 213.315h208.377v-121.553c25.7 0 15.802 0 40.634 0 2.535 0.441 5.797 2.794 7.78 6.017 12.82 17.355 33.139 28.447 56.049 28.447 38.361 0 69.459-31.098 69.459-69.459 0-2.169-0.099-4.314-0.294-6.432-2.734-30.281-26.005-55.449-56.157-61.132-4.598-1.004-9.383-1.54-14.293-1.54-22.154 0-41.758 10.918-53.726 27.666-2.948 4.367-7.652 7.070-12.987 7.070-0.611 0-1.215-0.036-1.807-0.105-22.676 0.007-10.694 0.007-33.268 0.007 0-29.867-28.826-86.824-105.578-86.824-1.14-0.046-2.478-0.072-3.822-0.072-50.887 0-93.019 37.48-100.298 86.34-24.726 0.555-14.828 0.555-39.833 0.555-2.535-0.441-5.797-2.794-7.78-6.017-12.746-18.188-33.546-29.892-57.081-29.892-38.361 0-69.459 31.098-69.459 69.459 0 2.741 0.159 5.444 0.468 8.102 2.724 30.229 25.995 55.398 56.147 61.080 4.598 1.004 9.383 1.54 14.293 1.54 22.154 0 41.758-10.918 53.726-27.666 2.935-4.459 7.69-7.232 13.094-7.232 0.574 0 1.14 0.031 1.698 0.092 22.679-0.006 10.697-0.006 34.661-0.006v121.553zM664.376 601.070l-217.58 80.746v80.92l217.58-80.92v-80.746zM664.376 739.815l-217.58 80.92h217.58v-80.92zM664.376 462.326l-217.58 80.746v80.746l217.58-80.746v-80.746zM446.795 404.328v80.746l217.58-80.746h-217.58z" />
32
+ <glyph unicode="&#x50;" glyph-name="pencil" d="M1005.714 835.657l-105.874 106.057c-11.205 10.989-26.57 17.772-43.52 17.772s-32.315-6.783-43.53-17.782l-90.139-89.773c-5.001-4.942-8.098-11.801-8.098-19.383s3.097-14.441 8.095-19.38l155.066-154.883c4.933-4.946 11.755-8.006 19.291-8.006s14.358 3.060 19.291 8.005l89.418 90.332c11.28 10.805 18.29 25.989 18.29 42.81 0 0.25-0.002 0.499-0.005 0.748 0.003 0.173 0.005 0.423 0.005 0.672 0 16.821-7.010 32.005-18.269 42.79zM85.577 195.657l-6.4-4.754-1.646-4.754-75.703-219.429-1.829-5.669c-0.513-1.557-0.809-3.35-0.809-5.211s0.296-3.654 0.843-5.333c-0.303-0.398 1.78-4.222 4.722-7.195 1.212-2.436 4.596-5.222 8.667-6.372 1.411-0.533 2.92-0.826 4.497-0.826s3.085 0.294 4.474 0.829l4.669 3.263 219.429 74.24 6.4 3.291 4.754 4.754c3.012 4.003 4.823 9.059 4.823 14.537s-1.811 10.534-4.868 14.6l-146.241 146.223c-3.377 2.079-7.47 3.311-11.849 3.311-0.334 0-0.667-0.007-0.998-0.021-0.021 0.003-0.101 0.003-0.181 0.003-4.96 0-9.371-2.351-12.18-6zM141.897 232.229l154.697-154.88c4.341-4.569 10.461-7.411 17.245-7.411 0.753 0 1.497 0.035 2.232 0.103 8.182 0.993 15.802 6.995 19.227 15.186l508.222 505.218c4.805 1.237 8.299 5.531 8.299 10.641 0 0.83-0.092 1.638-0.267 2.415 0.044 0.358 0.062 0.86 0.062 1.367 0 6.796-3.142 12.858-8.052 16.813l-154.739 154.912c-4.933 4.946-11.755 8.006-19.291 8.006s-14.358-3.060-19.291-8.005l-507.612-505.783c-4.946-4.933-8.006-11.755-8.006-19.291s3.060-14.358 8.005-19.291z" />
33
+ <glyph unicode="&#x51;" glyph-name="quora" horiz-adv-x="911" d="M695.79 106.019c3.596-15.101 23.817-39.586 50.242-54.246-40.601 22.728 2.827-5.557 50.912-24.625 9.205-2.488 13.998-8.286 13.998-15.204 0-0.382-0.015-0.761-0.043-1.136 0.003-17.605 0.003-35.261 0.003-52.916 0.257-1.013 0.404-2.177 0.404-3.375 0-7.898-6.403-14.301-14.301-14.301-0.266 0-0.531 0.007-0.794 0.022-59.108-9.182-115.605-5.828-166.805 29.129-7.085-0.7-40.335 30.641-61.431 69.534-3.148 6.217-8.387 9.67-14.433 9.67-1.336 0-2.632-0.169-3.869-0.486 2.529-0.954-45.655-7.205-94.816-9.766-3.969-0.12-5.873-0.132-7.78-0.132-94.629 0-182.061 30.815-252.809 82.957-85.845 51.128-164.078 162.048-186.131 292.088-5.712 28.702-8.77 58.662-8.77 89.337 0 116.169 43.862 222.094 115.928 302.117 45.578 64.244 143.675 127.546 256.753 147.171 27.893 5.565 56.97 8.538 86.741 8.538 104.131 0 199.769-36.366 274.906-97.090 75.283-48.643 146.935-154.036 168.449-276.688 5.832-29.094 8.949-59.458 8.949-90.549 0-103.708-34.672-199.318-93.057-275.871 16.652 8.453-41.705-60.467-114.896-108.714l-7.526-5.466zM629.407 245.495c1.236 1.766 4.237 5.473 7.062 9.534 33.173 48.522 52.973 108.474 52.973 173.049 0 0.735-0.003 1.469-0.008 2.203 0.319 11.927 0.501 26.1 0.501 40.317 0 51.28-2.361 102.009-6.982 152.083-3.832 61.431-43.719 131.186-103.212 176.534-33.71 26.441-75.921 42.117-121.793 42.117-51.63 0-98.622-19.858-133.754-52.353-59.034-54.74-96.017-132.976-96.090-219.851-1.412-44.858 0-89.878 0-134.722-0.011-0.992-0.017-2.164-0.017-3.337 0-42.177 8.042-82.475 22.677-119.446 31.895-82.723 109.754-169.41 226.985-158.817 10.417 0.883 20.657 3.708 33.368 6.003-26.659 40.96-57.732 69.385-103.283 79.095-4.557 1.173-8.784 5.253-10.387 10.481-0.912 24.477-0.030 49.017-0.030 73.382-0.027 0.266-0.043 0.574-0.043 0.886 0 5.070 4.11 9.181 9.181 9.181 0.64 0 1.265-0.065 1.868-0.19 4.087 0.251 8.936 0.389 13.818 0.389 42.722 0 82.986-10.523 118.342-29.118 29.503-15.928 57.751-37.291 89.001-57.771z" />
34
+ <glyph unicode="&#x52;" glyph-name="recycle" d="M0 240.022c3.708 17.655 6.532 35.31 11.299 51.377-7.126-8.74 11.71 43.949 40.441 89.805q27.355 46.14 55.426 93.985l5.12 9.357c-17.655 11.123-33.898 21.539-50.141 33.015 5.822-5.696-10.335 5.639-22.639 20.313-4.919 5.51-7.844 12.605-7.844 20.383 0 9.889 4.727 18.675 12.046 24.219-3.645-1.351 9.614 8.768 24.869 15.010 56.421 23.003 112.387 45.249 168.178 67.494-6.106-1.961 5.043 2.664 16.931 5.336 4.708 1.271 9.284 1.923 14.013 1.923 26.118 0 47.589-19.9 50.077-45.365 0.783-4.665 1.359-11.168 1.428-17.793 0.001-57.978 0.001-116.063 0.001-173.972-0.021-10.077-2.028-20.3-5.67-29.708-4.239-12.323-16.269-21.427-30.425-21.427-3.504 0-6.878 0.558-10.037 1.589 6.52-3.21-10.628 2.488-25.818 11.211-5.909 3.025-11.736 7.615-17.032 11.499l-19.068 12.359c8.284 9.307 1.068 2.312-4.432-5.926q-27.524-46.156-54.89-92.060c-6.004-6.006-17.172-30.182-21.757-56.615-1.298-6.087-1.965-11.997-1.965-18.063 0-36.533 24.174-67.419 57.399-77.535 13.393-5.084 32.907-9.050 53.262-9.677 47.947-1.243 95.616-0.007 143.991-0.007v-127.47c-2.295 0-4.767 0-7.415 0-47.669 0-95.338 0-143.007 0-1.38-0.024-3.009-0.037-4.641-0.037-53.195 0-103.050 14.302-145.929 39.269-40.348 21.217-73.7 67.505-80.455 122.039 0.117 0.52-0.434 3.603-1.382 6.506l0.065 38.965zM529.655 960c8.121-1.766 16.066-3.354 24.011-5.473 41.158-5.964 94.925-41.852 129.257-92.078 26.639-37.158 48.531-76.529 72.365-114.664 5.473-8.651 10.417-17.655 16.066-27.189 17.655 11.652 34.251 23.305 51.553 33.721-3.028-0.505 11.386 7.634 27.317 12.175 3.654 1.177 6.994 1.751 10.469 1.751 13.188 0 24.446-8.262 28.88-19.893 3.479-7.925 5.842-18.24 6.072-29.080 0.001-59.408 0.001-118.729 0.001-178.051-0.015-8.262-1.436-16.972-4.052-25.147-9.543-30.29-39.733-43.179-73.808-30.467-39.548 14.83-78.742 30.543-118.113 45.903-19.597 7.592-39.018 15.183-58.439 23.128-15.99 3.526-29.254 17.061-32.616 34.149-0.057 0.657-0.064 1.101-0.064 1.547 0 17.183 9.899 32.055 24.305 39.223 13.319 9.295 26.737 17.77 40.332 26.774 0.441-0.988-0.304 1.449-1.462 3.635-22.196 36.972-43.382 74.754-67.040 110.948 8.017-6.546-12.692 21.384-39.313 42.065-14.667 12.194-33.179 19.41-53.376 19.41s-38.71-7.216-53.099-19.211c25.271 24.464-12.142-5.895-40.479-43.481 19.652 25.731-1.942 1.266-17.598-26.949l-100.686 59.592c35.31 60.381 75.211 113.699 141.241 141.241-34.894-12.533 6.236 4.964 49.994 15.797l38.282 0.622zM735.868 160.044c7.004-0.482 15.18-0.756 23.42-0.756 23.683 0 46.837 2.267 69.257 6.596 54.391 15.17 80.344 60.543 61.453 116.334 19.88-44.969-1.019 13.112-31.86 64.551-4.156 8.188-10.689 17.899-16.515 29.022l97.633 58.439c0.396 0.012 1.445-0.414 2.31-1.070 30.175-50.13 62.661-99.035 76.255-157.297 4.796-15.802 7.557-33.964 7.557-52.77 0-36.685-10.506-70.915-28.672-99.848-15.944-29.748-59.158-63.651-110.656-76.957-28.747-8.77-62.15-14.028-96.75-14.243-17.768-0.001-34.011-0.001-53.078-0.001 0-17.655 0-33.015 0-49.258-0.026-8.341-1.711-17.96-4.778-26.939-3.703-11.521-14.901-20.166-28.118-20.166-3.391 0-6.65 0.569-9.685 1.617 1.124-1.594-12.643 3.507-24.506 11.276q-79.804 51.514-159.605 103.774c-39.371 25.777-39.018 61.44 0 87.217l149.892 97.633c5.65 3.708 11.123 7.415 17.655 10.593 32.132 17.655 58.262 3.531 59.498-33.545-0.177-17.302-0.706-34.957-0.706-54.201z" />
35
+ <glyph unicode="&#x53;" glyph-name="seo" d="M640 324.32h-151.52v87.84h126.24c8.837 0 16 7.163 16 16v66.080c0 8.837-7.163 16-16 16h-126.24v73.6h150.72c8.837 0 16 7.163 16 16v66.080c0 8.837-7.163 16-16 16h-249.6c-8.837 0-16-7.163-16-16v-423.68c0-8.837 7.163-16 16-16h250.4c8.837 0 16 7.163 16 16v66.080c0 8.837-7.163 16-16 16v0zM295.040 449.12c-27.243 25.69-60.119 44.648-96 55.36-12.16 5.28-22.24 10.24-30.56 14.88-6.525 3.489-12.689 7.616-18.4 12.32-3.204 2.715-5.771 6.102-7.52 9.92-1.675 3.943-2.493 8.197-2.4 12.48-0.196 5.436 0.618 10.861 2.4 16 1.559 4.269 3.952 8.185 7.040 11.52 2.931 2.939 6.485 5.181 10.4 6.56 5.121 1.88 10.545 2.802 16 2.72 5.868 0.144 11.7-0.947 17.12-3.2 4.517-1.996 8.474-5.073 11.52-8.96 3.693-4.755 6.412-10.192 8-16 2.034-7.016 3.004-14.297 2.88-21.6 0-8.837 7.163-16 16-16h80c6.879-0.018 12.999 4.363 15.2 10.88v1.76c0.51 1.55 0.78 3.169 0.8 4.8v4c0.199 18.749-3.337 37.351-10.4 54.72-6.484 17.080-16.394 32.653-29.12 45.76-14.215 13.736-31.172 24.314-49.76 31.040-19.396 6.945-39.88 10.359-60.48 10.080-20.14 0.235-40.186-2.791-59.36-8.96-17.943-5.928-34.569-15.273-48.96-27.52-14.061-11.771-25.321-26.529-32.96-43.2-7.485-16.923-11.25-35.256-11.040-53.76-0.308-17.979 2.842-35.85 9.28-52.64 6.347-15.934 16.381-30.136 29.28-41.44 30.757-24.553 65.881-43.065 103.52-54.56 14.493-5.372 27.766-13.586 39.040-24.16 2.89-3.307 5.069-7.174 6.4-11.36 1.694-5.545 2.504-11.323 2.4-17.12 0.050-5.427-0.76-10.827-2.4-16-1.304-3.972-3.43-7.625-6.24-10.72l11.84-10.72-11.68 10.080c-2.624-2.855-5.926-5.001-9.6-6.24-5.624-1.846-11.523-2.712-17.44-2.56-8.13-0.199-16.237 0.936-24 3.36-5.492 1.716-10.487 4.736-14.56 8.8-4.135 4.554-7.1 10.045-8.64 16-2.43 9.347-3.561 18.984-3.36 28.64 0 8.837-7.163 16-16 16h-81.28c-6.879 0.018-12.999-4.363-15.2-10.88v-1.76c-0.494-1.499-0.764-3.062-0.8-4.64v-4.48c-0.349-21.369 3.794-42.573 12.16-62.24 8.179-18.8 20.875-35.288 36.96-48 32.617-25.906 73.234-39.653 114.88-38.88 20.378 0.054 40.622 3.293 60 9.6 17.592 5.53 33.909 14.504 48 26.4 13.909 11.625 24.873 26.373 32 43.040 7.182 17.558 10.72 36.393 10.4 55.36 0.036 17.877-2.994 35.628-8.96 52.48-5.571 16.093-14.579 30.78-26.4 43.040v0zM996.96 584.64c-7.145 20.974-18.775 40.138-34.080 56.16-14.863 15.548-32.935 27.669-52.96 35.52-42.728 15.595-89.592 15.595-132.32 0-19.961-7.869-37.937-20.053-52.64-35.68-15.124-16.074-26.587-35.233-33.6-56.16-7.557-23.019-11.234-47.135-10.88-71.36v-118.72c-0.368-24.279 3.309-48.449 10.88-71.52 7.046-20.853 18.568-39.912 33.76-55.84 14.748-15.457 32.721-27.475 52.64-35.2 42.865-15.442 89.775-15.442 132.64 0 19.957 7.741 37.978 19.756 52.8 35.2 15.254 15.909 26.832 34.97 33.92 55.84 7.595 23.065 11.272 47.24 10.88 71.52v118.72c0.371 24.291-3.361 48.471-11.040 71.52v0zM794.4 514.080c-0.139 12.101 1.096 24.178 3.68 36 1.741 8.286 5.054 16.162 9.76 23.2 3.551 5.173 8.409 9.314 14.080 12 13.895 5.682 29.465 5.682 43.36 0 5.828-2.793 10.841-7.035 14.56-12.32 4.796-6.91 8.218-14.678 10.080-22.88 2.661-11.864 3.896-24.003 3.68-36.16v-119.68c0.189-12.156-1.046-24.292-3.68-36.16-1.735-8.364-5.106-16.303-9.92-23.36-3.719-5.285-8.732-9.527-14.56-12.32-13.738-5.637-29.142-5.637-42.88 0-5.778 2.728-10.742 6.92-14.4 12.16-4.815 7.115-8.185 15.106-9.92 23.52-2.646 12.029-3.881 24.325-3.68 36.64v119.36h-0.16z" />
36
+ <glyph unicode="&#x54;" glyph-name="trash" horiz-adv-x="796" d="M57.026 903.15c0 0 0 0 0 0 0-31.397 25.452-56.85 56.85-56.85 0.062 0 0.124 0 0.177 0h568.497c0 0 0 0 0 0 31.397 0 56.85 25.452 56.85 56.85s-25.452 56.85-56.85 56.85c0 0 0 0 0 0h-568.506c-31.383-0.099-56.817-25.472-57.017-56.85zM739.585 618.726c31.286 0.099 56.641 25.392 56.84 56.673v57.026c0 0 0 0.001 0 0.001 0 31.397-25.452 56.85-56.85 56.85-0.124 0-0.248 0-0.353-0.001h-681.833c-0.062 0-0.124 0-0.186 0-31.433 0-56.926-25.431-57.026-56.85v-56.85c0-31.397 25.452-56.85 56.85-56.85v-625.523c0 0 0 0 0 0 0-31.53 25.51-57.102 57.026-57.202h568.516c31.457 0.2 56.908 25.713 57.007 57.203v625.523zM170.726 618.726h113.699v-569.026h-113.699v569.026zM341.451 618.726h113.699v-569.026h-113.699v569.026zM512.177 618.726h113.699v-569.026h-113.876v569.026z" />
37
+ <glyph unicode="&#x55;" glyph-name="uptime" horiz-adv-x="1134" d="M57.234 390.583h217.051l164.571-418.011c8.581-21.457 29.195-36.339 53.284-36.339 28.233 0 51.692 20.443 56.381 47.334l119.455 695.199 89.966-250.149c8.129-22.356 29.192-38.034 53.918-38.034 0.009 0 0.018 0 0.026 0h264.593c31.711 0 57.417 25.707 57.417 57.417s-25.707 57.417-57.417 57.417h-223.817l-150.126 416.549c-8.447 21.735-29.2 36.861-53.486 36.861-27.832 0-51.024-19.866-56.17-46.191l-122.207-707.105-103.314 263.497c-8.551 21.544-29.217 36.526-53.389 36.571h-256.006c-31.711 0-57.417-25.707-57.417-57.417s25.707-57.417 57.417-57.417v0z" />
38
+ <glyph unicode="&#x56;" glyph-name="upload" horiz-adv-x="1365" d="M1050.836-64h-749.992c-0.424-0.002-0.925-0.003-1.426-0.003-15.013 0-29.805 0.942-44.322 2.77-117.762 14.242-218.304 105.483-247.147 224.715-3.005 14.041-5.359 25.576-7.949 36.169v69.208c-0.121-0.517 1.417 1.772 2.319 4.359 11.525 110.342 91.606 206.428 199.228 241.984 7.938 1.803 12.284 6.922 12.284 13.057 0 1.006-0.117 1.986-0.338 2.925 0.011 0.63 0.007 1.476 0.007 2.323 0 163.941 132.901 296.842 296.842 296.842 20.495 0 40.506-2.077 59.832-6.032-0.203-0.254 1.768-0.59 3.817-0.59 6.46 0 12.14 3.336 15.413 8.378 26.059 43.611 96.992 96.055 180.393 117.272-11.657-2.522 15.599 5.389 44.039 9.689 10.816 1.059 21.262 1.533 31.817 1.533 18.246 0 36.161-1.416 53.642-4.144 69.441-4.088 148.797-45.322 204.691-107.946 55.785-58.363 89.947-137.21 89.947-224.035 0-13.662-0.846-27.126-2.488-40.343-0.163 0.309-0.348-1.151-0.348-2.653 0-6.791 3.784-12.699 9.359-15.729 68.861-34.597 134.23-117.504 155.763-216.754-1.424 7.797 3.362-11.618 5.916-31.73 1.696-13.937 2.586-28.537 2.586-43.344s-0.889-29.407-2.618-43.748c-15.395-134.38-118.284-249.368-253.362-283.546-10.044-3.904-33.128-8.976-57.16-10.586zM633.468 145.743h146.185c12.397 1.14 22.314 11.010 23.532 23.433l0.009 195.727c0.974 12.508 10.94 22.506 23.448 23.534l97.549 0.006c14.36 0 48.493 0 0 48.728l-195.149 194.913c-6.226 6.256-14.843 10.128-24.364 10.128s-18.139-3.872-24.363-10.127l-195.15-194.914c-49.199-49.199-11.535-48.728 0-48.728h97.457c13.001 0 23.54-10.539 23.54-23.54v-194.913c0.741-13.575 11.929-24.302 25.623-24.302 0.592 0 1.18 0.020 1.763 0.060z" />
39
+ <glyph unicode="&#x57;" glyph-name="world" d="M365.714 18.103c5.976-10.646 28.073-27.415 54.041-35.262 31.188-10.424 66.163-16.318 102.515-16.318 38.771 0 75.977 6.704 110.52 19.015-13.109-5.71 1.945-0.090 15.19 8.16-33.216 43.97-73.627 69.57-128.484 67.193s-103.131-25.783-153.783-42.789zM125.074 219.246c-3.508 4.984-5.606 11.179-5.606 17.865 0 9.726 4.44 18.414 11.404 24.149 7.002 8.637 15.414 15.952 21.631 24.912-4.73-9.278 15.3 15.941 28.060 45.071 11.803 37.763 8.328 48.369-17.82 67.203-1.097 0-2.011 1.829-3.109 2.56-14.538 5.499-40.503 33.064-54.492 66.844-3.657 7.945-7.497 14.527-10.423 21.659-15.909 34.194-29.989 68.206-21.577 108.434 8.298 9.68-1.302 0.041-8.378-11.33 20.448 38.773-2.988 0.547-18.783-41.421-10.326-34.045-15.799-70.328-15.799-107.889s5.474-73.844 15.667-108.095c-0.221-16.144 12.884-49.446 33.481-76.783 3.135-7.668 21.778-23.63 44.121-32.032zM454.217 861.257l1.28-2.194c8.042 10.711 0.704-0.748-8.764-10.044-18.299-15.19-36.584-30.184-54.87-45.361 59.907 40.798 9.274 11.484-33.074-26.82-1.783-2.523-3.062-6.094-3.062-9.964 0-1.683 0.242-3.309 0.693-4.846 2.261-3.854 6.823-6.973 12.148-7.552 0.898-0.057 1.861-0.085 2.832-0.085 6.38 0 12.471 1.238 18.045 3.486q91.104 35.176 180.521 71.382c2.854 1.477 5.345 4.779 6.024 8.702 0.122 0.926 0.186 1.91 0.186 2.909 0 12.725-10.315 23.040-23.040 23.040-1.615 0-3.192-0.166-4.713-0.482-0.754-0.189-1.792-0.313-2.859-0.313-6.948 0-12.673 5.237-13.443 11.979-2.099 5.094-3.315 10.939-3.315 17.068 0 0.45 0.007 0.898 0.020 1.345 0.23 0.933 0.363 2.080 0.363 3.259 0 7.25-5.023 13.327-11.779 14.94 8.614-5.016-0.37 1.021-10.353 5.127-9.261 4.806-26.68 9.694-45.095 10.962-78.148-2.53-171.621-39.469-246.413-98.904 37.597 34.161-25.949-13.059-74.639-72.857l13.606-28.078c4.925-1.539 10.588-2.426 16.458-2.426 9.768 0 18.962 2.455 27 6.781 6.459 3.32 14.452 5.354 22.919 5.354s16.46-2.034 23.515-5.639c-4.164 1.729 1.135-0.895 6.854-2.522 4.053-1.832 8.393-2.851 12.97-2.851 16.663 0 30.171 13.508 30.171 30.171 0 0.137-0.001 0.273-0.003 0.409 0.016-0.566 0.75 3.026 1.083 6.734 0.525 10.233 6.505 19.572 15.231 24.801-11.879-9.884-0.573 0.973 12.66 8.961q56.969 30.067 113.837 59.141c-6.309-2.273 3.829 2.272 14.694 4.98zM503.223 618.789c13.531 6.4 26.514 12.069 39.314 18.286 5.65 2.873 12.322 4.556 19.386 4.556 4.433 0 8.71-0.663 12.74-1.894-1.772 5.663 56.736-14.645 107.651-46.072-11.303 9.775 12.401-6.356 30.666-27.346 12.963-14.089 23.386-30.18 35.272-44.992-6.989 3.404 18.165-26.478 49.745-47.457 10.514-6.811 22.49-10.592 35.348-10.592 3.984 0 7.883 0.363 11.666 1.058 11.396 0.105 20.89 9.701 20.89 21.515 0 4.048-1.114 7.835-3.053 11.072-0.976 1.882-1.581 4.226-1.581 6.711 0 1.416 0.196 2.787 0.563 4.086 2.929 2.032 6.625 3.313 10.621 3.313 0.759 0 1.507-0.046 2.242-0.136 2.334-0.111 7.185-2.578 10.887-6.212 25.231-20.659 50.099-41.688 75.699-61.985 12.069-9.509 21.211-6.949 25.783 7.863 3.369 9.396 5.316 20.237 5.316 31.532 0 0.55-0.005 1.099-0.014 1.647-0.263 42.389-13.256 99.616-36.027 151.584 7.501-12.427-6.079 20.844-26.073 49.278 118.608-161.488 35.527-28.798-71.081 80.907 50.945-50.529 7.397-0.455-45.169 38.030-7.394 5.781-15.317 8.763-23.936 8.763-5.84 0-11.361-1.369-16.258-3.804-12.222-5.39-24.473-11.424-36.359-18.19-16.64-8.046-18.286-7.314-25.234 9.326-1.026 10.748-10.008 19.088-20.939 19.088-5.21 0-9.977-1.894-13.65-5.032-22.28-13.69-43.857-28.867-65.434-43.679-4.895-3.332-8.068-8.878-8.068-15.165 0-2.441 0.478-4.771 1.347-6.9q2.882-8.289 5.259-17.066c1.995-2.751 3.191-6.194 3.191-9.917 0-8.97-6.946-16.319-15.752-16.96-21.084-8.049-42.661-15.546-63.141-24.689 2.909 3.329-14.693-6.197-28.765-19.435-6.227-5.566-10.163-13.695-10.163-22.744 0-6.523 2.045-12.568 5.529-17.53zM593.554 562.834c-20.993 12.338-46.239 19.625-73.188 19.625-1.463 0-2.921-0.021-4.373-0.064-65.067-5.298-106.027-42.966-133.821-97.824-3.271-5.69-5.2-12.511-5.2-19.782 0-12.99 6.157-24.542 15.711-31.897-8.384 4.063 15.818-14.994 43.748-27.058-34.324 12.321 16.004-9.664 69.761-22.946 21.284-3.464 36.121-17.656 39.951-35.897-2.367 6.813 0.391-0.114 2.137-7.433 6.143-39.307 12.36-78.073 18.395-116.838-2.344 10.411 2.408-32.601 10.992-74.213 6.928-25.261 26.676-31.295 52.459-13.924-12.475-9.056 4.526 1.252 18.3 14.826-29.756-26.513 2.517-1.845 27.796 28.806 26.681 35.728 52.647 71.202 77.332 107.408 1.65 7.609 18.879 26.348 40.565 37.757 21.975 7.156 37.189 26.885 37.189 50.166 0 0.718-0.014 1.433-0.043 2.144-0.063 0.2-0.1 0.548-0.1 0.904s0.038 0.703 0.109 1.038c0.586 1.261 0.931 2.772 0.931 4.365 0 4.378-2.608 8.147-6.355 9.838 36.045-26.123 5.795-0.803-28.714 17.572-17.225 5.638-35.937 23.326-45.206 45.89 10.205-22.437 0.183 4.434-14.439 28.168 14.264-22.666 0.548 3.173-17.978 24.763-1.787 2.226-6.771 5.211-12.43 6.305-19.907 4.414-40.204 7.34-59.587 12.643 26.012-9.617-12.883 1.666-48.169 19.14-4.050 0.727-8.367 6.070-8.367 12.422 0 1.803 0.348 3.525 0.981 5.102zM539.977-64h-55.954c2.685-0.476-3.199 1.009-9.304 1.788-65.31 1.008-144.474 24.437-212.994 64.186-120.342 57.945-225.505 193.667-253.256 355.816-4.080 22.553-5.909 42.484-8.469 62.233v55.954c-0.579-3.095 0.961 2.979 1.785 9.279 1.727 81.753 33.964 174.177 87.408 250.693 62.601 105.24 193.094 195.584 345.686 217.516 18.059 2.695 33.601 4.341 49.144 6.17h55.954c-2.808 0.507 3.133-0.994 9.296-1.787 44.675-0.295 103.039-13.054 156.284-35.552 169.597-73.29 274.922-202.57 310.579-387.438 3.84-19.749 5.303-40.046 7.863-60.16v-54.857c0.445 2.562-1.023-3.265-1.789-9.311-0.264-42.76-13.201-101.078-35.915-154.22-75.118-174.938-208.604-281.544-400.055-314.458-15.177-2.56-30.72-3.84-46.263-5.851z" />
40
+ <glyph unicode="&#x58;" glyph-name="pos_middle" d="M0 255.81c0-35.241 28.456-63.81 64.056-63.81h895.888c35.377 0 64.056 28.994 64.056 63.81v384.38c0 35.241-28.456 63.81-64.056 63.81h-895.888c-35.377 0-64.056-28.994-64.056-63.81v-384.38zM0 800c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0 96c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0-32c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32zM0 928c0-17.673 14.476-32 31.769-32h960.462c17.546 0 31.769 14.844 31.769 32 0 17.673-14.476 32-31.769 32h-960.462c-17.546 0-31.769-14.844-31.769-32z" />
41
+ <glyph unicode="&#x59;" glyph-name="pos_footer" d="M0 384.19c0 35.241 28.456 63.81 64.056 63.81h895.888c35.377 0 64.056-28.994 64.056-63.81v-384.38c0-35.241-28.456-63.81-64.056-63.81h-895.888c-35.377 0-64.056 28.994-64.056 63.81v384.38zM0 672c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 800c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 928c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32zM0 544c0 17.673 14.476 32 31.769 32h960.462c17.546 0 31.769-14.844 31.769-32 0-17.673-14.476-32-31.769-32h-960.462c-17.546 0-31.769 14.844-31.769 32z" />
42
+ <glyph unicode="&#x5a;" glyph-name="star" horiz-adv-x="1108" d="M1061.82 608.734h-294.154c-0.215-0.002-0.468-0.003-0.722-0.003-32.971 0-61.217 20.227-73.008 48.949 2.219-5.396-0.573 0.484-2.378 6.781l-86.442 257.146-2.101 6.494c-8.374 19.126-27.135 32.245-48.96 32.245-23.194 0-42.927-14.817-50.25-35.502l-0.115-0.373-87.291-257.862c1.558 5.097-0.132-1.945-2.835-8.46-12.006-28.401-40.045-48.274-72.727-48.274-0.296 0-0.592 0.002-0.887 0.005h-294.682c-25.642-3.248-45.271-24.925-45.271-51.186 0-0.136 0.001-0.272 0.002-0.407 0.027-16.564 8.167-31.293 20.675-40.373l2.628-1.819 229.211-161.021c20.484-13.761 33.881-36.915 34-63.206 0-0.107 0.001-0.211 0.001-0.316 0-6.067-0.767-11.955-2.208-17.572 1.142 2.679-1.008-5.384-4.459-12.715l-86.355-256.883v-1.91c-1.388-4.412-2.187-9.486-2.187-14.747 0-28.061 22.748-50.808 50.808-50.808 0.702 0 1.401 0.014 2.096 0.042-0.047-0.003 0.015-0.004 0.077-0.004 9.536 0 18.494 2.478 26.264 6.826l8.705 6.163 231.885 162.74c12.206 7.704 27.058 12.276 42.977 12.276s30.771-4.572 43.314-12.474c-7.243 4.386 0.917 0.236 7.788-5.423l-0.102 0.082 231.885-162.931c7.777-4.564 17.128-7.259 27.108-7.259 0.073 0 0.145 0 0.218 0 0.221-0.004 0.495-0.006 0.77-0.006 28.12 0 51.003 22.423 51.745 50.364-0.002 5.381-0.911 10.616-2.582 15.497l0.101 2.144-88.055 258.435c1.605-4.417-1.49 2.474-3.341 9.859-1.674 6.132-2.58 12.65-2.58 19.38 0 0.062 0 0.124 0 0.186 0.066 24.265 11.745 45.936 29.802 59.64l6.108 4.338 226.155 158.729 6.303 4.011c11.197 8.706 18.704 22.538 19.1 38.138-0.050 26.51-20.083 48.268-45.805 51.043z" />
43
+ <glyph unicode="&#x61;" glyph-name="lock" d="M568 112h-112l20.8 120c-28.8 12.8-48 41.6-48 75.2 0 46.4 36.8 83.2 83.2 83.2s83.2-36.8 83.2-83.2c0-33.6-19.2-62.4-48-75.2l20.8-120zM624 504h-224v168c0 62.4 51.2 112 112 112s112-49.6 112-112v-168zM736 504v168c0 123.2-100.8 224-224 224s-224-100.8-224-224v-168h-56c-30.4 0-56-25.6-56-56v-392c0-30.4 25.6-56 56-56h560c30.4 0 56 25.6 56 56v392c0 30.4-25.6 56-56 56h-56z" />
44
+ <glyph unicode="&#x62;" glyph-name="book" horiz-adv-x="727" d="M707.467 808.92c-2.704 9.436-9.638 16.489-18.143 19.762-0.335 0.134-0.671 0.263-1.011 0.385-0.338 0.116-0.678 0.224-1.020 0.328-3.334 1.063-6.841 1.586-10.376 1.438-0.732-0.032-1.507-0.048-2.322-0.048-4.964-0.008-11.389 0.645-18.57 2.063-12.594 2.459-27.479 7.227-42.21 13.683-11.060 4.833-22.069 10.603-32.15 16.917-7.561 4.732-14.603 9.77-20.762 14.877-4.621 3.827-8.744 7.693-12.233 11.443-5.247 5.621-9.006 11-11.161 15.356-1.087 2.179-1.496 4.090-1.911 5.683-0.417 1.597-0.265 2.865-0.265 3.929v0.147c0 9.547-4.633 18.687-12.259 24.436-7.624 5.749-17.788 7.537-26.931 4.782l-474.675-143.044c-12.698-3.827-21.469-15.534-21.469-28.795v-666.072c0-10.182 1.798-20.104 4.889-29.476 2.707-8.21 6.395-16.027 10.827-23.458 7.77-13.003 17.797-24.86 29.448-35.633 17.493-16.137 38.693-29.876 62.282-40.397 23.591-10.496 49.603-17.75 76.729-20.243 3.777-0.346 7.663 0.039 11.299 1.119 0.985 0.293 2.247 0.677 3.919 1.192 6.43 1.98 18.749 5.841 35.546 11.126 117.454 36.968 452.335 143.268 452.35 143.274 12.466 3.956 20.976 15.585 20.976 28.664v653.767c0.633 4.15 0.433 8.495-0.798 12.795v0zM542.709 817.019c8.776-5.86 17.982-11.248 27.4-16.17-39.795-11.404-87.554-25.093-135.832-38.936-59.784-17.143-120.357-34.518-167.561-48.078-23.603-6.78-43.863-12.604-59.017-16.971-7.579-2.183-13.88-4.001-18.692-5.395-1.489-0.43-2.812-0.814-4.006-1.161-15.907 1.901-31.585 5.708-46.115 10.997-12.141 4.412-23.481 9.844-33.481 15.902-7.501 4.541-14.245 9.436-20.027 14.452-7.916 6.848-13.95 13.929-17.953 20.448l416.585 125.558c1.54-3.032 3.209-5.977 5.006-8.824 4.783-7.561 10.395-14.531 16.585-21.076 10.842-11.437 23.473-21.618 37.108-30.746v0zM105.647 46.507c-7.508 4.95-14.299 10.286-20.161 15.755-8.803 8.197-15.457 16.72-19.586 24.403-2.075 3.839-3.531 7.454-4.447 10.723-0.916 3.275-1.302 6.188-1.302 8.803v568.871c14.659-10.516 31.171-19.49 48.965-26.74 14.961-6.078 30.833-10.922 47.275-14.275v-610.805c-5.932 1.717-11.765 3.705-17.43 5.962-12.018 4.782-23.302 10.699-33.314 17.302v0zM256.541 40.302c-15.080-4.762-28.58-9.019-40-12.613v609.125c15.947 4.6 40.601 11.481 69.172 19.743v-267.943l83.133 83.765 55.211-27.922v252.161c45.112 12.656 89.321 25.505 129.125 36.914 37.621 10.783 71.111 20.275 94.933 27.1v-596.265c-42.103-13.361-141.164-44.792-237.658-75.363-56.069-17.762-111.271-35.236-153.917-48.702v0z" />
45
+ <glyph unicode="&#x63;" glyph-name="unlock" d="M800 512h-64v160c0 123.2-100.8 224-224 224s-224-100.8-224-224c0 0 0-40 0-48s8-16 16-16 72 0 80 0c8 0 16 8 16 16s0 48 0 48c0 62.4 51.2 112 112 112 62.4 0 112-49.6 112-112v-160h-400c-30.4 0-48-17.6-48-48v-408c0-30.4 25.6-56 56-56h560c30.4 0 56 25.6 56 56v408c0 30.4-17.6 48-48 48zM547.2 232l20.8-120h-112l20.8 120c-28.8 12.8-48 41.6-48 75.2 0 46.4 36.8 83.2 83.2 83.2s83.2-36.8 83.2-83.2c0-32-19.2-60.8-48-75.2z" />
46
+ <glyph unicode="&#x64;" glyph-name="plugin" d="M272 736c16 16 544-512 528-528-65.6-65.6-160-112-272-112-75.2 0-164.8 0-224 0-12.8 0-24-4.8-32-12.8-20.8-17.6-38.4-38.4-59.2-57.6-35.2-33.6-86.4-33.6-120 0-35.2 33.6-35.2 84.8-1.6 121.6 17.6 19.2 38.4 36.8 56 57.6 8 9.6 12.8 22.4 12.8 35.2 0 67.2 0 139.2 0 224 0 112 48 208 112 272zM785.6 353.6c-16-16-128 96-112 112s139.2 137.6 176 174.4c33.6 33.6 144-80 112-110.4-59.2-59.2-116.8-116.8-176-176zM545.6 593.6c-16-16-128 96-112 112s139.2 137.6 176 174.4c33.6 33.6 144-80 112-110.4-59.2-59.2-116.8-116.8-176-176z" />
47
+ <glyph unicode="&#x65;" glyph-name="caret_down" d="M779.2 508.8l-204.8-204.8c-14.4-14.4-32-32-62.4-32s-49.6 17.6-62.4 32l-204.8 204.8c-27.2 27.2-27.2 67.2 0 94.4s67.2 27.2 94.4 0l172.8-172.8 172.8 172.8c27.2 27.2 67.2 27.2 94.4 0s27.2-67.2 0-94.4z" />
48
+ <glyph unicode="&#x66;" glyph-name="power" d="M848 726.4c-16 20.8-46.4 24-67.2 6.4-20.8-16-24-46.4-6.4-67.2v0c48-59.2 75.2-131.2 75.2-212.8 0-92.8-38.4-177.6-99.2-238.4s-145.6-99.2-238.4-99.2c-92.8 0-177.6 38.4-238.4 99.2s-99.2 145.6-99.2 238.4c0 80 27.2 153.6 75.2 212.8 16 20.8 12.8 49.6-6.4 67.2-20.8 16-49.6 12.8-67.2-6.4-60.8-75.2-96-169.6-96-272 0-118.4 48-227.2 126.4-305.6s185.6-126.4 305.6-126.4c118.4 0 227.2 48 305.6 126.4s126.4 187.2 126.4 307.2c0 102.4-35.2 196.8-96 270.4zM512 398.4c27.2 0 48 20.8 48 48v384c0 27.2-20.8 48-48 48s-48-20.8-48-48v-384c0-27.2 20.8-48 48-48z" />
49
+ <glyph unicode="&#x67;" glyph-name="radio_checked" d="M512 896c-248 0-448-200-448-448s200-448 448-448 448 200 448 448-200 448-448 448zM720 496l-176-176c-3.2-3.2-28.8-32-64-32s-60.8 28.8-64 32l-112 112c-16 16-16 48 0 64s48 14.4 64-1.6l112-110.4 176 176c16 16 48 16 64 0s16-48 0-64z" />
50
+ <glyph unicode="&#x68;" glyph-name="radio_default, radio" d="M512 803.2c195.2 0 355.2-158.4 355.2-355.2s-160-355.2-355.2-355.2-355.2 160-355.2 355.2 160 355.2 355.2 355.2zM512 896c-248 0-448-200-448-448s200-448 448-448 448 200 448 448-200 448-448 448z" />
51
+ <glyph unicode="&#x69;" glyph-name="download_alt" d="M753.6 112c-174.4 0-318.4 0-492.8 0-16 0-27.2 1.6-28.8 1.6-80 11.2-145.6 70.4-163.2 150.4-1.6 8-3.2 14.4-4.8 22.4 0 14.4 0 30.4 0 44.8 0 1.6 1.6 1.6 1.6 3.2 12.8 78.4 57.6 131.2 132.8 160 6.4 1.6 6.4 4.8 6.4 9.6-1.6 123.2 112 217.6 233.6 193.6 6.4-1.6 9.6 0 14.4 4.8 32 38.4 72 64 120 76.8 9.6 1.6 19.2 4.8 28.8 6.4 25.6 3.2 52.8-1.6 54.4-1.6 54.4-8 99.2-30.4 136-70.4 44.8-49.6 64-105.6 57.6-172.8 0-6.4 1.6-9.6 6.4-12.8 54.4-33.6 88-81.6 102.4-144 1.6-8 3.2-12.8 3.2-20.8 3.2-28.8 0-54.4 0-56-12.8-91.2-78.4-164.8-168-188.8-12.8-3.2-27.2-6.4-40-6.4zM560 560c-32 0-73.6 0-96 0-8 0-16-8-16-16 0-43.2 0-84.8 0-128 0-9.6-8-16-16-16-27.2 0-38.4 0-64 0-9.6 0-32 0 0-32 44.8-44.8 84.8-84.8 128-128 8-8 22.4-9.6 32 0 43.2 43.2 84.8 84.8 128 128 32 32 8 32 0 32-16 0-48 0-64 0-9.6 0-16 8-16 16 0 48 0 80 0 128 0 9.6-8 16-16 16z" />
52
+ <glyph unicode="&#x6a;" glyph-name="rocket" d="M603.2 182.4c-36.8-36.8-148.8-36.8-184 0-19.2 19.2-35.2 0-35.2-19.2 0-33.6 0-78.4 0-112 0-19.2 17.6-36.8 36.8-19.2 11.2 11.2 24 24 36.8 36.8 11.2-27.2 25.6-64 36.8-92.8 9.6-24 27.2-24 36.8 0 9.6 25.6 27.2 70.4 36.8 92.8 9.6-9.6 17.6-17.6 36.8-36.8 17.6-17.6 36.8 0 36.8 19.2 0 32 0 78.4 0 112-1.6 19.2-19.2 38.4-38.4 19.2zM800 419.2c-19.2 19.2-80 60.8-80 80 0 168-51.2 307.2-144 400-52.8 52.8-76.8 51.2-128 0-92.8-92.8-144-232-144-400 0-17.6-62.4-62.4-80-80-36.8-36.8-32-76.8-32-96 0-56 25.6-140.8 32-160 11.2-36.8 60.8-35.2 80-16 36.8 36.8 83.2 83.2 96 96 56-56 168-56 224 0 12.8-12.8 59.2-59.2 96-96 19.2-19.2 70.4-20.8 80 16 4.8 19.2 32 104 32 160 0 19.2 4.8 59.2-32 96zM512 534.4c-52.8 0-96 43.2-96 96s43.2 96 96 96c51.2 0 96-44.8 96-96 0-49.6-43.2-96-96-96zM560 630.4c0-26.51-21.49-48-48-48s-48 21.49-48 48c0 26.51 21.49 48 48 48s48-21.49 48-48z" />
53
+ <glyph unicode="&#x6b;" glyph-name="search" d="M923.2 137.6l-228.8 230.4c33.6 52.8 52.8 112 52.8 179.2-1.6 184-150.4 332.8-334.4 332.8s-332.8-148.8-332.8-332.8 148.8-332.8 332.8-332.8c67.2 0 126.4 19.2 179.2 52.8l230.4-230.4c28.8-28.8 73.6-28.8 100.8 0s27.2 73.6 0 100.8zM174.4 547.2c0 131.2 105.6 238.4 238.4 238.4s238.4-105.6 238.4-238.4-107.2-236.8-238.4-236.8-238.4 105.6-238.4 236.8z" />
54
+ <glyph unicode="&#x6c;" glyph-name="theme" d="M336 704c113.6-113.6 224-224 336-336 16-16 16-33.6 0-48-24-24-57.6-57.6-80-80-16-16-32-16-48 0-17.6 17.6-62.4 62.4-80 80-30.4 28.8-51.2 12.8-64 0-16-16-80-128-160-208-81.6-81.6-152-104-208-48s-33.6 126.4 48 208c80 80 192 144 208 160s32 32 0 64c-19.2 19.2-60.8 60.8-80 80-16 16-16 32 0 48 24 24 56 56 80 80 16 16 32 17.6 48 0zM384 800c17.6 17.6 36.8 35.2 56 52.8 27.2 25.6 62.4 19.2 94.4 16 44.8-4.8 84.8-24 121.6-51.2 32-25.6 64-52.8 99.2-75.2 81.6-54.4 169.6-92.8 268.8-73.6-80-80-176-172.8-256-252.8-16-16-32-16-48 0-30.4 30.4-310.4 308.8-337.6 336-14.4 14.4-14.4 32 1.6 48z" />
55
+ <glyph unicode="&#x6d;" glyph-name="speach" d="M699.206 589.081h-345.743c-13.632 0-24.696-11.014-24.696-24.696 0-13.632 11.064-24.696 24.696-24.696h345.743c13.632 0 24.696 11.064 24.696 24.696 0 13.682-11.064 24.696-24.696 24.696zM699.206 292.729h-345.743c-13.632 0-24.696-11.014-24.696-24.696 0-13.632 11.064-24.696 24.696-24.696h345.743c13.632 0 24.696 11.064 24.696 24.696 0 13.682-11.064 24.696-24.696 24.696zM699.206 440.905h-345.743c-13.632 0-24.696-11.014-24.696-24.696 0-13.632 11.064-24.696 24.696-24.696h345.743c13.632 0 24.696 11.064 24.696 24.696 0 13.682-11.064 24.696-24.696 24.696zM501.639 931.12c-272.742 0-493.919-221.226-493.919-493.919 0-109.897 35.908-211.447 96.611-293.437l-51.318-177.218 175.983 58.727c78.089-51.911 171.884-81.991 272.643-81.991 272.742 0 493.919 221.078 493.919 493.919 0 272.693-221.177 493.919-493.919 493.919v0zM501.639 42.065c-78.138 0-153.461 22.671-217.917 65.494-16.398 10.916-35.463 16.497-54.726 16.497-9.681 0-19.362-1.432-28.845-4.297 7.162 28.598 1.185 59.023-16.398 82.781-50.528 68.21-77.249 149.312-77.249 234.661 0 217.868 177.268 395.135 395.135 395.135s395.135-177.268 395.135-395.135c0-217.868-177.268-395.135-395.135-395.135v0z" />
56
+ <glyph unicode="&#x6e;" glyph-name="support" horiz-adv-x="847" d="M504.231 4.118c22.087 9.699 42.18 20.276 60.268 31.085 39.815 23.797 69.925 48.698 90.442 68.056 1.536-0.142 3.092-0.214 4.664