Version Description
Download this release
Release Info
Developer | Nikschavan |
Plugin | Astra Starter Sites |
Version | 1.2.4 |
Comparing to | |
See all releases |
Code changes from version 1.2.3 to 1.2.4
- astra-sites.php +54 -54
- inc/assets/css/admin.css +462 -462
- inc/assets/js/admin-page.js +1373 -1373
- inc/assets/js/astra-sites-api.js +57 -57
- inc/assets/js/astra-sites-notices.js +20 -20
- inc/assets/js/eventsource.js +673 -673
- inc/assets/js/eventsource.min.js +5 -5
- inc/assets/js/render-grid.js +558 -518
- inc/importers/batch-processing/class-astra-sites-batch-processing-elementor-v2.php +328 -328
- inc/importers/batch-processing/helpers/class-wp-async-request.php +164 -164
- inc/importers/batch-processing/helpers/class-wp-background-process.php +513 -513
- inc/importers/class-widgets-importer.php +278 -278
- inc/importers/wxr-importer/class-logger.php +140 -140
- inc/importers/wxr-importer/class-wp-importer-logger-serversentevents.php +46 -46
- inc/importers/wxr-importer/class-wxr-import-info.php +20 -20
- inc/importers/wxr-importer/class-wxr-importer.php +2298 -2298
- inc/includes/admin-page.php +15 -8
- languages/astra-sites.pot +630 -630
- readme.txt +190 -186
astra-sites.php
CHANGED
@@ -1,54 +1,54 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Plugin Name: Astra Starter Sites
|
4 |
-
* Plugin URI: http://www.wpastra.com/pro/
|
5 |
-
* Description: Import free sites build with Astra theme.
|
6 |
-
* Version: 1.2.
|
7 |
-
* Author: Brainstorm Force
|
8 |
-
* Author URI: http://www.brainstormforce.com
|
9 |
-
* Text Domain: astra-sites
|
10 |
-
*
|
11 |
-
* @package Astra Sites
|
12 |
-
*/
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Set constants.
|
16 |
-
*/
|
17 |
-
if ( ! defined( 'ASTRA_SITES_NAME' ) ) {
|
18 |
-
define( 'ASTRA_SITES_NAME', __( 'Astra Sites', 'astra-sites' ) );
|
19 |
-
}
|
20 |
-
|
21 |
-
if ( ! defined( 'ASTRA_SITES_VER' ) ) {
|
22 |
-
define( 'ASTRA_SITES_VER', '1.2.
|
23 |
-
}
|
24 |
-
|
25 |
-
if ( ! defined( 'ASTRA_SITES_FILE' ) ) {
|
26 |
-
define( 'ASTRA_SITES_FILE', __FILE__ );
|
27 |
-
}
|
28 |
-
|
29 |
-
if ( ! defined( 'ASTRA_SITES_BASE' ) ) {
|
30 |
-
define( 'ASTRA_SITES_BASE', plugin_basename( ASTRA_SITES_FILE ) );
|
31 |
-
}
|
32 |
-
|
33 |
-
if ( ! defined( 'ASTRA_SITES_DIR' ) ) {
|
34 |
-
define( 'ASTRA_SITES_DIR', plugin_dir_path( ASTRA_SITES_FILE ) );
|
35 |
-
}
|
36 |
-
|
37 |
-
if ( ! defined( 'ASTRA_SITES_URI' ) ) {
|
38 |
-
define( 'ASTRA_SITES_URI', plugins_url( '/', ASTRA_SITES_FILE ) );
|
39 |
-
}
|
40 |
-
|
41 |
-
if ( ! function_exists( 'astra_sites_setup' ) ) :
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Astra Sites Setup
|
45 |
-
*
|
46 |
-
* @since 1.0.5
|
47 |
-
*/
|
48 |
-
function astra_sites_setup() {
|
49 |
-
require_once ASTRA_SITES_DIR . 'inc/classes/class-astra-sites.php';
|
50 |
-
}
|
51 |
-
|
52 |
-
add_action( 'plugins_loaded', 'astra_sites_setup' );
|
53 |
-
|
54 |
-
endif;
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Plugin Name: Astra Starter Sites
|
4 |
+
* Plugin URI: http://www.wpastra.com/pro/
|
5 |
+
* Description: Import free sites build with Astra theme.
|
6 |
+
* Version: 1.2.4
|
7 |
+
* Author: Brainstorm Force
|
8 |
+
* Author URI: http://www.brainstormforce.com
|
9 |
+
* Text Domain: astra-sites
|
10 |
+
*
|
11 |
+
* @package Astra Sites
|
12 |
+
*/
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Set constants.
|
16 |
+
*/
|
17 |
+
if ( ! defined( 'ASTRA_SITES_NAME' ) ) {
|
18 |
+
define( 'ASTRA_SITES_NAME', __( 'Astra Sites', 'astra-sites' ) );
|
19 |
+
}
|
20 |
+
|
21 |
+
if ( ! defined( 'ASTRA_SITES_VER' ) ) {
|
22 |
+
define( 'ASTRA_SITES_VER', '1.2.4' );
|
23 |
+
}
|
24 |
+
|
25 |
+
if ( ! defined( 'ASTRA_SITES_FILE' ) ) {
|
26 |
+
define( 'ASTRA_SITES_FILE', __FILE__ );
|
27 |
+
}
|
28 |
+
|
29 |
+
if ( ! defined( 'ASTRA_SITES_BASE' ) ) {
|
30 |
+
define( 'ASTRA_SITES_BASE', plugin_basename( ASTRA_SITES_FILE ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
if ( ! defined( 'ASTRA_SITES_DIR' ) ) {
|
34 |
+
define( 'ASTRA_SITES_DIR', plugin_dir_path( ASTRA_SITES_FILE ) );
|
35 |
+
}
|
36 |
+
|
37 |
+
if ( ! defined( 'ASTRA_SITES_URI' ) ) {
|
38 |
+
define( 'ASTRA_SITES_URI', plugins_url( '/', ASTRA_SITES_FILE ) );
|
39 |
+
}
|
40 |
+
|
41 |
+
if ( ! function_exists( 'astra_sites_setup' ) ) :
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Astra Sites Setup
|
45 |
+
*
|
46 |
+
* @since 1.0.5
|
47 |
+
*/
|
48 |
+
function astra_sites_setup() {
|
49 |
+
require_once ASTRA_SITES_DIR . 'inc/classes/class-astra-sites.php';
|
50 |
+
}
|
51 |
+
|
52 |
+
add_action( 'plugins_loaded', 'astra_sites_setup' );
|
53 |
+
|
54 |
+
endif;
|
inc/assets/css/admin.css
CHANGED
@@ -1,463 +1,463 @@
|
|
1 |
-
.wrap .status,
|
2 |
-
.wrap .site-type {
|
3 |
-
position: absolute;
|
4 |
-
z-index: 1;
|
5 |
-
color: #fff;
|
6 |
-
padding: 0.5em 1em;
|
7 |
-
top: -0.5em;
|
8 |
-
text-transform: uppercase;
|
9 |
-
}
|
10 |
-
.wrap .status,
|
11 |
-
.wrap .site-type.premium {
|
12 |
-
background: #0073aa;
|
13 |
-
}
|
14 |
-
.wrap .status {
|
15 |
-
left: -0.5em;
|
16 |
-
}
|
17 |
-
.wrap .site-type.premium {
|
18 |
-
right: -0.5em;
|
19 |
-
}
|
20 |
-
|
21 |
-
.wrap .status.publish,
|
22 |
-
.wrap .site-type.free {
|
23 |
-
display: none;
|
24 |
-
}
|
25 |
-
|
26 |
-
.install-theme-info .site-type {
|
27 |
-
display: none;
|
28 |
-
}
|
29 |
-
|
30 |
-
.theme {
|
31 |
-
position: relative;
|
32 |
-
}
|
33 |
-
.wrap .astra-sites-preview .site-type.premium {
|
34 |
-
display: block;
|
35 |
-
display: none;
|
36 |
-
position: relative;
|
37 |
-
margin: 0.5em 0em 1em 0em;
|
38 |
-
top: 0;
|
39 |
-
left: 0;
|
40 |
-
text-align: center;
|
41 |
-
}
|
42 |
-
|
43 |
-
.theme-details-read-more.open {
|
44 |
-
margin: 0.5em 0 0 0;
|
45 |
-
}
|
46 |
-
|
47 |
-
.astra-sites-preview .theme-screenshot {
|
48 |
-
width: 100%;
|
49 |
-
}
|
50 |
-
|
51 |
-
.install-theme-info .site-type.premium {
|
52 |
-
display: none;
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Required Plugins
|
57 |
-
*/
|
58 |
-
.required-plugins.loading {
|
59 |
-
text-align: center;
|
60 |
-
}
|
61 |
-
.required-plugins button {
|
62 |
-
float: right;
|
63 |
-
}
|
64 |
-
.required-plugins .plugin-card {
|
65 |
-
float: none;
|
66 |
-
width: 100%;
|
67 |
-
border: none;
|
68 |
-
margin: 0 0 0.8em 0;
|
69 |
-
display: flex;
|
70 |
-
justify-content: space-between;
|
71 |
-
align-items: center;
|
72 |
-
transition: background ease 0.8s;
|
73 |
-
}
|
74 |
-
.required-plugins .plugin-card.plugin-card-update-failed {
|
75 |
-
flex-wrap: wrap;
|
76 |
-
}
|
77 |
-
.required-plugins .spinner {
|
78 |
-
float: none;
|
79 |
-
margin: 0;
|
80 |
-
}
|
81 |
-
|
82 |
-
.expanded .wp-full-overlay-footer {
|
83 |
-
height: 111px;
|
84 |
-
}
|
85 |
-
|
86 |
-
.wp-full-overlay-footer .view-site,
|
87 |
-
.wp-full-overlay-footer .go-pro,
|
88 |
-
.wp-full-overlay-footer .astra-demo-import {
|
89 |
-
width: 100%;
|
90 |
-
text-align: center;
|
91 |
-
}
|
92 |
-
|
93 |
-
.wp-core-ui .wp-full-overlay-footer .button.button-hero,
|
94 |
-
.wp-core-ui .wp-full-overlay-footer .button-group.button-hero .button {
|
95 |
-
padding: 0 10px 1px;
|
96 |
-
}
|
97 |
-
|
98 |
-
.wp-full-overlay-footer .installing:before {
|
99 |
-
vertical-align: text-bottom;
|
100 |
-
}
|
101 |
-
|
102 |
-
.required-plugins-wrap h4 {
|
103 |
-
margin: 1em 0 0.5em 0;
|
104 |
-
padding: 0.5em 0;
|
105 |
-
transition: all ease 0.3s;
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Read more link
|
110 |
-
*/
|
111 |
-
.wp-core-ui .theme-details-read-more:focus,
|
112 |
-
.wp-core-ui .theme-details-read-more:hover {
|
113 |
-
outline: none;
|
114 |
-
box-shadow: none;
|
115 |
-
}
|
116 |
-
.wp-core-ui .theme-details-read-more {
|
117 |
-
margin: 10px 0;
|
118 |
-
display: none;
|
119 |
-
text-decoration: none;
|
120 |
-
}
|
121 |
-
|
122 |
-
/**
|
123 |
-
* Go pro.
|
124 |
-
*/
|
125 |
-
.wp-core-ui .go-pro.button[disabled] {
|
126 |
-
background-color: #fcb92c !important;
|
127 |
-
color: white !important;
|
128 |
-
box-shadow: 1px 0 #eab23a !important;
|
129 |
-
text-shadow: 1px 0 #6b4e13 !important;
|
130 |
-
border-color: #e2a932 !important;
|
131 |
-
cursor: pointer;
|
132 |
-
}
|
133 |
-
.wp-core-ui .view-site .dashicons,
|
134 |
-
.wp-core-ui .go-pro .dashicons {
|
135 |
-
font-size: 1rem;
|
136 |
-
vertical-align: middle;
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Errors
|
141 |
-
*/
|
142 |
-
.plugin-card-update-failed .notice {
|
143 |
-
margin-top: 1.5em;
|
144 |
-
}
|
145 |
-
|
146 |
-
.no-themes {
|
147 |
-
margin-top: 40px;
|
148 |
-
}
|
149 |
-
|
150 |
-
.no-themes p {
|
151 |
-
font-size: 15px;
|
152 |
-
}
|
153 |
-
|
154 |
-
.no-themes .left-margin {
|
155 |
-
margin-left: 30px;
|
156 |
-
}
|
157 |
-
|
158 |
-
/**
|
159 |
-
*
|
160 |
-
*/
|
161 |
-
.astra-sites-preview .wp-full-overlay-sidebar-content {
|
162 |
-
bottom: 100px;
|
163 |
-
}
|
164 |
-
|
165 |
-
.footer-import-button-wrap {
|
166 |
-
padding: 10px 20px;
|
167 |
-
}
|
168 |
-
|
169 |
-
.footer-import-button-wrap .button {
|
170 |
-
margin: 0;
|
171 |
-
}
|
172 |
-
|
173 |
-
.astra-sites-preview.expanded .wp-full-overlay-footer {
|
174 |
-
left: initial;
|
175 |
-
}
|
176 |
-
|
177 |
-
/**
|
178 |
-
* Menu Page
|
179 |
-
*/
|
180 |
-
.astra-sites-title {
|
181 |
-
float: left;
|
182 |
-
font-size: 23px;
|
183 |
-
font-weight: 400;
|
184 |
-
margin: 0 0 6px 0px;
|
185 |
-
padding: 0;
|
186 |
-
line-height: 29px;
|
187 |
-
}
|
188 |
-
|
189 |
-
#astra-sites-menu-page {
|
190 |
-
margin-top: 10px;
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* API Error
|
195 |
-
*/
|
196 |
-
.astra-api-error {
|
197 |
-
margin: 0 0 0.5em 0;
|
198 |
-
}
|
199 |
-
|
200 |
-
/**
|
201 |
-
* Grid
|
202 |
-
*/
|
203 |
-
.wp-filter .search-form {
|
204 |
-
margin-left: 1em;
|
205 |
-
}
|
206 |
-
.wp-filter .search-form input[type="search"] {
|
207 |
-
width: 200px;
|
208 |
-
font-size: 13px;
|
209 |
-
padding: 5px 10px;
|
210 |
-
}
|
211 |
-
.section-left {
|
212 |
-
display: inline-block;
|
213 |
-
}
|
214 |
-
.section-right {
|
215 |
-
float: right;
|
216 |
-
}
|
217 |
-
.filter-count {
|
218 |
-
min-width: 3em;
|
219 |
-
}
|
220 |
-
.astra-site-preview-on {
|
221 |
-
overflow: hidden;
|
222 |
-
}
|
223 |
-
|
224 |
-
#astra-sites-menu-page .notice {
|
225 |
-
margin-left: 0;
|
226 |
-
width: auto;
|
227 |
-
float: none;
|
228 |
-
}
|
229 |
-
.filters-wrap {
|
230 |
-
display: inline-block;
|
231 |
-
}
|
232 |
-
.spinner-wrap {
|
233 |
-
text-align: center;
|
234 |
-
}
|
235 |
-
.spinner-wrap .spinner {
|
236 |
-
float: none;
|
237 |
-
}
|
238 |
-
.hide-me {
|
239 |
-
display: none !important;
|
240 |
-
}
|
241 |
-
#astra-sites-admin {
|
242 |
-
height: 100vh;
|
243 |
-
}
|
244 |
-
.install-theme-info > .notice {
|
245 |
-
margin: 5px 0 10px 0;
|
246 |
-
}
|
247 |
-
|
248 |
-
.astra-sites-suggestions:before {
|
249 |
-
border: 5px dashed #ccc;
|
250 |
-
position: absolute;
|
251 |
-
left: 0;
|
252 |
-
right: 0;
|
253 |
-
top: 0;
|
254 |
-
bottom: 0px;
|
255 |
-
}
|
256 |
-
|
257 |
-
.astra-sites-suggestions {
|
258 |
-
min-height: 280px;
|
259 |
-
border: none !important;
|
260 |
-
}
|
261 |
-
|
262 |
-
.astra-sites-suggestions a {
|
263 |
-
border: none;
|
264 |
-
outline: none;
|
265 |
-
}
|
266 |
-
|
267 |
-
.astra-sites-suggestions .inner {
|
268 |
-
border: 6px solid #24282e !important;
|
269 |
-
padding: 27% 10% 50% 10%;
|
270 |
-
text-align: center;
|
271 |
-
position: absolute;
|
272 |
-
left: 0;
|
273 |
-
right: 0;
|
274 |
-
top: 0;
|
275 |
-
background: #33383d;
|
276 |
-
bottom: 0;
|
277 |
-
color: #eee;
|
278 |
-
cursor: auto;
|
279 |
-
}
|
280 |
-
|
281 |
-
.astra-sites-suggestions .inner a {
|
282 |
-
color: #00b9eb;
|
283 |
-
}
|
284 |
-
|
285 |
-
.astra-sites-suggestions p {
|
286 |
-
font-size: 1rem;
|
287 |
-
margin: 0;
|
288 |
-
}
|
289 |
-
|
290 |
-
.astra-notice {
|
291 |
-
margin: 2em 2em 0em 0em;
|
292 |
-
}
|
293 |
-
|
294 |
-
.no-themes .description {
|
295 |
-
display: block;
|
296 |
-
}
|
297 |
-
|
298 |
-
/**
|
299 |
-
* Responsive Button UI
|
300 |
-
*/
|
301 |
-
.astra-sites-preview .wp-full-overlay-footer .devices button.active:before,
|
302 |
-
.astra-sites-preview .wp-full-overlay-footer .devices button:hover:before {
|
303 |
-
color: #0073aa;
|
304 |
-
}
|
305 |
-
.astra-sites-preview .wp-full-overlay-footer .devices button:before {
|
306 |
-
color: #c1c1c1;
|
307 |
-
}
|
308 |
-
.astra-sites-preview .wp-full-overlay-footer .devices button:hover {
|
309 |
-
background-color: transparent;
|
310 |
-
}
|
311 |
-
.astra-sites-preview .wp-full-overlay-footer .devices button {
|
312 |
-
border: none;
|
313 |
-
}
|
314 |
-
.astra-sites-preview .wp-full-overlay-footer .devices button:focus,
|
315 |
-
.astra-sites-preview .wp-full-overlay-footer .devices button.active:hover {
|
316 |
-
border-bottom-color: transparent;
|
317 |
-
background-color: transparent;
|
318 |
-
}
|
319 |
-
.not-click-able {
|
320 |
-
pointer-events: none !important;
|
321 |
-
}
|
322 |
-
body.page-builder-selected .select-page-builder,
|
323 |
-
body.loading-content .select-page-builder {
|
324 |
-
display: none;
|
325 |
-
}
|
326 |
-
.select-page-builder .up-arrow {
|
327 |
-
-webkit-transform: rotate(90deg);
|
328 |
-
-moz-transform: rotate(90deg);
|
329 |
-
-ms-transform: rotate(90deg);
|
330 |
-
transform: rotate(90deg);
|
331 |
-
display: inline-block;
|
332 |
-
font-size: 1.5em;
|
333 |
-
color: #797979;
|
334 |
-
vertical-align: middle;
|
335 |
-
margin-right: 10px;
|
336 |
-
-webkit-transition: all linear 0.6s;
|
337 |
-
-moz-transition: all linear 0.6s;
|
338 |
-
-ms-transition: all linear 0.6s;
|
339 |
-
transition: all linear 0.6s;
|
340 |
-
-webkit-animation-duration: 1s;
|
341 |
-
animation-duration: 1s;
|
342 |
-
-webkit-animation-fill-mode: both;
|
343 |
-
animation-fill-mode: both;
|
344 |
-
-webkit-animation-timing-function: ease-in-out;
|
345 |
-
animation-timing-function: ease-in-out;
|
346 |
-
animation-iteration-count: infinite;
|
347 |
-
-webkit-animation-iteration-count: infinite;
|
348 |
-
animation-name: bounce;
|
349 |
-
-moz-animation-name: bounce;
|
350 |
-
}
|
351 |
-
.select-page-builder {
|
352 |
-
margin-left: 6em;
|
353 |
-
}
|
354 |
-
|
355 |
-
.select-page-builder img {
|
356 |
-
max-width: 100%;
|
357 |
-
}
|
358 |
-
|
359 |
-
.select-page-builder .note-wrap {
|
360 |
-
position: absolute;
|
361 |
-
padding: 40px 0;
|
362 |
-
margin-left: 170px;
|
363 |
-
right: 0;
|
364 |
-
left: 0;
|
365 |
-
}
|
366 |
-
|
367 |
-
.select-page-builder h3 {
|
368 |
-
margin: 0;
|
369 |
-
font-size: 2em;
|
370 |
-
}
|
371 |
-
.select-page-builder {
|
372 |
-
margin: -20px 0 0 -5px;
|
373 |
-
position: absolute;
|
374 |
-
}
|
375 |
-
.select-page-builder .note {
|
376 |
-
margin-left: 1.5em;
|
377 |
-
}
|
378 |
-
|
379 |
-
@keyframes bounce {
|
380 |
-
0%,
|
381 |
-
100%,
|
382 |
-
20%,
|
383 |
-
50%,
|
384 |
-
80% {
|
385 |
-
-webkit-transform: translateY(-0px) rotate(90deg);
|
386 |
-
-moz-transform: translateY(-0px) rotate(90deg);
|
387 |
-
-ms-transform: translateY(-0px) rotate(90deg);
|
388 |
-
transform: translateY(-0px) rotate(90deg);
|
389 |
-
}
|
390 |
-
40% {
|
391 |
-
-webkit-transform: translateY(-2px) rotate(90deg);
|
392 |
-
-moz-transform: translateY(-2px) rotate(90deg);
|
393 |
-
-ms-transform: translateY(-2px) rotate(90deg);
|
394 |
-
transform: translateY(-2px) rotate(90deg);
|
395 |
-
}
|
396 |
-
60% {
|
397 |
-
-webkit-transform: translateY(-1px) rotate(90deg);
|
398 |
-
-moz-transform: translateY(-1px) rotate(90deg);
|
399 |
-
-ms-transform: translateY(-1px) rotate(90deg);
|
400 |
-
transform: translateY(-1px) rotate(90deg);
|
401 |
-
}
|
402 |
-
}
|
403 |
-
|
404 |
-
/**
|
405 |
-
* Processing Animation
|
406 |
-
*/
|
407 |
-
.astra-demo-import.button.updating-message:before,
|
408 |
-
.astra-demo-import.button.installing:before {
|
409 |
-
-webkit-animation: cssAnimation .72s ease infinite;
|
410 |
-
-moz-animation: cssAnimation .72s ease infinite;
|
411 |
-
-o-animation: cssAnimation .72s ease infinite;
|
412 |
-
-ms-animation: cssAnimation .72s ease infinite;
|
413 |
-
animation: cssAnimation .72s ease infinite;
|
414 |
-
}
|
415 |
-
|
416 |
-
@-webkit-keyframes cssAnimation {
|
417 |
-
from {
|
418 |
-
-webkit-transform: rotate(0);
|
419 |
-
-moz-transform: rotate(0);
|
420 |
-
-o-transform: rotate(0);
|
421 |
-
-ms-transform: rotate(0);
|
422 |
-
transform: rotate(0);
|
423 |
-
}
|
424 |
-
to {
|
425 |
-
-webkit-transform: rotate(360deg);
|
426 |
-
-moz-transform: rotate(360deg);
|
427 |
-
-o-transform: rotate(360deg);
|
428 |
-
-ms-transform: rotate(360deg);
|
429 |
-
transform: rotate(360deg);
|
430 |
-
}
|
431 |
-
}
|
432 |
-
@-moz-keyframes cssAnimation {
|
433 |
-
from {
|
434 |
-
-webkit-transform: rotate(0);
|
435 |
-
-moz-transform: rotate(0);
|
436 |
-
-o-transform: rotate(0);
|
437 |
-
-ms-transform: rotate(0);
|
438 |
-
transform: rotate(0);
|
439 |
-
}
|
440 |
-
to {
|
441 |
-
-webkit-transform: rotate(360deg);
|
442 |
-
-moz-transform: rotate(360deg);
|
443 |
-
-o-transform: rotate(360deg);
|
444 |
-
-ms-transform: rotate(360deg);
|
445 |
-
transform: rotate(360deg);
|
446 |
-
}
|
447 |
-
}
|
448 |
-
@-o-keyframes cssAnimation {
|
449 |
-
from {
|
450 |
-
-webkit-transform: rotate(0);
|
451 |
-
-moz-transform: rotate(0);
|
452 |
-
-o-transform: rotate(0);
|
453 |
-
-ms-transform: rotate(0);
|
454 |
-
transform: rotate(0);
|
455 |
-
}
|
456 |
-
to {
|
457 |
-
-webkit-transform: rotate(360deg);
|
458 |
-
-moz-transform: rotate(360deg);
|
459 |
-
-o-transform: rotate(360deg);
|
460 |
-
-ms-transform: rotate(360deg);
|
461 |
-
transform: rotate(360deg);
|
462 |
-
}
|
463 |
ย
}
|
1 |
+
.wrap .status,
|
2 |
+
.wrap .site-type {
|
3 |
+
position: absolute;
|
4 |
+
z-index: 1;
|
5 |
+
color: #fff;
|
6 |
+
padding: 0.5em 1em;
|
7 |
+
top: -0.5em;
|
8 |
+
text-transform: uppercase;
|
9 |
+
}
|
10 |
+
.wrap .status,
|
11 |
+
.wrap .site-type.premium {
|
12 |
+
background: #0073aa;
|
13 |
+
}
|
14 |
+
.wrap .status {
|
15 |
+
left: -0.5em;
|
16 |
+
}
|
17 |
+
.wrap .site-type.premium {
|
18 |
+
right: -0.5em;
|
19 |
+
}
|
20 |
+
|
21 |
+
.wrap .status.publish,
|
22 |
+
.wrap .site-type.free {
|
23 |
+
display: none;
|
24 |
+
}
|
25 |
+
|
26 |
+
.install-theme-info .site-type {
|
27 |
+
display: none;
|
28 |
+
}
|
29 |
+
|
30 |
+
.theme {
|
31 |
+
position: relative;
|
32 |
+
}
|
33 |
+
.wrap .astra-sites-preview .site-type.premium {
|
34 |
+
display: block;
|
35 |
+
display: none;
|
36 |
+
position: relative;
|
37 |
+
margin: 0.5em 0em 1em 0em;
|
38 |
+
top: 0;
|
39 |
+
left: 0;
|
40 |
+
text-align: center;
|
41 |
+
}
|
42 |
+
|
43 |
+
.theme-details-read-more.open {
|
44 |
+
margin: 0.5em 0 0 0;
|
45 |
+
}
|
46 |
+
|
47 |
+
.astra-sites-preview .theme-screenshot {
|
48 |
+
width: 100%;
|
49 |
+
}
|
50 |
+
|
51 |
+
.install-theme-info .site-type.premium {
|
52 |
+
display: none;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Required Plugins
|
57 |
+
*/
|
58 |
+
.required-plugins.loading {
|
59 |
+
text-align: center;
|
60 |
+
}
|
61 |
+
.required-plugins button {
|
62 |
+
float: right;
|
63 |
+
}
|
64 |
+
.required-plugins .plugin-card {
|
65 |
+
float: none;
|
66 |
+
width: 100%;
|
67 |
+
border: none;
|
68 |
+
margin: 0 0 0.8em 0;
|
69 |
+
display: flex;
|
70 |
+
justify-content: space-between;
|
71 |
+
align-items: center;
|
72 |
+
transition: background ease 0.8s;
|
73 |
+
}
|
74 |
+
.required-plugins .plugin-card.plugin-card-update-failed {
|
75 |
+
flex-wrap: wrap;
|
76 |
+
}
|
77 |
+
.required-plugins .spinner {
|
78 |
+
float: none;
|
79 |
+
margin: 0;
|
80 |
+
}
|
81 |
+
|
82 |
+
.expanded .wp-full-overlay-footer {
|
83 |
+
height: 111px;
|
84 |
+
}
|
85 |
+
|
86 |
+
.wp-full-overlay-footer .view-site,
|
87 |
+
.wp-full-overlay-footer .go-pro,
|
88 |
+
.wp-full-overlay-footer .astra-demo-import {
|
89 |
+
width: 100%;
|
90 |
+
text-align: center;
|
91 |
+
}
|
92 |
+
|
93 |
+
.wp-core-ui .wp-full-overlay-footer .button.button-hero,
|
94 |
+
.wp-core-ui .wp-full-overlay-footer .button-group.button-hero .button {
|
95 |
+
padding: 0 10px 1px;
|
96 |
+
}
|
97 |
+
|
98 |
+
.wp-full-overlay-footer .installing:before {
|
99 |
+
vertical-align: text-bottom;
|
100 |
+
}
|
101 |
+
|
102 |
+
.required-plugins-wrap h4 {
|
103 |
+
margin: 1em 0 0.5em 0;
|
104 |
+
padding: 0.5em 0;
|
105 |
+
transition: all ease 0.3s;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Read more link
|
110 |
+
*/
|
111 |
+
.wp-core-ui .theme-details-read-more:focus,
|
112 |
+
.wp-core-ui .theme-details-read-more:hover {
|
113 |
+
outline: none;
|
114 |
+
box-shadow: none;
|
115 |
+
}
|
116 |
+
.wp-core-ui .theme-details-read-more {
|
117 |
+
margin: 10px 0;
|
118 |
+
display: none;
|
119 |
+
text-decoration: none;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Go pro.
|
124 |
+
*/
|
125 |
+
.wp-core-ui .go-pro.button[disabled] {
|
126 |
+
background-color: #fcb92c !important;
|
127 |
+
color: white !important;
|
128 |
+
box-shadow: 1px 0 #eab23a !important;
|
129 |
+
text-shadow: 1px 0 #6b4e13 !important;
|
130 |
+
border-color: #e2a932 !important;
|
131 |
+
cursor: pointer;
|
132 |
+
}
|
133 |
+
.wp-core-ui .view-site .dashicons,
|
134 |
+
.wp-core-ui .go-pro .dashicons {
|
135 |
+
font-size: 1rem;
|
136 |
+
vertical-align: middle;
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Errors
|
141 |
+
*/
|
142 |
+
.plugin-card-update-failed .notice {
|
143 |
+
margin-top: 1.5em;
|
144 |
+
}
|
145 |
+
|
146 |
+
.no-themes {
|
147 |
+
margin-top: 40px;
|
148 |
+
}
|
149 |
+
|
150 |
+
.no-themes p {
|
151 |
+
font-size: 15px;
|
152 |
+
}
|
153 |
+
|
154 |
+
.no-themes .left-margin {
|
155 |
+
margin-left: 30px;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
*
|
160 |
+
*/
|
161 |
+
.astra-sites-preview .wp-full-overlay-sidebar-content {
|
162 |
+
bottom: 100px;
|
163 |
+
}
|
164 |
+
|
165 |
+
.footer-import-button-wrap {
|
166 |
+
padding: 10px 20px;
|
167 |
+
}
|
168 |
+
|
169 |
+
.footer-import-button-wrap .button {
|
170 |
+
margin: 0;
|
171 |
+
}
|
172 |
+
|
173 |
+
.astra-sites-preview.expanded .wp-full-overlay-footer {
|
174 |
+
left: initial;
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* Menu Page
|
179 |
+
*/
|
180 |
+
.astra-sites-title {
|
181 |
+
float: left;
|
182 |
+
font-size: 23px;
|
183 |
+
font-weight: 400;
|
184 |
+
margin: 0 0 6px 0px;
|
185 |
+
padding: 0;
|
186 |
+
line-height: 29px;
|
187 |
+
}
|
188 |
+
|
189 |
+
#astra-sites-menu-page {
|
190 |
+
margin-top: 10px;
|
191 |
+
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* API Error
|
195 |
+
*/
|
196 |
+
.astra-api-error {
|
197 |
+
margin: 0 0 0.5em 0;
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Grid
|
202 |
+
*/
|
203 |
+
.wp-filter .search-form {
|
204 |
+
margin-left: 1em;
|
205 |
+
}
|
206 |
+
.wp-filter .search-form input[type="search"] {
|
207 |
+
width: 200px;
|
208 |
+
font-size: 13px;
|
209 |
+
padding: 5px 10px;
|
210 |
+
}
|
211 |
+
.section-left {
|
212 |
+
display: inline-block;
|
213 |
+
}
|
214 |
+
.section-right {
|
215 |
+
float: right;
|
216 |
+
}
|
217 |
+
.filter-count {
|
218 |
+
min-width: 3em;
|
219 |
+
}
|
220 |
+
.astra-site-preview-on {
|
221 |
+
overflow: hidden;
|
222 |
+
}
|
223 |
+
|
224 |
+
#astra-sites-menu-page .notice {
|
225 |
+
margin-left: 0;
|
226 |
+
width: auto;
|
227 |
+
float: none;
|
228 |
+
}
|
229 |
+
.filters-wrap {
|
230 |
+
display: inline-block;
|
231 |
+
}
|
232 |
+
.spinner-wrap {
|
233 |
+
text-align: center;
|
234 |
+
}
|
235 |
+
.spinner-wrap .spinner {
|
236 |
+
float: none;
|
237 |
+
}
|
238 |
+
.hide-me {
|
239 |
+
display: none !important;
|
240 |
+
}
|
241 |
+
#astra-sites-admin {
|
242 |
+
height: 100vh;
|
243 |
+
}
|
244 |
+
.install-theme-info > .notice {
|
245 |
+
margin: 5px 0 10px 0;
|
246 |
+
}
|
247 |
+
|
248 |
+
.astra-sites-suggestions:before {
|
249 |
+
border: 5px dashed #ccc;
|
250 |
+
position: absolute;
|
251 |
+
left: 0;
|
252 |
+
right: 0;
|
253 |
+
top: 0;
|
254 |
+
bottom: 0px;
|
255 |
+
}
|
256 |
+
|
257 |
+
.astra-sites-suggestions {
|
258 |
+
min-height: 280px;
|
259 |
+
border: none !important;
|
260 |
+
}
|
261 |
+
|
262 |
+
.astra-sites-suggestions a {
|
263 |
+
border: none;
|
264 |
+
outline: none;
|
265 |
+
}
|
266 |
+
|
267 |
+
.astra-sites-suggestions .inner {
|
268 |
+
border: 6px solid #24282e !important;
|
269 |
+
padding: 27% 10% 50% 10%;
|
270 |
+
text-align: center;
|
271 |
+
position: absolute;
|
272 |
+
left: 0;
|
273 |
+
right: 0;
|
274 |
+
top: 0;
|
275 |
+
background: #33383d;
|
276 |
+
bottom: 0;
|
277 |
+
color: #eee;
|
278 |
+
cursor: auto;
|
279 |
+
}
|
280 |
+
|
281 |
+
.astra-sites-suggestions .inner a {
|
282 |
+
color: #00b9eb;
|
283 |
+
}
|
284 |
+
|
285 |
+
.astra-sites-suggestions p {
|
286 |
+
font-size: 1rem;
|
287 |
+
margin: 0;
|
288 |
+
}
|
289 |
+
|
290 |
+
.astra-notice {
|
291 |
+
margin: 2em 2em 0em 0em;
|
292 |
+
}
|
293 |
+
|
294 |
+
.no-themes .description {
|
295 |
+
display: block;
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Responsive Button UI
|
300 |
+
*/
|
301 |
+
.astra-sites-preview .wp-full-overlay-footer .devices button.active:before,
|
302 |
+
.astra-sites-preview .wp-full-overlay-footer .devices button:hover:before {
|
303 |
+
color: #0073aa;
|
304 |
+
}
|
305 |
+
.astra-sites-preview .wp-full-overlay-footer .devices button:before {
|
306 |
+
color: #c1c1c1;
|
307 |
+
}
|
308 |
+
.astra-sites-preview .wp-full-overlay-footer .devices button:hover {
|
309 |
+
background-color: transparent;
|
310 |
+
}
|
311 |
+
.astra-sites-preview .wp-full-overlay-footer .devices button {
|
312 |
+
border: none;
|
313 |
+
}
|
314 |
+
.astra-sites-preview .wp-full-overlay-footer .devices button:focus,
|
315 |
+
.astra-sites-preview .wp-full-overlay-footer .devices button.active:hover {
|
316 |
+
border-bottom-color: transparent;
|
317 |
+
background-color: transparent;
|
318 |
+
}
|
319 |
+
.not-click-able {
|
320 |
+
pointer-events: none !important;
|
321 |
+
}
|
322 |
+
body.page-builder-selected .select-page-builder,
|
323 |
+
body.loading-content .select-page-builder {
|
324 |
+
display: none;
|
325 |
+
}
|
326 |
+
.select-page-builder .up-arrow {
|
327 |
+
-webkit-transform: rotate(90deg);
|
328 |
+
-moz-transform: rotate(90deg);
|
329 |
+
-ms-transform: rotate(90deg);
|
330 |
+
transform: rotate(90deg);
|
331 |
+
display: inline-block;
|
332 |
+
font-size: 1.5em;
|
333 |
+
color: #797979;
|
334 |
+
vertical-align: middle;
|
335 |
+
margin-right: 10px;
|
336 |
+
-webkit-transition: all linear 0.6s;
|
337 |
+
-moz-transition: all linear 0.6s;
|
338 |
+
-ms-transition: all linear 0.6s;
|
339 |
+
transition: all linear 0.6s;
|
340 |
+
-webkit-animation-duration: 1s;
|
341 |
+
animation-duration: 1s;
|
342 |
+
-webkit-animation-fill-mode: both;
|
343 |
+
animation-fill-mode: both;
|
344 |
+
-webkit-animation-timing-function: ease-in-out;
|
345 |
+
animation-timing-function: ease-in-out;
|
346 |
+
animation-iteration-count: infinite;
|
347 |
+
-webkit-animation-iteration-count: infinite;
|
348 |
+
animation-name: bounce;
|
349 |
+
-moz-animation-name: bounce;
|
350 |
+
}
|
351 |
+
.select-page-builder {
|
352 |
+
margin-left: 6em;
|
353 |
+
}
|
354 |
+
|
355 |
+
.select-page-builder img {
|
356 |
+
max-width: 100%;
|
357 |
+
}
|
358 |
+
|
359 |
+
.select-page-builder .note-wrap {
|
360 |
+
position: absolute;
|
361 |
+
padding: 40px 0;
|
362 |
+
margin-left: 170px;
|
363 |
+
right: 0;
|
364 |
+
left: 0;
|
365 |
+
}
|
366 |
+
|
367 |
+
.select-page-builder h3 {
|
368 |
+
margin: 0;
|
369 |
+
font-size: 2em;
|
370 |
+
}
|
371 |
+
.select-page-builder {
|
372 |
+
margin: -20px 0 0 -5px;
|
373 |
+
position: absolute;
|
374 |
+
}
|
375 |
+
.select-page-builder .note {
|
376 |
+
margin-left: 1.5em;
|
377 |
+
}
|
378 |
+
|
379 |
+
@keyframes bounce {
|
380 |
+
0%,
|
381 |
+
100%,
|
382 |
+
20%,
|
383 |
+
50%,
|
384 |
+
80% {
|
385 |
+
-webkit-transform: translateY(-0px) rotate(90deg);
|
386 |
+
-moz-transform: translateY(-0px) rotate(90deg);
|
387 |
+
-ms-transform: translateY(-0px) rotate(90deg);
|
388 |
+
transform: translateY(-0px) rotate(90deg);
|
389 |
+
}
|
390 |
+
40% {
|
391 |
+
-webkit-transform: translateY(-2px) rotate(90deg);
|
392 |
+
-moz-transform: translateY(-2px) rotate(90deg);
|
393 |
+
-ms-transform: translateY(-2px) rotate(90deg);
|
394 |
+
transform: translateY(-2px) rotate(90deg);
|
395 |
+
}
|
396 |
+
60% {
|
397 |
+
-webkit-transform: translateY(-1px) rotate(90deg);
|
398 |
+
-moz-transform: translateY(-1px) rotate(90deg);
|
399 |
+
-ms-transform: translateY(-1px) rotate(90deg);
|
400 |
+
transform: translateY(-1px) rotate(90deg);
|
401 |
+
}
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Processing Animation
|
406 |
+
*/
|
407 |
+
.astra-demo-import.button.updating-message:before,
|
408 |
+
.astra-demo-import.button.installing:before {
|
409 |
+
-webkit-animation: cssAnimation .72s ease infinite;
|
410 |
+
-moz-animation: cssAnimation .72s ease infinite;
|
411 |
+
-o-animation: cssAnimation .72s ease infinite;
|
412 |
+
-ms-animation: cssAnimation .72s ease infinite;
|
413 |
+
animation: cssAnimation .72s ease infinite;
|
414 |
+
}
|
415 |
+
|
416 |
+
@-webkit-keyframes cssAnimation {
|
417 |
+
from {
|
418 |
+
-webkit-transform: rotate(0);
|
419 |
+
-moz-transform: rotate(0);
|
420 |
+
-o-transform: rotate(0);
|
421 |
+
-ms-transform: rotate(0);
|
422 |
+
transform: rotate(0);
|
423 |
+
}
|
424 |
+
to {
|
425 |
+
-webkit-transform: rotate(360deg);
|
426 |
+
-moz-transform: rotate(360deg);
|
427 |
+
-o-transform: rotate(360deg);
|
428 |
+
-ms-transform: rotate(360deg);
|
429 |
+
transform: rotate(360deg);
|
430 |
+
}
|
431 |
+
}
|
432 |
+
@-moz-keyframes cssAnimation {
|
433 |
+
from {
|
434 |
+
-webkit-transform: rotate(0);
|
435 |
+
-moz-transform: rotate(0);
|
436 |
+
-o-transform: rotate(0);
|
437 |
+
-ms-transform: rotate(0);
|
438 |
+
transform: rotate(0);
|
439 |
+
}
|
440 |
+
to {
|
441 |
+
-webkit-transform: rotate(360deg);
|
442 |
+
-moz-transform: rotate(360deg);
|
443 |
+
-o-transform: rotate(360deg);
|
444 |
+
-ms-transform: rotate(360deg);
|
445 |
+
transform: rotate(360deg);
|
446 |
+
}
|
447 |
+
}
|
448 |
+
@-o-keyframes cssAnimation {
|
449 |
+
from {
|
450 |
+
-webkit-transform: rotate(0);
|
451 |
+
-moz-transform: rotate(0);
|
452 |
+
-o-transform: rotate(0);
|
453 |
+
-ms-transform: rotate(0);
|
454 |
+
transform: rotate(0);
|
455 |
+
}
|
456 |
+
to {
|
457 |
+
-webkit-transform: rotate(360deg);
|
458 |
+
-moz-transform: rotate(360deg);
|
459 |
+
-o-transform: rotate(360deg);
|
460 |
+
-ms-transform: rotate(360deg);
|
461 |
+
transform: rotate(360deg);
|
462 |
+
}
|
463 |
ย
}
|
inc/assets/js/admin-page.js
CHANGED
@@ -1,1374 +1,1374 @@
|
|
1 |
-
/**
|
2 |
-
* AJAX Request Queue
|
3 |
-
*
|
4 |
-
* - add()
|
5 |
-
* - remove()
|
6 |
-
* - run()
|
7 |
-
* - stop()
|
8 |
-
*
|
9 |
-
* @since 1.0.0
|
10 |
-
*/
|
11 |
-
var AstraSitesAjaxQueue = (function() {
|
12 |
-
|
13 |
-
var requests = [];
|
14 |
-
|
15 |
-
return {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* Add AJAX request
|
19 |
-
*
|
20 |
-
* @since 1.0.0
|
21 |
-
*/
|
22 |
-
add: function(opt) {
|
23 |
-
requests.push(opt);
|
24 |
-
},
|
25 |
-
|
26 |
-
/**
|
27 |
-
* Remove AJAX request
|
28 |
-
*
|
29 |
-
* @since 1.0.0
|
30 |
-
*/
|
31 |
-
remove: function(opt) {
|
32 |
-
if( jQuery.inArray(opt, requests) > -1 )
|
33 |
-
requests.splice($.inArray(opt, requests), 1);
|
34 |
-
},
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Run / Process AJAX request
|
38 |
-
*
|
39 |
-
* @since 1.0.0
|
40 |
-
*/
|
41 |
-
run: function() {
|
42 |
-
var self = this,
|
43 |
-
oriSuc;
|
44 |
-
|
45 |
-
if( requests.length ) {
|
46 |
-
oriSuc = requests[0].complete;
|
47 |
-
|
48 |
-
requests[0].complete = function() {
|
49 |
-
if( typeof(oriSuc) === 'function' ) oriSuc();
|
50 |
-
requests.shift();
|
51 |
-
self.run.apply(self, []);
|
52 |
-
};
|
53 |
-
|
54 |
-
jQuery.ajax(requests[0]);
|
55 |
-
|
56 |
-
} else {
|
57 |
-
|
58 |
-
self.tid = setTimeout(function() {
|
59 |
-
self.run.apply(self, []);
|
60 |
-
}, 1000);
|
61 |
-
}
|
62 |
-
},
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Stop AJAX request
|
66 |
-
*
|
67 |
-
* @since 1.0.0
|
68 |
-
*/
|
69 |
-
stop: function() {
|
70 |
-
|
71 |
-
requests = [];
|
72 |
-
clearTimeout(this.tid);
|
73 |
-
}
|
74 |
-
};
|
75 |
-
|
76 |
-
}());
|
77 |
-
|
78 |
-
(function($){
|
79 |
-
|
80 |
-
var AstraSSEImport = {
|
81 |
-
complete: {
|
82 |
-
posts: 0,
|
83 |
-
media: 0,
|
84 |
-
users: 0,
|
85 |
-
comments: 0,
|
86 |
-
terms: 0,
|
87 |
-
},
|
88 |
-
|
89 |
-
updateDelta: function (type, delta) {
|
90 |
-
this.complete[ type ] += delta;
|
91 |
-
|
92 |
-
var self = this;
|
93 |
-
requestAnimationFrame(function () {
|
94 |
-
self.render();
|
95 |
-
});
|
96 |
-
},
|
97 |
-
updateProgress: function ( type, complete, total ) {
|
98 |
-
var text = complete + '/' + total;
|
99 |
-
|
100 |
-
if( 'undefined' !== type && 'undefined' !== text ) {
|
101 |
-
total = parseInt( total, 10 );
|
102 |
-
if ( 0 === total || isNaN( total ) ) {
|
103 |
-
total = 1;
|
104 |
-
}
|
105 |
-
var percent = parseInt( complete, 10 ) / total;
|
106 |
-
var progress = Math.round( percent * 100 ) + '%';
|
107 |
-
var progress_bar = percent * 100;
|
108 |
-
}
|
109 |
-
},
|
110 |
-
render: function () {
|
111 |
-
var types = Object.keys( this.complete );
|
112 |
-
var complete = 0;
|
113 |
-
var total = 0;
|
114 |
-
|
115 |
-
for (var i = types.length - 1; i >= 0; i--) {
|
116 |
-
var type = types[i];
|
117 |
-
this.updateProgress( type, this.complete[ type ], this.data.count[ type ] );
|
118 |
-
|
119 |
-
complete += this.complete[ type ];
|
120 |
-
total += this.data.count[ type ];
|
121 |
-
}
|
122 |
-
|
123 |
-
this.updateProgress( 'total', complete, total );
|
124 |
-
}
|
125 |
-
};
|
126 |
-
|
127 |
-
AstraSitesAdmin = {
|
128 |
-
|
129 |
-
log_file : '',
|
130 |
-
customizer_data : '',
|
131 |
-
wxr_url : '',
|
132 |
-
options_data : '',
|
133 |
-
widgets_data : '',
|
134 |
-
|
135 |
-
init: function()
|
136 |
-
{
|
137 |
-
this._resetPagedCount();
|
138 |
-
this._bind();
|
139 |
-
},
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Debugging.
|
143 |
-
*
|
144 |
-
* @param {mixed} data Mixed data.
|
145 |
-
*/
|
146 |
-
_log: function( data ) {
|
147 |
-
|
148 |
-
if( astraSitesAdmin.debug ) {
|
149 |
-
|
150 |
-
var date = new Date();
|
151 |
-
var time = date.toLocaleTimeString();
|
152 |
-
|
153 |
-
if (typeof data == 'object') {
|
154 |
-
console.log('%c ' + JSON.stringify( data ) + ' ' + time, 'background: #ededed; color: #444');
|
155 |
-
} else {
|
156 |
-
console.log('%c ' + data + ' ' + time, 'background: #ededed; color: #444');
|
157 |
-
}
|
158 |
-
|
159 |
-
|
160 |
-
}
|
161 |
-
},
|
162 |
-
|
163 |
-
/**
|
164 |
-
* Binds events for the Astra Sites.
|
165 |
-
*
|
166 |
-
* @since 1.0.0
|
167 |
-
* @access private
|
168 |
-
* @method _bind
|
169 |
-
*/
|
170 |
-
_bind: function()
|
171 |
-
{
|
172 |
-
$( document ).on('click' , '.devices button', AstraSitesAdmin._previewDevice);
|
173 |
-
$( document ).on('click' , '.theme-browser .theme-screenshot, .theme-browser .more-details, .theme-browser .install-theme-preview', AstraSitesAdmin._preview);
|
174 |
-
$( document ).on('click' , '.next-theme', AstraSitesAdmin._nextTheme);
|
175 |
-
$( document ).on('click' , '.previous-theme', AstraSitesAdmin._previousTheme);
|
176 |
-
$( document ).on('click' , '.collapse-sidebar', AstraSitesAdmin._collapse);
|
177 |
-
$( document ).on('click' , '.astra-demo-import', AstraSitesAdmin._importDemo);
|
178 |
-
$( document ).on('click' , '.install-now', AstraSitesAdmin._installNow);
|
179 |
-
$( document ).on('click' , '.close-full-overlay', AstraSitesAdmin._fullOverlay);
|
180 |
-
$( document ).on('click' , '.activate-now', AstraSitesAdmin._activateNow);
|
181 |
-
$( document ).on('wp-plugin-installing' , AstraSitesAdmin._pluginInstalling);
|
182 |
-
$( document ).on('wp-plugin-install-error' , AstraSitesAdmin._installError);
|
183 |
-
$( document ).on('wp-plugin-install-success' , AstraSitesAdmin._installSuccess);
|
184 |
-
|
185 |
-
$( document ).on('astra-sites-import-set-site-data-done' , AstraSitesAdmin._importCustomizerSettings );
|
186 |
-
$( document ).on('astra-sites-import-customizer-settings-done' , AstraSitesAdmin._importPrepareXML );
|
187 |
-
$( document ).on('astra-sites-import-xml-done' , AstraSitesAdmin._importSiteOptions );
|
188 |
-
$( document ).on('astra-sites-import-options-done' , AstraSitesAdmin._importWidgets );
|
189 |
-
$( document ).on('astra-sites-import-widgets-done' , AstraSitesAdmin._importEnd );
|
190 |
-
},
|
191 |
-
|
192 |
-
/**
|
193 |
-
* 5. Import Complete.
|
194 |
-
*/
|
195 |
-
_importEnd: function( event ) {
|
196 |
-
|
197 |
-
$.ajax({
|
198 |
-
url : astraSitesAdmin.ajaxurl,
|
199 |
-
type : 'POST',
|
200 |
-
dataType: 'json',
|
201 |
-
data : {
|
202 |
-
action : 'astra-sites-import-end',
|
203 |
-
},
|
204 |
-
beforeSend: function() {
|
205 |
-
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importComplete );
|
206 |
-
}
|
207 |
-
})
|
208 |
-
.fail(function( jqXHR ){
|
209 |
-
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
210 |
-
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
211 |
-
})
|
212 |
-
.done(function ( data ) {
|
213 |
-
|
214 |
-
// 5. Fail - Import Complete.
|
215 |
-
if( false === data.success ) {
|
216 |
-
AstraSitesAdmin._importFailMessage( data.data );
|
217 |
-
AstraSitesAdmin._log( data.data );
|
218 |
-
} else {
|
219 |
-
|
220 |
-
$('body').removeClass('importing-site');
|
221 |
-
$('.previous-theme, .next-theme').removeClass('disabled');
|
222 |
-
|
223 |
-
// 5. Pass - Import Complete.
|
224 |
-
AstraSitesAdmin._importSuccessMessage();
|
225 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.success + ' ' + astraSitesAdmin.siteURL );
|
226 |
-
}
|
227 |
-
});
|
228 |
-
},
|
229 |
-
|
230 |
-
/**
|
231 |
-
* 4. Import Widgets.
|
232 |
-
*/
|
233 |
-
_importWidgets: function( event ) {
|
234 |
-
|
235 |
-
$.ajax({
|
236 |
-
url : astraSitesAdmin.ajaxurl,
|
237 |
-
type : 'POST',
|
238 |
-
dataType: 'json',
|
239 |
-
data : {
|
240 |
-
action : 'astra-sites-import-widgets',
|
241 |
-
widgets_data : AstraSitesAdmin.widgets_data,
|
242 |
-
},
|
243 |
-
beforeSend: function() {
|
244 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importWidgets );
|
245 |
-
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importingWidgets );
|
246 |
-
},
|
247 |
-
})
|
248 |
-
.fail(function( jqXHR ){
|
249 |
-
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
250 |
-
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
251 |
-
})
|
252 |
-
.done(function ( widgets_data ) {
|
253 |
-
|
254 |
-
// 4. Fail - Import Widgets.
|
255 |
-
if( false === widgets_data.success ) {
|
256 |
-
AstraSitesAdmin._importFailMessage( widgets_data.data );
|
257 |
-
AstraSitesAdmin._log( widgets_data.data );
|
258 |
-
|
259 |
-
} else {
|
260 |
-
|
261 |
-
// 4. Pass - Import Widgets.
|
262 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importWidgetsSuccess );
|
263 |
-
$(document).trigger( 'astra-sites-import-widgets-done' );
|
264 |
-
}
|
265 |
-
});
|
266 |
-
},
|
267 |
-
|
268 |
-
/**
|
269 |
-
* 3. Import Site Options.
|
270 |
-
*/
|
271 |
-
_importSiteOptions: function( event ) {
|
272 |
-
|
273 |
-
$.ajax({
|
274 |
-
url : astraSitesAdmin.ajaxurl,
|
275 |
-
type : 'POST',
|
276 |
-
dataType: 'json',
|
277 |
-
data : {
|
278 |
-
action : 'astra-sites-import-options',
|
279 |
-
options_data : AstraSitesAdmin.options_data,
|
280 |
-
},
|
281 |
-
beforeSend: function() {
|
282 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importOptions );
|
283 |
-
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importingOptions );
|
284 |
-
},
|
285 |
-
})
|
286 |
-
.fail(function( jqXHR ){
|
287 |
-
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
288 |
-
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
289 |
-
})
|
290 |
-
.done(function ( options_data ) {
|
291 |
-
|
292 |
-
// 3. Fail - Import Site Options.
|
293 |
-
if( false === options_data.success ) {
|
294 |
-
AstraSitesAdmin._log( options_data );
|
295 |
-
AstraSitesAdmin._importFailMessage( options_data.data );
|
296 |
-
AstraSitesAdmin._log( options_data.data );
|
297 |
-
|
298 |
-
} else {
|
299 |
-
|
300 |
-
// 3. Pass - Import Site Options.
|
301 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importOptionsSuccess );
|
302 |
-
$(document).trigger( 'astra-sites-import-options-done' );
|
303 |
-
}
|
304 |
-
});
|
305 |
-
},
|
306 |
-
|
307 |
-
/**
|
308 |
-
* 2. Prepare XML Data.
|
309 |
-
*/
|
310 |
-
_importPrepareXML: function( event ) {
|
311 |
-
|
312 |
-
$.ajax({
|
313 |
-
url : astraSitesAdmin.ajaxurl,
|
314 |
-
type : 'POST',
|
315 |
-
dataType: 'json',
|
316 |
-
data : {
|
317 |
-
action : 'astra-sites-import-prepare-xml',
|
318 |
-
wxr_url : AstraSitesAdmin.wxr_url,
|
319 |
-
},
|
320 |
-
beforeSend: function() {
|
321 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importXMLPrepare );
|
322 |
-
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importXMLPreparing );
|
323 |
-
},
|
324 |
-
})
|
325 |
-
.fail(function( jqXHR ){
|
326 |
-
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
327 |
-
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
328 |
-
})
|
329 |
-
.done(function ( xml_data ) {
|
330 |
-
|
331 |
-
// 2. Fail - Prepare XML Data.
|
332 |
-
if( false === xml_data.success ) {
|
333 |
-
AstraSitesAdmin._log( xml_data );
|
334 |
-
AstraSitesAdmin._importFailMessage( xml_data.data );
|
335 |
-
AstraSitesAdmin._log( xml_data.data );
|
336 |
-
|
337 |
-
} else {
|
338 |
-
|
339 |
-
// 2. Pass - Prepare XML Data.
|
340 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importXMLPrepareSuccess );
|
341 |
-
|
342 |
-
// Import XML though Event Source.
|
343 |
-
AstraSSEImport.data = xml_data.data;
|
344 |
-
AstraSSEImport.render();
|
345 |
-
|
346 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importXML );
|
347 |
-
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importingXML );
|
348 |
-
|
349 |
-
var evtSource = new EventSource( AstraSSEImport.data.url );
|
350 |
-
evtSource.onmessage = function ( message ) {
|
351 |
-
var data = JSON.parse( message.data );
|
352 |
-
switch ( data.action ) {
|
353 |
-
case 'updateDelta':
|
354 |
-
AstraSSEImport.updateDelta( data.type, data.delta );
|
355 |
-
break;
|
356 |
-
|
357 |
-
case 'complete':
|
358 |
-
evtSource.close();
|
359 |
-
|
360 |
-
// 2. Pass - Import XML though "Source Event".
|
361 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importXMLSuccess );
|
362 |
-
AstraSitesAdmin._log( '----- SSE - XML import Complete -----' );
|
363 |
-
|
364 |
-
$(document).trigger( 'astra-sites-import-xml-done' );
|
365 |
-
|
366 |
-
break;
|
367 |
-
}
|
368 |
-
};
|
369 |
-
evtSource.addEventListener( 'log', function ( message ) {
|
370 |
-
var data = JSON.parse( message.data );
|
371 |
-
AstraSitesAdmin._log( data.level + ' ' + data.message );
|
372 |
-
});
|
373 |
-
}
|
374 |
-
});
|
375 |
-
},
|
376 |
-
|
377 |
-
/**
|
378 |
-
* 1. Import Customizer Options.
|
379 |
-
*/
|
380 |
-
_importCustomizerSettings: function( event ) {
|
381 |
-
|
382 |
-
$.ajax({
|
383 |
-
url : astraSitesAdmin.ajaxurl,
|
384 |
-
type : 'POST',
|
385 |
-
dataType: 'json',
|
386 |
-
data : {
|
387 |
-
action : 'astra-sites-import-customizer-settings',
|
388 |
-
customizer_data : AstraSitesAdmin.customizer_data,
|
389 |
-
},
|
390 |
-
beforeSend: function() {
|
391 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importCustomizer );
|
392 |
-
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importingCustomizer );
|
393 |
-
},
|
394 |
-
})
|
395 |
-
.fail(function( jqXHR ){
|
396 |
-
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
397 |
-
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
398 |
-
})
|
399 |
-
.done(function ( customizer_data ) {
|
400 |
-
|
401 |
-
// 1. Fail - Import Customizer Options.
|
402 |
-
if( false === customizer_data.success ) {
|
403 |
-
AstraSitesAdmin._importFailMessage( customizer_data.data );
|
404 |
-
AstraSitesAdmin._log( customizer_data.data );
|
405 |
-
} else {
|
406 |
-
|
407 |
-
// 1. Pass - Import Customizer Options.
|
408 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importCustomizerSuccess );
|
409 |
-
|
410 |
-
$(document).trigger( 'astra-sites-import-customizer-settings-done' );
|
411 |
-
}
|
412 |
-
});
|
413 |
-
},
|
414 |
-
|
415 |
-
/**
|
416 |
-
* Import Success Button.
|
417 |
-
*
|
418 |
-
* @param {string} data Error message.
|
419 |
-
*/
|
420 |
-
_importSuccessMessage: function() {
|
421 |
-
|
422 |
-
$('.astra-demo-import').removeClass('updating-message installing')
|
423 |
-
.removeAttr('data-import')
|
424 |
-
.addClass('view-site')
|
425 |
-
.removeClass('astra-demo-import')
|
426 |
-
.text( astraSitesAdmin.strings.viewSite )
|
427 |
-
.attr('target', '_blank')
|
428 |
-
.append('<i class="dashicons dashicons-external"></i>')
|
429 |
-
.attr('href', astraSitesAdmin.siteURL );
|
430 |
-
},
|
431 |
-
|
432 |
-
/**
|
433 |
-
* Preview Device
|
434 |
-
*/
|
435 |
-
_previewDevice: function( event ) {
|
436 |
-
var device = $( event.currentTarget ).data( 'device' );
|
437 |
-
|
438 |
-
$('.theme-install-overlay')
|
439 |
-
.removeClass( 'preview-desktop preview-tablet preview-mobile' )
|
440 |
-
.addClass( 'preview-' + device )
|
441 |
-
.data( 'current-preview-device', device );
|
442 |
-
|
443 |
-
AstraSitesAdmin._tooglePreviewDeviceButtons( device );
|
444 |
-
},
|
445 |
-
|
446 |
-
/**
|
447 |
-
* Toggle Preview Buttons
|
448 |
-
*/
|
449 |
-
_tooglePreviewDeviceButtons: function( newDevice ) {
|
450 |
-
var $devices = $( '.wp-full-overlay-footer .devices' );
|
451 |
-
|
452 |
-
$devices.find( 'button' )
|
453 |
-
.removeClass( 'active' )
|
454 |
-
.attr( 'aria-pressed', false );
|
455 |
-
|
456 |
-
$devices.find( 'button.preview-' + newDevice )
|
457 |
-
.addClass( 'active' )
|
458 |
-
.attr( 'aria-pressed', true );
|
459 |
-
},
|
460 |
-
|
461 |
-
/**
|
462 |
-
* Import Error Button.
|
463 |
-
*
|
464 |
-
* @param {string} data Error message.
|
465 |
-
*/
|
466 |
-
_importFailMessage: function( message, from ) {
|
467 |
-
|
468 |
-
$('.astra-demo-import')
|
469 |
-
.addClass('go-pro button-primary')
|
470 |
-
.removeClass('updating-message installing')
|
471 |
-
.removeAttr('data-import')
|
472 |
-
.attr('target', '_blank')
|
473 |
-
.append('<i class="dashicons dashicons-external"></i>')
|
474 |
-
.removeClass('astra-demo-import');
|
475 |
-
|
476 |
-
// Add the doc link due to import log file not generated.
|
477 |
-
if( 'undefined' === from ) {
|
478 |
-
|
479 |
-
$('.wp-full-overlay-header .go-pro').text( astraSitesAdmin.strings.importFailedBtnSmall );
|
480 |
-
$('.wp-full-overlay-footer .go-pro').text( astraSitesAdmin.strings.importFailedBtnLarge );
|
481 |
-
$('.go-pro').attr('href', astraSitesAdmin.log.serverConfiguration );
|
482 |
-
|
483 |
-
// Add the import log file link.
|
484 |
-
} else {
|
485 |
-
|
486 |
-
$('.wp-full-overlay-header .go-pro').text( astraSitesAdmin.strings.importFailBtn );
|
487 |
-
$('.wp-full-overlay-footer .go-pro').text( astraSitesAdmin.strings.importFailBtnLarge )
|
488 |
-
|
489 |
-
// Add the import log file link.
|
490 |
-
if( 'undefined' !== AstraSitesAdmin.log_file_url ) {
|
491 |
-
$('.go-pro').attr('href', AstraSitesAdmin.log_file_url );
|
492 |
-
} else {
|
493 |
-
$('.go-pro').attr('href', astraSitesAdmin.log.serverConfiguration );
|
494 |
-
}
|
495 |
-
}
|
496 |
-
|
497 |
-
var output = '<div class="astra-api-error notice notice-error notice-alt is-dismissible">';
|
498 |
-
output += ' <p>'+message+'</p>';
|
499 |
-
output += ' <button type="button" class="notice-dismiss">';
|
500 |
-
output += ' <span class="screen-reader-text">'+commonL10n.dismiss+'</span>';
|
501 |
-
output += ' </button>';
|
502 |
-
output += '</div>';
|
503 |
-
|
504 |
-
// Fail Notice.
|
505 |
-
$('.install-theme-info').append( output );
|
506 |
-
|
507 |
-
|
508 |
-
// !important to add trigger.
|
509 |
-
// Which reinitialize the dismiss error message events.
|
510 |
-
$(document).trigger('wp-updates-notice-added');
|
511 |
-
},
|
512 |
-
|
513 |
-
|
514 |
-
/**
|
515 |
-
* Install Now
|
516 |
-
*/
|
517 |
-
_installNow: function(event)
|
518 |
-
{
|
519 |
-
event.preventDefault();
|
520 |
-
|
521 |
-
var $button = jQuery( event.target ),
|
522 |
-
$document = jQuery(document);
|
523 |
-
|
524 |
-
if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) {
|
525 |
-
return;
|
526 |
-
}
|
527 |
-
|
528 |
-
if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) {
|
529 |
-
wp.updates.requestFilesystemCredentials( event );
|
530 |
-
|
531 |
-
$document.on( 'credential-modal-cancel', function() {
|
532 |
-
var $message = $( '.install-now.updating-message' );
|
533 |
-
|
534 |
-
$message
|
535 |
-
.removeClass( 'updating-message' )
|
536 |
-
.text( wp.updates.l10n.installNow );
|
537 |
-
|
538 |
-
wp.a11y.speak( wp.updates.l10n.updateCancel, 'polite' );
|
539 |
-
} );
|
540 |
-
}
|
541 |
-
|
542 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.installingPlugin + ' ' + $button.data( 'slug' ) );
|
543 |
-
|
544 |
-
wp.updates.installPlugin( {
|
545 |
-
slug: $button.data( 'slug' )
|
546 |
-
} );
|
547 |
-
},
|
548 |
-
|
549 |
-
/**
|
550 |
-
* Install Success
|
551 |
-
*/
|
552 |
-
_installSuccess: function( event, response ) {
|
553 |
-
|
554 |
-
event.preventDefault();
|
555 |
-
|
556 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.installed + ' ' + response.slug );
|
557 |
-
|
558 |
-
var $message = jQuery( '.plugin-card-' + response.slug ).find( '.button' );
|
559 |
-
var $siteOptions = jQuery( '.wp-full-overlay-header').find('.astra-site-options').val();
|
560 |
-
var $enabledExtensions = jQuery( '.wp-full-overlay-header').find('.astra-enabled-extensions').val();
|
561 |
-
|
562 |
-
// Transform the 'Install' button into an 'Activate' button.
|
563 |
-
var $init = $message.data('init');
|
564 |
-
|
565 |
-
$message.removeClass( 'install-now installed button-disabled updated-message' )
|
566 |
-
.addClass('updating-message')
|
567 |
-
.html( astraSitesAdmin.strings.btnActivating );
|
568 |
-
|
569 |
-
// Reset not installed plugins list.
|
570 |
-
var pluginsList = astraSitesAdmin.requiredPlugins.notinstalled;
|
571 |
-
astraSitesAdmin.requiredPlugins.notinstalled = AstraSitesAdmin._removePluginFromQueue( response.slug, pluginsList );
|
572 |
-
|
573 |
-
// WordPress adds "Activate" button after waiting for 1000ms. So we will run our activation after that.
|
574 |
-
setTimeout( function() {
|
575 |
-
|
576 |
-
$.ajax({
|
577 |
-
url: astraSitesAdmin.ajaxurl,
|
578 |
-
type: 'POST',
|
579 |
-
data: {
|
580 |
-
'action' : 'astra-required-plugin-activate',
|
581 |
-
'init' : $init,
|
582 |
-
'options' : $siteOptions,
|
583 |
-
'enabledExtensions' : $enabledExtensions,
|
584 |
-
},
|
585 |
-
})
|
586 |
-
.done(function (result) {
|
587 |
-
|
588 |
-
if( result.success ) {
|
589 |
-
|
590 |
-
var pluginsList = astraSitesAdmin.requiredPlugins.inactive;
|
591 |
-
|
592 |
-
// Reset not installed plugins list.
|
593 |
-
astraSitesAdmin.requiredPlugins.inactive = AstraSitesAdmin._removePluginFromQueue( response.slug, pluginsList );
|
594 |
-
|
595 |
-
$message.removeClass( 'button-primary install-now activate-now updating-message' )
|
596 |
-
.attr('disabled', 'disabled')
|
597 |
-
.addClass('disabled')
|
598 |
-
.text( astraSitesAdmin.strings.btnActive );
|
599 |
-
|
600 |
-
// Enable Demo Import Button
|
601 |
-
AstraSitesAdmin._enable_demo_import_button();
|
602 |
-
|
603 |
-
} else {
|
604 |
-
|
605 |
-
$message.removeClass( 'updating-message' );
|
606 |
-
|
607 |
-
}
|
608 |
-
|
609 |
-
});
|
610 |
-
|
611 |
-
}, 1200 );
|
612 |
-
|
613 |
-
},
|
614 |
-
|
615 |
-
/**
|
616 |
-
* Plugin Installation Error.
|
617 |
-
*/
|
618 |
-
_installError: function( event, response ) {
|
619 |
-
|
620 |
-
var $card = jQuery( '.plugin-card-' + response.slug );
|
621 |
-
|
622 |
-
AstraSitesAdmin._log( response.errorMessage + ' ' + response.slug );
|
623 |
-
|
624 |
-
$card
|
625 |
-
.removeClass( 'button-primary' )
|
626 |
-
.addClass( 'disabled' )
|
627 |
-
.html( wp.updates.l10n.installFailedShort );
|
628 |
-
|
629 |
-
AstraSitesAdmin._importFailMessage( response.errorMessage );
|
630 |
-
},
|
631 |
-
|
632 |
-
/**
|
633 |
-
* Installing Plugin
|
634 |
-
*/
|
635 |
-
_pluginInstalling: function(event, args) {
|
636 |
-
event.preventDefault();
|
637 |
-
|
638 |
-
var $card = jQuery( '.plugin-card-' + args.slug );
|
639 |
-
var $button = $card.find( '.button' );
|
640 |
-
|
641 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.installingPlugin + ' ' + args.slug );
|
642 |
-
|
643 |
-
$card.addClass('updating-message');
|
644 |
-
$button.addClass('already-started');
|
645 |
-
|
646 |
-
},
|
647 |
-
|
648 |
-
/**
|
649 |
-
* Render Demo Preview
|
650 |
-
*/
|
651 |
-
_activateNow: function( eventn ) {
|
652 |
-
|
653 |
-
event.preventDefault();
|
654 |
-
|
655 |
-
var $button = jQuery( event.target ),
|
656 |
-
$init = $button.data( 'init' ),
|
657 |
-
$slug = $button.data( 'slug' );
|
658 |
-
|
659 |
-
if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) {
|
660 |
-
return;
|
661 |
-
}
|
662 |
-
|
663 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.activating + ' ' + $slug );
|
664 |
-
|
665 |
-
$button.addClass('updating-message button-primary')
|
666 |
-
.html( astraSitesAdmin.strings.btnActivating );
|
667 |
-
|
668 |
-
var $siteOptions = jQuery( '.wp-full-overlay-header').find('.astra-site-options').val();
|
669 |
-
var $enabledExtensions = jQuery( '.wp-full-overlay-header').find('.astra-enabled-extensions').val();
|
670 |
-
|
671 |
-
$.ajax({
|
672 |
-
url: astraSitesAdmin.ajaxurl,
|
673 |
-
type: 'POST',
|
674 |
-
data: {
|
675 |
-
'action' : 'astra-required-plugin-activate',
|
676 |
-
'init' : $init,
|
677 |
-
'options' : $siteOptions,
|
678 |
-
'enabledExtensions' : $enabledExtensions,
|
679 |
-
},
|
680 |
-
})
|
681 |
-
.done(function (result) {
|
682 |
-
|
683 |
-
if( result.success ) {
|
684 |
-
|
685 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.activated + ' ' + $slug );
|
686 |
-
|
687 |
-
var pluginsList = astraSitesAdmin.requiredPlugins.inactive;
|
688 |
-
|
689 |
-
// Reset not installed plugins list.
|
690 |
-
astraSitesAdmin.requiredPlugins.inactive = AstraSitesAdmin._removePluginFromQueue( $slug, pluginsList );
|
691 |
-
|
692 |
-
$button.removeClass( 'button-primary install-now activate-now updating-message' )
|
693 |
-
.attr('disabled', 'disabled')
|
694 |
-
.addClass('disabled')
|
695 |
-
.text( astraSitesAdmin.strings.btnActive );
|
696 |
-
|
697 |
-
// Enable Demo Import Button
|
698 |
-
AstraSitesAdmin._enable_demo_import_button();
|
699 |
-
|
700 |
-
}
|
701 |
-
|
702 |
-
})
|
703 |
-
.fail(function () {
|
704 |
-
});
|
705 |
-
|
706 |
-
},
|
707 |
-
|
708 |
-
/**
|
709 |
-
* Full Overlay
|
710 |
-
*/
|
711 |
-
_fullOverlay: function (event) {
|
712 |
-
event.preventDefault();
|
713 |
-
|
714 |
-
// Import process is started?
|
715 |
-
// And Closing the window? Then showing the warning confirm message.
|
716 |
-
if( $('body').hasClass('importing-site') && ! confirm( astraSitesAdmin.strings.warningBeforeCloseWindow ) ) {
|
717 |
-
return;
|
718 |
-
}
|
719 |
-
|
720 |
-
$('body').removeClass('importing-site');
|
721 |
-
$('.previous-theme, .next-theme').removeClass('disabled');
|
722 |
-
$('.theme-install-overlay').css('display', 'none');
|
723 |
-
$('.theme-install-overlay').remove();
|
724 |
-
$('.theme-preview-on').removeClass('theme-preview-on');
|
725 |
-
$('html').removeClass('astra-site-preview-on');
|
726 |
-
},
|
727 |
-
|
728 |
-
/**
|
729 |
-
* Bulk Plugin Active & Install
|
730 |
-
*/
|
731 |
-
_bulkPluginInstallActivate: function()
|
732 |
-
{
|
733 |
-
if( 0 === astraSitesAdmin.requiredPlugins.length ) {
|
734 |
-
return;
|
735 |
-
}
|
736 |
-
|
737 |
-
jQuery('.required-plugins')
|
738 |
-
.find('.install-now')
|
739 |
-
.addClass( 'updating-message' )
|
740 |
-
.removeClass( 'install-now' )
|
741 |
-
.text( wp.updates.l10n.installing );
|
742 |
-
|
743 |
-
jQuery('.required-plugins')
|
744 |
-
.find('.activate-now')
|
745 |
-
.addClass('updating-message')
|
746 |
-
.removeClass( 'activate-now' )
|
747 |
-
.html( astraSitesAdmin.strings.btnActivating );
|
748 |
-
|
749 |
-
var not_installed = astraSitesAdmin.requiredPlugins.notinstalled || '';
|
750 |
-
var activate_plugins = astraSitesAdmin.requiredPlugins.inactive || '';
|
751 |
-
|
752 |
-
// First Install Bulk.
|
753 |
-
if( not_installed.length > 0 ) {
|
754 |
-
AstraSitesAdmin._installAllPlugins( not_installed );
|
755 |
-
}
|
756 |
-
|
757 |
-
// Second Activate Bulk.
|
758 |
-
if( activate_plugins.length > 0 ) {
|
759 |
-
AstraSitesAdmin._activateAllPlugins( activate_plugins );
|
760 |
-
}
|
761 |
-
|
762 |
-
},
|
763 |
-
|
764 |
-
/**
|
765 |
-
* Activate All Plugins.
|
766 |
-
*/
|
767 |
-
_activateAllPlugins: function( activate_plugins ) {
|
768 |
-
|
769 |
-
// Activate ALl Plugins.
|
770 |
-
AstraSitesAjaxQueue.stop();
|
771 |
-
AstraSitesAjaxQueue.run();
|
772 |
-
|
773 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.bulkActivation );
|
774 |
-
|
775 |
-
$.each( activate_plugins, function(index, single_plugin) {
|
776 |
-
|
777 |
-
var $card = jQuery( '.plugin-card-' + single_plugin.slug ),
|
778 |
-
$button = $card.find('.button'),
|
779 |
-
$siteOptions = jQuery( '.wp-full-overlay-header').find('.astra-site-options').val(),
|
780 |
-
$enabledExtensions = jQuery( '.wp-full-overlay-header').find('.astra-enabled-extensions').val();
|
781 |
-
|
782 |
-
$button.addClass('updating-message');
|
783 |
-
|
784 |
-
AstraSitesAjaxQueue.add({
|
785 |
-
url: astraSitesAdmin.ajaxurl,
|
786 |
-
type: 'POST',
|
787 |
-
data: {
|
788 |
-
'action' : 'astra-required-plugin-activate',
|
789 |
-
'init' : single_plugin.init,
|
790 |
-
'options' : $siteOptions,
|
791 |
-
'enabledExtensions' : $enabledExtensions,
|
792 |
-
},
|
793 |
-
success: function( result ){
|
794 |
-
|
795 |
-
if( result.success ) {
|
796 |
-
|
797 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.activate + ' ' + single_plugin.slug );
|
798 |
-
|
799 |
-
var $card = jQuery( '.plugin-card-' + single_plugin.slug );
|
800 |
-
var $button = $card.find( '.button' );
|
801 |
-
if( ! $button.hasClass('already-started') ) {
|
802 |
-
var pluginsList = astraSitesAdmin.requiredPlugins.inactive;
|
803 |
-
|
804 |
-
// Reset not installed plugins list.
|
805 |
-
astraSitesAdmin.requiredPlugins.inactive = AstraSitesAdmin._removePluginFromQueue( single_plugin.slug, pluginsList );
|
806 |
-
}
|
807 |
-
|
808 |
-
$button.removeClass( 'button-primary install-now activate-now updating-message' )
|
809 |
-
.attr('disabled', 'disabled')
|
810 |
-
.addClass('disabled')
|
811 |
-
.text( astraSitesAdmin.strings.btnActive );
|
812 |
-
|
813 |
-
// Enable Demo Import Button
|
814 |
-
AstraSitesAdmin._enable_demo_import_button();
|
815 |
-
} else {
|
816 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.activationError + ' - ' + single_plugin.slug );
|
817 |
-
}
|
818 |
-
}
|
819 |
-
});
|
820 |
-
});
|
821 |
-
},
|
822 |
-
|
823 |
-
/**
|
824 |
-
* Install All Plugins.
|
825 |
-
*/
|
826 |
-
_installAllPlugins: function( not_installed ) {
|
827 |
-
|
828 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.bulkInstall );
|
829 |
-
|
830 |
-
$.each( not_installed, function(index, single_plugin) {
|
831 |
-
|
832 |
-
var $card = jQuery( '.plugin-card-' + single_plugin.slug ),
|
833 |
-
$button = $card.find('.button');
|
834 |
-
|
835 |
-
if( ! $button.hasClass('already-started') ) {
|
836 |
-
|
837 |
-
// Add each plugin activate request in Ajax queue.
|
838 |
-
// @see wp-admin/js/updates.js
|
839 |
-
wp.updates.queue.push( {
|
840 |
-
action: 'install-plugin', // Required action.
|
841 |
-
data: {
|
842 |
-
slug: single_plugin.slug
|
843 |
-
}
|
844 |
-
} );
|
845 |
-
}
|
846 |
-
});
|
847 |
-
|
848 |
-
// Required to set queue.
|
849 |
-
wp.updates.queueChecker();
|
850 |
-
},
|
851 |
-
|
852 |
-
/**
|
853 |
-
* Fires when a nav item is clicked.
|
854 |
-
*
|
855 |
-
* @since 1.0
|
856 |
-
* @access private
|
857 |
-
* @method _importDemo
|
858 |
-
*/
|
859 |
-
_importDemo: function()
|
860 |
-
{
|
861 |
-
var $this = jQuery(this),
|
862 |
-
$theme = $this.closest('.astra-sites-preview').find('.wp-full-overlay-header'),
|
863 |
-
apiURL = $theme.data('demo-api') || '',
|
864 |
-
plugins = $theme.data('required-plugins');
|
865 |
-
|
866 |
-
var disabled = $this.attr('data-import');
|
867 |
-
|
868 |
-
if ( typeof disabled !== 'undefined' && disabled === 'disabled' || $this.hasClass('disabled') ) {
|
869 |
-
|
870 |
-
$('.astra-demo-import').addClass('updating-message installing')
|
871 |
-
.text( wp.updates.l10n.installing );
|
872 |
-
|
873 |
-
/**
|
874 |
-
* Process Bulk Plugin Install & Activate
|
875 |
-
*/
|
876 |
-
AstraSitesAdmin._bulkPluginInstallActivate();
|
877 |
-
|
878 |
-
return;
|
879 |
-
}
|
880 |
-
|
881 |
-
// Proceed?
|
882 |
-
if( ! confirm( astraSitesAdmin.strings.importWarning ) ) {
|
883 |
-
return;
|
884 |
-
}
|
885 |
-
|
886 |
-
$('body').addClass('importing-site');
|
887 |
-
$('.previous-theme, .next-theme').addClass('disabled');
|
888 |
-
|
889 |
-
// Remove all notices before import start.
|
890 |
-
$('.install-theme-info > .notice').remove();
|
891 |
-
|
892 |
-
$('.astra-demo-import').attr('data-import', 'disabled')
|
893 |
-
.addClass('updating-message installing')
|
894 |
-
.text( astraSitesAdmin.strings.importingDemo );
|
895 |
-
|
896 |
-
$this.closest('.theme').focus();
|
897 |
-
|
898 |
-
var $theme = $this.closest('.astra-sites-preview').find('.wp-full-overlay-header');
|
899 |
-
|
900 |
-
var apiURL = $theme.data('demo-api') || '';
|
901 |
-
|
902 |
-
// Site Import by API URL.
|
903 |
-
if( apiURL ) {
|
904 |
-
AstraSitesAdmin._importSite( apiURL );
|
905 |
-
}
|
906 |
-
|
907 |
-
},
|
908 |
-
|
909 |
-
/**
|
910 |
-
* Start Import Process by API URL.
|
911 |
-
*
|
912 |
-
* @param {string} apiURL Site API URL.
|
913 |
-
*/
|
914 |
-
_importSite: function( apiURL ) {
|
915 |
-
|
916 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.api + ' : ' + apiURL );
|
917 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.importing );
|
918 |
-
|
919 |
-
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.gettingData );
|
920 |
-
|
921 |
-
// 1. Request Site Import
|
922 |
-
$.ajax({
|
923 |
-
url : astraSitesAdmin.ajaxurl,
|
924 |
-
type : 'POST',
|
925 |
-
dataType: 'json',
|
926 |
-
data : {
|
927 |
-
'action' : 'astra-sites-import-set-site-data',
|
928 |
-
'api_url' : apiURL,
|
929 |
-
},
|
930 |
-
})
|
931 |
-
.fail(function( jqXHR ){
|
932 |
-
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
933 |
-
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
934 |
-
})
|
935 |
-
.done(function ( demo_data ) {
|
936 |
-
|
937 |
-
// 1. Fail - Request Site Import
|
938 |
-
if( false === demo_data.success ) {
|
939 |
-
|
940 |
-
AstraSitesAdmin._importFailMessage( demo_data.data );
|
941 |
-
|
942 |
-
} else {
|
943 |
-
|
944 |
-
// Set log file URL.
|
945 |
-
if( 'log_file' in demo_data.data ){
|
946 |
-
AstraSitesAdmin.log_file_url = decodeURIComponent( demo_data.data.log_file ) || '';
|
947 |
-
}
|
948 |
-
|
949 |
-
// 1. Pass - Request Site Import
|
950 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.processingRequest );
|
951 |
-
|
952 |
-
AstraSitesAdmin.customizer_data = JSON.stringify( demo_data.data['astra-site-customizer-data'] ) || '';
|
953 |
-
AstraSitesAdmin.wxr_url = encodeURI( demo_data.data['astra-site-wxr-path'] ) || '';
|
954 |
-
AstraSitesAdmin.options_data = JSON.stringify( demo_data.data['astra-site-options-data'] ) || '';
|
955 |
-
AstraSitesAdmin.widgets_data = JSON.stringify( demo_data.data['astra-site-widgets-data'] ) || '';
|
956 |
-
|
957 |
-
$(document).trigger( 'astra-sites-import-set-site-data-done' );
|
958 |
-
}
|
959 |
-
|
960 |
-
});
|
961 |
-
|
962 |
-
},
|
963 |
-
|
964 |
-
/**
|
965 |
-
* Collapse Sidebar.
|
966 |
-
*/
|
967 |
-
_collapse: function() {
|
968 |
-
event.preventDefault();
|
969 |
-
|
970 |
-
overlay = jQuery('.wp-full-overlay');
|
971 |
-
|
972 |
-
if (overlay.hasClass('expanded')) {
|
973 |
-
overlay.removeClass('expanded');
|
974 |
-
overlay.addClass('collapsed');
|
975 |
-
return;
|
976 |
-
}
|
977 |
-
|
978 |
-
if (overlay.hasClass('collapsed')) {
|
979 |
-
overlay.removeClass('collapsed');
|
980 |
-
overlay.addClass('expanded');
|
981 |
-
return;
|
982 |
-
}
|
983 |
-
},
|
984 |
-
|
985 |
-
/**
|
986 |
-
* Previous Theme.
|
987 |
-
*/
|
988 |
-
_previousTheme: function (event) {
|
989 |
-
event.preventDefault();
|
990 |
-
|
991 |
-
currentDemo = jQuery('.theme-preview-on');
|
992 |
-
currentDemo.removeClass('theme-preview-on');
|
993 |
-
prevDemo = currentDemo.prev('.theme');
|
994 |
-
prevDemo.addClass('theme-preview-on');
|
995 |
-
|
996 |
-
AstraSitesAdmin._renderDemoPreview(prevDemo);
|
997 |
-
},
|
998 |
-
|
999 |
-
/**
|
1000 |
-
* Next Theme.
|
1001 |
-
*/
|
1002 |
-
_nextTheme: function (event) {
|
1003 |
-
event.preventDefault();
|
1004 |
-
currentDemo = jQuery('.theme-preview-on')
|
1005 |
-
currentDemo.removeClass('theme-preview-on');
|
1006 |
-
nextDemo = currentDemo.next('.theme');
|
1007 |
-
nextDemo.addClass('theme-preview-on');
|
1008 |
-
|
1009 |
-
AstraSitesAdmin._renderDemoPreview( nextDemo );
|
1010 |
-
},
|
1011 |
-
|
1012 |
-
/**
|
1013 |
-
* Individual Site Preview
|
1014 |
-
*
|
1015 |
-
* On click on image, more link & preview button.
|
1016 |
-
*/
|
1017 |
-
_preview: function( event ) {
|
1018 |
-
|
1019 |
-
event.preventDefault();
|
1020 |
-
|
1021 |
-
var self = jQuery(this).parents('.theme');
|
1022 |
-
self.addClass('theme-preview-on');
|
1023 |
-
|
1024 |
-
jQuery('html').addClass('astra-site-preview-on');
|
1025 |
-
|
1026 |
-
AstraSitesAdmin._renderDemoPreview( self );
|
1027 |
-
},
|
1028 |
-
|
1029 |
-
/**
|
1030 |
-
* Check Next Previous Buttons.
|
1031 |
-
*/
|
1032 |
-
_checkNextPrevButtons: function() {
|
1033 |
-
currentDemo = jQuery('.theme-preview-on');
|
1034 |
-
nextDemo = currentDemo.nextAll('.theme').length;
|
1035 |
-
prevDemo = currentDemo.prevAll('.theme').length;
|
1036 |
-
|
1037 |
-
if (nextDemo == 0) {
|
1038 |
-
jQuery('.next-theme').addClass('disabled');
|
1039 |
-
} else if (nextDemo != 0) {
|
1040 |
-
jQuery('.next-theme').removeClass('disabled');
|
1041 |
-
}
|
1042 |
-
|
1043 |
-
if (prevDemo == 0) {
|
1044 |
-
jQuery('.previous-theme').addClass('disabled');
|
1045 |
-
} else if (prevDemo != 0) {
|
1046 |
-
jQuery('.previous-theme').removeClass('disabled');
|
1047 |
-
}
|
1048 |
-
|
1049 |
-
return;
|
1050 |
-
},
|
1051 |
-
|
1052 |
-
/**
|
1053 |
-
* Render Demo Preview
|
1054 |
-
*/
|
1055 |
-
_renderDemoPreview: function(anchor) {
|
1056 |
-
|
1057 |
-
var demoId = anchor.data('id') || '',
|
1058 |
-
apiURL = anchor.data('demo-api') || '',
|
1059 |
-
demoType = anchor.data('demo-type') || '',
|
1060 |
-
demoURL = anchor.data('demo-url') || '',
|
1061 |
-
screenshot = anchor.data('screenshot') || '',
|
1062 |
-
demo_name = anchor.data('demo-name') || '',
|
1063 |
-
demo_slug = anchor.data('demo-slug') || '',
|
1064 |
-
content = anchor.data('content') || '',
|
1065 |
-
requiredPlugins = anchor.data('required-plugins') || '',
|
1066 |
-
astraSiteOptions = anchor.find('.astra-site-options').val() || '';
|
1067 |
-
astraEnabledExtensions = anchor.find('.astra-enabled-extensions').val() || '';
|
1068 |
-
|
1069 |
-
AstraSitesAdmin._log( astraSitesAdmin.log.preview + ' "' + demo_name + '" URL : ' + demoURL );
|
1070 |
-
|
1071 |
-
var template = wp.template('astra-site-preview');
|
1072 |
-
|
1073 |
-
templateData = [{
|
1074 |
-
id : demoId,
|
1075 |
-
astra_demo_type : demoType,
|
1076 |
-
astra_demo_url : demoURL,
|
1077 |
-
demo_api : apiURL,
|
1078 |
-
screenshot : screenshot,
|
1079 |
-
demo_name : demo_name,
|
1080 |
-
slug : demo_slug,
|
1081 |
-
content : content,
|
1082 |
-
required_plugins : JSON.stringify(requiredPlugins),
|
1083 |
-
astra_site_options : astraSiteOptions,
|
1084 |
-
astra_enabled_extensions : astraEnabledExtensions,
|
1085 |
-
}];
|
1086 |
-
|
1087 |
-
// delete any earlier fullscreen preview before we render new one.
|
1088 |
-
jQuery('.theme-install-overlay').remove();
|
1089 |
-
|
1090 |
-
jQuery('#astra-sites-menu-page').append(template(templateData[0]));
|
1091 |
-
jQuery('.theme-install-overlay').css('display', 'block');
|
1092 |
-
AstraSitesAdmin._checkNextPrevButtons();
|
1093 |
-
|
1094 |
-
var desc = jQuery('.theme-details');
|
1095 |
-
var descHeight = parseInt( desc.outerHeight() );
|
1096 |
-
var descBtn = jQuery('.theme-details-read-more');
|
1097 |
-
|
1098 |
-
if( $.isArray( requiredPlugins ) ) {
|
1099 |
-
|
1100 |
-
if( descHeight >= 55 ) {
|
1101 |
-
|
1102 |
-
// Show button.
|
1103 |
-
descBtn.css( 'display', 'inline-block' );
|
1104 |
-
|
1105 |
-
// Set height upto 3 line.
|
1106 |
-
desc.css( 'height', 57 );
|
1107 |
-
|
1108 |
-
// Button Click.
|
1109 |
-
descBtn.click(function(event) {
|
1110 |
-
|
1111 |
-
if( descBtn.hasClass('open') ) {
|
1112 |
-
desc.animate({ height: 57 },
|
1113 |
-
300, function() {
|
1114 |
-
descBtn.removeClass('open');
|
1115 |
-
descBtn.html( astraSitesAdmin.strings.DescExpand );
|
1116 |
-
});
|
1117 |
-
} else {
|
1118 |
-
desc.animate({ height: descHeight },
|
1119 |
-
300, function() {
|
1120 |
-
descBtn.addClass('open');
|
1121 |
-
descBtn.html( astraSitesAdmin.strings.DescCollapse );
|
1122 |
-
});
|
1123 |
-
}
|
1124 |
-
|
1125 |
-
});
|
1126 |
-
}
|
1127 |
-
|
1128 |
-
// or
|
1129 |
-
var $pluginsFilter = jQuery( '#plugin-filter' ),
|
1130 |
-
data = {
|
1131 |
-
action : 'astra-required-plugins',
|
1132 |
-
_ajax_nonce : astraSitesAdmin._ajax_nonce,
|
1133 |
-
required_plugins : requiredPlugins
|
1134 |
-
};
|
1135 |
-
|
1136 |
-
// Add disabled class from import button.
|
1137 |
-
$('.astra-demo-import')
|
1138 |
-
.addClass('disabled not-click-able')
|
1139 |
-
.removeAttr('data-import');
|
1140 |
-
|
1141 |
-
$('.required-plugins').addClass('loading').html('<span class="spinner is-active"></span>');
|
1142 |
-
|
1143 |
-
// Required Required.
|
1144 |
-
$.ajax({
|
1145 |
-
url : astraSitesAdmin.ajaxurl,
|
1146 |
-
type : 'POST',
|
1147 |
-
data : data,
|
1148 |
-
})
|
1149 |
-
.fail(function( jqXHR ){
|
1150 |
-
|
1151 |
-
// Remove loader.
|
1152 |
-
jQuery('.required-plugins').removeClass('loading').html('');
|
1153 |
-
|
1154 |
-
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText, 'plugins' );
|
1155 |
-
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
1156 |
-
})
|
1157 |
-
.done(function ( response ) {
|
1158 |
-
|
1159 |
-
// Release disabled class from import button.
|
1160 |
-
$('.astra-demo-import')
|
1161 |
-
.removeClass('disabled not-click-able')
|
1162 |
-
.attr('data-import', 'disabled');
|
1163 |
-
|
1164 |
-
// Remove loader.
|
1165 |
-
$('.required-plugins').removeClass('loading').html('');
|
1166 |
-
|
1167 |
-
/**
|
1168 |
-
* Count remaining plugins.
|
1169 |
-
* @type number
|
1170 |
-
*/
|
1171 |
-
var remaining_plugins = 0;
|
1172 |
-
|
1173 |
-
/**
|
1174 |
-
* Not Installed
|
1175 |
-
*
|
1176 |
-
* List of not installed required plugins.
|
1177 |
-
*/
|
1178 |
-
if ( typeof response.data.notinstalled !== 'undefined' ) {
|
1179 |
-
|
1180 |
-
// Add not have installed plugins count.
|
1181 |
-
remaining_plugins += parseInt( response.data.notinstalled.length );
|
1182 |
-
|
1183 |
-
jQuery( response.data.notinstalled ).each(function( index, plugin ) {
|
1184 |
-
|
1185 |
-
var output = '<div class="plugin-card ';
|
1186 |
-
output += ' plugin-card-'+plugin.slug+'"';
|
1187 |
-
output += ' data-slug="'+plugin.slug+'"';
|
1188 |
-
output += ' data-init="'+plugin.init+'">';
|
1189 |
-
output += ' <span class="title">'+plugin.name+'</span>';
|
1190 |
-
output += ' <button class="button install-now"';
|
1191 |
-
output += ' data-init="' + plugin.init + '"';
|
1192 |
-
output += ' data-slug="' + plugin.slug + '"';
|
1193 |
-
output += ' data-name="' + plugin.name + '">';
|
1194 |
-
output += wp.updates.l10n.installNow;
|
1195 |
-
output += ' </button>';
|
1196 |
-
// output += ' <span class="dashicons-no dashicons"></span>';
|
1197 |
-
output += '</div>';
|
1198 |
-
|
1199 |
-
jQuery('.required-plugins').append(output);
|
1200 |
-
|
1201 |
-
});
|
1202 |
-
}
|
1203 |
-
|
1204 |
-
/**
|
1205 |
-
* Inactive
|
1206 |
-
*
|
1207 |
-
* List of not inactive required plugins.
|
1208 |
-
*/
|
1209 |
-
if ( typeof response.data.inactive !== 'undefined' ) {
|
1210 |
-
|
1211 |
-
// Add inactive plugins count.
|
1212 |
-
remaining_plugins += parseInt( response.data.inactive.length );
|
1213 |
-
|
1214 |
-
jQuery( response.data.inactive ).each(function( index, plugin ) {
|
1215 |
-
|
1216 |
-
var output = '<div class="plugin-card ';
|
1217 |
-
output += ' plugin-card-'+plugin.slug+'"';
|
1218 |
-
output += ' data-slug="'+plugin.slug+'"';
|
1219 |
-
output += ' data-init="'+plugin.init+'">';
|
1220 |
-
output += ' <span class="title">'+plugin.name+'</span>';
|
1221 |
-
output += ' <button class="button activate-now button-primary"';
|
1222 |
-
output += ' data-init="' + plugin.init + '"';
|
1223 |
-
output += ' data-slug="' + plugin.slug + '"';
|
1224 |
-
output += ' data-name="' + plugin.name + '">';
|
1225 |
-
output += wp.updates.l10n.activatePlugin;
|
1226 |
-
output += ' </button>';
|
1227 |
-
// output += ' <span class="dashicons-no dashicons"></span>';
|
1228 |
-
output += '</div>';
|
1229 |
-
|
1230 |
-
jQuery('.required-plugins').append(output);
|
1231 |
-
|
1232 |
-
});
|
1233 |
-
}
|
1234 |
-
|
1235 |
-
/**
|
1236 |
-
* Active
|
1237 |
-
*
|
1238 |
-
* List of not active required plugins.
|
1239 |
-
*/
|
1240 |
-
if ( typeof response.data.active !== 'undefined' ) {
|
1241 |
-
|
1242 |
-
jQuery( response.data.active ).each(function( index, plugin ) {
|
1243 |
-
|
1244 |
-
var output = '<div class="plugin-card ';
|
1245 |
-
output += ' plugin-card-'+plugin.slug+'"';
|
1246 |
-
output += ' data-slug="'+plugin.slug+'"';
|
1247 |
-
output += ' data-init="'+plugin.init+'">';
|
1248 |
-
output += ' <span class="title">'+plugin.name+'</span>';
|
1249 |
-
output += ' <button class="button disabled"';
|
1250 |
-
output += ' data-slug="' + plugin.slug + '"';
|
1251 |
-
output += ' data-name="' + plugin.name + '">';
|
1252 |
-
output += astraSitesAdmin.strings.btnActive;
|
1253 |
-
output += ' </button>';
|
1254 |
-
// output += ' <span class="dashicons-yes dashicons"></span>';
|
1255 |
-
output += '</div>';
|
1256 |
-
|
1257 |
-
jQuery('.required-plugins').append(output);
|
1258 |
-
|
1259 |
-
});
|
1260 |
-
}
|
1261 |
-
|
1262 |
-
/**
|
1263 |
-
* Enable Demo Import Button
|
1264 |
-
* @type number
|
1265 |
-
*/
|
1266 |
-
astraSitesAdmin.requiredPlugins = response.data;
|
1267 |
-
AstraSitesAdmin._enable_demo_import_button();
|
1268 |
-
|
1269 |
-
});
|
1270 |
-
|
1271 |
-
} else {
|
1272 |
-
|
1273 |
-
// Enable Demo Import Button
|
1274 |
-
AstraSitesAdmin._enable_demo_import_button( demoType );
|
1275 |
-
jQuery('.required-plugins-wrap').remove();
|
1276 |
-
}
|
1277 |
-
|
1278 |
-
return;
|
1279 |
-
},
|
1280 |
-
|
1281 |
-
/**
|
1282 |
-
* Enable Demo Import Button.
|
1283 |
-
*/
|
1284 |
-
_enable_demo_import_button: function( type ) {
|
1285 |
-
|
1286 |
-
type = ( undefined !== type ) ? type : 'free';
|
1287 |
-
|
1288 |
-
switch( type ) {
|
1289 |
-
|
1290 |
-
case 'free':
|
1291 |
-
var all_buttons = parseInt( jQuery( '.plugin-card .button' ).length ) || 0,
|
1292 |
-
disabled_buttons = parseInt( jQuery( '.plugin-card .button.disabled' ).length ) || 0;
|
1293 |
-
|
1294 |
-
if( all_buttons === disabled_buttons ) {
|
1295 |
-
|
1296 |
-
jQuery('.astra-demo-import')
|
1297 |
-
.removeAttr('data-import')
|
1298 |
-
.removeClass('installing updating-message')
|
1299 |
-
.addClass('button-primary')
|
1300 |
-
.text( astraSitesAdmin.strings.importDemo );
|
1301 |
-
}
|
1302 |
-
|
1303 |
-
break;
|
1304 |
-
|
1305 |
-
case 'upgrade':
|
1306 |
-
var demo_slug = jQuery('.wp-full-overlay-header').attr('data-demo-slug');
|
1307 |
-
|
1308 |
-
jQuery('.astra-demo-import')
|
1309 |
-
.addClass('go-pro button-primary')
|
1310 |
-
.removeClass('astra-demo-import')
|
1311 |
-
.attr('target', '_blank')
|
1312 |
-
.attr('href', astraSitesAdmin.getUpgradeURL + demo_slug )
|
1313 |
-
.text( astraSitesAdmin.getUpgradeText )
|
1314 |
-
.append('<i class="dashicons dashicons-external"></i>');
|
1315 |
-
break;
|
1316 |
-
|
1317 |
-
default:
|
1318 |
-
var demo_slug = jQuery('.wp-full-overlay-header').attr('data-demo-slug');
|
1319 |
-
|
1320 |
-
jQuery('.astra-demo-import')
|
1321 |
-
.addClass('go-pro button-primary')
|
1322 |
-
.removeClass('astra-demo-import')
|
1323 |
-
.attr('target', '_blank')
|
1324 |
-
.attr('href', astraSitesAdmin.getProURL )
|
1325 |
-
.text( astraSitesAdmin.getProText )
|
1326 |
-
.append('<i class="dashicons dashicons-external"></i>');
|
1327 |
-
break;
|
1328 |
-
}
|
1329 |
-
|
1330 |
-
},
|
1331 |
-
|
1332 |
-
/**
|
1333 |
-
* Update Page Count.
|
1334 |
-
*/
|
1335 |
-
_updatedPagedCount: function() {
|
1336 |
-
paged = parseInt(jQuery('body').attr('data-astra-demo-paged'));
|
1337 |
-
jQuery('body').attr('data-astra-demo-paged', paged + 1);
|
1338 |
-
window.setTimeout(function () {
|
1339 |
-
jQuery('body').data('scrolling', false);
|
1340 |
-
}, 800);
|
1341 |
-
},
|
1342 |
-
|
1343 |
-
/**
|
1344 |
-
* Reset Page Count.
|
1345 |
-
*/
|
1346 |
-
_resetPagedCount: function() {
|
1347 |
-
|
1348 |
-
$('body').addClass('loading-content');
|
1349 |
-
$('body').attr('data-astra-demo-last-request', '1');
|
1350 |
-
$('body').attr('data-astra-demo-paged', '1');
|
1351 |
-
$('body').attr('data-astra-demo-search', '');
|
1352 |
-
$('body').attr('data-scrolling', false);
|
1353 |
-
|
1354 |
-
},
|
1355 |
-
|
1356 |
-
/**
|
1357 |
-
* Remove plugin from the queue.
|
1358 |
-
*/
|
1359 |
-
_removePluginFromQueue: function( removeItem, pluginsList ) {
|
1360 |
-
return jQuery.grep(pluginsList, function( value ) {
|
1361 |
-
return value.slug != removeItem;
|
1362 |
-
});
|
1363 |
-
}
|
1364 |
-
|
1365 |
-
};
|
1366 |
-
|
1367 |
-
/**
|
1368 |
-
* Initialize AstraSitesAdmin
|
1369 |
-
*/
|
1370 |
-
$(function(){
|
1371 |
-
AstraSitesAdmin.init();
|
1372 |
-
});
|
1373 |
-
|
1374 |
ย
})(jQuery);
|
1 |
+
/**
|
2 |
+
* AJAX Request Queue
|
3 |
+
*
|
4 |
+
* - add()
|
5 |
+
* - remove()
|
6 |
+
* - run()
|
7 |
+
* - stop()
|
8 |
+
*
|
9 |
+
* @since 1.0.0
|
10 |
+
*/
|
11 |
+
var AstraSitesAjaxQueue = (function() {
|
12 |
+
|
13 |
+
var requests = [];
|
14 |
+
|
15 |
+
return {
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Add AJAX request
|
19 |
+
*
|
20 |
+
* @since 1.0.0
|
21 |
+
*/
|
22 |
+
add: function(opt) {
|
23 |
+
requests.push(opt);
|
24 |
+
},
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Remove AJAX request
|
28 |
+
*
|
29 |
+
* @since 1.0.0
|
30 |
+
*/
|
31 |
+
remove: function(opt) {
|
32 |
+
if( jQuery.inArray(opt, requests) > -1 )
|
33 |
+
requests.splice($.inArray(opt, requests), 1);
|
34 |
+
},
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Run / Process AJAX request
|
38 |
+
*
|
39 |
+
* @since 1.0.0
|
40 |
+
*/
|
41 |
+
run: function() {
|
42 |
+
var self = this,
|
43 |
+
oriSuc;
|
44 |
+
|
45 |
+
if( requests.length ) {
|
46 |
+
oriSuc = requests[0].complete;
|
47 |
+
|
48 |
+
requests[0].complete = function() {
|
49 |
+
if( typeof(oriSuc) === 'function' ) oriSuc();
|
50 |
+
requests.shift();
|
51 |
+
self.run.apply(self, []);
|
52 |
+
};
|
53 |
+
|
54 |
+
jQuery.ajax(requests[0]);
|
55 |
+
|
56 |
+
} else {
|
57 |
+
|
58 |
+
self.tid = setTimeout(function() {
|
59 |
+
self.run.apply(self, []);
|
60 |
+
}, 1000);
|
61 |
+
}
|
62 |
+
},
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Stop AJAX request
|
66 |
+
*
|
67 |
+
* @since 1.0.0
|
68 |
+
*/
|
69 |
+
stop: function() {
|
70 |
+
|
71 |
+
requests = [];
|
72 |
+
clearTimeout(this.tid);
|
73 |
+
}
|
74 |
+
};
|
75 |
+
|
76 |
+
}());
|
77 |
+
|
78 |
+
(function($){
|
79 |
+
|
80 |
+
var AstraSSEImport = {
|
81 |
+
complete: {
|
82 |
+
posts: 0,
|
83 |
+
media: 0,
|
84 |
+
users: 0,
|
85 |
+
comments: 0,
|
86 |
+
terms: 0,
|
87 |
+
},
|
88 |
+
|
89 |
+
updateDelta: function (type, delta) {
|
90 |
+
this.complete[ type ] += delta;
|
91 |
+
|
92 |
+
var self = this;
|
93 |
+
requestAnimationFrame(function () {
|
94 |
+
self.render();
|
95 |
+
});
|
96 |
+
},
|
97 |
+
updateProgress: function ( type, complete, total ) {
|
98 |
+
var text = complete + '/' + total;
|
99 |
+
|
100 |
+
if( 'undefined' !== type && 'undefined' !== text ) {
|
101 |
+
total = parseInt( total, 10 );
|
102 |
+
if ( 0 === total || isNaN( total ) ) {
|
103 |
+
total = 1;
|
104 |
+
}
|
105 |
+
var percent = parseInt( complete, 10 ) / total;
|
106 |
+
var progress = Math.round( percent * 100 ) + '%';
|
107 |
+
var progress_bar = percent * 100;
|
108 |
+
}
|
109 |
+
},
|
110 |
+
render: function () {
|
111 |
+
var types = Object.keys( this.complete );
|
112 |
+
var complete = 0;
|
113 |
+
var total = 0;
|
114 |
+
|
115 |
+
for (var i = types.length - 1; i >= 0; i--) {
|
116 |
+
var type = types[i];
|
117 |
+
this.updateProgress( type, this.complete[ type ], this.data.count[ type ] );
|
118 |
+
|
119 |
+
complete += this.complete[ type ];
|
120 |
+
total += this.data.count[ type ];
|
121 |
+
}
|
122 |
+
|
123 |
+
this.updateProgress( 'total', complete, total );
|
124 |
+
}
|
125 |
+
};
|
126 |
+
|
127 |
+
AstraSitesAdmin = {
|
128 |
+
|
129 |
+
log_file : '',
|
130 |
+
customizer_data : '',
|
131 |
+
wxr_url : '',
|
132 |
+
options_data : '',
|
133 |
+
widgets_data : '',
|
134 |
+
|
135 |
+
init: function()
|
136 |
+
{
|
137 |
+
this._resetPagedCount();
|
138 |
+
this._bind();
|
139 |
+
},
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Debugging.
|
143 |
+
*
|
144 |
+
* @param {mixed} data Mixed data.
|
145 |
+
*/
|
146 |
+
_log: function( data ) {
|
147 |
+
|
148 |
+
if( astraSitesAdmin.debug ) {
|
149 |
+
|
150 |
+
var date = new Date();
|
151 |
+
var time = date.toLocaleTimeString();
|
152 |
+
|
153 |
+
if (typeof data == 'object') {
|
154 |
+
console.log('%c ' + JSON.stringify( data ) + ' ' + time, 'background: #ededed; color: #444');
|
155 |
+
} else {
|
156 |
+
console.log('%c ' + data + ' ' + time, 'background: #ededed; color: #444');
|
157 |
+
}
|
158 |
+
|
159 |
+
|
160 |
+
}
|
161 |
+
},
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Binds events for the Astra Sites.
|
165 |
+
*
|
166 |
+
* @since 1.0.0
|
167 |
+
* @access private
|
168 |
+
* @method _bind
|
169 |
+
*/
|
170 |
+
_bind: function()
|
171 |
+
{
|
172 |
+
$( document ).on('click' , '.devices button', AstraSitesAdmin._previewDevice);
|
173 |
+
$( document ).on('click' , '.theme-browser .theme-screenshot, .theme-browser .more-details, .theme-browser .install-theme-preview', AstraSitesAdmin._preview);
|
174 |
+
$( document ).on('click' , '.next-theme', AstraSitesAdmin._nextTheme);
|
175 |
+
$( document ).on('click' , '.previous-theme', AstraSitesAdmin._previousTheme);
|
176 |
+
$( document ).on('click' , '.collapse-sidebar', AstraSitesAdmin._collapse);
|
177 |
+
$( document ).on('click' , '.astra-demo-import', AstraSitesAdmin._importDemo);
|
178 |
+
$( document ).on('click' , '.install-now', AstraSitesAdmin._installNow);
|
179 |
+
$( document ).on('click' , '.close-full-overlay', AstraSitesAdmin._fullOverlay);
|
180 |
+
$( document ).on('click' , '.activate-now', AstraSitesAdmin._activateNow);
|
181 |
+
$( document ).on('wp-plugin-installing' , AstraSitesAdmin._pluginInstalling);
|
182 |
+
$( document ).on('wp-plugin-install-error' , AstraSitesAdmin._installError);
|
183 |
+
$( document ).on('wp-plugin-install-success' , AstraSitesAdmin._installSuccess);
|
184 |
+
|
185 |
+
$( document ).on('astra-sites-import-set-site-data-done' , AstraSitesAdmin._importCustomizerSettings );
|
186 |
+
$( document ).on('astra-sites-import-customizer-settings-done' , AstraSitesAdmin._importPrepareXML );
|
187 |
+
$( document ).on('astra-sites-import-xml-done' , AstraSitesAdmin._importSiteOptions );
|
188 |
+
$( document ).on('astra-sites-import-options-done' , AstraSitesAdmin._importWidgets );
|
189 |
+
$( document ).on('astra-sites-import-widgets-done' , AstraSitesAdmin._importEnd );
|
190 |
+
},
|
191 |
+
|
192 |
+
/**
|
193 |
+
* 5. Import Complete.
|
194 |
+
*/
|
195 |
+
_importEnd: function( event ) {
|
196 |
+
|
197 |
+
$.ajax({
|
198 |
+
url : astraSitesAdmin.ajaxurl,
|
199 |
+
type : 'POST',
|
200 |
+
dataType: 'json',
|
201 |
+
data : {
|
202 |
+
action : 'astra-sites-import-end',
|
203 |
+
},
|
204 |
+
beforeSend: function() {
|
205 |
+
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importComplete );
|
206 |
+
}
|
207 |
+
})
|
208 |
+
.fail(function( jqXHR ){
|
209 |
+
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
210 |
+
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
211 |
+
})
|
212 |
+
.done(function ( data ) {
|
213 |
+
|
214 |
+
// 5. Fail - Import Complete.
|
215 |
+
if( false === data.success ) {
|
216 |
+
AstraSitesAdmin._importFailMessage( data.data );
|
217 |
+
AstraSitesAdmin._log( data.data );
|
218 |
+
} else {
|
219 |
+
|
220 |
+
$('body').removeClass('importing-site');
|
221 |
+
$('.previous-theme, .next-theme').removeClass('disabled');
|
222 |
+
|
223 |
+
// 5. Pass - Import Complete.
|
224 |
+
AstraSitesAdmin._importSuccessMessage();
|
225 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.success + ' ' + astraSitesAdmin.siteURL );
|
226 |
+
}
|
227 |
+
});
|
228 |
+
},
|
229 |
+
|
230 |
+
/**
|
231 |
+
* 4. Import Widgets.
|
232 |
+
*/
|
233 |
+
_importWidgets: function( event ) {
|
234 |
+
|
235 |
+
$.ajax({
|
236 |
+
url : astraSitesAdmin.ajaxurl,
|
237 |
+
type : 'POST',
|
238 |
+
dataType: 'json',
|
239 |
+
data : {
|
240 |
+
action : 'astra-sites-import-widgets',
|
241 |
+
widgets_data : AstraSitesAdmin.widgets_data,
|
242 |
+
},
|
243 |
+
beforeSend: function() {
|
244 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importWidgets );
|
245 |
+
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importingWidgets );
|
246 |
+
},
|
247 |
+
})
|
248 |
+
.fail(function( jqXHR ){
|
249 |
+
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
250 |
+
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
251 |
+
})
|
252 |
+
.done(function ( widgets_data ) {
|
253 |
+
|
254 |
+
// 4. Fail - Import Widgets.
|
255 |
+
if( false === widgets_data.success ) {
|
256 |
+
AstraSitesAdmin._importFailMessage( widgets_data.data );
|
257 |
+
AstraSitesAdmin._log( widgets_data.data );
|
258 |
+
|
259 |
+
} else {
|
260 |
+
|
261 |
+
// 4. Pass - Import Widgets.
|
262 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importWidgetsSuccess );
|
263 |
+
$(document).trigger( 'astra-sites-import-widgets-done' );
|
264 |
+
}
|
265 |
+
});
|
266 |
+
},
|
267 |
+
|
268 |
+
/**
|
269 |
+
* 3. Import Site Options.
|
270 |
+
*/
|
271 |
+
_importSiteOptions: function( event ) {
|
272 |
+
|
273 |
+
$.ajax({
|
274 |
+
url : astraSitesAdmin.ajaxurl,
|
275 |
+
type : 'POST',
|
276 |
+
dataType: 'json',
|
277 |
+
data : {
|
278 |
+
action : 'astra-sites-import-options',
|
279 |
+
options_data : AstraSitesAdmin.options_data,
|
280 |
+
},
|
281 |
+
beforeSend: function() {
|
282 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importOptions );
|
283 |
+
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importingOptions );
|
284 |
+
},
|
285 |
+
})
|
286 |
+
.fail(function( jqXHR ){
|
287 |
+
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
288 |
+
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
289 |
+
})
|
290 |
+
.done(function ( options_data ) {
|
291 |
+
|
292 |
+
// 3. Fail - Import Site Options.
|
293 |
+
if( false === options_data.success ) {
|
294 |
+
AstraSitesAdmin._log( options_data );
|
295 |
+
AstraSitesAdmin._importFailMessage( options_data.data );
|
296 |
+
AstraSitesAdmin._log( options_data.data );
|
297 |
+
|
298 |
+
} else {
|
299 |
+
|
300 |
+
// 3. Pass - Import Site Options.
|
301 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importOptionsSuccess );
|
302 |
+
$(document).trigger( 'astra-sites-import-options-done' );
|
303 |
+
}
|
304 |
+
});
|
305 |
+
},
|
306 |
+
|
307 |
+
/**
|
308 |
+
* 2. Prepare XML Data.
|
309 |
+
*/
|
310 |
+
_importPrepareXML: function( event ) {
|
311 |
+
|
312 |
+
$.ajax({
|
313 |
+
url : astraSitesAdmin.ajaxurl,
|
314 |
+
type : 'POST',
|
315 |
+
dataType: 'json',
|
316 |
+
data : {
|
317 |
+
action : 'astra-sites-import-prepare-xml',
|
318 |
+
wxr_url : AstraSitesAdmin.wxr_url,
|
319 |
+
},
|
320 |
+
beforeSend: function() {
|
321 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importXMLPrepare );
|
322 |
+
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importXMLPreparing );
|
323 |
+
},
|
324 |
+
})
|
325 |
+
.fail(function( jqXHR ){
|
326 |
+
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
327 |
+
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
328 |
+
})
|
329 |
+
.done(function ( xml_data ) {
|
330 |
+
|
331 |
+
// 2. Fail - Prepare XML Data.
|
332 |
+
if( false === xml_data.success ) {
|
333 |
+
AstraSitesAdmin._log( xml_data );
|
334 |
+
AstraSitesAdmin._importFailMessage( xml_data.data );
|
335 |
+
AstraSitesAdmin._log( xml_data.data );
|
336 |
+
|
337 |
+
} else {
|
338 |
+
|
339 |
+
// 2. Pass - Prepare XML Data.
|
340 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importXMLPrepareSuccess );
|
341 |
+
|
342 |
+
// Import XML though Event Source.
|
343 |
+
AstraSSEImport.data = xml_data.data;
|
344 |
+
AstraSSEImport.render();
|
345 |
+
|
346 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importXML );
|
347 |
+
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importingXML );
|
348 |
+
|
349 |
+
var evtSource = new EventSource( AstraSSEImport.data.url );
|
350 |
+
evtSource.onmessage = function ( message ) {
|
351 |
+
var data = JSON.parse( message.data );
|
352 |
+
switch ( data.action ) {
|
353 |
+
case 'updateDelta':
|
354 |
+
AstraSSEImport.updateDelta( data.type, data.delta );
|
355 |
+
break;
|
356 |
+
|
357 |
+
case 'complete':
|
358 |
+
evtSource.close();
|
359 |
+
|
360 |
+
// 2. Pass - Import XML though "Source Event".
|
361 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importXMLSuccess );
|
362 |
+
AstraSitesAdmin._log( '----- SSE - XML import Complete -----' );
|
363 |
+
|
364 |
+
$(document).trigger( 'astra-sites-import-xml-done' );
|
365 |
+
|
366 |
+
break;
|
367 |
+
}
|
368 |
+
};
|
369 |
+
evtSource.addEventListener( 'log', function ( message ) {
|
370 |
+
var data = JSON.parse( message.data );
|
371 |
+
AstraSitesAdmin._log( data.level + ' ' + data.message );
|
372 |
+
});
|
373 |
+
}
|
374 |
+
});
|
375 |
+
},
|
376 |
+
|
377 |
+
/**
|
378 |
+
* 1. Import Customizer Options.
|
379 |
+
*/
|
380 |
+
_importCustomizerSettings: function( event ) {
|
381 |
+
|
382 |
+
$.ajax({
|
383 |
+
url : astraSitesAdmin.ajaxurl,
|
384 |
+
type : 'POST',
|
385 |
+
dataType: 'json',
|
386 |
+
data : {
|
387 |
+
action : 'astra-sites-import-customizer-settings',
|
388 |
+
customizer_data : AstraSitesAdmin.customizer_data,
|
389 |
+
},
|
390 |
+
beforeSend: function() {
|
391 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importCustomizer );
|
392 |
+
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.importingCustomizer );
|
393 |
+
},
|
394 |
+
})
|
395 |
+
.fail(function( jqXHR ){
|
396 |
+
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
397 |
+
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
398 |
+
})
|
399 |
+
.done(function ( customizer_data ) {
|
400 |
+
|
401 |
+
// 1. Fail - Import Customizer Options.
|
402 |
+
if( false === customizer_data.success ) {
|
403 |
+
AstraSitesAdmin._importFailMessage( customizer_data.data );
|
404 |
+
AstraSitesAdmin._log( customizer_data.data );
|
405 |
+
} else {
|
406 |
+
|
407 |
+
// 1. Pass - Import Customizer Options.
|
408 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importCustomizerSuccess );
|
409 |
+
|
410 |
+
$(document).trigger( 'astra-sites-import-customizer-settings-done' );
|
411 |
+
}
|
412 |
+
});
|
413 |
+
},
|
414 |
+
|
415 |
+
/**
|
416 |
+
* Import Success Button.
|
417 |
+
*
|
418 |
+
* @param {string} data Error message.
|
419 |
+
*/
|
420 |
+
_importSuccessMessage: function() {
|
421 |
+
|
422 |
+
$('.astra-demo-import').removeClass('updating-message installing')
|
423 |
+
.removeAttr('data-import')
|
424 |
+
.addClass('view-site')
|
425 |
+
.removeClass('astra-demo-import')
|
426 |
+
.text( astraSitesAdmin.strings.viewSite )
|
427 |
+
.attr('target', '_blank')
|
428 |
+
.append('<i class="dashicons dashicons-external"></i>')
|
429 |
+
.attr('href', astraSitesAdmin.siteURL );
|
430 |
+
},
|
431 |
+
|
432 |
+
/**
|
433 |
+
* Preview Device
|
434 |
+
*/
|
435 |
+
_previewDevice: function( event ) {
|
436 |
+
var device = $( event.currentTarget ).data( 'device' );
|
437 |
+
|
438 |
+
$('.theme-install-overlay')
|
439 |
+
.removeClass( 'preview-desktop preview-tablet preview-mobile' )
|
440 |
+
.addClass( 'preview-' + device )
|
441 |
+
.data( 'current-preview-device', device );
|
442 |
+
|
443 |
+
AstraSitesAdmin._tooglePreviewDeviceButtons( device );
|
444 |
+
},
|
445 |
+
|
446 |
+
/**
|
447 |
+
* Toggle Preview Buttons
|
448 |
+
*/
|
449 |
+
_tooglePreviewDeviceButtons: function( newDevice ) {
|
450 |
+
var $devices = $( '.wp-full-overlay-footer .devices' );
|
451 |
+
|
452 |
+
$devices.find( 'button' )
|
453 |
+
.removeClass( 'active' )
|
454 |
+
.attr( 'aria-pressed', false );
|
455 |
+
|
456 |
+
$devices.find( 'button.preview-' + newDevice )
|
457 |
+
.addClass( 'active' )
|
458 |
+
.attr( 'aria-pressed', true );
|
459 |
+
},
|
460 |
+
|
461 |
+
/**
|
462 |
+
* Import Error Button.
|
463 |
+
*
|
464 |
+
* @param {string} data Error message.
|
465 |
+
*/
|
466 |
+
_importFailMessage: function( message, from ) {
|
467 |
+
|
468 |
+
$('.astra-demo-import')
|
469 |
+
.addClass('go-pro button-primary')
|
470 |
+
.removeClass('updating-message installing')
|
471 |
+
.removeAttr('data-import')
|
472 |
+
.attr('target', '_blank')
|
473 |
+
.append('<i class="dashicons dashicons-external"></i>')
|
474 |
+
.removeClass('astra-demo-import');
|
475 |
+
|
476 |
+
// Add the doc link due to import log file not generated.
|
477 |
+
if( 'undefined' === from ) {
|
478 |
+
|
479 |
+
$('.wp-full-overlay-header .go-pro').text( astraSitesAdmin.strings.importFailedBtnSmall );
|
480 |
+
$('.wp-full-overlay-footer .go-pro').text( astraSitesAdmin.strings.importFailedBtnLarge );
|
481 |
+
$('.go-pro').attr('href', astraSitesAdmin.log.serverConfiguration );
|
482 |
+
|
483 |
+
// Add the import log file link.
|
484 |
+
} else {
|
485 |
+
|
486 |
+
$('.wp-full-overlay-header .go-pro').text( astraSitesAdmin.strings.importFailBtn );
|
487 |
+
$('.wp-full-overlay-footer .go-pro').text( astraSitesAdmin.strings.importFailBtnLarge )
|
488 |
+
|
489 |
+
// Add the import log file link.
|
490 |
+
if( 'undefined' !== AstraSitesAdmin.log_file_url ) {
|
491 |
+
$('.go-pro').attr('href', AstraSitesAdmin.log_file_url );
|
492 |
+
} else {
|
493 |
+
$('.go-pro').attr('href', astraSitesAdmin.log.serverConfiguration );
|
494 |
+
}
|
495 |
+
}
|
496 |
+
|
497 |
+
var output = '<div class="astra-api-error notice notice-error notice-alt is-dismissible">';
|
498 |
+
output += ' <p>'+message+'</p>';
|
499 |
+
output += ' <button type="button" class="notice-dismiss">';
|
500 |
+
output += ' <span class="screen-reader-text">'+commonL10n.dismiss+'</span>';
|
501 |
+
output += ' </button>';
|
502 |
+
output += '</div>';
|
503 |
+
|
504 |
+
// Fail Notice.
|
505 |
+
$('.install-theme-info').append( output );
|
506 |
+
|
507 |
+
|
508 |
+
// !important to add trigger.
|
509 |
+
// Which reinitialize the dismiss error message events.
|
510 |
+
$(document).trigger('wp-updates-notice-added');
|
511 |
+
},
|
512 |
+
|
513 |
+
|
514 |
+
/**
|
515 |
+
* Install Now
|
516 |
+
*/
|
517 |
+
_installNow: function(event)
|
518 |
+
{
|
519 |
+
event.preventDefault();
|
520 |
+
|
521 |
+
var $button = jQuery( event.target ),
|
522 |
+
$document = jQuery(document);
|
523 |
+
|
524 |
+
if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) {
|
525 |
+
return;
|
526 |
+
}
|
527 |
+
|
528 |
+
if ( wp.updates.shouldRequestFilesystemCredentials && ! wp.updates.ajaxLocked ) {
|
529 |
+
wp.updates.requestFilesystemCredentials( event );
|
530 |
+
|
531 |
+
$document.on( 'credential-modal-cancel', function() {
|
532 |
+
var $message = $( '.install-now.updating-message' );
|
533 |
+
|
534 |
+
$message
|
535 |
+
.removeClass( 'updating-message' )
|
536 |
+
.text( wp.updates.l10n.installNow );
|
537 |
+
|
538 |
+
wp.a11y.speak( wp.updates.l10n.updateCancel, 'polite' );
|
539 |
+
} );
|
540 |
+
}
|
541 |
+
|
542 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.installingPlugin + ' ' + $button.data( 'slug' ) );
|
543 |
+
|
544 |
+
wp.updates.installPlugin( {
|
545 |
+
slug: $button.data( 'slug' )
|
546 |
+
} );
|
547 |
+
},
|
548 |
+
|
549 |
+
/**
|
550 |
+
* Install Success
|
551 |
+
*/
|
552 |
+
_installSuccess: function( event, response ) {
|
553 |
+
|
554 |
+
event.preventDefault();
|
555 |
+
|
556 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.installed + ' ' + response.slug );
|
557 |
+
|
558 |
+
var $message = jQuery( '.plugin-card-' + response.slug ).find( '.button' );
|
559 |
+
var $siteOptions = jQuery( '.wp-full-overlay-header').find('.astra-site-options').val();
|
560 |
+
var $enabledExtensions = jQuery( '.wp-full-overlay-header').find('.astra-enabled-extensions').val();
|
561 |
+
|
562 |
+
// Transform the 'Install' button into an 'Activate' button.
|
563 |
+
var $init = $message.data('init');
|
564 |
+
|
565 |
+
$message.removeClass( 'install-now installed button-disabled updated-message' )
|
566 |
+
.addClass('updating-message')
|
567 |
+
.html( astraSitesAdmin.strings.btnActivating );
|
568 |
+
|
569 |
+
// Reset not installed plugins list.
|
570 |
+
var pluginsList = astraSitesAdmin.requiredPlugins.notinstalled;
|
571 |
+
astraSitesAdmin.requiredPlugins.notinstalled = AstraSitesAdmin._removePluginFromQueue( response.slug, pluginsList );
|
572 |
+
|
573 |
+
// WordPress adds "Activate" button after waiting for 1000ms. So we will run our activation after that.
|
574 |
+
setTimeout( function() {
|
575 |
+
|
576 |
+
$.ajax({
|
577 |
+
url: astraSitesAdmin.ajaxurl,
|
578 |
+
type: 'POST',
|
579 |
+
data: {
|
580 |
+
'action' : 'astra-required-plugin-activate',
|
581 |
+
'init' : $init,
|
582 |
+
'options' : $siteOptions,
|
583 |
+
'enabledExtensions' : $enabledExtensions,
|
584 |
+
},
|
585 |
+
})
|
586 |
+
.done(function (result) {
|
587 |
+
|
588 |
+
if( result.success ) {
|
589 |
+
|
590 |
+
var pluginsList = astraSitesAdmin.requiredPlugins.inactive;
|
591 |
+
|
592 |
+
// Reset not installed plugins list.
|
593 |
+
astraSitesAdmin.requiredPlugins.inactive = AstraSitesAdmin._removePluginFromQueue( response.slug, pluginsList );
|
594 |
+
|
595 |
+
$message.removeClass( 'button-primary install-now activate-now updating-message' )
|
596 |
+
.attr('disabled', 'disabled')
|
597 |
+
.addClass('disabled')
|
598 |
+
.text( astraSitesAdmin.strings.btnActive );
|
599 |
+
|
600 |
+
// Enable Demo Import Button
|
601 |
+
AstraSitesAdmin._enable_demo_import_button();
|
602 |
+
|
603 |
+
} else {
|
604 |
+
|
605 |
+
$message.removeClass( 'updating-message' );
|
606 |
+
|
607 |
+
}
|
608 |
+
|
609 |
+
});
|
610 |
+
|
611 |
+
}, 1200 );
|
612 |
+
|
613 |
+
},
|
614 |
+
|
615 |
+
/**
|
616 |
+
* Plugin Installation Error.
|
617 |
+
*/
|
618 |
+
_installError: function( event, response ) {
|
619 |
+
|
620 |
+
var $card = jQuery( '.plugin-card-' + response.slug );
|
621 |
+
|
622 |
+
AstraSitesAdmin._log( response.errorMessage + ' ' + response.slug );
|
623 |
+
|
624 |
+
$card
|
625 |
+
.removeClass( 'button-primary' )
|
626 |
+
.addClass( 'disabled' )
|
627 |
+
.html( wp.updates.l10n.installFailedShort );
|
628 |
+
|
629 |
+
AstraSitesAdmin._importFailMessage( response.errorMessage );
|
630 |
+
},
|
631 |
+
|
632 |
+
/**
|
633 |
+
* Installing Plugin
|
634 |
+
*/
|
635 |
+
_pluginInstalling: function(event, args) {
|
636 |
+
event.preventDefault();
|
637 |
+
|
638 |
+
var $card = jQuery( '.plugin-card-' + args.slug );
|
639 |
+
var $button = $card.find( '.button' );
|
640 |
+
|
641 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.installingPlugin + ' ' + args.slug );
|
642 |
+
|
643 |
+
$card.addClass('updating-message');
|
644 |
+
$button.addClass('already-started');
|
645 |
+
|
646 |
+
},
|
647 |
+
|
648 |
+
/**
|
649 |
+
* Render Demo Preview
|
650 |
+
*/
|
651 |
+
_activateNow: function( eventn ) {
|
652 |
+
|
653 |
+
event.preventDefault();
|
654 |
+
|
655 |
+
var $button = jQuery( event.target ),
|
656 |
+
$init = $button.data( 'init' ),
|
657 |
+
$slug = $button.data( 'slug' );
|
658 |
+
|
659 |
+
if ( $button.hasClass( 'updating-message' ) || $button.hasClass( 'button-disabled' ) ) {
|
660 |
+
return;
|
661 |
+
}
|
662 |
+
|
663 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.activating + ' ' + $slug );
|
664 |
+
|
665 |
+
$button.addClass('updating-message button-primary')
|
666 |
+
.html( astraSitesAdmin.strings.btnActivating );
|
667 |
+
|
668 |
+
var $siteOptions = jQuery( '.wp-full-overlay-header').find('.astra-site-options').val();
|
669 |
+
var $enabledExtensions = jQuery( '.wp-full-overlay-header').find('.astra-enabled-extensions').val();
|
670 |
+
|
671 |
+
$.ajax({
|
672 |
+
url: astraSitesAdmin.ajaxurl,
|
673 |
+
type: 'POST',
|
674 |
+
data: {
|
675 |
+
'action' : 'astra-required-plugin-activate',
|
676 |
+
'init' : $init,
|
677 |
+
'options' : $siteOptions,
|
678 |
+
'enabledExtensions' : $enabledExtensions,
|
679 |
+
},
|
680 |
+
})
|
681 |
+
.done(function (result) {
|
682 |
+
|
683 |
+
if( result.success ) {
|
684 |
+
|
685 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.activated + ' ' + $slug );
|
686 |
+
|
687 |
+
var pluginsList = astraSitesAdmin.requiredPlugins.inactive;
|
688 |
+
|
689 |
+
// Reset not installed plugins list.
|
690 |
+
astraSitesAdmin.requiredPlugins.inactive = AstraSitesAdmin._removePluginFromQueue( $slug, pluginsList );
|
691 |
+
|
692 |
+
$button.removeClass( 'button-primary install-now activate-now updating-message' )
|
693 |
+
.attr('disabled', 'disabled')
|
694 |
+
.addClass('disabled')
|
695 |
+
.text( astraSitesAdmin.strings.btnActive );
|
696 |
+
|
697 |
+
// Enable Demo Import Button
|
698 |
+
AstraSitesAdmin._enable_demo_import_button();
|
699 |
+
|
700 |
+
}
|
701 |
+
|
702 |
+
})
|
703 |
+
.fail(function () {
|
704 |
+
});
|
705 |
+
|
706 |
+
},
|
707 |
+
|
708 |
+
/**
|
709 |
+
* Full Overlay
|
710 |
+
*/
|
711 |
+
_fullOverlay: function (event) {
|
712 |
+
event.preventDefault();
|
713 |
+
|
714 |
+
// Import process is started?
|
715 |
+
// And Closing the window? Then showing the warning confirm message.
|
716 |
+
if( $('body').hasClass('importing-site') && ! confirm( astraSitesAdmin.strings.warningBeforeCloseWindow ) ) {
|
717 |
+
return;
|
718 |
+
}
|
719 |
+
|
720 |
+
$('body').removeClass('importing-site');
|
721 |
+
$('.previous-theme, .next-theme').removeClass('disabled');
|
722 |
+
$('.theme-install-overlay').css('display', 'none');
|
723 |
+
$('.theme-install-overlay').remove();
|
724 |
+
$('.theme-preview-on').removeClass('theme-preview-on');
|
725 |
+
$('html').removeClass('astra-site-preview-on');
|
726 |
+
},
|
727 |
+
|
728 |
+
/**
|
729 |
+
* Bulk Plugin Active & Install
|
730 |
+
*/
|
731 |
+
_bulkPluginInstallActivate: function()
|
732 |
+
{
|
733 |
+
if( 0 === astraSitesAdmin.requiredPlugins.length ) {
|
734 |
+
return;
|
735 |
+
}
|
736 |
+
|
737 |
+
jQuery('.required-plugins')
|
738 |
+
.find('.install-now')
|
739 |
+
.addClass( 'updating-message' )
|
740 |
+
.removeClass( 'install-now' )
|
741 |
+
.text( wp.updates.l10n.installing );
|
742 |
+
|
743 |
+
jQuery('.required-plugins')
|
744 |
+
.find('.activate-now')
|
745 |
+
.addClass('updating-message')
|
746 |
+
.removeClass( 'activate-now' )
|
747 |
+
.html( astraSitesAdmin.strings.btnActivating );
|
748 |
+
|
749 |
+
var not_installed = astraSitesAdmin.requiredPlugins.notinstalled || '';
|
750 |
+
var activate_plugins = astraSitesAdmin.requiredPlugins.inactive || '';
|
751 |
+
|
752 |
+
// First Install Bulk.
|
753 |
+
if( not_installed.length > 0 ) {
|
754 |
+
AstraSitesAdmin._installAllPlugins( not_installed );
|
755 |
+
}
|
756 |
+
|
757 |
+
// Second Activate Bulk.
|
758 |
+
if( activate_plugins.length > 0 ) {
|
759 |
+
AstraSitesAdmin._activateAllPlugins( activate_plugins );
|
760 |
+
}
|
761 |
+
|
762 |
+
},
|
763 |
+
|
764 |
+
/**
|
765 |
+
* Activate All Plugins.
|
766 |
+
*/
|
767 |
+
_activateAllPlugins: function( activate_plugins ) {
|
768 |
+
|
769 |
+
// Activate ALl Plugins.
|
770 |
+
AstraSitesAjaxQueue.stop();
|
771 |
+
AstraSitesAjaxQueue.run();
|
772 |
+
|
773 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.bulkActivation );
|
774 |
+
|
775 |
+
$.each( activate_plugins, function(index, single_plugin) {
|
776 |
+
|
777 |
+
var $card = jQuery( '.plugin-card-' + single_plugin.slug ),
|
778 |
+
$button = $card.find('.button'),
|
779 |
+
$siteOptions = jQuery( '.wp-full-overlay-header').find('.astra-site-options').val(),
|
780 |
+
$enabledExtensions = jQuery( '.wp-full-overlay-header').find('.astra-enabled-extensions').val();
|
781 |
+
|
782 |
+
$button.addClass('updating-message');
|
783 |
+
|
784 |
+
AstraSitesAjaxQueue.add({
|
785 |
+
url: astraSitesAdmin.ajaxurl,
|
786 |
+
type: 'POST',
|
787 |
+
data: {
|
788 |
+
'action' : 'astra-required-plugin-activate',
|
789 |
+
'init' : single_plugin.init,
|
790 |
+
'options' : $siteOptions,
|
791 |
+
'enabledExtensions' : $enabledExtensions,
|
792 |
+
},
|
793 |
+
success: function( result ){
|
794 |
+
|
795 |
+
if( result.success ) {
|
796 |
+
|
797 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.activate + ' ' + single_plugin.slug );
|
798 |
+
|
799 |
+
var $card = jQuery( '.plugin-card-' + single_plugin.slug );
|
800 |
+
var $button = $card.find( '.button' );
|
801 |
+
if( ! $button.hasClass('already-started') ) {
|
802 |
+
var pluginsList = astraSitesAdmin.requiredPlugins.inactive;
|
803 |
+
|
804 |
+
// Reset not installed plugins list.
|
805 |
+
astraSitesAdmin.requiredPlugins.inactive = AstraSitesAdmin._removePluginFromQueue( single_plugin.slug, pluginsList );
|
806 |
+
}
|
807 |
+
|
808 |
+
$button.removeClass( 'button-primary install-now activate-now updating-message' )
|
809 |
+
.attr('disabled', 'disabled')
|
810 |
+
.addClass('disabled')
|
811 |
+
.text( astraSitesAdmin.strings.btnActive );
|
812 |
+
|
813 |
+
// Enable Demo Import Button
|
814 |
+
AstraSitesAdmin._enable_demo_import_button();
|
815 |
+
} else {
|
816 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.activationError + ' - ' + single_plugin.slug );
|
817 |
+
}
|
818 |
+
}
|
819 |
+
});
|
820 |
+
});
|
821 |
+
},
|
822 |
+
|
823 |
+
/**
|
824 |
+
* Install All Plugins.
|
825 |
+
*/
|
826 |
+
_installAllPlugins: function( not_installed ) {
|
827 |
+
|
828 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.bulkInstall );
|
829 |
+
|
830 |
+
$.each( not_installed, function(index, single_plugin) {
|
831 |
+
|
832 |
+
var $card = jQuery( '.plugin-card-' + single_plugin.slug ),
|
833 |
+
$button = $card.find('.button');
|
834 |
+
|
835 |
+
if( ! $button.hasClass('already-started') ) {
|
836 |
+
|
837 |
+
// Add each plugin activate request in Ajax queue.
|
838 |
+
// @see wp-admin/js/updates.js
|
839 |
+
wp.updates.queue.push( {
|
840 |
+
action: 'install-plugin', // Required action.
|
841 |
+
data: {
|
842 |
+
slug: single_plugin.slug
|
843 |
+
}
|
844 |
+
} );
|
845 |
+
}
|
846 |
+
});
|
847 |
+
|
848 |
+
// Required to set queue.
|
849 |
+
wp.updates.queueChecker();
|
850 |
+
},
|
851 |
+
|
852 |
+
/**
|
853 |
+
* Fires when a nav item is clicked.
|
854 |
+
*
|
855 |
+
* @since 1.0
|
856 |
+
* @access private
|
857 |
+
* @method _importDemo
|
858 |
+
*/
|
859 |
+
_importDemo: function()
|
860 |
+
{
|
861 |
+
var $this = jQuery(this),
|
862 |
+
$theme = $this.closest('.astra-sites-preview').find('.wp-full-overlay-header'),
|
863 |
+
apiURL = $theme.data('demo-api') || '',
|
864 |
+
plugins = $theme.data('required-plugins');
|
865 |
+
|
866 |
+
var disabled = $this.attr('data-import');
|
867 |
+
|
868 |
+
if ( typeof disabled !== 'undefined' && disabled === 'disabled' || $this.hasClass('disabled') ) {
|
869 |
+
|
870 |
+
$('.astra-demo-import').addClass('updating-message installing')
|
871 |
+
.text( wp.updates.l10n.installing );
|
872 |
+
|
873 |
+
/**
|
874 |
+
* Process Bulk Plugin Install & Activate
|
875 |
+
*/
|
876 |
+
AstraSitesAdmin._bulkPluginInstallActivate();
|
877 |
+
|
878 |
+
return;
|
879 |
+
}
|
880 |
+
|
881 |
+
// Proceed?
|
882 |
+
if( ! confirm( astraSitesAdmin.strings.importWarning ) ) {
|
883 |
+
return;
|
884 |
+
}
|
885 |
+
|
886 |
+
$('body').addClass('importing-site');
|
887 |
+
$('.previous-theme, .next-theme').addClass('disabled');
|
888 |
+
|
889 |
+
// Remove all notices before import start.
|
890 |
+
$('.install-theme-info > .notice').remove();
|
891 |
+
|
892 |
+
$('.astra-demo-import').attr('data-import', 'disabled')
|
893 |
+
.addClass('updating-message installing')
|
894 |
+
.text( astraSitesAdmin.strings.importingDemo );
|
895 |
+
|
896 |
+
$this.closest('.theme').focus();
|
897 |
+
|
898 |
+
var $theme = $this.closest('.astra-sites-preview').find('.wp-full-overlay-header');
|
899 |
+
|
900 |
+
var apiURL = $theme.data('demo-api') || '';
|
901 |
+
|
902 |
+
// Site Import by API URL.
|
903 |
+
if( apiURL ) {
|
904 |
+
AstraSitesAdmin._importSite( apiURL );
|
905 |
+
}
|
906 |
+
|
907 |
+
},
|
908 |
+
|
909 |
+
/**
|
910 |
+
* Start Import Process by API URL.
|
911 |
+
*
|
912 |
+
* @param {string} apiURL Site API URL.
|
913 |
+
*/
|
914 |
+
_importSite: function( apiURL ) {
|
915 |
+
|
916 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.api + ' : ' + apiURL );
|
917 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.importing );
|
918 |
+
|
919 |
+
$('.button-hero.astra-demo-import').text( astraSitesAdmin.log.gettingData );
|
920 |
+
|
921 |
+
// 1. Request Site Import
|
922 |
+
$.ajax({
|
923 |
+
url : astraSitesAdmin.ajaxurl,
|
924 |
+
type : 'POST',
|
925 |
+
dataType: 'json',
|
926 |
+
data : {
|
927 |
+
'action' : 'astra-sites-import-set-site-data',
|
928 |
+
'api_url' : apiURL,
|
929 |
+
},
|
930 |
+
})
|
931 |
+
.fail(function( jqXHR ){
|
932 |
+
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText );
|
933 |
+
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
934 |
+
})
|
935 |
+
.done(function ( demo_data ) {
|
936 |
+
|
937 |
+
// 1. Fail - Request Site Import
|
938 |
+
if( false === demo_data.success ) {
|
939 |
+
|
940 |
+
AstraSitesAdmin._importFailMessage( demo_data.data );
|
941 |
+
|
942 |
+
} else {
|
943 |
+
|
944 |
+
// Set log file URL.
|
945 |
+
if( 'log_file' in demo_data.data ){
|
946 |
+
AstraSitesAdmin.log_file_url = decodeURIComponent( demo_data.data.log_file ) || '';
|
947 |
+
}
|
948 |
+
|
949 |
+
// 1. Pass - Request Site Import
|
950 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.processingRequest );
|
951 |
+
|
952 |
+
AstraSitesAdmin.customizer_data = JSON.stringify( demo_data.data['astra-site-customizer-data'] ) || '';
|
953 |
+
AstraSitesAdmin.wxr_url = encodeURI( demo_data.data['astra-site-wxr-path'] ) || '';
|
954 |
+
AstraSitesAdmin.options_data = JSON.stringify( demo_data.data['astra-site-options-data'] ) || '';
|
955 |
+
AstraSitesAdmin.widgets_data = JSON.stringify( demo_data.data['astra-site-widgets-data'] ) || '';
|
956 |
+
|
957 |
+
$(document).trigger( 'astra-sites-import-set-site-data-done' );
|
958 |
+
}
|
959 |
+
|
960 |
+
});
|
961 |
+
|
962 |
+
},
|
963 |
+
|
964 |
+
/**
|
965 |
+
* Collapse Sidebar.
|
966 |
+
*/
|
967 |
+
_collapse: function() {
|
968 |
+
event.preventDefault();
|
969 |
+
|
970 |
+
overlay = jQuery('.wp-full-overlay');
|
971 |
+
|
972 |
+
if (overlay.hasClass('expanded')) {
|
973 |
+
overlay.removeClass('expanded');
|
974 |
+
overlay.addClass('collapsed');
|
975 |
+
return;
|
976 |
+
}
|
977 |
+
|
978 |
+
if (overlay.hasClass('collapsed')) {
|
979 |
+
overlay.removeClass('collapsed');
|
980 |
+
overlay.addClass('expanded');
|
981 |
+
return;
|
982 |
+
}
|
983 |
+
},
|
984 |
+
|
985 |
+
/**
|
986 |
+
* Previous Theme.
|
987 |
+
*/
|
988 |
+
_previousTheme: function (event) {
|
989 |
+
event.preventDefault();
|
990 |
+
|
991 |
+
currentDemo = jQuery('.theme-preview-on');
|
992 |
+
currentDemo.removeClass('theme-preview-on');
|
993 |
+
prevDemo = currentDemo.prev('.theme');
|
994 |
+
prevDemo.addClass('theme-preview-on');
|
995 |
+
|
996 |
+
AstraSitesAdmin._renderDemoPreview(prevDemo);
|
997 |
+
},
|
998 |
+
|
999 |
+
/**
|
1000 |
+
* Next Theme.
|
1001 |
+
*/
|
1002 |
+
_nextTheme: function (event) {
|
1003 |
+
event.preventDefault();
|
1004 |
+
currentDemo = jQuery('.theme-preview-on')
|
1005 |
+
currentDemo.removeClass('theme-preview-on');
|
1006 |
+
nextDemo = currentDemo.next('.theme');
|
1007 |
+
nextDemo.addClass('theme-preview-on');
|
1008 |
+
|
1009 |
+
AstraSitesAdmin._renderDemoPreview( nextDemo );
|
1010 |
+
},
|
1011 |
+
|
1012 |
+
/**
|
1013 |
+
* Individual Site Preview
|
1014 |
+
*
|
1015 |
+
* On click on image, more link & preview button.
|
1016 |
+
*/
|
1017 |
+
_preview: function( event ) {
|
1018 |
+
|
1019 |
+
event.preventDefault();
|
1020 |
+
|
1021 |
+
var self = jQuery(this).parents('.theme');
|
1022 |
+
self.addClass('theme-preview-on');
|
1023 |
+
|
1024 |
+
jQuery('html').addClass('astra-site-preview-on');
|
1025 |
+
|
1026 |
+
AstraSitesAdmin._renderDemoPreview( self );
|
1027 |
+
},
|
1028 |
+
|
1029 |
+
/**
|
1030 |
+
* Check Next Previous Buttons.
|
1031 |
+
*/
|
1032 |
+
_checkNextPrevButtons: function() {
|
1033 |
+
currentDemo = jQuery('.theme-preview-on');
|
1034 |
+
nextDemo = currentDemo.nextAll('.theme').length;
|
1035 |
+
prevDemo = currentDemo.prevAll('.theme').length;
|
1036 |
+
|
1037 |
+
if (nextDemo == 0) {
|
1038 |
+
jQuery('.next-theme').addClass('disabled');
|
1039 |
+
} else if (nextDemo != 0) {
|
1040 |
+
jQuery('.next-theme').removeClass('disabled');
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
if (prevDemo == 0) {
|
1044 |
+
jQuery('.previous-theme').addClass('disabled');
|
1045 |
+
} else if (prevDemo != 0) {
|
1046 |
+
jQuery('.previous-theme').removeClass('disabled');
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
return;
|
1050 |
+
},
|
1051 |
+
|
1052 |
+
/**
|
1053 |
+
* Render Demo Preview
|
1054 |
+
*/
|
1055 |
+
_renderDemoPreview: function(anchor) {
|
1056 |
+
|
1057 |
+
var demoId = anchor.data('id') || '',
|
1058 |
+
apiURL = anchor.data('demo-api') || '',
|
1059 |
+
demoType = anchor.data('demo-type') || '',
|
1060 |
+
demoURL = anchor.data('demo-url') || '',
|
1061 |
+
screenshot = anchor.data('screenshot') || '',
|
1062 |
+
demo_name = anchor.data('demo-name') || '',
|
1063 |
+
demo_slug = anchor.data('demo-slug') || '',
|
1064 |
+
content = anchor.data('content') || '',
|
1065 |
+
requiredPlugins = anchor.data('required-plugins') || '',
|
1066 |
+
astraSiteOptions = anchor.find('.astra-site-options').val() || '';
|
1067 |
+
astraEnabledExtensions = anchor.find('.astra-enabled-extensions').val() || '';
|
1068 |
+
|
1069 |
+
AstraSitesAdmin._log( astraSitesAdmin.log.preview + ' "' + demo_name + '" URL : ' + demoURL );
|
1070 |
+
|
1071 |
+
var template = wp.template('astra-site-preview');
|
1072 |
+
|
1073 |
+
templateData = [{
|
1074 |
+
id : demoId,
|
1075 |
+
astra_demo_type : demoType,
|
1076 |
+
astra_demo_url : demoURL,
|
1077 |
+
demo_api : apiURL,
|
1078 |
+
screenshot : screenshot,
|
1079 |
+
demo_name : demo_name,
|
1080 |
+
slug : demo_slug,
|
1081 |
+
content : content,
|
1082 |
+
required_plugins : JSON.stringify(requiredPlugins),
|
1083 |
+
astra_site_options : astraSiteOptions,
|
1084 |
+
astra_enabled_extensions : astraEnabledExtensions,
|
1085 |
+
}];
|
1086 |
+
|
1087 |
+
// delete any earlier fullscreen preview before we render new one.
|
1088 |
+
jQuery('.theme-install-overlay').remove();
|
1089 |
+
|
1090 |
+
jQuery('#astra-sites-menu-page').append(template(templateData[0]));
|
1091 |
+
jQuery('.theme-install-overlay').css('display', 'block');
|
1092 |
+
AstraSitesAdmin._checkNextPrevButtons();
|
1093 |
+
|
1094 |
+
var desc = jQuery('.theme-details');
|
1095 |
+
var descHeight = parseInt( desc.outerHeight() );
|
1096 |
+
var descBtn = jQuery('.theme-details-read-more');
|
1097 |
+
|
1098 |
+
if( $.isArray( requiredPlugins ) ) {
|
1099 |
+
|
1100 |
+
if( descHeight >= 55 ) {
|
1101 |
+
|
1102 |
+
// Show button.
|
1103 |
+
descBtn.css( 'display', 'inline-block' );
|
1104 |
+
|
1105 |
+
// Set height upto 3 line.
|
1106 |
+
desc.css( 'height', 57 );
|
1107 |
+
|
1108 |
+
// Button Click.
|
1109 |
+
descBtn.click(function(event) {
|
1110 |
+
|
1111 |
+
if( descBtn.hasClass('open') ) {
|
1112 |
+
desc.animate({ height: 57 },
|
1113 |
+
300, function() {
|
1114 |
+
descBtn.removeClass('open');
|
1115 |
+
descBtn.html( astraSitesAdmin.strings.DescExpand );
|
1116 |
+
});
|
1117 |
+
} else {
|
1118 |
+
desc.animate({ height: descHeight },
|
1119 |
+
300, function() {
|
1120 |
+
descBtn.addClass('open');
|
1121 |
+
descBtn.html( astraSitesAdmin.strings.DescCollapse );
|
1122 |
+
});
|
1123 |
+
}
|
1124 |
+
|
1125 |
+
});
|
1126 |
+
}
|
1127 |
+
|
1128 |
+
// or
|
1129 |
+
var $pluginsFilter = jQuery( '#plugin-filter' ),
|
1130 |
+
data = {
|
1131 |
+
action : 'astra-required-plugins',
|
1132 |
+
_ajax_nonce : astraSitesAdmin._ajax_nonce,
|
1133 |
+
required_plugins : requiredPlugins
|
1134 |
+
};
|
1135 |
+
|
1136 |
+
// Add disabled class from import button.
|
1137 |
+
$('.astra-demo-import')
|
1138 |
+
.addClass('disabled not-click-able')
|
1139 |
+
.removeAttr('data-import');
|
1140 |
+
|
1141 |
+
$('.required-plugins').addClass('loading').html('<span class="spinner is-active"></span>');
|
1142 |
+
|
1143 |
+
// Required Required.
|
1144 |
+
$.ajax({
|
1145 |
+
url : astraSitesAdmin.ajaxurl,
|
1146 |
+
type : 'POST',
|
1147 |
+
data : data,
|
1148 |
+
})
|
1149 |
+
.fail(function( jqXHR ){
|
1150 |
+
|
1151 |
+
// Remove loader.
|
1152 |
+
jQuery('.required-plugins').removeClass('loading').html('');
|
1153 |
+
|
1154 |
+
AstraSitesAdmin._importFailMessage( jqXHR.status + ' ' + jqXHR.responseText, 'plugins' );
|
1155 |
+
AstraSitesAdmin._log( jqXHR.status + ' ' + jqXHR.responseText );
|
1156 |
+
})
|
1157 |
+
.done(function ( response ) {
|
1158 |
+
|
1159 |
+
// Release disabled class from import button.
|
1160 |
+
$('.astra-demo-import')
|
1161 |
+
.removeClass('disabled not-click-able')
|
1162 |
+
.attr('data-import', 'disabled');
|
1163 |
+
|
1164 |
+
// Remove loader.
|
1165 |
+
$('.required-plugins').removeClass('loading').html('');
|
1166 |
+
|
1167 |
+
/**
|
1168 |
+
* Count remaining plugins.
|
1169 |
+
* @type number
|
1170 |
+
*/
|
1171 |
+
var remaining_plugins = 0;
|
1172 |
+
|
1173 |
+
/**
|
1174 |
+
* Not Installed
|
1175 |
+
*
|
1176 |
+
* List of not installed required plugins.
|
1177 |
+
*/
|
1178 |
+
if ( typeof response.data.notinstalled !== 'undefined' ) {
|
1179 |
+
|
1180 |
+
// Add not have installed plugins count.
|
1181 |
+
remaining_plugins += parseInt( response.data.notinstalled.length );
|
1182 |
+
|
1183 |
+
jQuery( response.data.notinstalled ).each(function( index, plugin ) {
|
1184 |
+
|
1185 |
+
var output = '<div class="plugin-card ';
|
1186 |
+
output += ' plugin-card-'+plugin.slug+'"';
|
1187 |
+
output += ' data-slug="'+plugin.slug+'"';
|
1188 |
+
output += ' data-init="'+plugin.init+'">';
|
1189 |
+
output += ' <span class="title">'+plugin.name+'</span>';
|
1190 |
+
output += ' <button class="button install-now"';
|
1191 |
+
output += ' data-init="' + plugin.init + '"';
|
1192 |
+
output += ' data-slug="' + plugin.slug + '"';
|
1193 |
+
output += ' data-name="' + plugin.name + '">';
|
1194 |
+
output += wp.updates.l10n.installNow;
|
1195 |
+
output += ' </button>';
|
1196 |
+
// output += ' <span class="dashicons-no dashicons"></span>';
|
1197 |
+
output += '</div>';
|
1198 |
+
|
1199 |
+
jQuery('.required-plugins').append(output);
|
1200 |
+
|
1201 |
+
});
|
1202 |
+
}
|
1203 |
+
|
1204 |
+
/**
|
1205 |
+
* Inactive
|
1206 |
+
*
|
1207 |
+
* List of not inactive required plugins.
|
1208 |
+
*/
|
1209 |
+
if ( typeof response.data.inactive !== 'undefined' ) {
|
1210 |
+
|
1211 |
+
// Add inactive plugins count.
|
1212 |
+
remaining_plugins += parseInt( response.data.inactive.length );
|
1213 |
+
|
1214 |
+
jQuery( response.data.inactive ).each(function( index, plugin ) {
|
1215 |
+
|
1216 |
+
var output = '<div class="plugin-card ';
|
1217 |
+
output += ' plugin-card-'+plugin.slug+'"';
|
1218 |
+
output += ' data-slug="'+plugin.slug+'"';
|
1219 |
+
output += ' data-init="'+plugin.init+'">';
|
1220 |
+
output += ' <span class="title">'+plugin.name+'</span>';
|
1221 |
+
output += ' <button class="button activate-now button-primary"';
|
1222 |
+
output += ' data-init="' + plugin.init + '"';
|
1223 |
+
output += ' data-slug="' + plugin.slug + '"';
|
1224 |
+
output += ' data-name="' + plugin.name + '">';
|
1225 |
+
output += wp.updates.l10n.activatePlugin;
|
1226 |
+
output += ' </button>';
|
1227 |
+
// output += ' <span class="dashicons-no dashicons"></span>';
|
1228 |
+
output += '</div>';
|
1229 |
+
|
1230 |
+
jQuery('.required-plugins').append(output);
|
1231 |
+
|
1232 |
+
});
|
1233 |
+
}
|
1234 |
+
|
1235 |
+
/**
|
1236 |
+
* Active
|
1237 |
+
*
|
1238 |
+
* List of not active required plugins.
|
1239 |
+
*/
|
1240 |
+
if ( typeof response.data.active !== 'undefined' ) {
|
1241 |
+
|
1242 |
+
jQuery( response.data.active ).each(function( index, plugin ) {
|
1243 |
+
|
1244 |
+
var output = '<div class="plugin-card ';
|
1245 |
+
output += ' plugin-card-'+plugin.slug+'"';
|
1246 |
+
output += ' data-slug="'+plugin.slug+'"';
|
1247 |
+
output += ' data-init="'+plugin.init+'">';
|
1248 |
+
output += ' <span class="title">'+plugin.name+'</span>';
|
1249 |
+
output += ' <button class="button disabled"';
|
1250 |
+
output += ' data-slug="' + plugin.slug + '"';
|
1251 |
+
output += ' data-name="' + plugin.name + '">';
|
1252 |
+
output += astraSitesAdmin.strings.btnActive;
|
1253 |
+
output += ' </button>';
|
1254 |
+
// output += ' <span class="dashicons-yes dashicons"></span>';
|
1255 |
+
output += '</div>';
|
1256 |
+
|
1257 |
+
jQuery('.required-plugins').append(output);
|
1258 |
+
|
1259 |
+
});
|
1260 |
+
}
|
1261 |
+
|
1262 |
+
/**
|
1263 |
+
* Enable Demo Import Button
|
1264 |
+
* @type number
|
1265 |
+
*/
|
1266 |
+
astraSitesAdmin.requiredPlugins = response.data;
|
1267 |
+
AstraSitesAdmin._enable_demo_import_button();
|
1268 |
+
|
1269 |
+
});
|
1270 |
+
|
1271 |
+
} else {
|
1272 |
+
|
1273 |
+
// Enable Demo Import Button
|
1274 |
+
AstraSitesAdmin._enable_demo_import_button( demoType );
|
1275 |
+
jQuery('.required-plugins-wrap').remove();
|
1276 |
+
}
|
1277 |
+
|
1278 |
+
return;
|
1279 |
+
},
|
1280 |
+
|
1281 |
+
/**
|
1282 |
+
* Enable Demo Import Button.
|
1283 |
+
*/
|
1284 |
+
_enable_demo_import_button: function( type ) {
|
1285 |
+
|
1286 |
+
type = ( undefined !== type ) ? type : 'free';
|
1287 |
+
|
1288 |
+
switch( type ) {
|
1289 |
+
|
1290 |
+
case 'free':
|
1291 |
+
var all_buttons = parseInt( jQuery( '.plugin-card .button' ).length ) || 0,
|
1292 |
+
disabled_buttons = parseInt( jQuery( '.plugin-card .button.disabled' ).length ) || 0;
|
1293 |
+
|
1294 |
+
if( all_buttons === disabled_buttons ) {
|
1295 |
+
|
1296 |
+
jQuery('.astra-demo-import')
|
1297 |
+
.removeAttr('data-import')
|
1298 |
+
.removeClass('installing updating-message')
|
1299 |
+
.addClass('button-primary')
|
1300 |
+
.text( astraSitesAdmin.strings.importDemo );
|
1301 |
+
}
|
1302 |
+
|
1303 |
+
break;
|
1304 |
+
|
1305 |
+
case 'upgrade':
|
1306 |
+
var demo_slug = jQuery('.wp-full-overlay-header').attr('data-demo-slug');
|
1307 |
+
|
1308 |
+
jQuery('.astra-demo-import')
|
1309 |
+
.addClass('go-pro button-primary')
|
1310 |
+
.removeClass('astra-demo-import')
|
1311 |
+
.attr('target', '_blank')
|
1312 |
+
.attr('href', astraSitesAdmin.getUpgradeURL + demo_slug )
|
1313 |
+
.text( astraSitesAdmin.getUpgradeText )
|
1314 |
+
.append('<i class="dashicons dashicons-external"></i>');
|
1315 |
+
break;
|
1316 |
+
|
1317 |
+
default:
|
1318 |
+
var demo_slug = jQuery('.wp-full-overlay-header').attr('data-demo-slug');
|
1319 |
+
|
1320 |
+
jQuery('.astra-demo-import')
|
1321 |
+
.addClass('go-pro button-primary')
|
1322 |
+
.removeClass('astra-demo-import')
|
1323 |
+
.attr('target', '_blank')
|
1324 |
+
.attr('href', astraSitesAdmin.getProURL )
|
1325 |
+
.text( astraSitesAdmin.getProText )
|
1326 |
+
.append('<i class="dashicons dashicons-external"></i>');
|
1327 |
+
break;
|
1328 |
+
}
|
1329 |
+
|
1330 |
+
},
|
1331 |
+
|
1332 |
+
/**
|
1333 |
+
* Update Page Count.
|
1334 |
+
*/
|
1335 |
+
_updatedPagedCount: function() {
|
1336 |
+
paged = parseInt(jQuery('body').attr('data-astra-demo-paged'));
|
1337 |
+
jQuery('body').attr('data-astra-demo-paged', paged + 1);
|
1338 |
+
window.setTimeout(function () {
|
1339 |
+
jQuery('body').data('scrolling', false);
|
1340 |
+
}, 800);
|
1341 |
+
},
|
1342 |
+
|
1343 |
+
/**
|
1344 |
+
* Reset Page Count.
|
1345 |
+
*/
|
1346 |
+
_resetPagedCount: function() {
|
1347 |
+
|
1348 |
+
$('body').addClass('loading-content');
|
1349 |
+
$('body').attr('data-astra-demo-last-request', '1');
|
1350 |
+
$('body').attr('data-astra-demo-paged', '1');
|
1351 |
+
$('body').attr('data-astra-demo-search', '');
|
1352 |
+
$('body').attr('data-scrolling', false);
|
1353 |
+
|
1354 |
+
},
|
1355 |
+
|
1356 |
+
/**
|
1357 |
+
* Remove plugin from the queue.
|
1358 |
+
*/
|
1359 |
+
_removePluginFromQueue: function( removeItem, pluginsList ) {
|
1360 |
+
return jQuery.grep(pluginsList, function( value ) {
|
1361 |
+
return value.slug != removeItem;
|
1362 |
+
});
|
1363 |
+
}
|
1364 |
+
|
1365 |
+
};
|
1366 |
+
|
1367 |
+
/**
|
1368 |
+
* Initialize AstraSitesAdmin
|
1369 |
+
*/
|
1370 |
+
$(function(){
|
1371 |
+
AstraSitesAdmin.init();
|
1372 |
+
});
|
1373 |
+
|
1374 |
ย
})(jQuery);
|
inc/assets/js/astra-sites-api.js
CHANGED
@@ -1,58 +1,58 @@
|
|
1 |
-
|
2 |
-
(function($){
|
3 |
-
|
4 |
-
AstraSitesAPI = {
|
5 |
-
|
6 |
-
_api_url : astraSitesApi.ApiURL,
|
7 |
-
|
8 |
-
/**
|
9 |
-
* API Request
|
10 |
-
*/
|
11 |
-
_api_request: function( args ) {
|
12 |
-
|
13 |
-
// Set API Request Data.
|
14 |
-
var data = {
|
15 |
-
url: AstraSitesAPI._api_url + args.slug,
|
16 |
-
cache: false,
|
17 |
-
};
|
18 |
-
|
19 |
-
if( astraRenderGrid.headers ) {
|
20 |
-
data.headers = astraRenderGrid.headers;
|
21 |
-
}
|
22 |
-
|
23 |
-
$.ajax( data )
|
24 |
-
.done(function( items, status, XHR ) {
|
25 |
-
|
26 |
-
if( 'success' === status && XHR.getResponseHeader('x-wp-total') ) {
|
27 |
-
|
28 |
-
var data = {
|
29 |
-
args : args,
|
30 |
-
items : items,
|
31 |
-
items_count : XHR.getResponseHeader('x-wp-total') || 0,
|
32 |
-
};
|
33 |
-
|
34 |
-
if( 'undefined' !== args.trigger && '' !== args.trigger ) {
|
35 |
-
$(document).trigger( args.trigger, [data] );
|
36 |
-
}
|
37 |
-
|
38 |
-
} else {
|
39 |
-
$(document).trigger( 'astra-sites-api-request-error' );
|
40 |
-
}
|
41 |
-
|
42 |
-
})
|
43 |
-
.fail(function( jqXHR, textStatus ) {
|
44 |
-
|
45 |
-
$(document).trigger( 'astra-sites-api-request-fail' );
|
46 |
-
|
47 |
-
})
|
48 |
-
.always(function() {
|
49 |
-
|
50 |
-
$(document).trigger( 'astra-sites-api-request-always' );
|
51 |
-
|
52 |
-
});
|
53 |
-
|
54 |
-
},
|
55 |
-
|
56 |
-
};
|
57 |
-
|
58 |
ย
})(jQuery);
|
1 |
+
|
2 |
+
(function($){
|
3 |
+
|
4 |
+
AstraSitesAPI = {
|
5 |
+
|
6 |
+
_api_url : astraSitesApi.ApiURL,
|
7 |
+
|
8 |
+
/**
|
9 |
+
* API Request
|
10 |
+
*/
|
11 |
+
_api_request: function( args ) {
|
12 |
+
|
13 |
+
// Set API Request Data.
|
14 |
+
var data = {
|
15 |
+
url: AstraSitesAPI._api_url + args.slug,
|
16 |
+
cache: false,
|
17 |
+
};
|
18 |
+
|
19 |
+
if( astraRenderGrid.headers ) {
|
20 |
+
data.headers = astraRenderGrid.headers;
|
21 |
+
}
|
22 |
+
|
23 |
+
$.ajax( data )
|
24 |
+
.done(function( items, status, XHR ) {
|
25 |
+
|
26 |
+
if( 'success' === status && XHR.getResponseHeader('x-wp-total') ) {
|
27 |
+
|
28 |
+
var data = {
|
29 |
+
args : args,
|
30 |
+
items : items,
|
31 |
+
items_count : XHR.getResponseHeader('x-wp-total') || 0,
|
32 |
+
};
|
33 |
+
|
34 |
+
if( 'undefined' !== args.trigger && '' !== args.trigger ) {
|
35 |
+
$(document).trigger( args.trigger, [data] );
|
36 |
+
}
|
37 |
+
|
38 |
+
} else {
|
39 |
+
$(document).trigger( 'astra-sites-api-request-error' );
|
40 |
+
}
|
41 |
+
|
42 |
+
})
|
43 |
+
.fail(function( jqXHR, textStatus ) {
|
44 |
+
|
45 |
+
$(document).trigger( 'astra-sites-api-request-fail' );
|
46 |
+
|
47 |
+
})
|
48 |
+
.always(function() {
|
49 |
+
|
50 |
+
$(document).trigger( 'astra-sites-api-request-always' );
|
51 |
+
|
52 |
+
});
|
53 |
+
|
54 |
+
},
|
55 |
+
|
56 |
+
};
|
57 |
+
|
58 |
ย
})(jQuery);
|
inc/assets/js/astra-sites-notices.js
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
jQuery(document).ready(function ($) {
|
2 |
-
|
3 |
-
jQuery( '.astra-notice.is-dismissible .notice-dismiss' ).on( 'click', function() {
|
4 |
-
var $id = jQuery( this ).attr( 'id' ) || '';
|
5 |
-
var $time = jQuery( this ).attr( 'dismissible-time' ) || '';
|
6 |
-
var $meta = jQuery( this ).attr( 'dismissible-meta' ) || '';
|
7 |
-
|
8 |
-
jQuery.ajax({
|
9 |
-
url: ajaxurl,
|
10 |
-
type: 'POST',
|
11 |
-
data: {
|
12 |
-
action : 'astra-notices',
|
13 |
-
id : $id,
|
14 |
-
meta : $meta,
|
15 |
-
time : $time,
|
16 |
-
},
|
17 |
-
});
|
18 |
-
|
19 |
-
});
|
20 |
-
|
21 |
ย
});
|
1 |
+
jQuery(document).ready(function ($) {
|
2 |
+
|
3 |
+
jQuery( '.astra-notice.is-dismissible .notice-dismiss' ).on( 'click', function() {
|
4 |
+
var $id = jQuery( this ).attr( 'id' ) || '';
|
5 |
+
var $time = jQuery( this ).attr( 'dismissible-time' ) || '';
|
6 |
+
var $meta = jQuery( this ).attr( 'dismissible-meta' ) || '';
|
7 |
+
|
8 |
+
jQuery.ajax({
|
9 |
+
url: ajaxurl,
|
10 |
+
type: 'POST',
|
11 |
+
data: {
|
12 |
+
action : 'astra-notices',
|
13 |
+
id : $id,
|
14 |
+
meta : $meta,
|
15 |
+
time : $time,
|
16 |
+
},
|
17 |
+
});
|
18 |
+
|
19 |
+
});
|
20 |
+
|
21 |
ย
});
|
inc/assets/js/eventsource.js
CHANGED
@@ -1,673 +1,673 @@
|
|
1 |
-
/** @license
|
2 |
-
* eventsource.js
|
3 |
-
* Available under MIT License (MIT)
|
4 |
-
* https://github.com/Yaffle/EventSource/
|
5 |
-
*/
|
6 |
-
|
7 |
-
/*jslint indent: 2, vars: true, plusplus: true */
|
8 |
-
/*global setTimeout, clearTimeout */
|
9 |
-
|
10 |
-
(function (global) {
|
11 |
-
"use strict";
|
12 |
-
|
13 |
-
var setTimeout = global.setTimeout;
|
14 |
-
var clearTimeout = global.clearTimeout;
|
15 |
-
var XMLHttpRequest = global.XMLHttpRequest;
|
16 |
-
var XDomainRequest = global.XDomainRequest;
|
17 |
-
var NativeEventSource = global.EventSource;
|
18 |
-
var document = global.document;
|
19 |
-
|
20 |
-
if (Object.create == null) {
|
21 |
-
Object.create = function (C) {
|
22 |
-
function F(){}
|
23 |
-
F.prototype = C;
|
24 |
-
return new F();
|
25 |
-
};
|
26 |
-
}
|
27 |
-
|
28 |
-
var k = function () {
|
29 |
-
};
|
30 |
-
|
31 |
-
function XHRWrapper(xhr) {
|
32 |
-
this.withCredentials = false;
|
33 |
-
this.responseType = "";
|
34 |
-
this.readyState = 0;
|
35 |
-
this.status = 0;
|
36 |
-
this.statusText = "";
|
37 |
-
this.responseText = "";
|
38 |
-
this.onprogress = k;
|
39 |
-
this.onreadystatechange = k;
|
40 |
-
this._contentType = "";
|
41 |
-
this._xhr = xhr;
|
42 |
-
this._sendTimeout = 0;
|
43 |
-
this._abort = k;
|
44 |
-
}
|
45 |
-
|
46 |
-
XHRWrapper.prototype.open = function (method, url) {
|
47 |
-
this._abort(true);
|
48 |
-
|
49 |
-
var that = this;
|
50 |
-
var xhr = this._xhr;
|
51 |
-
var state = 1;
|
52 |
-
var timeout = 0;
|
53 |
-
|
54 |
-
this._abort = function (silent) {
|
55 |
-
if (that._sendTimeout !== 0) {
|
56 |
-
clearTimeout(that._sendTimeout);
|
57 |
-
that._sendTimeout = 0;
|
58 |
-
}
|
59 |
-
if (state === 1 || state === 2 || state === 3) {
|
60 |
-
state = 4;
|
61 |
-
xhr.onload = k;
|
62 |
-
xhr.onerror = k;
|
63 |
-
xhr.onabort = k;
|
64 |
-
xhr.onprogress = k;
|
65 |
-
xhr.onreadystatechange = k;
|
66 |
-
// IE 8 - 9: XDomainRequest#abort() does not fire any event
|
67 |
-
// Opera < 10: XMLHttpRequest#abort() does not fire any event
|
68 |
-
xhr.abort();
|
69 |
-
if (timeout !== 0) {
|
70 |
-
clearTimeout(timeout);
|
71 |
-
timeout = 0;
|
72 |
-
}
|
73 |
-
if (!silent) {
|
74 |
-
that.readyState = 4;
|
75 |
-
that.onreadystatechange();
|
76 |
-
}
|
77 |
-
}
|
78 |
-
state = 0;
|
79 |
-
};
|
80 |
-
|
81 |
-
var onStart = function () {
|
82 |
-
if (state === 1) {
|
83 |
-
//state = 2;
|
84 |
-
var status = 0;
|
85 |
-
var statusText = "";
|
86 |
-
var contentType = undefined;
|
87 |
-
if (!("contentType" in xhr)) {
|
88 |
-
try {
|
89 |
-
status = xhr.status;
|
90 |
-
statusText = xhr.statusText;
|
91 |
-
contentType = xhr.getResponseHeader("Content-Type");
|
92 |
-
} catch (error) {
|
93 |
-
// IE < 10 throws exception for `xhr.status` when xhr.readyState === 2 || xhr.readyState === 3
|
94 |
-
// Opera < 11 throws exception for `xhr.status` when xhr.readyState === 2
|
95 |
-
// https://bugs.webkit.org/show_bug.cgi?id=29121
|
96 |
-
status = 0;
|
97 |
-
statusText = "";
|
98 |
-
contentType = undefined;
|
99 |
-
// Firefox < 14, Chrome ?, Safari ?
|
100 |
-
// https://bugs.webkit.org/show_bug.cgi?id=29658
|
101 |
-
// https://bugs.webkit.org/show_bug.cgi?id=77854
|
102 |
-
}
|
103 |
-
} else {
|
104 |
-
status = 200;
|
105 |
-
statusText = "OK";
|
106 |
-
contentType = xhr.contentType;
|
107 |
-
}
|
108 |
-
if (status !== 0) {
|
109 |
-
state = 2;
|
110 |
-
that.readyState = 2;
|
111 |
-
that.status = status;
|
112 |
-
that.statusText = statusText;
|
113 |
-
that._contentType = contentType;
|
114 |
-
that.onreadystatechange();
|
115 |
-
}
|
116 |
-
}
|
117 |
-
};
|
118 |
-
var onProgress = function () {
|
119 |
-
onStart();
|
120 |
-
if (state === 2 || state === 3) {
|
121 |
-
state = 3;
|
122 |
-
var responseText = "";
|
123 |
-
try {
|
124 |
-
responseText = xhr.responseText;
|
125 |
-
} catch (error) {
|
126 |
-
// IE 8 - 9 with XMLHttpRequest
|
127 |
-
}
|
128 |
-
that.readyState = 3;
|
129 |
-
that.responseText = responseText;
|
130 |
-
that.onprogress();
|
131 |
-
}
|
132 |
-
};
|
133 |
-
var onFinish = function () {
|
134 |
-
// Firefox 52 fires "readystatechange" (xhr.readyState === 4) without final "readystatechange" (xhr.readyState === 3)
|
135 |
-
// IE 8 fires "onload" without "onprogress"
|
136 |
-
onProgress();
|
137 |
-
if (state === 1 || state === 2 || state === 3) {
|
138 |
-
state = 4;
|
139 |
-
if (timeout !== 0) {
|
140 |
-
clearTimeout(timeout);
|
141 |
-
timeout = 0;
|
142 |
-
}
|
143 |
-
that.readyState = 4;
|
144 |
-
that.onreadystatechange();
|
145 |
-
}
|
146 |
-
};
|
147 |
-
var onReadyStateChange = function () {
|
148 |
-
if (xhr != undefined) { // Opera 12
|
149 |
-
if (xhr.readyState === 4) {
|
150 |
-
onFinish();
|
151 |
-
} else if (xhr.readyState === 3) {
|
152 |
-
onProgress();
|
153 |
-
} else if (xhr.readyState === 2) {
|
154 |
-
onStart();
|
155 |
-
}
|
156 |
-
}
|
157 |
-
};
|
158 |
-
var onTimeout = function () {
|
159 |
-
timeout = setTimeout(function () {
|
160 |
-
onTimeout();
|
161 |
-
}, 500);
|
162 |
-
if (xhr.readyState === 3) {
|
163 |
-
onProgress();
|
164 |
-
}
|
165 |
-
};
|
166 |
-
|
167 |
-
// XDomainRequest#abort removes onprogress, onerror, onload
|
168 |
-
xhr.onload = onFinish;
|
169 |
-
xhr.onerror = onFinish;
|
170 |
-
// improper fix to match Firefox behaviour, but it is better than just ignore abort
|
171 |
-
// see https://bugzilla.mozilla.org/show_bug.cgi?id=768596
|
172 |
-
// https://bugzilla.mozilla.org/show_bug.cgi?id=880200
|
173 |
-
// https://code.google.com/p/chromium/issues/detail?id=153570
|
174 |
-
// IE 8 fires "onload" without "onprogress
|
175 |
-
xhr.onabort = onFinish;
|
176 |
-
|
177 |
-
// https://bugzilla.mozilla.org/show_bug.cgi?id=736723
|
178 |
-
if (!("sendAsBinary" in XMLHttpRequest.prototype) && !("mozAnon" in XMLHttpRequest.prototype)) {
|
179 |
-
xhr.onprogress = onProgress;
|
180 |
-
}
|
181 |
-
|
182 |
-
// IE 8 - 9 (XMLHTTPRequest)
|
183 |
-
// Opera < 12
|
184 |
-
// Firefox < 3.5
|
185 |
-
// Firefox 3.5 - 3.6 - ? < 9.0
|
186 |
-
// onprogress is not fired sometimes or delayed
|
187 |
-
// see also #64
|
188 |
-
xhr.onreadystatechange = onReadyStateChange;
|
189 |
-
|
190 |
-
if ("contentType" in xhr) {
|
191 |
-
url += (url.indexOf("?", 0) === -1 ? "?" : "&") + "padding=true";
|
192 |
-
}
|
193 |
-
xhr.open(method, url, true);
|
194 |
-
|
195 |
-
if ("readyState" in xhr) {
|
196 |
-
// workaround for Opera 12 issue with "progress" events
|
197 |
-
// #91
|
198 |
-
timeout = setTimeout(function () {
|
199 |
-
onTimeout();
|
200 |
-
}, 0);
|
201 |
-
}
|
202 |
-
};
|
203 |
-
XHRWrapper.prototype.abort = function () {
|
204 |
-
this._abort(false);
|
205 |
-
};
|
206 |
-
XHRWrapper.prototype.getResponseHeader = function (name) {
|
207 |
-
return this._contentType;
|
208 |
-
};
|
209 |
-
XHRWrapper.prototype.setRequestHeader = function (name, value) {
|
210 |
-
var xhr = this._xhr;
|
211 |
-
if ("setRequestHeader" in xhr) {
|
212 |
-
xhr.setRequestHeader(name, value);
|
213 |
-
}
|
214 |
-
};
|
215 |
-
XHRWrapper.prototype.send = function () {
|
216 |
-
// loading indicator in Safari < ? (6), Chrome < 14, Firefox
|
217 |
-
if (!("ontimeout" in XMLHttpRequest.prototype) &&
|
218 |
-
document != undefined &&
|
219 |
-
document.readyState != undefined &&
|
220 |
-
document.readyState !== "complete") {
|
221 |
-
var that = this;
|
222 |
-
that._sendTimeout = setTimeout(function () {
|
223 |
-
that._sendTimeout = 0;
|
224 |
-
that.send();
|
225 |
-
}, 4);
|
226 |
-
return;
|
227 |
-
}
|
228 |
-
|
229 |
-
var xhr = this._xhr;
|
230 |
-
// withCredentials should be set after "open" for Safari and Chrome (< 19 ?)
|
231 |
-
xhr.withCredentials = this.withCredentials;
|
232 |
-
xhr.responseType = this.responseType;
|
233 |
-
try {
|
234 |
-
// xhr.send(); throws "Not enough arguments" in Firefox 3.0
|
235 |
-
xhr.send(undefined);
|
236 |
-
} catch (error1) {
|
237 |
-
// Safari 5.1.7, Opera 12
|
238 |
-
throw error1;
|
239 |
-
}
|
240 |
-
};
|
241 |
-
|
242 |
-
function XHRTransport(xhr) {
|
243 |
-
this._xhr = new XHRWrapper(xhr);
|
244 |
-
}
|
245 |
-
|
246 |
-
XHRTransport.prototype.open = function (onStartCallback, onProgressCallback, onFinishCallback, url, withCredentials, headers) {
|
247 |
-
var xhr = this._xhr;
|
248 |
-
xhr.open("GET", url);
|
249 |
-
var offset = 0;
|
250 |
-
xhr.onprogress = function () {
|
251 |
-
var responseText = xhr.responseText;
|
252 |
-
var chunk = responseText.slice(offset);
|
253 |
-
offset += chunk.length;
|
254 |
-
onProgressCallback(chunk);
|
255 |
-
};
|
256 |
-
xhr.onreadystatechange = function () {
|
257 |
-
if (xhr.readyState === 2) {
|
258 |
-
var status = xhr.status;
|
259 |
-
var statusText = xhr.statusText;
|
260 |
-
var contentType = xhr.getResponseHeader("Content-Type");
|
261 |
-
onStartCallback(status, statusText, contentType);
|
262 |
-
} else if (xhr.readyState === 4) {
|
263 |
-
onFinishCallback();
|
264 |
-
}
|
265 |
-
};
|
266 |
-
xhr.withCredentials = withCredentials;
|
267 |
-
xhr.responseType = "text";
|
268 |
-
for (var name in headers) {
|
269 |
-
if (Object.prototype.hasOwnProperty.call(headers, name)) {
|
270 |
-
xhr.setRequestHeader(name, headers[name]);
|
271 |
-
}
|
272 |
-
}
|
273 |
-
xhr.send();
|
274 |
-
};
|
275 |
-
|
276 |
-
XHRTransport.prototype.cancel = function () {
|
277 |
-
var xhr = this._xhr;
|
278 |
-
xhr.abort();
|
279 |
-
};
|
280 |
-
|
281 |
-
function EventTarget() {
|
282 |
-
this._listeners = Object.create(null);
|
283 |
-
}
|
284 |
-
|
285 |
-
function throwError(e) {
|
286 |
-
setTimeout(function () {
|
287 |
-
throw e;
|
288 |
-
}, 0);
|
289 |
-
}
|
290 |
-
|
291 |
-
EventTarget.prototype.dispatchEvent = function (event) {
|
292 |
-
event.target = this;
|
293 |
-
var typeListeners = this._listeners[event.type];
|
294 |
-
if (typeListeners != undefined) {
|
295 |
-
var length = typeListeners.length;
|
296 |
-
for (var i = 0; i < length; i += 1) {
|
297 |
-
var listener = typeListeners[i];
|
298 |
-
try {
|
299 |
-
if (typeof listener.handleEvent === "function") {
|
300 |
-
listener.handleEvent(event);
|
301 |
-
} else {
|
302 |
-
listener.call(this, event);
|
303 |
-
}
|
304 |
-
} catch (e) {
|
305 |
-
throwError(e);
|
306 |
-
}
|
307 |
-
}
|
308 |
-
}
|
309 |
-
};
|
310 |
-
EventTarget.prototype.addEventListener = function (type, listener) {
|
311 |
-
type = String(type);
|
312 |
-
var listeners = this._listeners;
|
313 |
-
var typeListeners = listeners[type];
|
314 |
-
if (typeListeners == undefined) {
|
315 |
-
typeListeners = [];
|
316 |
-
listeners[type] = typeListeners;
|
317 |
-
}
|
318 |
-
var found = false;
|
319 |
-
for (var i = 0; i < typeListeners.length; i += 1) {
|
320 |
-
if (typeListeners[i] === listener) {
|
321 |
-
found = true;
|
322 |
-
}
|
323 |
-
}
|
324 |
-
if (!found) {
|
325 |
-
typeListeners.push(listener);
|
326 |
-
}
|
327 |
-
};
|
328 |
-
EventTarget.prototype.removeEventListener = function (type, listener) {
|
329 |
-
type = String(type);
|
330 |
-
var listeners = this._listeners;
|
331 |
-
var typeListeners = listeners[type];
|
332 |
-
if (typeListeners != undefined) {
|
333 |
-
var filtered = [];
|
334 |
-
for (var i = 0; i < typeListeners.length; i += 1) {
|
335 |
-
if (typeListeners[i] !== listener) {
|
336 |
-
filtered.push(typeListeners[i]);
|
337 |
-
}
|
338 |
-
}
|
339 |
-
if (filtered.length === 0) {
|
340 |
-
delete listeners[type];
|
341 |
-
} else {
|
342 |
-
listeners[type] = filtered;
|
343 |
-
}
|
344 |
-
}
|
345 |
-
};
|
346 |
-
|
347 |
-
function Event(type) {
|
348 |
-
this.type = type;
|
349 |
-
this.target = undefined;
|
350 |
-
}
|
351 |
-
|
352 |
-
function MessageEvent(type, options) {
|
353 |
-
Event.call(this, type);
|
354 |
-
this.data = options.data;
|
355 |
-
this.lastEventId = options.lastEventId;
|
356 |
-
}
|
357 |
-
|
358 |
-
MessageEvent.prototype = Object.create(Event.prototype);
|
359 |
-
|
360 |
-
var WAITING = -1;
|
361 |
-
var CONNECTING = 0;
|
362 |
-
var OPEN = 1;
|
363 |
-
var CLOSED = 2;
|
364 |
-
|
365 |
-
var AFTER_CR = -1;
|
366 |
-
var FIELD_START = 0;
|
367 |
-
var FIELD = 1;
|
368 |
-
var VALUE_START = 2;
|
369 |
-
var VALUE = 3;
|
370 |
-
|
371 |
-
var contentTypeRegExp = /^text\/event\-stream;?(\s*charset\=utf\-8)?$/i;
|
372 |
-
|
373 |
-
var MINIMUM_DURATION = 1000;
|
374 |
-
var MAXIMUM_DURATION = 18000000;
|
375 |
-
|
376 |
-
var parseDuration = function (value, def) {
|
377 |
-
var n = parseInt(value, 10);
|
378 |
-
if (n !== n) {
|
379 |
-
n = def;
|
380 |
-
}
|
381 |
-
return clampDuration(n);
|
382 |
-
};
|
383 |
-
var clampDuration = function (n) {
|
384 |
-
return Math.min(Math.max(n, MINIMUM_DURATION), MAXIMUM_DURATION);
|
385 |
-
};
|
386 |
-
|
387 |
-
var fire = function (that, f, event) {
|
388 |
-
try {
|
389 |
-
if (typeof f === "function") {
|
390 |
-
f.call(that, event);
|
391 |
-
}
|
392 |
-
} catch (e) {
|
393 |
-
throwError(e);
|
394 |
-
}
|
395 |
-
};
|
396 |
-
|
397 |
-
function EventSourcePolyfill(url, options) {
|
398 |
-
EventTarget.call(this);
|
399 |
-
|
400 |
-
this.onopen = undefined;
|
401 |
-
this.onmessage = undefined;
|
402 |
-
this.onerror = undefined;
|
403 |
-
|
404 |
-
this.url = undefined;
|
405 |
-
this.readyState = undefined;
|
406 |
-
this.withCredentials = undefined;
|
407 |
-
|
408 |
-
this._close = undefined;
|
409 |
-
|
410 |
-
start(this, url, options);
|
411 |
-
}
|
412 |
-
|
413 |
-
function start(es, url, options) {
|
414 |
-
url = String(url);
|
415 |
-
var withCredentials = options != undefined && Boolean(options.withCredentials);
|
416 |
-
|
417 |
-
var initialRetry = clampDuration(1000);
|
418 |
-
var heartbeatTimeout = clampDuration(45000);
|
419 |
-
|
420 |
-
var lastEventId = "";
|
421 |
-
var retry = initialRetry;
|
422 |
-
var wasActivity = false;
|
423 |
-
var headers = options != undefined && options.headers != undefined ? JSON.parse(JSON.stringify(options.headers)) : undefined;
|
424 |
-
var CurrentTransport = options != undefined && options.Transport != undefined ? options.Transport : (XDomainRequest != undefined ? XDomainRequest : XMLHttpRequest);
|
425 |
-
var transport = new XHRTransport(new CurrentTransport());
|
426 |
-
var timeout = 0;
|
427 |
-
var currentState = WAITING;
|
428 |
-
var dataBuffer = "";
|
429 |
-
var lastEventIdBuffer = "";
|
430 |
-
var eventTypeBuffer = "";
|
431 |
-
|
432 |
-
var textBuffer = "";
|
433 |
-
var state = FIELD_START;
|
434 |
-
var fieldStart = 0;
|
435 |
-
var valueStart = 0;
|
436 |
-
|
437 |
-
var onStart = function (status, statusText, contentType) {
|
438 |
-
if (currentState === CONNECTING) {
|
439 |
-
if (status === 200 && contentType != undefined && contentTypeRegExp.test(contentType)) {
|
440 |
-
currentState = OPEN;
|
441 |
-
wasActivity = true;
|
442 |
-
retry = initialRetry;
|
443 |
-
es.readyState = OPEN;
|
444 |
-
var event = new Event("open");
|
445 |
-
es.dispatchEvent(event);
|
446 |
-
fire(es, es.onopen, event);
|
447 |
-
} else {
|
448 |
-
var message = "";
|
449 |
-
if (status !== 200) {
|
450 |
-
if (statusText) {
|
451 |
-
statusText = statusText.replace(/\s+/g, " ");
|
452 |
-
}
|
453 |
-
message = "EventSource's response has a status " + status + " " + statusText + " that is not 200. Aborting the connection.";
|
454 |
-
} else {
|
455 |
-
message = "EventSource's response has a Content-Type specifying an unsupported type: " + (contentType == undefined ? "-" : contentType.replace(/\s+/g, " ")) + ". Aborting the connection.";
|
456 |
-
}
|
457 |
-
throwError(new Error(message));
|
458 |
-
close();
|
459 |
-
var event = new Event("error");
|
460 |
-
es.dispatchEvent(event);
|
461 |
-
fire(es, es.onerror, event);
|
462 |
-
}
|
463 |
-
}
|
464 |
-
};
|
465 |
-
|
466 |
-
var onProgress = function (textChunk) {
|
467 |
-
if (currentState === OPEN) {
|
468 |
-
var n = -1;
|
469 |
-
for (var i = 0; i < textChunk.length; i += 1) {
|
470 |
-
var c = textChunk.charCodeAt(i);
|
471 |
-
if (c === "\n".charCodeAt(0) || c === "\r".charCodeAt(0)) {
|
472 |
-
n = i;
|
473 |
-
}
|
474 |
-
}
|
475 |
-
var chunk = (n !== -1 ? textBuffer : "") + textChunk.slice(0, n + 1);
|
476 |
-
textBuffer = (n === -1 ? textBuffer : "") + textChunk.slice(n + 1);
|
477 |
-
if (chunk !== "") {
|
478 |
-
wasActivity = true;
|
479 |
-
}
|
480 |
-
for (var position = 0; position < chunk.length; position += 1) {
|
481 |
-
var c = chunk.charCodeAt(position);
|
482 |
-
if (state === AFTER_CR && c === "\n".charCodeAt(0)) {
|
483 |
-
state = FIELD_START;
|
484 |
-
} else {
|
485 |
-
if (state === AFTER_CR) {
|
486 |
-
state = FIELD_START;
|
487 |
-
}
|
488 |
-
if (c === "\r".charCodeAt(0) || c === "\n".charCodeAt(0)) {
|
489 |
-
if (state !== FIELD_START) {
|
490 |
-
if (state === FIELD) {
|
491 |
-
valueStart = position + 1;
|
492 |
-
}
|
493 |
-
var field = chunk.slice(fieldStart, valueStart - 1);
|
494 |
-
var value = chunk.slice(valueStart + (valueStart < position && chunk.charCodeAt(valueStart) === " ".charCodeAt(0) ? 1 : 0), position);
|
495 |
-
if (field === "data") {
|
496 |
-
dataBuffer += "\n";
|
497 |
-
dataBuffer += value;
|
498 |
-
} else if (field === "id") {
|
499 |
-
lastEventIdBuffer = value;
|
500 |
-
} else if (field === "event") {
|
501 |
-
eventTypeBuffer = value;
|
502 |
-
} else if (field === "retry") {
|
503 |
-
initialRetry = parseDuration(value, initialRetry);
|
504 |
-
retry = initialRetry;
|
505 |
-
} else if (field === "heartbeatTimeout") {
|
506 |
-
heartbeatTimeout = parseDuration(value, heartbeatTimeout);
|
507 |
-
if (timeout !== 0) {
|
508 |
-
clearTimeout(timeout);
|
509 |
-
timeout = setTimeout(function () {
|
510 |
-
onTimeout();
|
511 |
-
}, heartbeatTimeout);
|
512 |
-
}
|
513 |
-
}
|
514 |
-
}
|
515 |
-
if (state === FIELD_START) {
|
516 |
-
if (dataBuffer !== "") {
|
517 |
-
lastEventId = lastEventIdBuffer;
|
518 |
-
if (eventTypeBuffer === "") {
|
519 |
-
eventTypeBuffer = "message";
|
520 |
-
}
|
521 |
-
var event = new MessageEvent(eventTypeBuffer, {
|
522 |
-
data: dataBuffer.slice(1),
|
523 |
-
lastEventId: lastEventIdBuffer
|
524 |
-
});
|
525 |
-
es.dispatchEvent(event);
|
526 |
-
if (eventTypeBuffer === "message") {
|
527 |
-
fire(es, es.onmessage, event);
|
528 |
-
}
|
529 |
-
if (currentState === CLOSED) {
|
530 |
-
return;
|
531 |
-
}
|
532 |
-
}
|
533 |
-
dataBuffer = "";
|
534 |
-
eventTypeBuffer = "";
|
535 |
-
}
|
536 |
-
state = c === "\r".charCodeAt(0) ? AFTER_CR : FIELD_START;
|
537 |
-
} else {
|
538 |
-
if (state === FIELD_START) {
|
539 |
-
fieldStart = position;
|
540 |
-
state = FIELD;
|
541 |
-
}
|
542 |
-
if (state === FIELD) {
|
543 |
-
if (c === ":".charCodeAt(0)) {
|
544 |
-
valueStart = position + 1;
|
545 |
-
state = VALUE_START;
|
546 |
-
}
|
547 |
-
} else if (state === VALUE_START) {
|
548 |
-
state = VALUE;
|
549 |
-
}
|
550 |
-
}
|
551 |
-
}
|
552 |
-
}
|
553 |
-
}
|
554 |
-
};
|
555 |
-
|
556 |
-
var onFinish = function () {
|
557 |
-
if (currentState === OPEN || currentState === CONNECTING) {
|
558 |
-
currentState = WAITING;
|
559 |
-
if (timeout !== 0) {
|
560 |
-
clearTimeout(timeout);
|
561 |
-
timeout = 0;
|
562 |
-
}
|
563 |
-
timeout = setTimeout(function () {
|
564 |
-
onTimeout();
|
565 |
-
}, retry);
|
566 |
-
retry = clampDuration(Math.min(initialRetry * 16, retry * 2));
|
567 |
-
|
568 |
-
es.readyState = CONNECTING;
|
569 |
-
var event = new Event("error");
|
570 |
-
es.dispatchEvent(event);
|
571 |
-
fire(es, es.onerror, event);
|
572 |
-
}
|
573 |
-
};
|
574 |
-
|
575 |
-
var close = function () {
|
576 |
-
currentState = CLOSED;
|
577 |
-
transport.cancel();
|
578 |
-
if (timeout !== 0) {
|
579 |
-
clearTimeout(timeout);
|
580 |
-
timeout = 0;
|
581 |
-
}
|
582 |
-
es.readyState = CLOSED;
|
583 |
-
};
|
584 |
-
|
585 |
-
var onTimeout = function () {
|
586 |
-
timeout = 0;
|
587 |
-
|
588 |
-
if (currentState !== WAITING) {
|
589 |
-
if (!wasActivity) {
|
590 |
-
throwError(new Error("No activity within " + heartbeatTimeout + " milliseconds. Reconnecting."));
|
591 |
-
transport.cancel();
|
592 |
-
} else {
|
593 |
-
wasActivity = false;
|
594 |
-
timeout = setTimeout(function () {
|
595 |
-
onTimeout();
|
596 |
-
}, heartbeatTimeout);
|
597 |
-
}
|
598 |
-
return;
|
599 |
-
}
|
600 |
-
|
601 |
-
wasActivity = false;
|
602 |
-
timeout = setTimeout(function () {
|
603 |
-
onTimeout();
|
604 |
-
}, heartbeatTimeout);
|
605 |
-
|
606 |
-
currentState = CONNECTING;
|
607 |
-
dataBuffer = "";
|
608 |
-
eventTypeBuffer = "";
|
609 |
-
lastEventIdBuffer = lastEventId;
|
610 |
-
textBuffer = "";
|
611 |
-
fieldStart = 0;
|
612 |
-
valueStart = 0;
|
613 |
-
state = FIELD_START;
|
614 |
-
|
615 |
-
// https://bugzilla.mozilla.org/show_bug.cgi?id=428916
|
616 |
-
// Request header field Last-Event-ID is not allowed by Access-Control-Allow-Headers.
|
617 |
-
var requestURL = url;
|
618 |
-
if (url.slice(0, 5) !== "data:" &&
|
619 |
-
url.slice(0, 5) !== "blob:") {
|
620 |
-
requestURL = url + (url.indexOf("?", 0) === -1 ? "?" : "&") + "lastEventId=" + encodeURIComponent(lastEventId);
|
621 |
-
}
|
622 |
-
var requestHeaders = {};
|
623 |
-
requestHeaders["Accept"] = "text/event-stream";
|
624 |
-
if (headers != undefined) {
|
625 |
-
for (var name in headers) {
|
626 |
-
if (Object.prototype.hasOwnProperty.call(headers, name)) {
|
627 |
-
requestHeaders[name] = headers[name];
|
628 |
-
}
|
629 |
-
}
|
630 |
-
}
|
631 |
-
try {
|
632 |
-
transport.open(onStart, onProgress, onFinish, requestURL, withCredentials, requestHeaders);
|
633 |
-
} catch (error) {
|
634 |
-
close();
|
635 |
-
throw error;
|
636 |
-
}
|
637 |
-
};
|
638 |
-
|
639 |
-
es.url = url;
|
640 |
-
es.readyState = CONNECTING;
|
641 |
-
es.withCredentials = withCredentials;
|
642 |
-
es._close = close;
|
643 |
-
|
644 |
-
onTimeout();
|
645 |
-
}
|
646 |
-
|
647 |
-
EventSourcePolyfill.prototype = Object.create(EventTarget.prototype);
|
648 |
-
EventSourcePolyfill.prototype.CONNECTING = CONNECTING;
|
649 |
-
EventSourcePolyfill.prototype.OPEN = OPEN;
|
650 |
-
EventSourcePolyfill.prototype.CLOSED = CLOSED;
|
651 |
-
EventSourcePolyfill.prototype.close = function () {
|
652 |
-
this._close();
|
653 |
-
};
|
654 |
-
|
655 |
-
EventSourcePolyfill.CONNECTING = CONNECTING;
|
656 |
-
EventSourcePolyfill.OPEN = OPEN;
|
657 |
-
EventSourcePolyfill.CLOSED = CLOSED;
|
658 |
-
EventSourcePolyfill.prototype.withCredentials = undefined;
|
659 |
-
|
660 |
-
global.EventSourcePolyfill = EventSourcePolyfill;
|
661 |
-
global.NativeEventSource = NativeEventSource;
|
662 |
-
|
663 |
-
if (XMLHttpRequest != undefined && (NativeEventSource == undefined || !("withCredentials" in NativeEventSource.prototype))) {
|
664 |
-
// Why replace a native EventSource ?
|
665 |
-
// https://bugzilla.mozilla.org/show_bug.cgi?id=444328
|
666 |
-
// https://bugzilla.mozilla.org/show_bug.cgi?id=831392
|
667 |
-
// https://code.google.com/p/chromium/issues/detail?id=260144
|
668 |
-
// https://code.google.com/p/chromium/issues/detail?id=225654
|
669 |
-
// ...
|
670 |
-
global.EventSource = EventSourcePolyfill;
|
671 |
-
}
|
672 |
-
|
673 |
-
}(typeof window !== 'undefined' ? window : this));
|
1 |
+
/** @license
|
2 |
+
* eventsource.js
|
3 |
+
* Available under MIT License (MIT)
|
4 |
+
* https://github.com/Yaffle/EventSource/
|
5 |
+
*/
|
6 |
+
|
7 |
+
/*jslint indent: 2, vars: true, plusplus: true */
|
8 |
+
/*global setTimeout, clearTimeout */
|
9 |
+
|
10 |
+
(function (global) {
|
11 |
+
"use strict";
|
12 |
+
|
13 |
+
var setTimeout = global.setTimeout;
|
14 |
+
var clearTimeout = global.clearTimeout;
|
15 |
+
var XMLHttpRequest = global.XMLHttpRequest;
|
16 |
+
var XDomainRequest = global.XDomainRequest;
|
17 |
+
var NativeEventSource = global.EventSource;
|
18 |
+
var document = global.document;
|
19 |
+
|
20 |
+
if (Object.create == null) {
|
21 |
+
Object.create = function (C) {
|
22 |
+
function F(){}
|
23 |
+
F.prototype = C;
|
24 |
+
return new F();
|
25 |
+
};
|
26 |
+
}
|
27 |
+
|
28 |
+
var k = function () {
|
29 |
+
};
|
30 |
+
|
31 |
+
function XHRWrapper(xhr) {
|
32 |
+
this.withCredentials = false;
|
33 |
+
this.responseType = "";
|
34 |
+
this.readyState = 0;
|
35 |
+
this.status = 0;
|
36 |
+
this.statusText = "";
|
37 |
+
this.responseText = "";
|
38 |
+
this.onprogress = k;
|
39 |
+
this.onreadystatechange = k;
|
40 |
+
this._contentType = "";
|
41 |
+
this._xhr = xhr;
|
42 |
+
this._sendTimeout = 0;
|
43 |
+
this._abort = k;
|
44 |
+
}
|
45 |
+
|
46 |
+
XHRWrapper.prototype.open = function (method, url) {
|
47 |
+
this._abort(true);
|
48 |
+
|
49 |
+
var that = this;
|
50 |
+
var xhr = this._xhr;
|
51 |
+
var state = 1;
|
52 |
+
var timeout = 0;
|
53 |
+
|
54 |
+
this._abort = function (silent) {
|
55 |
+
if (that._sendTimeout !== 0) {
|
56 |
+
clearTimeout(that._sendTimeout);
|
57 |
+
that._sendTimeout = 0;
|
58 |
+
}
|
59 |
+
if (state === 1 || state === 2 || state === 3) {
|
60 |
+
state = 4;
|
61 |
+
xhr.onload = k;
|
62 |
+
xhr.onerror = k;
|
63 |
+
xhr.onabort = k;
|
64 |
+
xhr.onprogress = k;
|
65 |
+
xhr.onreadystatechange = k;
|
66 |
+
// IE 8 - 9: XDomainRequest#abort() does not fire any event
|
67 |
+
// Opera < 10: XMLHttpRequest#abort() does not fire any event
|
68 |
+
xhr.abort();
|
69 |
+
if (timeout !== 0) {
|
70 |
+
clearTimeout(timeout);
|
71 |
+
timeout = 0;
|
72 |
+
}
|
73 |
+
if (!silent) {
|
74 |
+
that.readyState = 4;
|
75 |
+
that.onreadystatechange();
|
76 |
+
}
|
77 |
+
}
|
78 |
+
state = 0;
|
79 |
+
};
|
80 |
+
|
81 |
+
var onStart = function () {
|
82 |
+
if (state === 1) {
|
83 |
+
//state = 2;
|
84 |
+
var status = 0;
|
85 |
+
var statusText = "";
|
86 |
+
var contentType = undefined;
|
87 |
+
if (!("contentType" in xhr)) {
|
88 |
+
try {
|
89 |
+
status = xhr.status;
|
90 |
+
statusText = xhr.statusText;
|
91 |
+
contentType = xhr.getResponseHeader("Content-Type");
|
92 |
+
} catch (error) {
|
93 |
+
// IE < 10 throws exception for `xhr.status` when xhr.readyState === 2 || xhr.readyState === 3
|
94 |
+
// Opera < 11 throws exception for `xhr.status` when xhr.readyState === 2
|
95 |
+
// https://bugs.webkit.org/show_bug.cgi?id=29121
|
96 |
+
status = 0;
|
97 |
+
statusText = "";
|
98 |
+
contentType = undefined;
|
99 |
+
// Firefox < 14, Chrome ?, Safari ?
|
100 |
+
// https://bugs.webkit.org/show_bug.cgi?id=29658
|
101 |
+
// https://bugs.webkit.org/show_bug.cgi?id=77854
|
102 |
+
}
|
103 |
+
} else {
|
104 |
+
status = 200;
|
105 |
+
statusText = "OK";
|
106 |
+
contentType = xhr.contentType;
|
107 |
+
}
|
108 |
+
if (status !== 0) {
|
109 |
+
state = 2;
|
110 |
+
that.readyState = 2;
|
111 |
+
that.status = status;
|
112 |
+
that.statusText = statusText;
|
113 |
+
that._contentType = contentType;
|
114 |
+
that.onreadystatechange();
|
115 |
+
}
|
116 |
+
}
|
117 |
+
};
|
118 |
+
var onProgress = function () {
|
119 |
+
onStart();
|
120 |
+
if (state === 2 || state === 3) {
|
121 |
+
state = 3;
|
122 |
+
var responseText = "";
|
123 |
+
try {
|
124 |
+
responseText = xhr.responseText;
|
125 |
+
} catch (error) {
|
126 |
+
// IE 8 - 9 with XMLHttpRequest
|
127 |
+
}
|
128 |
+
that.readyState = 3;
|
129 |
+
that.responseText = responseText;
|
130 |
+
that.onprogress();
|
131 |
+
}
|
132 |
+
};
|
133 |
+
var onFinish = function () {
|
134 |
+
// Firefox 52 fires "readystatechange" (xhr.readyState === 4) without final "readystatechange" (xhr.readyState === 3)
|
135 |
+
// IE 8 fires "onload" without "onprogress"
|
136 |
+
onProgress();
|
137 |
+
if (state === 1 || state === 2 || state === 3) {
|
138 |
+
state = 4;
|
139 |
+
if (timeout !== 0) {
|
140 |
+
clearTimeout(timeout);
|
141 |
+
timeout = 0;
|
142 |
+
}
|
143 |
+
that.readyState = 4;
|
144 |
+
that.onreadystatechange();
|
145 |
+
}
|
146 |
+
};
|
147 |
+
var onReadyStateChange = function () {
|
148 |
+
if (xhr != undefined) { // Opera 12
|
149 |
+
if (xhr.readyState === 4) {
|
150 |
+
onFinish();
|
151 |
+
} else if (xhr.readyState === 3) {
|
152 |
+
onProgress();
|
153 |
+
} else if (xhr.readyState === 2) {
|
154 |
+
onStart();
|
155 |
+
}
|
156 |
+
}
|
157 |
+
};
|
158 |
+
var onTimeout = function () {
|
159 |
+
timeout = setTimeout(function () {
|
160 |
+
onTimeout();
|
161 |
+
}, 500);
|
162 |
+
if (xhr.readyState === 3) {
|
163 |
+
onProgress();
|
164 |
+
}
|
165 |
+
};
|
166 |
+
|
167 |
+
// XDomainRequest#abort removes onprogress, onerror, onload
|
168 |
+
xhr.onload = onFinish;
|
169 |
+
xhr.onerror = onFinish;
|
170 |
+
// improper fix to match Firefox behaviour, but it is better than just ignore abort
|
171 |
+
// see https://bugzilla.mozilla.org/show_bug.cgi?id=768596
|
172 |
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=880200
|
173 |
+
// https://code.google.com/p/chromium/issues/detail?id=153570
|
174 |
+
// IE 8 fires "onload" without "onprogress
|
175 |
+
xhr.onabort = onFinish;
|
176 |
+
|
177 |
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=736723
|
178 |
+
if (!("sendAsBinary" in XMLHttpRequest.prototype) && !("mozAnon" in XMLHttpRequest.prototype)) {
|
179 |
+
xhr.onprogress = onProgress;
|
180 |
+
}
|
181 |
+
|
182 |
+
// IE 8 - 9 (XMLHTTPRequest)
|
183 |
+
// Opera < 12
|
184 |
+
// Firefox < 3.5
|
185 |
+
// Firefox 3.5 - 3.6 - ? < 9.0
|
186 |
+
// onprogress is not fired sometimes or delayed
|
187 |
+
// see also #64
|
188 |
+
xhr.onreadystatechange = onReadyStateChange;
|
189 |
+
|
190 |
+
if ("contentType" in xhr) {
|
191 |
+
url += (url.indexOf("?", 0) === -1 ? "?" : "&") + "padding=true";
|
192 |
+
}
|
193 |
+
xhr.open(method, url, true);
|
194 |
+
|
195 |
+
if ("readyState" in xhr) {
|
196 |
+
// workaround for Opera 12 issue with "progress" events
|
197 |
+
// #91
|
198 |
+
timeout = setTimeout(function () {
|
199 |
+
onTimeout();
|
200 |
+
}, 0);
|
201 |
+
}
|
202 |
+
};
|
203 |
+
XHRWrapper.prototype.abort = function () {
|
204 |
+
this._abort(false);
|
205 |
+
};
|
206 |
+
XHRWrapper.prototype.getResponseHeader = function (name) {
|
207 |
+
return this._contentType;
|
208 |
+
};
|
209 |
+
XHRWrapper.prototype.setRequestHeader = function (name, value) {
|
210 |
+
var xhr = this._xhr;
|
211 |
+
if ("setRequestHeader" in xhr) {
|
212 |
+
xhr.setRequestHeader(name, value);
|
213 |
+
}
|
214 |
+
};
|
215 |
+
XHRWrapper.prototype.send = function () {
|
216 |
+
// loading indicator in Safari < ? (6), Chrome < 14, Firefox
|
217 |
+
if (!("ontimeout" in XMLHttpRequest.prototype) &&
|
218 |
+
document != undefined &&
|
219 |
+
document.readyState != undefined &&
|
220 |
+
document.readyState !== "complete") {
|
221 |
+
var that = this;
|
222 |
+
that._sendTimeout = setTimeout(function () {
|
223 |
+
that._sendTimeout = 0;
|
224 |
+
that.send();
|
225 |
+
}, 4);
|
226 |
+
return;
|
227 |
+
}
|
228 |
+
|
229 |
+
var xhr = this._xhr;
|
230 |
+
// withCredentials should be set after "open" for Safari and Chrome (< 19 ?)
|
231 |
+
xhr.withCredentials = this.withCredentials;
|
232 |
+
xhr.responseType = this.responseType;
|
233 |
+
try {
|
234 |
+
// xhr.send(); throws "Not enough arguments" in Firefox 3.0
|
235 |
+
xhr.send(undefined);
|
236 |
+
} catch (error1) {
|
237 |
+
// Safari 5.1.7, Opera 12
|
238 |
+
throw error1;
|
239 |
+
}
|
240 |
+
};
|
241 |
+
|
242 |
+
function XHRTransport(xhr) {
|
243 |
+
this._xhr = new XHRWrapper(xhr);
|
244 |
+
}
|
245 |
+
|
246 |
+
XHRTransport.prototype.open = function (onStartCallback, onProgressCallback, onFinishCallback, url, withCredentials, headers) {
|
247 |
+
var xhr = this._xhr;
|
248 |
+
xhr.open("GET", url);
|
249 |
+
var offset = 0;
|
250 |
+
xhr.onprogress = function () {
|
251 |
+
var responseText = xhr.responseText;
|
252 |
+
var chunk = responseText.slice(offset);
|
253 |
+
offset += chunk.length;
|
254 |
+
onProgressCallback(chunk);
|
255 |
+
};
|
256 |
+
xhr.onreadystatechange = function () {
|
257 |
+
if (xhr.readyState === 2) {
|
258 |
+
var status = xhr.status;
|
259 |
+
var statusText = xhr.statusText;
|
260 |
+
var contentType = xhr.getResponseHeader("Content-Type");
|
261 |
+
onStartCallback(status, statusText, contentType);
|
262 |
+
} else if (xhr.readyState === 4) {
|
263 |
+
onFinishCallback();
|
264 |
+
}
|
265 |
+
};
|
266 |
+
xhr.withCredentials = withCredentials;
|
267 |
+
xhr.responseType = "text";
|
268 |
+
for (var name in headers) {
|
269 |
+
if (Object.prototype.hasOwnProperty.call(headers, name)) {
|
270 |
+
xhr.setRequestHeader(name, headers[name]);
|
271 |
+
}
|
272 |
+
}
|
273 |
+
xhr.send();
|
274 |
+
};
|
275 |
+
|
276 |
+
XHRTransport.prototype.cancel = function () {
|
277 |
+
var xhr = this._xhr;
|
278 |
+
xhr.abort();
|
279 |
+
};
|
280 |
+
|
281 |
+
function EventTarget() {
|
282 |
+
this._listeners = Object.create(null);
|
283 |
+
}
|
284 |
+
|
285 |
+
function throwError(e) {
|
286 |
+
setTimeout(function () {
|
287 |
+
throw e;
|
288 |
+
}, 0);
|
289 |
+
}
|
290 |
+
|
291 |
+
EventTarget.prototype.dispatchEvent = function (event) {
|
292 |
+
event.target = this;
|
293 |
+
var typeListeners = this._listeners[event.type];
|
294 |
+
if (typeListeners != undefined) {
|
295 |
+
var length = typeListeners.length;
|
296 |
+
for (var i = 0; i < length; i += 1) {
|
297 |
+
var listener = typeListeners[i];
|
298 |
+
try {
|
299 |
+
if (typeof listener.handleEvent === "function") {
|
300 |
+
listener.handleEvent(event);
|
301 |
+
} else {
|
302 |
+
listener.call(this, event);
|
303 |
+
}
|
304 |
+
} catch (e) {
|
305 |
+
throwError(e);
|
306 |
+
}
|
307 |
+
}
|
308 |
+
}
|
309 |
+
};
|
310 |
+
EventTarget.prototype.addEventListener = function (type, listener) {
|
311 |
+
type = String(type);
|
312 |
+
var listeners = this._listeners;
|
313 |
+
var typeListeners = listeners[type];
|
314 |
+
if (typeListeners == undefined) {
|
315 |
+
typeListeners = [];
|
316 |
+
listeners[type] = typeListeners;
|
317 |
+
}
|
318 |
+
var found = false;
|
319 |
+
for (var i = 0; i < typeListeners.length; i += 1) {
|
320 |
+
if (typeListeners[i] === listener) {
|
321 |
+
found = true;
|
322 |
+
}
|
323 |
+
}
|
324 |
+
if (!found) {
|
325 |
+
typeListeners.push(listener);
|
326 |
+
}
|
327 |
+
};
|
328 |
+
EventTarget.prototype.removeEventListener = function (type, listener) {
|
329 |
+
type = String(type);
|
330 |
+
var listeners = this._listeners;
|
331 |
+
var typeListeners = listeners[type];
|
332 |
+
if (typeListeners != undefined) {
|
333 |
+
var filtered = [];
|
334 |
+
for (var i = 0; i < typeListeners.length; i += 1) {
|
335 |
+
if (typeListeners[i] !== listener) {
|
336 |
+
filtered.push(typeListeners[i]);
|
337 |
+
}
|
338 |
+
}
|
339 |
+
if (filtered.length === 0) {
|
340 |
+
delete listeners[type];
|
341 |
+
} else {
|
342 |
+
listeners[type] = filtered;
|
343 |
+
}
|
344 |
+
}
|
345 |
+
};
|
346 |
+
|
347 |
+
function Event(type) {
|
348 |
+
this.type = type;
|
349 |
+
this.target = undefined;
|
350 |
+
}
|
351 |
+
|
352 |
+
function MessageEvent(type, options) {
|
353 |
+
Event.call(this, type);
|
354 |
+
this.data = options.data;
|
355 |
+
this.lastEventId = options.lastEventId;
|
356 |
+
}
|
357 |
+
|
358 |
+
MessageEvent.prototype = Object.create(Event.prototype);
|
359 |
+
|
360 |
+
var WAITING = -1;
|
361 |
+
var CONNECTING = 0;
|
362 |
+
var OPEN = 1;
|
363 |
+
var CLOSED = 2;
|
364 |
+
|
365 |
+
var AFTER_CR = -1;
|
366 |
+
var FIELD_START = 0;
|
367 |
+
var FIELD = 1;
|
368 |
+
var VALUE_START = 2;
|
369 |
+
var VALUE = 3;
|
370 |
+
|
371 |
+
var contentTypeRegExp = /^text\/event\-stream;?(\s*charset\=utf\-8)?$/i;
|
372 |
+
|
373 |
+
var MINIMUM_DURATION = 1000;
|
374 |
+
var MAXIMUM_DURATION = 18000000;
|
375 |
+
|
376 |
+
var parseDuration = function (value, def) {
|
377 |
+
var n = parseInt(value, 10);
|
378 |
+
if (n !== n) {
|
379 |
+
n = def;
|
380 |
+
}
|
381 |
+
return clampDuration(n);
|
382 |
+
};
|
383 |
+
var clampDuration = function (n) {
|
384 |
+
return Math.min(Math.max(n, MINIMUM_DURATION), MAXIMUM_DURATION);
|
385 |
+
};
|
386 |
+
|
387 |
+
var fire = function (that, f, event) {
|
388 |
+
try {
|
389 |
+
if (typeof f === "function") {
|
390 |
+
f.call(that, event);
|
391 |
+
}
|
392 |
+
} catch (e) {
|
393 |
+
throwError(e);
|
394 |
+
}
|
395 |
+
};
|
396 |
+
|
397 |
+
function EventSourcePolyfill(url, options) {
|
398 |
+
EventTarget.call(this);
|
399 |
+
|
400 |
+
this.onopen = undefined;
|
401 |
+
this.onmessage = undefined;
|
402 |
+
this.onerror = undefined;
|
403 |
+
|
404 |
+
this.url = undefined;
|
405 |
+
this.readyState = undefined;
|
406 |
+
this.withCredentials = undefined;
|
407 |
+
|
408 |
+
this._close = undefined;
|
409 |
+
|
410 |
+
start(this, url, options);
|
411 |
+
}
|
412 |
+
|
413 |
+
function start(es, url, options) {
|
414 |
+
url = String(url);
|
415 |
+
var withCredentials = options != undefined && Boolean(options.withCredentials);
|
416 |
+
|
417 |
+
var initialRetry = clampDuration(1000);
|
418 |
+
var heartbeatTimeout = clampDuration(45000);
|
419 |
+
|
420 |
+
var lastEventId = "";
|
421 |
+
var retry = initialRetry;
|
422 |
+
var wasActivity = false;
|
423 |
+
var headers = options != undefined && options.headers != undefined ? JSON.parse(JSON.stringify(options.headers)) : undefined;
|
424 |
+
var CurrentTransport = options != undefined && options.Transport != undefined ? options.Transport : (XDomainRequest != undefined ? XDomainRequest : XMLHttpRequest);
|
425 |
+
var transport = new XHRTransport(new CurrentTransport());
|
426 |
+
var timeout = 0;
|
427 |
+
var currentState = WAITING;
|
428 |
+
var dataBuffer = "";
|
429 |
+
var lastEventIdBuffer = "";
|
430 |
+
var eventTypeBuffer = "";
|
431 |
+
|
432 |
+
var textBuffer = "";
|
433 |
+
var state = FIELD_START;
|
434 |
+
var fieldStart = 0;
|
435 |
+
var valueStart = 0;
|
436 |
+
|
437 |
+
var onStart = function (status, statusText, contentType) {
|
438 |
+
if (currentState === CONNECTING) {
|
439 |
+
if (status === 200 && contentType != undefined && contentTypeRegExp.test(contentType)) {
|
440 |
+
currentState = OPEN;
|
441 |
+
wasActivity = true;
|
442 |
+
retry = initialRetry;
|
443 |
+
es.readyState = OPEN;
|
444 |
+
var event = new Event("open");
|
445 |
+
es.dispatchEvent(event);
|
446 |
+
fire(es, es.onopen, event);
|
447 |
+
} else {
|
448 |
+
var message = "";
|
449 |
+
if (status !== 200) {
|
450 |
+
if (statusText) {
|
451 |
+
statusText = statusText.replace(/\s+/g, " ");
|
452 |
+
}
|
453 |
+
message = "EventSource's response has a status " + status + " " + statusText + " that is not 200. Aborting the connection.";
|
454 |
+
} else {
|
455 |
+
message = "EventSource's response has a Content-Type specifying an unsupported type: " + (contentType == undefined ? "-" : contentType.replace(/\s+/g, " ")) + ". Aborting the connection.";
|
456 |
+
}
|
457 |
+
throwError(new Error(message));
|
458 |
+
close();
|
459 |
+
var event = new Event("error");
|
460 |
+
es.dispatchEvent(event);
|
461 |
+
fire(es, es.onerror, event);
|
462 |
+
}
|
463 |
+
}
|
464 |
+
};
|
465 |
+
|
466 |
+
var onProgress = function (textChunk) {
|
467 |
+
if (currentState === OPEN) {
|
468 |
+
var n = -1;
|
469 |
+
for (var i = 0; i < textChunk.length; i += 1) {
|
470 |
+
var c = textChunk.charCodeAt(i);
|
471 |
+
if (c === "\n".charCodeAt(0) || c === "\r".charCodeAt(0)) {
|
472 |
+
n = i;
|
473 |
+
}
|
474 |
+
}
|
475 |
+
var chunk = (n !== -1 ? textBuffer : "") + textChunk.slice(0, n + 1);
|
476 |
+
textBuffer = (n === -1 ? textBuffer : "") + textChunk.slice(n + 1);
|
477 |
+
if (chunk !== "") {
|
478 |
+
wasActivity = true;
|
479 |
+
}
|
480 |
+
for (var position = 0; position < chunk.length; position += 1) {
|
481 |
+
var c = chunk.charCodeAt(position);
|
482 |
+
if (state === AFTER_CR && c === "\n".charCodeAt(0)) {
|
483 |
+
state = FIELD_START;
|
484 |
+
} else {
|
485 |
+
if (state === AFTER_CR) {
|
486 |
+
state = FIELD_START;
|
487 |
+
}
|
488 |
+
if (c === "\r".charCodeAt(0) || c === "\n".charCodeAt(0)) {
|
489 |
+
if (state !== FIELD_START) {
|
490 |
+
if (state === FIELD) {
|
491 |
+
valueStart = position + 1;
|
492 |
+
}
|
493 |
+
var field = chunk.slice(fieldStart, valueStart - 1);
|
494 |
+
var value = chunk.slice(valueStart + (valueStart < position && chunk.charCodeAt(valueStart) === " ".charCodeAt(0) ? 1 : 0), position);
|
495 |
+
if (field === "data") {
|
496 |
+
dataBuffer += "\n";
|
497 |
+
dataBuffer += value;
|
498 |
+
} else if (field === "id") {
|
499 |
+
lastEventIdBuffer = value;
|
500 |
+
} else if (field === "event") {
|
501 |
+
eventTypeBuffer = value;
|
502 |
+
} else if (field === "retry") {
|
503 |
+
initialRetry = parseDuration(value, initialRetry);
|
504 |
+
retry = initialRetry;
|
505 |
+
} else if (field === "heartbeatTimeout") {
|
506 |
+
heartbeatTimeout = parseDuration(value, heartbeatTimeout);
|
507 |
+
if (timeout !== 0) {
|
508 |
+
clearTimeout(timeout);
|
509 |
+
timeout = setTimeout(function () {
|
510 |
+
onTimeout();
|
511 |
+
}, heartbeatTimeout);
|
512 |
+
}
|
513 |
+
}
|
514 |
+
}
|
515 |
+
if (state === FIELD_START) {
|
516 |
+
if (dataBuffer !== "") {
|
517 |
+
lastEventId = lastEventIdBuffer;
|
518 |
+
if (eventTypeBuffer === "") {
|
519 |
+
eventTypeBuffer = "message";
|
520 |
+
}
|
521 |
+
var event = new MessageEvent(eventTypeBuffer, {
|
522 |
+
data: dataBuffer.slice(1),
|
523 |
+
lastEventId: lastEventIdBuffer
|
524 |
+
});
|
525 |
+
es.dispatchEvent(event);
|
526 |
+
if (eventTypeBuffer === "message") {
|
527 |
+
fire(es, es.onmessage, event);
|
528 |
+
}
|
529 |
+
if (currentState === CLOSED) {
|
530 |
+
return;
|
531 |
+
}
|
532 |
+
}
|
533 |
+
dataBuffer = "";
|
534 |
+
eventTypeBuffer = "";
|
535 |
+
}
|
536 |
+
state = c === "\r".charCodeAt(0) ? AFTER_CR : FIELD_START;
|
537 |
+
} else {
|
538 |
+
if (state === FIELD_START) {
|
539 |
+
fieldStart = position;
|
540 |
+
state = FIELD;
|
541 |
+
}
|
542 |
+
if (state === FIELD) {
|
543 |
+
if (c === ":".charCodeAt(0)) {
|
544 |
+
valueStart = position + 1;
|
545 |
+
state = VALUE_START;
|
546 |
+
}
|
547 |
+
} else if (state === VALUE_START) {
|
548 |
+
state = VALUE;
|
549 |
+
}
|
550 |
+
}
|
551 |
+
}
|
552 |
+
}
|
553 |
+
}
|
554 |
+
};
|
555 |
+
|
556 |
+
var onFinish = function () {
|
557 |
+
if (currentState === OPEN || currentState === CONNECTING) {
|
558 |
+
currentState = WAITING;
|
559 |
+
if (timeout !== 0) {
|
560 |
+
clearTimeout(timeout);
|
561 |
+
timeout = 0;
|
562 |
+
}
|
563 |
+
timeout = setTimeout(function () {
|
564 |
+
onTimeout();
|
565 |
+
}, retry);
|
566 |
+
retry = clampDuration(Math.min(initialRetry * 16, retry * 2));
|
567 |
+
|
568 |
+
es.readyState = CONNECTING;
|
569 |
+
var event = new Event("error");
|
570 |
+
es.dispatchEvent(event);
|
571 |
+
fire(es, es.onerror, event);
|
572 |
+
}
|
573 |
+
};
|
574 |
+
|
575 |
+
var close = function () {
|
576 |
+
currentState = CLOSED;
|
577 |
+
transport.cancel();
|
578 |
+
if (timeout !== 0) {
|
579 |
+
clearTimeout(timeout);
|
580 |
+
timeout = 0;
|
581 |
+
}
|
582 |
+
es.readyState = CLOSED;
|
583 |
+
};
|
584 |
+
|
585 |
+
var onTimeout = function () {
|
586 |
+
timeout = 0;
|
587 |
+
|
588 |
+
if (currentState !== WAITING) {
|
589 |
+
if (!wasActivity) {
|
590 |
+
throwError(new Error("No activity within " + heartbeatTimeout + " milliseconds. Reconnecting."));
|
591 |
+
transport.cancel();
|
592 |
+
} else {
|
593 |
+
wasActivity = false;
|
594 |
+
timeout = setTimeout(function () {
|
595 |
+
onTimeout();
|
596 |
+
}, heartbeatTimeout);
|
597 |
+
}
|
598 |
+
return;
|
599 |
+
}
|
600 |
+
|
601 |
+
wasActivity = false;
|
602 |
+
timeout = setTimeout(function () {
|
603 |
+
onTimeout();
|
604 |
+
}, heartbeatTimeout);
|
605 |
+
|
606 |
+
currentState = CONNECTING;
|
607 |
+
dataBuffer = "";
|
608 |
+
eventTypeBuffer = "";
|
609 |
+
lastEventIdBuffer = lastEventId;
|
610 |
+
textBuffer = "";
|
611 |
+
fieldStart = 0;
|
612 |
+
valueStart = 0;
|
613 |
+
state = FIELD_START;
|
614 |
+
|
615 |
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=428916
|
616 |
+
// Request header field Last-Event-ID is not allowed by Access-Control-Allow-Headers.
|
617 |
+
var requestURL = url;
|
618 |
+
if (url.slice(0, 5) !== "data:" &&
|
619 |
+
url.slice(0, 5) !== "blob:") {
|
620 |
+
requestURL = url + (url.indexOf("?", 0) === -1 ? "?" : "&") + "lastEventId=" + encodeURIComponent(lastEventId);
|
621 |
+
}
|
622 |
+
var requestHeaders = {};
|
623 |
+
requestHeaders["Accept"] = "text/event-stream";
|
624 |
+
if (headers != undefined) {
|
625 |
+
for (var name in headers) {
|
626 |
+
if (Object.prototype.hasOwnProperty.call(headers, name)) {
|
627 |
+
requestHeaders[name] = headers[name];
|
628 |
+
}
|
629 |
+
}
|
630 |
+
}
|
631 |
+
try {
|
632 |
+
transport.open(onStart, onProgress, onFinish, requestURL, withCredentials, requestHeaders);
|
633 |
+
} catch (error) {
|
634 |
+
close();
|
635 |
+
throw error;
|
636 |
+
}
|
637 |
+
};
|
638 |
+
|
639 |
+
es.url = url;
|
640 |
+
es.readyState = CONNECTING;
|
641 |
+
es.withCredentials = withCredentials;
|
642 |
+
es._close = close;
|
643 |
+
|
644 |
+
onTimeout();
|
645 |
+
}
|
646 |
+
|
647 |
+
EventSourcePolyfill.prototype = Object.create(EventTarget.prototype);
|
648 |
+
EventSourcePolyfill.prototype.CONNECTING = CONNECTING;
|
649 |
+
EventSourcePolyfill.prototype.OPEN = OPEN;
|
650 |
+
EventSourcePolyfill.prototype.CLOSED = CLOSED;
|
651 |
+
EventSourcePolyfill.prototype.close = function () {
|
652 |
+
this._close();
|
653 |
+
};
|
654 |
+
|
655 |
+
EventSourcePolyfill.CONNECTING = CONNECTING;
|
656 |
+
EventSourcePolyfill.OPEN = OPEN;
|
657 |
+
EventSourcePolyfill.CLOSED = CLOSED;
|
658 |
+
EventSourcePolyfill.prototype.withCredentials = undefined;
|
659 |
+
|
660 |
+
global.EventSourcePolyfill = EventSourcePolyfill;
|
661 |
+
global.NativeEventSource = NativeEventSource;
|
662 |
+
|
663 |
+
if (XMLHttpRequest != undefined && (NativeEventSource == undefined || !("withCredentials" in NativeEventSource.prototype))) {
|
664 |
+
// Why replace a native EventSource ?
|
665 |
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=444328
|
666 |
+
// https://bugzilla.mozilla.org/show_bug.cgi?id=831392
|
667 |
+
// https://code.google.com/p/chromium/issues/detail?id=260144
|
668 |
+
// https://code.google.com/p/chromium/issues/detail?id=225654
|
669 |
+
// ...
|
670 |
+
global.EventSource = EventSourcePolyfill;
|
671 |
+
}
|
672 |
+
|
673 |
+
}(typeof window !== 'undefined' ? window : this));
|
inc/assets/js/eventsource.min.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
-
/** @license
|
2 |
-
* eventsource.js
|
3 |
-
* Available under MIT License (MIT)
|
4 |
-
* https://github.com/Yaffle/EventSource/
|
5 |
-
*/
|
6 |
ย
!function(a){"use strict";function b(a){this.withCredentials=!1,this.responseType="",this.readyState=0,this.status=0,this.statusText="",this.responseText="",this.onprogress=p,this.onreadystatechange=p,this._contentType="",this._xhr=a,this._sendTimeout=0,this._abort=p}function c(a){this._xhr=new b(a)}function d(){this._listeners=Object.create(null)}function e(a){j(function(){throw a},0)}function f(a){this.type=a,this.target=void 0}function g(a,b){f.call(this,a),this.data=b.data,this.lastEventId=b.lastEventId}function h(a,b){d.call(this),this.onopen=void 0,this.onmessage=void 0,this.onerror=void 0,this.url=void 0,this.readyState=void 0,this.withCredentials=void 0,this._close=void 0,i(this,a,b)}function i(a,b,d){b=String(b);var h=void 0!=d&&Boolean(d.withCredentials),i=D(1e3),n=D(45e3),o="",p=i,A=!1,B=void 0!=d&&void 0!=d.headers?JSON.parse(JSON.stringify(d.headers)):void 0,F=void 0!=d&&void 0!=d.Transport?d.Transport:void 0!=m?m:l,G=new c(new F),H=0,I=q,J="",K="",L="",M="",N=v,O=0,P=0,Q=function(b,c,d){if(I===r)if(200===b&&void 0!=d&&z.test(d)){I=s,A=!0,p=i,a.readyState=s;var g=new f("open");a.dispatchEvent(g),E(a,a.onopen,g)}else{var h="";200!==b?(c&&(c=c.replace(/\s+/g," ")),h="EventSource's response has a status "+b+" "+c+" that is not 200. Aborting the connection."):h="EventSource's response has a Content-Type specifying an unsupported type: "+(void 0==d?"-":d.replace(/\s+/g," "))+". Aborting the connection.",e(new Error(h)),T();var g=new f("error");a.dispatchEvent(g),E(a,a.onerror,g)}},R=function(b){if(I===s){for(var c=-1,d=0;d<b.length;d+=1){var e=b.charCodeAt(d);(e==="\n".charCodeAt(0)||e==="\r".charCodeAt(0))&&(c=d)}var f=(-1!==c?M:"")+b.slice(0,c+1);M=(-1===c?M:"")+b.slice(c+1),""!==f&&(A=!0);for(var h=0;h<f.length;h+=1){var e=f.charCodeAt(h);if(N===u&&e==="\n".charCodeAt(0))N=v;else if(N===u&&(N=v),e==="\r".charCodeAt(0)||e==="\n".charCodeAt(0)){if(N!==v){N===w&&(P=h+1);var l=f.slice(O,P-1),m=f.slice(P+(h>P&&f.charCodeAt(P)===" ".charCodeAt(0)?1:0),h);"data"===l?(J+="\n",J+=m):"id"===l?K=m:"event"===l?L=m:"retry"===l?(i=C(m,i),p=i):"heartbeatTimeout"===l&&(n=C(m,n),0!==H&&(k(H),H=j(function(){U()},n)))}if(N===v){if(""!==J){o=K,""===L&&(L="message");var q=new g(L,{data:J.slice(1),lastEventId:K});if(a.dispatchEvent(q),"message"===L&&E(a,a.onmessage,q),I===t)return}J="",L=""}N=e==="\r".charCodeAt(0)?u:v}else N===v&&(O=h,N=w),N===w?e===":".charCodeAt(0)&&(P=h+1,N=x):N===x&&(N=y)}}},S=function(){if(I===s||I===r){I=q,0!==H&&(k(H),H=0),H=j(function(){U()},p),p=D(Math.min(16*i,2*p)),a.readyState=r;var b=new f("error");a.dispatchEvent(b),E(a,a.onerror,b)}},T=function(){I=t,G.cancel(),0!==H&&(k(H),H=0),a.readyState=t},U=function(){if(H=0,I!==q)return void(A?(A=!1,H=j(function(){U()},n)):(e(new Error("No activity within "+n+" milliseconds. Reconnecting.")),G.cancel()));A=!1,H=j(function(){U()},n),I=r,J="",L="",K=o,M="",O=0,P=0,N=v;var a=b;"data:"!==b.slice(0,5)&&"blob:"!==b.slice(0,5)&&(a=b+(-1===b.indexOf("?",0)?"?":"&")+"lastEventId="+encodeURIComponent(o));var c={};if(c.Accept="text/event-stream",void 0!=B)for(var d in B)Object.prototype.hasOwnProperty.call(B,d)&&(c[d]=B[d]);try{G.open(Q,R,S,a,h,c)}catch(f){throw T(),f}};a.url=b,a.readyState=r,a.withCredentials=h,a._close=T,U()}var j=a.setTimeout,k=a.clearTimeout,l=a.XMLHttpRequest,m=a.XDomainRequest,n=a.EventSource,o=a.document;null==Object.create&&(Object.create=function(a){function b(){}return b.prototype=a,new b});var p=function(){};b.prototype.open=function(a,b){this._abort(!0);var c=this,d=this._xhr,e=1,f=0;this._abort=function(a){0!==c._sendTimeout&&(k(c._sendTimeout),c._sendTimeout=0),(1===e||2===e||3===e)&&(e=4,d.onload=p,d.onerror=p,d.onabort=p,d.onprogress=p,d.onreadystatechange=p,d.abort(),0!==f&&(k(f),f=0),a||(c.readyState=4,c.onreadystatechange())),e=0};var g=function(){if(1===e){var a=0,b="",f=void 0;if("contentType"in d)a=200,b="OK",f=d.contentType;else try{a=d.status,b=d.statusText,f=d.getResponseHeader("Content-Type")}catch(g){a=0,b="",f=void 0}0!==a&&(e=2,c.readyState=2,c.status=a,c.statusText=b,c._contentType=f,c.onreadystatechange())}},h=function(){if(g(),2===e||3===e){e=3;var a="";try{a=d.responseText}catch(b){}c.readyState=3,c.responseText=a,c.onprogress()}},i=function(){h(),(1===e||2===e||3===e)&&(e=4,0!==f&&(k(f),f=0),c.readyState=4,c.onreadystatechange())},m=function(){void 0!=d&&(4===d.readyState?i():3===d.readyState?h():2===d.readyState&&g())},n=function(){f=j(function(){n()},500),3===d.readyState&&h()};d.onload=i,d.onerror=i,d.onabort=i,"sendAsBinary"in l.prototype||"mozAnon"in l.prototype||(d.onprogress=h),d.onreadystatechange=m,"contentType"in d&&(b+=(-1===b.indexOf("?",0)?"?":"&")+"padding=true"),d.open(a,b,!0),"readyState"in d&&(f=j(function(){n()},0))},b.prototype.abort=function(){this._abort(!1)},b.prototype.getResponseHeader=function(a){return this._contentType},b.prototype.setRequestHeader=function(a,b){var c=this._xhr;"setRequestHeader"in c&&c.setRequestHeader(a,b)},b.prototype.send=function(){if(!("ontimeout"in l.prototype)&&void 0!=o&&void 0!=o.readyState&&"complete"!==o.readyState){var a=this;return void(a._sendTimeout=j(function(){a._sendTimeout=0,a.send()},4))}var b=this._xhr;b.withCredentials=this.withCredentials,b.responseType=this.responseType;try{b.send(void 0)}catch(c){throw c}},c.prototype.open=function(a,b,c,d,e,f){var g=this._xhr;g.open("GET",d);var h=0;g.onprogress=function(){var a=g.responseText,c=a.slice(h);h+=c.length,b(c)},g.onreadystatechange=function(){if(2===g.readyState){var b=g.status,d=g.statusText,e=g.getResponseHeader("Content-Type");a(b,d,e)}else 4===g.readyState&&c()},g.withCredentials=e,g.responseType="text";for(var i in f)Object.prototype.hasOwnProperty.call(f,i)&&g.setRequestHeader(i,f[i]);g.send()},c.prototype.cancel=function(){var a=this._xhr;a.abort()},d.prototype.dispatchEvent=function(a){a.target=this;var b=this._listeners[a.type];if(void 0!=b)for(var c=b.length,d=0;c>d;d+=1){var f=b[d];try{"function"==typeof f.handleEvent?f.handleEvent(a):f.call(this,a)}catch(g){e(g)}}},d.prototype.addEventListener=function(a,b){a=String(a);var c=this._listeners,d=c[a];void 0==d&&(d=[],c[a]=d);for(var e=!1,f=0;f<d.length;f+=1)d[f]===b&&(e=!0);e||d.push(b)},d.prototype.removeEventListener=function(a,b){a=String(a);var c=this._listeners,d=c[a];if(void 0!=d){for(var e=[],f=0;f<d.length;f+=1)d[f]!==b&&e.push(d[f]);0===e.length?delete c[a]:c[a]=e}},g.prototype=Object.create(f.prototype);var q=-1,r=0,s=1,t=2,u=-1,v=0,w=1,x=2,y=3,z=/^text\/event\-stream;?(\s*charset\=utf\-8)?$/i,A=1e3,B=18e6,C=function(a,b){var c=parseInt(a,10);return c!==c&&(c=b),D(c)},D=function(a){return Math.min(Math.max(a,A),B)},E=function(a,b,c){try{"function"==typeof b&&b.call(a,c)}catch(d){e(d)}};h.prototype=Object.create(d.prototype),h.prototype.CONNECTING=r,h.prototype.OPEN=s,h.prototype.CLOSED=t,h.prototype.close=function(){this._close()},h.CONNECTING=r,h.OPEN=s,h.CLOSED=t,h.prototype.withCredentials=void 0,a.EventSourcePolyfill=h,a.NativeEventSource=n,void 0==l||void 0!=n&&"withCredentials"in n.prototype||(a.EventSource=h)}("undefined"!=typeof window?window:this);
|
1 |
+
/** @license
|
2 |
+
* eventsource.js
|
3 |
+
* Available under MIT License (MIT)
|
4 |
+
* https://github.com/Yaffle/EventSource/
|
5 |
+
*/
|
6 |
ย
!function(a){"use strict";function b(a){this.withCredentials=!1,this.responseType="",this.readyState=0,this.status=0,this.statusText="",this.responseText="",this.onprogress=p,this.onreadystatechange=p,this._contentType="",this._xhr=a,this._sendTimeout=0,this._abort=p}function c(a){this._xhr=new b(a)}function d(){this._listeners=Object.create(null)}function e(a){j(function(){throw a},0)}function f(a){this.type=a,this.target=void 0}function g(a,b){f.call(this,a),this.data=b.data,this.lastEventId=b.lastEventId}function h(a,b){d.call(this),this.onopen=void 0,this.onmessage=void 0,this.onerror=void 0,this.url=void 0,this.readyState=void 0,this.withCredentials=void 0,this._close=void 0,i(this,a,b)}function i(a,b,d){b=String(b);var h=void 0!=d&&Boolean(d.withCredentials),i=D(1e3),n=D(45e3),o="",p=i,A=!1,B=void 0!=d&&void 0!=d.headers?JSON.parse(JSON.stringify(d.headers)):void 0,F=void 0!=d&&void 0!=d.Transport?d.Transport:void 0!=m?m:l,G=new c(new F),H=0,I=q,J="",K="",L="",M="",N=v,O=0,P=0,Q=function(b,c,d){if(I===r)if(200===b&&void 0!=d&&z.test(d)){I=s,A=!0,p=i,a.readyState=s;var g=new f("open");a.dispatchEvent(g),E(a,a.onopen,g)}else{var h="";200!==b?(c&&(c=c.replace(/\s+/g," ")),h="EventSource's response has a status "+b+" "+c+" that is not 200. Aborting the connection."):h="EventSource's response has a Content-Type specifying an unsupported type: "+(void 0==d?"-":d.replace(/\s+/g," "))+". Aborting the connection.",e(new Error(h)),T();var g=new f("error");a.dispatchEvent(g),E(a,a.onerror,g)}},R=function(b){if(I===s){for(var c=-1,d=0;d<b.length;d+=1){var e=b.charCodeAt(d);(e==="\n".charCodeAt(0)||e==="\r".charCodeAt(0))&&(c=d)}var f=(-1!==c?M:"")+b.slice(0,c+1);M=(-1===c?M:"")+b.slice(c+1),""!==f&&(A=!0);for(var h=0;h<f.length;h+=1){var e=f.charCodeAt(h);if(N===u&&e==="\n".charCodeAt(0))N=v;else if(N===u&&(N=v),e==="\r".charCodeAt(0)||e==="\n".charCodeAt(0)){if(N!==v){N===w&&(P=h+1);var l=f.slice(O,P-1),m=f.slice(P+(h>P&&f.charCodeAt(P)===" ".charCodeAt(0)?1:0),h);"data"===l?(J+="\n",J+=m):"id"===l?K=m:"event"===l?L=m:"retry"===l?(i=C(m,i),p=i):"heartbeatTimeout"===l&&(n=C(m,n),0!==H&&(k(H),H=j(function(){U()},n)))}if(N===v){if(""!==J){o=K,""===L&&(L="message");var q=new g(L,{data:J.slice(1),lastEventId:K});if(a.dispatchEvent(q),"message"===L&&E(a,a.onmessage,q),I===t)return}J="",L=""}N=e==="\r".charCodeAt(0)?u:v}else N===v&&(O=h,N=w),N===w?e===":".charCodeAt(0)&&(P=h+1,N=x):N===x&&(N=y)}}},S=function(){if(I===s||I===r){I=q,0!==H&&(k(H),H=0),H=j(function(){U()},p),p=D(Math.min(16*i,2*p)),a.readyState=r;var b=new f("error");a.dispatchEvent(b),E(a,a.onerror,b)}},T=function(){I=t,G.cancel(),0!==H&&(k(H),H=0),a.readyState=t},U=function(){if(H=0,I!==q)return void(A?(A=!1,H=j(function(){U()},n)):(e(new Error("No activity within "+n+" milliseconds. Reconnecting.")),G.cancel()));A=!1,H=j(function(){U()},n),I=r,J="",L="",K=o,M="",O=0,P=0,N=v;var a=b;"data:"!==b.slice(0,5)&&"blob:"!==b.slice(0,5)&&(a=b+(-1===b.indexOf("?",0)?"?":"&")+"lastEventId="+encodeURIComponent(o));var c={};if(c.Accept="text/event-stream",void 0!=B)for(var d in B)Object.prototype.hasOwnProperty.call(B,d)&&(c[d]=B[d]);try{G.open(Q,R,S,a,h,c)}catch(f){throw T(),f}};a.url=b,a.readyState=r,a.withCredentials=h,a._close=T,U()}var j=a.setTimeout,k=a.clearTimeout,l=a.XMLHttpRequest,m=a.XDomainRequest,n=a.EventSource,o=a.document;null==Object.create&&(Object.create=function(a){function b(){}return b.prototype=a,new b});var p=function(){};b.prototype.open=function(a,b){this._abort(!0);var c=this,d=this._xhr,e=1,f=0;this._abort=function(a){0!==c._sendTimeout&&(k(c._sendTimeout),c._sendTimeout=0),(1===e||2===e||3===e)&&(e=4,d.onload=p,d.onerror=p,d.onabort=p,d.onprogress=p,d.onreadystatechange=p,d.abort(),0!==f&&(k(f),f=0),a||(c.readyState=4,c.onreadystatechange())),e=0};var g=function(){if(1===e){var a=0,b="",f=void 0;if("contentType"in d)a=200,b="OK",f=d.contentType;else try{a=d.status,b=d.statusText,f=d.getResponseHeader("Content-Type")}catch(g){a=0,b="",f=void 0}0!==a&&(e=2,c.readyState=2,c.status=a,c.statusText=b,c._contentType=f,c.onreadystatechange())}},h=function(){if(g(),2===e||3===e){e=3;var a="";try{a=d.responseText}catch(b){}c.readyState=3,c.responseText=a,c.onprogress()}},i=function(){h(),(1===e||2===e||3===e)&&(e=4,0!==f&&(k(f),f=0),c.readyState=4,c.onreadystatechange())},m=function(){void 0!=d&&(4===d.readyState?i():3===d.readyState?h():2===d.readyState&&g())},n=function(){f=j(function(){n()},500),3===d.readyState&&h()};d.onload=i,d.onerror=i,d.onabort=i,"sendAsBinary"in l.prototype||"mozAnon"in l.prototype||(d.onprogress=h),d.onreadystatechange=m,"contentType"in d&&(b+=(-1===b.indexOf("?",0)?"?":"&")+"padding=true"),d.open(a,b,!0),"readyState"in d&&(f=j(function(){n()},0))},b.prototype.abort=function(){this._abort(!1)},b.prototype.getResponseHeader=function(a){return this._contentType},b.prototype.setRequestHeader=function(a,b){var c=this._xhr;"setRequestHeader"in c&&c.setRequestHeader(a,b)},b.prototype.send=function(){if(!("ontimeout"in l.prototype)&&void 0!=o&&void 0!=o.readyState&&"complete"!==o.readyState){var a=this;return void(a._sendTimeout=j(function(){a._sendTimeout=0,a.send()},4))}var b=this._xhr;b.withCredentials=this.withCredentials,b.responseType=this.responseType;try{b.send(void 0)}catch(c){throw c}},c.prototype.open=function(a,b,c,d,e,f){var g=this._xhr;g.open("GET",d);var h=0;g.onprogress=function(){var a=g.responseText,c=a.slice(h);h+=c.length,b(c)},g.onreadystatechange=function(){if(2===g.readyState){var b=g.status,d=g.statusText,e=g.getResponseHeader("Content-Type");a(b,d,e)}else 4===g.readyState&&c()},g.withCredentials=e,g.responseType="text";for(var i in f)Object.prototype.hasOwnProperty.call(f,i)&&g.setRequestHeader(i,f[i]);g.send()},c.prototype.cancel=function(){var a=this._xhr;a.abort()},d.prototype.dispatchEvent=function(a){a.target=this;var b=this._listeners[a.type];if(void 0!=b)for(var c=b.length,d=0;c>d;d+=1){var f=b[d];try{"function"==typeof f.handleEvent?f.handleEvent(a):f.call(this,a)}catch(g){e(g)}}},d.prototype.addEventListener=function(a,b){a=String(a);var c=this._listeners,d=c[a];void 0==d&&(d=[],c[a]=d);for(var e=!1,f=0;f<d.length;f+=1)d[f]===b&&(e=!0);e||d.push(b)},d.prototype.removeEventListener=function(a,b){a=String(a);var c=this._listeners,d=c[a];if(void 0!=d){for(var e=[],f=0;f<d.length;f+=1)d[f]!==b&&e.push(d[f]);0===e.length?delete c[a]:c[a]=e}},g.prototype=Object.create(f.prototype);var q=-1,r=0,s=1,t=2,u=-1,v=0,w=1,x=2,y=3,z=/^text\/event\-stream;?(\s*charset\=utf\-8)?$/i,A=1e3,B=18e6,C=function(a,b){var c=parseInt(a,10);return c!==c&&(c=b),D(c)},D=function(a){return Math.min(Math.max(a,A),B)},E=function(a,b,c){try{"function"==typeof b&&b.call(a,c)}catch(d){e(d)}};h.prototype=Object.create(d.prototype),h.prototype.CONNECTING=r,h.prototype.OPEN=s,h.prototype.CLOSED=t,h.prototype.close=function(){this._close()},h.CONNECTING=r,h.OPEN=s,h.CLOSED=t,h.prototype.withCredentials=void 0,a.EventSourcePolyfill=h,a.NativeEventSource=n,void 0==l||void 0!=n&&"withCredentials"in n.prototype||(a.EventSource=h)}("undefined"!=typeof window?window:this);
|
inc/assets/js/render-grid.js
CHANGED
@@ -1,519 +1,559 @@
|
|
1 |
-
(function($){
|
2 |
-
AstraRender = {
|
3 |
-
|
4 |
-
_ref : null,
|
5 |
-
|
6 |
-
/**
|
7 |
-
* _api_params = {
|
8 |
-
* 'search' : '',
|
9 |
-
* 'per_page' : '',
|
10 |
-
* 'astra-site-category' : '',
|
11 |
-
* 'astra-site-page-builder' : '',
|
12 |
-
* 'page' : '',
|
13 |
-
* };
|
14 |
-
*
|
15 |
-
* E.g. per_page=<page-id>&astra-site-category=<category-ids>&astra-site-page-builder=<page-builder-ids>&page=<page>
|
16 |
-
*/
|
17 |
-
_api_params : {},
|
18 |
-
_breakpoint : 768,
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
this.
|
24 |
-
this.
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
*
|
30 |
-
*
|
31 |
-
* @
|
32 |
-
* @
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
$( document ).on('astra-sites-api-request-
|
38 |
-
$( document ).on('astra-api-
|
39 |
-
$( document ).on('astra-api-post-loaded'
|
40 |
-
$( document ).on('astra-api-
|
41 |
-
$( document ).on('astra-api-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
$( document ).on('
|
46 |
-
$( document ).on('
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
*
|
53 |
-
*
|
54 |
-
*
|
55 |
-
* -
|
56 |
-
* -
|
57 |
-
* - Added '
|
58 |
-
* -
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
$(this).
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
$('.
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
$('
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
*
|
91 |
-
*
|
92 |
-
*
|
93 |
-
* -
|
94 |
-
* - Added '
|
95 |
-
* -
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
$('
|
108 |
-
$('.
|
109 |
-
|
110 |
-
|
111 |
-
$('
|
112 |
-
|
113 |
-
|
114 |
-
AstraRender._ref
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
jQuery('body').
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
themesBottom =
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
storedCategories =
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
storedBuilders =
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
*
|
239 |
-
*
|
240 |
-
*
|
241 |
-
*
|
242 |
-
* @param {
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
AstraRender.
|
263 |
-
AstraRender.
|
264 |
-
AstraRender.
|
265 |
-
AstraRender.
|
266 |
-
AstraRender.
|
267 |
-
AstraRender.
|
268 |
-
AstraRender.
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
*
|
283 |
-
*
|
284 |
-
* @
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
*
|
306 |
-
*
|
307 |
-
* @
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
$('
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
519 |
ย
})(jQuery);
|
1 |
+
(function($){
|
2 |
+
AstraRender = {
|
3 |
+
|
4 |
+
_ref : null,
|
5 |
+
|
6 |
+
/**
|
7 |
+
* _api_params = {
|
8 |
+
* 'search' : '',
|
9 |
+
* 'per_page' : '',
|
10 |
+
* 'astra-site-category' : '',
|
11 |
+
* 'astra-site-page-builder' : '',
|
12 |
+
* 'page' : '',
|
13 |
+
* };
|
14 |
+
*
|
15 |
+
* E.g. per_page=<page-id>&astra-site-category=<category-ids>&astra-site-page-builder=<page-builder-ids>&page=<page>
|
16 |
+
*/
|
17 |
+
_api_params : {},
|
18 |
+
_breakpoint : 768,
|
19 |
+
_has_default_page_builder : false,
|
20 |
+
|
21 |
+
init: function()
|
22 |
+
{
|
23 |
+
this._resetPagedCount();
|
24 |
+
this._bind();
|
25 |
+
this._loadPageBuilders();
|
26 |
+
},
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Binds events for the Astra Sites.
|
30 |
+
*
|
31 |
+
* @since 1.0.0
|
32 |
+
* @access private
|
33 |
+
* @method _bind
|
34 |
+
*/
|
35 |
+
_bind: function()
|
36 |
+
{
|
37 |
+
$( document ).on('astra-sites-api-request-error' , AstraRender._addSuggestionBox );
|
38 |
+
$( document ).on('astra-sites-api-request-fail' , AstraRender._addSuggestionBox );
|
39 |
+
$( document ).on('astra-api-post-loaded-on-scroll' , AstraRender._reinitGridScrolled );
|
40 |
+
$( document ).on('astra-api-post-loaded' , AstraRender._reinitGrid );
|
41 |
+
$( document ).on('astra-api-page-builder-loaded' , AstraRender._addPageBuilders );
|
42 |
+
$( document ).on('astra-api-category-loaded' , AstraRender._loadFirstGrid );
|
43 |
+
|
44 |
+
// Event's for API request.
|
45 |
+
$( document ).on('click' , '.filter-links a', AstraRender._filterClick );
|
46 |
+
$( document ).on('keyup input' , '#wp-filter-search-input', AstraRender._search );
|
47 |
+
$( document ).on('scroll' , AstraRender._scroll );
|
48 |
+
|
49 |
+
},
|
50 |
+
|
51 |
+
/**
|
52 |
+
* On Filter Clicked
|
53 |
+
*
|
54 |
+
* Prepare Before API Request:
|
55 |
+
* - Empty search input field to avoid search term on filter click.
|
56 |
+
* - Remove Inline Height
|
57 |
+
* - Added 'hide-me' class to hide the 'No more sites!' string.
|
58 |
+
* - Added 'loading-content' for body.
|
59 |
+
* - Show spinner.
|
60 |
+
*/
|
61 |
+
_filterClick: function( event ) {
|
62 |
+
|
63 |
+
event.preventDefault();
|
64 |
+
|
65 |
+
if( $( this ).parents('.astra-site-category').length && ! $('body').hasClass('page-builder-selected') ) {
|
66 |
+
return;
|
67 |
+
}
|
68 |
+
|
69 |
+
$(this).parents('.filter-links').find('a').removeClass('current');
|
70 |
+
$(this).addClass('current');
|
71 |
+
|
72 |
+
// Prepare Before Search.
|
73 |
+
$('.no-more-demos').addClass('hide-me');
|
74 |
+
$('.astra-sites-suggestions').remove();
|
75 |
+
|
76 |
+
// Empty the search input only click on category filter not on page builder filter.
|
77 |
+
if( $(this).parents('.filter-links').hasClass('astra-site-category') ) {
|
78 |
+
$('#wp-filter-search-input').val('');
|
79 |
+
}
|
80 |
+
$('#astra-sites').hide().css('height', '');
|
81 |
+
|
82 |
+
$('body').addClass('loading-content');
|
83 |
+
$('#astra-sites-admin').find('.spinner').removeClass('hide-me');
|
84 |
+
|
85 |
+
// Show sites.
|
86 |
+
AstraRender._showSites();
|
87 |
+
},
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Search Site.
|
91 |
+
*
|
92 |
+
* Prepare Before API Request:
|
93 |
+
* - Remove Inline Height
|
94 |
+
* - Added 'hide-me' class to hide the 'No more sites!' string.
|
95 |
+
* - Added 'loading-content' for body.
|
96 |
+
* - Show spinner.
|
97 |
+
*/
|
98 |
+
_search: function() {
|
99 |
+
|
100 |
+
if( ! $('body').hasClass('page-builder-selected') ) {
|
101 |
+
return;
|
102 |
+
}
|
103 |
+
|
104 |
+
$this = jQuery('#wp-filter-search-input').val();
|
105 |
+
|
106 |
+
// Prepare Before Search.
|
107 |
+
$('#astra-sites').hide().css('height', '');
|
108 |
+
$('.no-more-demos').addClass('hide-me');
|
109 |
+
$('.astra-sites-suggestions').remove();
|
110 |
+
|
111 |
+
$('body').addClass('loading-content');
|
112 |
+
$('#astra-sites-admin').find('.spinner').removeClass('hide-me');
|
113 |
+
|
114 |
+
window.clearTimeout(AstraRender._ref);
|
115 |
+
AstraRender._ref = window.setTimeout(function () {
|
116 |
+
AstraRender._ref = null;
|
117 |
+
|
118 |
+
AstraRender._resetPagedCount();
|
119 |
+
jQuery('body').addClass('loading-content');
|
120 |
+
jQuery('body').attr('data-astra-demo-search', $this);
|
121 |
+
|
122 |
+
AstraRender._showSites();
|
123 |
+
|
124 |
+
}, 500);
|
125 |
+
|
126 |
+
},
|
127 |
+
|
128 |
+
/**
|
129 |
+
* On Scroll
|
130 |
+
*/
|
131 |
+
_scroll: function(event) {
|
132 |
+
|
133 |
+
if( ! $('body').hasClass('page-builder-selected') ) {
|
134 |
+
return;
|
135 |
+
}
|
136 |
+
|
137 |
+
if( ! $('body').hasClass('listed-all-sites') ) {
|
138 |
+
|
139 |
+
var scrollDistance = jQuery(window).scrollTop();
|
140 |
+
|
141 |
+
var themesBottom = Math.abs(jQuery(window).height() - jQuery('#astra-sites').offset().top - jQuery('#astra-sites').height());
|
142 |
+
themesBottom = themesBottom - 100;
|
143 |
+
|
144 |
+
ajaxLoading = jQuery('body').data('scrolling');
|
145 |
+
|
146 |
+
if (scrollDistance > themesBottom && ajaxLoading == false) {
|
147 |
+
AstraRender._updatedPagedCount();
|
148 |
+
|
149 |
+
if( ! $('#astra-sites .no-themes').length ) {
|
150 |
+
$('#astra-sites-admin').find('.spinner').addClass('is-active');
|
151 |
+
}
|
152 |
+
|
153 |
+
jQuery('body').data('scrolling', true);
|
154 |
+
|
155 |
+
/**
|
156 |
+
* @see _reinitGridScrolled() which called in trigger 'astra-api-post-loaded-on-scroll'
|
157 |
+
*/
|
158 |
+
AstraRender._showSites( false, 'astra-api-post-loaded-on-scroll' );
|
159 |
+
}
|
160 |
+
}
|
161 |
+
},
|
162 |
+
|
163 |
+
_apiAddParam_status: function() {
|
164 |
+
if( astraRenderGrid.sites && astraRenderGrid.sites.status ) {
|
165 |
+
AstraRender._api_params['status'] = astraRenderGrid.sites.status;
|
166 |
+
}
|
167 |
+
},
|
168 |
+
|
169 |
+
// Add 'search'
|
170 |
+
_apiAddParam_search: function() {
|
171 |
+
var search_val = jQuery('#wp-filter-search-input').val() || '';
|
172 |
+
if( '' !== search_val ) {
|
173 |
+
AstraRender._api_params['search'] = search_val;
|
174 |
+
}
|
175 |
+
},
|
176 |
+
|
177 |
+
_apiAddParam_per_page: function() {
|
178 |
+
// Add 'per_page'
|
179 |
+
var per_page_val = 15;
|
180 |
+
if( astraRenderGrid.sites && astraRenderGrid.sites["par-page"] ) {
|
181 |
+
per_page_val = parseInt( astraRenderGrid.sites["par-page"] );
|
182 |
+
}
|
183 |
+
AstraRender._api_params['per_page'] = per_page_val;
|
184 |
+
},
|
185 |
+
|
186 |
+
_apiAddParam_astra_site_category: function() {
|
187 |
+
// Add 'astra-site-category'
|
188 |
+
var selected_category_id = jQuery('.filter-links.astra-site-category').find('.current').data('group') || '';
|
189 |
+
if( '' !== selected_category_id && 'all' !== selected_category_id ) {
|
190 |
+
AstraRender._api_params['astra-site-category'] = selected_category_id;
|
191 |
+
} else if( 'astra-site-category' in astraRenderGrid.settings ) {
|
192 |
+
|
193 |
+
if( $.inArray('all', astraRenderGrid.settings['astra-site-category']) !== -1 ) {
|
194 |
+
var storedCategories = astraRenderGrid.settings['astra-site-category'];
|
195 |
+
storedCategories = jQuery.grep(storedCategories, function(value) {
|
196 |
+
return value != 'all';
|
197 |
+
});
|
198 |
+
AstraRender._api_params['astra-site-category'] = storedCategories.join(',');
|
199 |
+
}
|
200 |
+
}
|
201 |
+
},
|
202 |
+
|
203 |
+
_apiAddParam_astra_site_page_builder: function() {
|
204 |
+
// Add 'astra-site-page-builder'
|
205 |
+
var selected_page_builder_id = jQuery('.filter-links.astra-site-page-builder').find('.current').data('group') || '';
|
206 |
+
if( '' !== selected_page_builder_id && 'all' !== selected_page_builder_id ) {
|
207 |
+
AstraRender._api_params['astra-site-page-builder'] = selected_page_builder_id;
|
208 |
+
} else if( 'astra-site-page-builder' in astraRenderGrid.settings ) {
|
209 |
+
if( $.inArray('all', astraRenderGrid.settings['astra-site-page-builder']) !== -1 ) {
|
210 |
+
var storedBuilders = astraRenderGrid.settings['astra-site-page-builder'];
|
211 |
+
storedBuilders = jQuery.grep(storedBuilders, function(value) {
|
212 |
+
return value != 'all';
|
213 |
+
});
|
214 |
+
AstraRender._api_params['astra-site-page-builder'] = storedBuilders.join(',');
|
215 |
+
}
|
216 |
+
}
|
217 |
+
},
|
218 |
+
|
219 |
+
_apiAddParam_page: function() {
|
220 |
+
// Add 'page'
|
221 |
+
var page_val = parseInt(jQuery('body').attr('data-astra-demo-paged')) || 1;
|
222 |
+
AstraRender._api_params['page'] = page_val;
|
223 |
+
},
|
224 |
+
|
225 |
+
_apiAddParam_purchase_key: function() {
|
226 |
+
if( astraRenderGrid.sites && astraRenderGrid.sites.purchase_key ) {
|
227 |
+
AstraRender._api_params['purchase_key'] = astraRenderGrid.sites.purchase_key;
|
228 |
+
}
|
229 |
+
},
|
230 |
+
|
231 |
+
_apiAddParam_site_url: function() {
|
232 |
+
if( astraRenderGrid.sites && astraRenderGrid.sites.site_url ) {
|
233 |
+
AstraRender._api_params['site_url'] = astraRenderGrid.sites.site_url;
|
234 |
+
}
|
235 |
+
},
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Show Sites
|
239 |
+
*
|
240 |
+
* Params E.g. per_page=<page-id>&astra-site-category=<category-ids>&astra-site-page-builder=<page-builder-ids>&page=<page>
|
241 |
+
*
|
242 |
+
* @param {Boolean} resetPagedCount Reset Paged Count.
|
243 |
+
* @param {String} trigger Filtered Trigger.
|
244 |
+
*/
|
245 |
+
_showSites: function( resetPagedCount, trigger ) {
|
246 |
+
|
247 |
+
if( undefined === resetPagedCount ) {
|
248 |
+
resetPagedCount = true
|
249 |
+
}
|
250 |
+
|
251 |
+
if( undefined === trigger ) {
|
252 |
+
trigger = 'astra-api-post-loaded';
|
253 |
+
}
|
254 |
+
|
255 |
+
if( resetPagedCount ) {
|
256 |
+
AstraRender._resetPagedCount();
|
257 |
+
}
|
258 |
+
|
259 |
+
// Add Params for API request.
|
260 |
+
AstraRender._api_params = {};
|
261 |
+
|
262 |
+
AstraRender._apiAddParam_status();
|
263 |
+
AstraRender._apiAddParam_search();
|
264 |
+
AstraRender._apiAddParam_per_page();
|
265 |
+
AstraRender._apiAddParam_astra_site_category();
|
266 |
+
AstraRender._apiAddParam_astra_site_page_builder();
|
267 |
+
AstraRender._apiAddParam_page();
|
268 |
+
AstraRender._apiAddParam_site_url();
|
269 |
+
AstraRender._apiAddParam_purchase_key();
|
270 |
+
|
271 |
+
// API Request.
|
272 |
+
var api_post = {
|
273 |
+
slug: 'astra-sites?' + decodeURIComponent( $.param( AstraRender._api_params ) ),
|
274 |
+
trigger: trigger,
|
275 |
+
};
|
276 |
+
|
277 |
+
AstraSitesAPI._api_request( api_post );
|
278 |
+
|
279 |
+
},
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Get Category Params
|
283 |
+
*
|
284 |
+
* @since 1.2.4
|
285 |
+
* @param {string} category_slug Category Slug.
|
286 |
+
* @return {mixed} Add `include=<category-ids>` in API request.
|
287 |
+
*/
|
288 |
+
_getPageBuilderParams: function()
|
289 |
+
{
|
290 |
+
var _category_params = {};
|
291 |
+
|
292 |
+
if( astraRenderGrid.sites && astraRenderGrid.sites.purchase_key ) {
|
293 |
+
_category_params['purchase_key'] = astraRenderGrid.sites.purchase_key;
|
294 |
+
}
|
295 |
+
|
296 |
+
if( astraRenderGrid.sites && astraRenderGrid.sites.site_url ) {
|
297 |
+
_category_params['site_url'] = astraRenderGrid.sites.site_url;
|
298 |
+
}
|
299 |
+
|
300 |
+
return '/?' + decodeURIComponent( $.param( _category_params ) );
|
301 |
+
},
|
302 |
+
|
303 |
+
/**
|
304 |
+
* Get Category Params
|
305 |
+
*
|
306 |
+
* @param {string} category_slug Category Slug.
|
307 |
+
* @return {mixed} Add `include=<category-ids>` in API request.
|
308 |
+
*/
|
309 |
+
_getCategoryParams: function( category_slug ) {
|
310 |
+
|
311 |
+
// Has category?
|
312 |
+
if( category_slug in astraRenderGrid.settings ) {
|
313 |
+
|
314 |
+
var storedBuilders = astraRenderGrid.settings[ category_slug ];
|
315 |
+
|
316 |
+
// Remove `all` from stored list?
|
317 |
+
storedBuilders = jQuery.grep(storedBuilders, function(value) {
|
318 |
+
return value != 'all';
|
319 |
+
});
|
320 |
+
|
321 |
+
return '?include='+storedBuilders.join(',');
|
322 |
+
}
|
323 |
+
|
324 |
+
return '';
|
325 |
+
},
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Get All Select Status
|
329 |
+
*
|
330 |
+
* @param {string} category_slug Category Slug.
|
331 |
+
* @return {boolean} Return true/false.
|
332 |
+
*/
|
333 |
+
_getCategoryAllSelectStatus: function( category_slug ) {
|
334 |
+
|
335 |
+
// Has category?
|
336 |
+
if( category_slug in astraRenderGrid.settings ) {
|
337 |
+
|
338 |
+
// Has `all` in stored list?
|
339 |
+
if( $.inArray('all', astraRenderGrid.settings[ category_slug ]) === -1 ) {
|
340 |
+
return false;
|
341 |
+
}
|
342 |
+
}
|
343 |
+
|
344 |
+
return true;
|
345 |
+
},
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Show Filters
|
349 |
+
*/
|
350 |
+
_loadPageBuilders: function() {
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Page Builder
|
354 |
+
*/
|
355 |
+
var category_slug = 'astra-site-page-builder';
|
356 |
+
var category = {
|
357 |
+
slug : category_slug + AstraRender._getPageBuilderParams(),
|
358 |
+
id : category_slug,
|
359 |
+
class : category_slug,
|
360 |
+
trigger : 'astra-api-page-builder-loaded',
|
361 |
+
wrapper_class : 'filter-links',
|
362 |
+
show_all : false,
|
363 |
+
};
|
364 |
+
|
365 |
+
AstraSitesAPI._api_request( category );
|
366 |
+
},
|
367 |
+
|
368 |
+
/**
|
369 |
+
* Load First Grid.
|
370 |
+
*
|
371 |
+
* This is triggered after all category loaded.
|
372 |
+
*
|
373 |
+
* @param {object} event Event Object.
|
374 |
+
*/
|
375 |
+
_loadFirstGrid: function( event, data ) {
|
376 |
+
|
377 |
+
event.preventDefault();
|
378 |
+
|
379 |
+
if( $('#' + data.args.id).length ) {
|
380 |
+
var template = wp.template('astra-site-filters');
|
381 |
+
$('#' + data.args.id).html(template( data ));
|
382 |
+
|
383 |
+
if( 'true' === $('body').attr( 'data-default-page-builder-selected' ) ) {
|
384 |
+
$('#' + data.args.id).find('li:first a').addClass('current');
|
385 |
+
AstraRender._showSites();
|
386 |
+
} else {
|
387 |
+
$('body').removeClass('loading-content');
|
388 |
+
if( ! $('#astra-sites-admin .astra-site-select-page-builder').length ) {
|
389 |
+
$('#astra-sites-admin').append( wp.template( 'astra-site-select-page-builder' ) );
|
390 |
+
}
|
391 |
+
}
|
392 |
+
}
|
393 |
+
|
394 |
+
},
|
395 |
+
|
396 |
+
/**
|
397 |
+
* Append filters.
|
398 |
+
*
|
399 |
+
* @param {object} event Object.
|
400 |
+
* @param {object} data API response data.
|
401 |
+
*/
|
402 |
+
_addPageBuilders: function( event, data ) {
|
403 |
+
event.preventDefault();
|
404 |
+
|
405 |
+
if( $('#' + data.args.id).length ) {
|
406 |
+
var template = wp.template('astra-site-filters');
|
407 |
+
$('#' + data.args.id).html(template( data ));
|
408 |
+
|
409 |
+
if( 1 === parseInt( data.items_count ) ) {
|
410 |
+
$('body').attr( 'data-default-page-builder-selected', true );
|
411 |
+
$('#' + data.args.id).find('li:first a').addClass('current');
|
412 |
+
}
|
413 |
+
}
|
414 |
+
|
415 |
+
/**
|
416 |
+
* Categories
|
417 |
+
*/
|
418 |
+
var category_slug = 'astra-site-category';
|
419 |
+
var category = {
|
420 |
+
slug : category_slug + AstraRender._getCategoryParams( category_slug ),
|
421 |
+
id : category_slug,
|
422 |
+
class : category_slug,
|
423 |
+
trigger : 'astra-api-category-loaded',
|
424 |
+
wrapper_class : 'filter-links',
|
425 |
+
show_all : AstraRender._getCategoryAllSelectStatus( category_slug ),
|
426 |
+
};
|
427 |
+
|
428 |
+
AstraSitesAPI._api_request( category );
|
429 |
+
|
430 |
+
},
|
431 |
+
|
432 |
+
|
433 |
+
/**
|
434 |
+
* Append sites on scroll.
|
435 |
+
*
|
436 |
+
* @param {object} event Object.
|
437 |
+
* @param {object} data API response data.
|
438 |
+
*/
|
439 |
+
_reinitGridScrolled: function( event, data ) {
|
440 |
+
|
441 |
+
var template = wp.template('astra-sites-list');
|
442 |
+
|
443 |
+
if( data.items.length > 0 ) {
|
444 |
+
|
445 |
+
$('body').removeClass( 'loading-content' );
|
446 |
+
$('.filter-count .count').text( data.items_count );
|
447 |
+
|
448 |
+
setTimeout(function() {
|
449 |
+
jQuery('#astra-sites').append(template( data ));
|
450 |
+
|
451 |
+
AstraRender._imagesLoaded();
|
452 |
+
}, 800);
|
453 |
+
} else {
|
454 |
+
$('body').addClass('listed-all-sites');
|
455 |
+
}
|
456 |
+
|
457 |
+
},
|
458 |
+
|
459 |
+
/**
|
460 |
+
* Update Astra sites list.
|
461 |
+
*
|
462 |
+
* @param {object} event Object.
|
463 |
+
* @param {object} data API response data.
|
464 |
+
*/
|
465 |
+
_reinitGrid: function( event, data ) {
|
466 |
+
|
467 |
+
var template = wp.template('astra-sites-list');
|
468 |
+
|
469 |
+
$('body').addClass( 'page-builder-selected' );
|
470 |
+
$('body').removeClass( 'loading-content' );
|
471 |
+
$('.filter-count .count').text( data.items_count );
|
472 |
+
|
473 |
+
jQuery('body').attr('data-astra-demo-last-request', data.items_count);
|
474 |
+
|
475 |
+
jQuery('#astra-sites').show().html(template( data ));
|
476 |
+
|
477 |
+
AstraRender._imagesLoaded();
|
478 |
+
|
479 |
+
$('#astra-sites-admin').find('.spinner').removeClass('is-active');
|
480 |
+
|
481 |
+
if( data.items_count <= 0 ) {
|
482 |
+
$('#astra-sites-admin').find('.spinner').removeClass('is-active');
|
483 |
+
$('.no-more-demos').addClass('hide-me');
|
484 |
+
$('.astra-sites-suggestions').remove();
|
485 |
+
|
486 |
+
} else {
|
487 |
+
$('body').removeClass('listed-all-sites');
|
488 |
+
}
|
489 |
+
|
490 |
+
|
491 |
+
},
|
492 |
+
|
493 |
+
/**
|
494 |
+
* Check image loaded with function `imagesLoaded()`
|
495 |
+
*/
|
496 |
+
_imagesLoaded: function() {
|
497 |
+
|
498 |
+
var self = jQuery('#sites-filter.execute-only-one-time a');
|
499 |
+
|
500 |
+
$('.astra-sites-grid').imagesLoaded()
|
501 |
+
.always( function( instance ) {
|
502 |
+
if( jQuery( window ).outerWidth() > AstraRender._breakpoint ) {
|
503 |
+
// $('#astra-sites').masonry('reload');
|
504 |
+
}
|
505 |
+
|
506 |
+
$('#astra-sites-admin').find('.spinner').removeClass('is-active');
|
507 |
+
})
|
508 |
+
.progress( function( instance, image ) {
|
509 |
+
var result = image.isLoaded ? 'loaded' : 'broken';
|
510 |
+
});
|
511 |
+
|
512 |
+
},
|
513 |
+
|
514 |
+
/**
|
515 |
+
* Add Suggestion Box
|
516 |
+
*/
|
517 |
+
_addSuggestionBox: function() {
|
518 |
+
$('#astra-sites-admin').find('.spinner').removeClass('is-active').addClass('hide-me');
|
519 |
+
|
520 |
+
$('#astra-sites-admin').find('.no-more-demos').removeClass('hide-me');
|
521 |
+
var template = wp.template('astra-sites-suggestions');
|
522 |
+
if( ! $( '.astra-sites-suggestions').length ) {
|
523 |
+
$('#astra-sites').append( template );
|
524 |
+
}
|
525 |
+
},
|
526 |
+
|
527 |
+
/**
|
528 |
+
* Update Page Count.
|
529 |
+
*/
|
530 |
+
_updatedPagedCount: function() {
|
531 |
+
paged = parseInt(jQuery('body').attr('data-astra-demo-paged'));
|
532 |
+
jQuery('body').attr('data-astra-demo-paged', paged + 1);
|
533 |
+
window.setTimeout(function () {
|
534 |
+
jQuery('body').data('scrolling', false);
|
535 |
+
}, 800);
|
536 |
+
},
|
537 |
+
|
538 |
+
/**
|
539 |
+
* Reset Page Count.
|
540 |
+
*/
|
541 |
+
_resetPagedCount: function() {
|
542 |
+
|
543 |
+
jQuery('body').attr('data-astra-demo-last-request', '1');
|
544 |
+
jQuery('body').attr('data-astra-demo-paged', '1');
|
545 |
+
jQuery('body').attr('data-astra-demo-search', '');
|
546 |
+
jQuery('body').attr('data-scrolling', false);
|
547 |
+
|
548 |
+
}
|
549 |
+
|
550 |
+
};
|
551 |
+
|
552 |
+
/**
|
553 |
+
* Initialize AstraRender
|
554 |
+
*/
|
555 |
+
$(function(){
|
556 |
+
AstraRender.init();
|
557 |
+
});
|
558 |
+
|
559 |
ย
})(jQuery);
|
inc/importers/batch-processing/class-astra-sites-batch-processing-elementor-v2.php
CHANGED
@@ -1,328 +1,328 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Elementor Images Batch Processing
|
4 |
-
*
|
5 |
-
* @package Astra Sites
|
6 |
-
* @since 1.0.0
|
7 |
-
*/
|
8 |
-
|
9 |
-
namespace Elementor;
|
10 |
-
|
11 |
-
// If plugin - 'Elementor' not exist then return.
|
12 |
-
if ( ! class_exists( '\Elementor\Plugin' ) ) {
|
13 |
-
return;
|
14 |
-
}
|
15 |
-
|
16 |
-
namespace Elementor\TemplateLibrary;
|
17 |
-
|
18 |
-
use Elementor\Controls_Stack;
|
19 |
-
use Elementor\Core\Settings\Manager as SettingsManager;
|
20 |
-
use Elementor\TemplateLibrary\Classes\Import_Images;
|
21 |
-
use Elementor\TemplateLibrary;
|
22 |
-
use Elementor\TemplateLibrary\Classes;
|
23 |
-
use Elementor\Api;
|
24 |
-
use Elementor\PageSettings\Page;
|
25 |
-
|
26 |
-
// For working protected methods defined in.
|
27 |
-
// file '/elementor/includes/template-library/sources/base.php'.
|
28 |
-
use Elementor\Plugin;
|
29 |
-
use Elementor\Utils;
|
30 |
-
|
31 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
32 |
-
exit; // Exit if accessed directly.
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Astra Source Remote
|
37 |
-
*/
|
38 |
-
class Astra_Sites_Batch_Processing_Elementor extends Source_Base {
|
39 |
-
|
40 |
-
|
41 |
-
/**
|
42 |
-
* Get ID
|
43 |
-
*
|
44 |
-
* @since 1.0.4
|
45 |
-
*
|
46 |
-
* @return string
|
47 |
-
*/
|
48 |
-
public function get_id() {
|
49 |
-
return 'remote';
|
50 |
-
}
|
51 |
-
|
52 |
-
/**
|
53 |
-
* Get Title.
|
54 |
-
*
|
55 |
-
* @since 1.0.4
|
56 |
-
*
|
57 |
-
* @return string
|
58 |
-
*/
|
59 |
-
public function get_title() {
|
60 |
-
return __( 'Remote', 'astra-sites' );
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Get Data
|
65 |
-
*
|
66 |
-
* @since 1.0.4
|
67 |
-
*
|
68 |
-
* @return void
|
69 |
-
*/
|
70 |
-
public function register_data() {}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Get Items
|
74 |
-
*
|
75 |
-
* @since 1.0.4
|
76 |
-
*
|
77 |
-
* @param array $args Arguments.
|
78 |
-
* @return array
|
79 |
-
*/
|
80 |
-
public function get_items( $args = array() ) {
|
81 |
-
$templates_data = Api::get_templates_data();
|
82 |
-
|
83 |
-
$templates = array();
|
84 |
-
|
85 |
-
if ( ! empty( $templates_data ) ) {
|
86 |
-
foreach ( $templates_data as $template_data ) {
|
87 |
-
$templates[] = $this->get_item( $template_data );
|
88 |
-
}
|
89 |
-
}
|
90 |
-
|
91 |
-
if ( ! empty( $args ) ) {
|
92 |
-
$templates = wp_list_filter( $templates, $args );
|
93 |
-
}
|
94 |
-
|
95 |
-
return $templates;
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
* Get Item
|
100 |
-
*
|
101 |
-
* @param array $template_data Template Data.
|
102 |
-
*
|
103 |
-
* @return array
|
104 |
-
*/
|
105 |
-
public function get_item( $template_data ) {
|
106 |
-
return array(
|
107 |
-
'template_id' => $template_data['id'],
|
108 |
-
'source' => $this->get_id(),
|
109 |
-
'title' => $template_data['title'],
|
110 |
-
'thumbnail' => $template_data['thumbnail'],
|
111 |
-
'date' => date( get_option( 'date_format' ), $template_data['tmpl_created'] ),
|
112 |
-
'author' => $template_data['author'],
|
113 |
-
'categories' => array(),
|
114 |
-
'keywords' => array(),
|
115 |
-
'isPro' => ( '1' === $template_data['is_pro'] ),
|
116 |
-
'hasPageSettings' => ( '1' === $template_data['has_page_settings'] ),
|
117 |
-
'url' => $template_data['url'],
|
118 |
-
);
|
119 |
-
}
|
120 |
-
|
121 |
-
/**
|
122 |
-
* Template Data
|
123 |
-
*
|
124 |
-
* @param boolean $template_data Template Data.
|
125 |
-
* @return boolean Return false.
|
126 |
-
*/
|
127 |
-
public function save_item( $template_data ) {
|
128 |
-
return false;
|
129 |
-
}
|
130 |
-
|
131 |
-
/**
|
132 |
-
* Update Item
|
133 |
-
*
|
134 |
-
* @param boolean $new_data New Data.
|
135 |
-
* @return boolean Return false.
|
136 |
-
*/
|
137 |
-
public function update_item( $new_data ) {
|
138 |
-
return false;
|
139 |
-
}
|
140 |
-
|
141 |
-
/**
|
142 |
-
* Delete Template
|
143 |
-
*
|
144 |
-
* @param boolean $template_id Template ID.
|
145 |
-
* @return boolean Return false.
|
146 |
-
*/
|
147 |
-
public function delete_template( $template_id ) {
|
148 |
-
return false;
|
149 |
-
}
|
150 |
-
|
151 |
-
/**
|
152 |
-
* Delete Template
|
153 |
-
*
|
154 |
-
* @param boolean $template_id Template ID.
|
155 |
-
* @return boolean Return false.
|
156 |
-
*/
|
157 |
-
public function export_template( $template_id ) {
|
158 |
-
return false;
|
159 |
-
}
|
160 |
-
|
161 |
-
/**
|
162 |
-
* Get Data
|
163 |
-
*
|
164 |
-
* @param array $args Arguments.
|
165 |
-
* @param string $context Context.
|
166 |
-
* @return array Data.
|
167 |
-
*/
|
168 |
-
public function get_data( array $args, $context = 'display' ) {
|
169 |
-
$data = Api::get_template_content( $args['template_id'] );
|
170 |
-
|
171 |
-
if ( is_wp_error( $data ) ) {
|
172 |
-
return $data;
|
173 |
-
}
|
174 |
-
|
175 |
-
// TODO: since 1.5.0 to content container named `content` instead of `data`.
|
176 |
-
if ( ! empty( $data['data'] ) ) {
|
177 |
-
$data['content'] = $data['data'];
|
178 |
-
unset( $data['data'] );
|
179 |
-
}
|
180 |
-
|
181 |
-
$data['content'] = $this->replace_elements_ids( $data['content'] );
|
182 |
-
$data['content'] = $this->process_export_import_content( $data['content'], 'on_import' );
|
183 |
-
|
184 |
-
if ( ! empty( $args['page_settings'] ) && ! empty( $data['page_settings'] ) ) {
|
185 |
-
$page = new Page(
|
186 |
-
array(
|
187 |
-
'settings' => $data['page_settings'],
|
188 |
-
)
|
189 |
-
);
|
190 |
-
|
191 |
-
$page_settings_data = $this->process_element_export_import_content( $page, 'on_import' );
|
192 |
-
$data['page_settings'] = $page_settings_data['settings'];
|
193 |
-
}
|
194 |
-
|
195 |
-
return $data;
|
196 |
-
}
|
197 |
-
|
198 |
-
/**
|
199 |
-
* Replace Elements Ids
|
200 |
-
*
|
201 |
-
* @param string $content Context.
|
202 |
-
* @return array Element.
|
203 |
-
*/
|
204 |
-
public function replace_elements_ids( $content ) {
|
205 |
-
return Plugin::$instance->db->iterate_data(
|
206 |
-
$content, function( $element ) {
|
207 |
-
$element['id'] = Utils::generate_random_string();
|
208 |
-
|
209 |
-
return $element;
|
210 |
-
}
|
211 |
-
);
|
212 |
-
}
|
213 |
-
|
214 |
-
/**
|
215 |
-
* Process Import Content.
|
216 |
-
*
|
217 |
-
* @param array $content a set of elements.
|
218 |
-
* @param string $method (on_export|on_import).
|
219 |
-
*
|
220 |
-
* @return mixed
|
221 |
-
*/
|
222 |
-
public function process_export_import_content( $content, $method ) {
|
223 |
-
return Plugin::$instance->db->iterate_data(
|
224 |
-
$content, function( $element_data ) use ( $method ) {
|
225 |
-
$element = Plugin::$instance->elements_manager->create_element_instance( $element_data );
|
226 |
-
|
227 |
-
// If the widget/element isn't exist, like a plugin that creates a widget but deactivated.
|
228 |
-
if ( ! $element ) {
|
229 |
-
return null;
|
230 |
-
}
|
231 |
-
|
232 |
-
$instance = new Astra_Sites_Batch_Processing_Elementor();
|
233 |
-
|
234 |
-
return $instance->process_element_export_import_content( $element, $method );
|
235 |
-
}
|
236 |
-
);
|
237 |
-
}
|
238 |
-
|
239 |
-
/**
|
240 |
-
* Process Element/Export Import Content.
|
241 |
-
*
|
242 |
-
* @param \Elementor\Controls_Stack $element Element.
|
243 |
-
* @param string $method Method.
|
244 |
-
*
|
245 |
-
* @return array
|
246 |
-
*/
|
247 |
-
public function process_element_export_import_content( Controls_Stack $element, $method ) {
|
248 |
-
$element_data = $element->get_data();
|
249 |
-
|
250 |
-
if ( method_exists( $element, $method ) ) {
|
251 |
-
// TODO: Use the internal element data without parameters.
|
252 |
-
$element_data = $element->{$method}( $element_data );
|
253 |
-
}
|
254 |
-
|
255 |
-
foreach ( $element->get_controls() as $control ) {
|
256 |
-
$control_class = Plugin::$instance->controls_manager->get_control( $control['type'] );
|
257 |
-
|
258 |
-
// If the control isn't exist, like a plugin that creates the control but deactivated.
|
259 |
-
if ( ! $control_class ) {
|
260 |
-
return $element_data;
|
261 |
-
}
|
262 |
-
|
263 |
-
if ( method_exists( $control_class, $method ) ) {
|
264 |
-
$element_data['settings'][ $control['name'] ] = $control_class->{$method}( $element->get_settings( $control['name'] ) );
|
265 |
-
}
|
266 |
-
}
|
267 |
-
|
268 |
-
return $element_data;
|
269 |
-
}
|
270 |
-
|
271 |
-
/**
|
272 |
-
* Import
|
273 |
-
*
|
274 |
-
* @since 1.0.14
|
275 |
-
* @return void
|
276 |
-
*/
|
277 |
-
public function import() {
|
278 |
-
|
279 |
-
\Astra_Sites_Image_Importer::log( '---- Processing WordPress Posts / Pages - for Elementor ----' );
|
280 |
-
|
281 |
-
$post_ids = \Astra_Sites_Batch_Processing::get_pages();
|
282 |
-
if ( is_array( $post_ids ) ) {
|
283 |
-
foreach ( $post_ids as $post_id ) {
|
284 |
-
$this->import_single_post( $post_id );
|
285 |
-
}
|
286 |
-
}
|
287 |
-
|
288 |
-
}
|
289 |
-
|
290 |
-
/**
|
291 |
-
* Update post meta.
|
292 |
-
*
|
293 |
-
* @since 1.0.14
|
294 |
-
* @param integer $post_id Post ID.
|
295 |
-
* @return void
|
296 |
-
*/
|
297 |
-
public function import_single_post( $post_id = 0 ) {
|
298 |
-
|
299 |
-
\Astra_Sites_Image_Importer::log( 'Post ID: ' . $post_id );
|
300 |
-
|
301 |
-
if ( ! empty( $post_id ) ) {
|
302 |
-
|
303 |
-
$hotlink_imported = get_post_meta( $post_id, '_astra_sites_hotlink_imported', true );
|
304 |
-
|
305 |
-
if ( empty( $hotlink_imported ) ) {
|
306 |
-
|
307 |
-
$data = get_post_meta( $post_id, '_elementor_data', true );
|
308 |
-
|
309 |
-
if ( ! empty( $data ) ) {
|
310 |
-
|
311 |
-
$data = json_decode( $data, true );
|
312 |
-
|
313 |
-
$data = $this->replace_elements_ids( $data );
|
314 |
-
$data = $this->process_export_import_content( $data, 'on_import' );
|
315 |
-
|
316 |
-
// Update processed meta.
|
317 |
-
update_metadata( 'post', $post_id, '_elementor_data', $data );
|
318 |
-
update_metadata( 'post', $post_id, '_astra_sites_hotlink_imported', true );
|
319 |
-
|
320 |
-
// !important, Clear the cache after images import.
|
321 |
-
Plugin::$instance->posts_css_manager->clear_cache();
|
322 |
-
|
323 |
-
}
|
324 |
-
}
|
325 |
-
}
|
326 |
-
|
327 |
-
}
|
328 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Elementor Images Batch Processing
|
4 |
+
*
|
5 |
+
* @package Astra Sites
|
6 |
+
* @since 1.0.0
|
7 |
+
*/
|
8 |
+
|
9 |
+
namespace Elementor;
|
10 |
+
|
11 |
+
// If plugin - 'Elementor' not exist then return.
|
12 |
+
if ( ! class_exists( '\Elementor\Plugin' ) ) {
|
13 |
+
return;
|
14 |
+
}
|
15 |
+
|
16 |
+
namespace Elementor\TemplateLibrary;
|
17 |
+
|
18 |
+
use Elementor\Controls_Stack;
|
19 |
+
use Elementor\Core\Settings\Manager as SettingsManager;
|
20 |
+
use Elementor\TemplateLibrary\Classes\Import_Images;
|
21 |
+
use Elementor\TemplateLibrary;
|
22 |
+
use Elementor\TemplateLibrary\Classes;
|
23 |
+
use Elementor\Api;
|
24 |
+
use Elementor\PageSettings\Page;
|
25 |
+
|
26 |
+
// For working protected methods defined in.
|
27 |
+
// file '/elementor/includes/template-library/sources/base.php'.
|
28 |
+
use Elementor\Plugin;
|
29 |
+
use Elementor\Utils;
|
30 |
+
|
31 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
32 |
+
exit; // Exit if accessed directly.
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Astra Source Remote
|
37 |
+
*/
|
38 |
+
class Astra_Sites_Batch_Processing_Elementor extends Source_Base {
|
39 |
+
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Get ID
|
43 |
+
*
|
44 |
+
* @since 1.0.4
|
45 |
+
*
|
46 |
+
* @return string
|
47 |
+
*/
|
48 |
+
public function get_id() {
|
49 |
+
return 'remote';
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Get Title.
|
54 |
+
*
|
55 |
+
* @since 1.0.4
|
56 |
+
*
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function get_title() {
|
60 |
+
return __( 'Remote', 'astra-sites' );
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Get Data
|
65 |
+
*
|
66 |
+
* @since 1.0.4
|
67 |
+
*
|
68 |
+
* @return void
|
69 |
+
*/
|
70 |
+
public function register_data() {}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Get Items
|
74 |
+
*
|
75 |
+
* @since 1.0.4
|
76 |
+
*
|
77 |
+
* @param array $args Arguments.
|
78 |
+
* @return array
|
79 |
+
*/
|
80 |
+
public function get_items( $args = array() ) {
|
81 |
+
$templates_data = Api::get_templates_data();
|
82 |
+
|
83 |
+
$templates = array();
|
84 |
+
|
85 |
+
if ( ! empty( $templates_data ) ) {
|
86 |
+
foreach ( $templates_data as $template_data ) {
|
87 |
+
$templates[] = $this->get_item( $template_data );
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
if ( ! empty( $args ) ) {
|
92 |
+
$templates = wp_list_filter( $templates, $args );
|
93 |
+
}
|
94 |
+
|
95 |
+
return $templates;
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Get Item
|
100 |
+
*
|
101 |
+
* @param array $template_data Template Data.
|
102 |
+
*
|
103 |
+
* @return array
|
104 |
+
*/
|
105 |
+
public function get_item( $template_data ) {
|
106 |
+
return array(
|
107 |
+
'template_id' => $template_data['id'],
|
108 |
+
'source' => $this->get_id(),
|
109 |
+
'title' => $template_data['title'],
|
110 |
+
'thumbnail' => $template_data['thumbnail'],
|
111 |
+
'date' => date( get_option( 'date_format' ), $template_data['tmpl_created'] ),
|
112 |
+
'author' => $template_data['author'],
|
113 |
+
'categories' => array(),
|
114 |
+
'keywords' => array(),
|
115 |
+
'isPro' => ( '1' === $template_data['is_pro'] ),
|
116 |
+
'hasPageSettings' => ( '1' === $template_data['has_page_settings'] ),
|
117 |
+
'url' => $template_data['url'],
|
118 |
+
);
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Template Data
|
123 |
+
*
|
124 |
+
* @param boolean $template_data Template Data.
|
125 |
+
* @return boolean Return false.
|
126 |
+
*/
|
127 |
+
public function save_item( $template_data ) {
|
128 |
+
return false;
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Update Item
|
133 |
+
*
|
134 |
+
* @param boolean $new_data New Data.
|
135 |
+
* @return boolean Return false.
|
136 |
+
*/
|
137 |
+
public function update_item( $new_data ) {
|
138 |
+
return false;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Delete Template
|
143 |
+
*
|
144 |
+
* @param boolean $template_id Template ID.
|
145 |
+
* @return boolean Return false.
|
146 |
+
*/
|
147 |
+
public function delete_template( $template_id ) {
|
148 |
+
return false;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Delete Template
|
153 |
+
*
|
154 |
+
* @param boolean $template_id Template ID.
|
155 |
+
* @return boolean Return false.
|
156 |
+
*/
|
157 |
+
public function export_template( $template_id ) {
|
158 |
+
return false;
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Get Data
|
163 |
+
*
|
164 |
+
* @param array $args Arguments.
|
165 |
+
* @param string $context Context.
|
166 |
+
* @return array Data.
|
167 |
+
*/
|
168 |
+
public function get_data( array $args, $context = 'display' ) {
|
169 |
+
$data = Api::get_template_content( $args['template_id'] );
|
170 |
+
|
171 |
+
if ( is_wp_error( $data ) ) {
|
172 |
+
return $data;
|
173 |
+
}
|
174 |
+
|
175 |
+
// TODO: since 1.5.0 to content container named `content` instead of `data`.
|
176 |
+
if ( ! empty( $data['data'] ) ) {
|
177 |
+
$data['content'] = $data['data'];
|
178 |
+
unset( $data['data'] );
|
179 |
+
}
|
180 |
+
|
181 |
+
$data['content'] = $this->replace_elements_ids( $data['content'] );
|
182 |
+
$data['content'] = $this->process_export_import_content( $data['content'], 'on_import' );
|
183 |
+
|
184 |
+
if ( ! empty( $args['page_settings'] ) && ! empty( $data['page_settings'] ) ) {
|
185 |
+
$page = new Page(
|
186 |
+
array(
|
187 |
+
'settings' => $data['page_settings'],
|
188 |
+
)
|
189 |
+
);
|
190 |
+
|
191 |
+
$page_settings_data = $this->process_element_export_import_content( $page, 'on_import' );
|
192 |
+
$data['page_settings'] = $page_settings_data['settings'];
|
193 |
+
}
|
194 |
+
|
195 |
+
return $data;
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Replace Elements Ids
|
200 |
+
*
|
201 |
+
* @param string $content Context.
|
202 |
+
* @return array Element.
|
203 |
+
*/
|
204 |
+
public function replace_elements_ids( $content ) {
|
205 |
+
return Plugin::$instance->db->iterate_data(
|
206 |
+
$content, function( $element ) {
|
207 |
+
$element['id'] = Utils::generate_random_string();
|
208 |
+
|
209 |
+
return $element;
|
210 |
+
}
|
211 |
+
);
|
212 |
+
}
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Process Import Content.
|
216 |
+
*
|
217 |
+
* @param array $content a set of elements.
|
218 |
+
* @param string $method (on_export|on_import).
|
219 |
+
*
|
220 |
+
* @return mixed
|
221 |
+
*/
|
222 |
+
public function process_export_import_content( $content, $method ) {
|
223 |
+
return Plugin::$instance->db->iterate_data(
|
224 |
+
$content, function( $element_data ) use ( $method ) {
|
225 |
+
$element = Plugin::$instance->elements_manager->create_element_instance( $element_data );
|
226 |
+
|
227 |
+
// If the widget/element isn't exist, like a plugin that creates a widget but deactivated.
|
228 |
+
if ( ! $element ) {
|
229 |
+
return null;
|
230 |
+
}
|
231 |
+
|
232 |
+
$instance = new Astra_Sites_Batch_Processing_Elementor();
|
233 |
+
|
234 |
+
return $instance->process_element_export_import_content( $element, $method );
|
235 |
+
}
|
236 |
+
);
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* Process Element/Export Import Content.
|
241 |
+
*
|
242 |
+
* @param \Elementor\Controls_Stack $element Element.
|
243 |
+
* @param string $method Method.
|
244 |
+
*
|
245 |
+
* @return array
|
246 |
+
*/
|
247 |
+
public function process_element_export_import_content( Controls_Stack $element, $method ) {
|
248 |
+
$element_data = $element->get_data();
|
249 |
+
|
250 |
+
if ( method_exists( $element, $method ) ) {
|
251 |
+
// TODO: Use the internal element data without parameters.
|
252 |
+
$element_data = $element->{$method}( $element_data );
|
253 |
+
}
|
254 |
+
|
255 |
+
foreach ( $element->get_controls() as $control ) {
|
256 |
+
$control_class = Plugin::$instance->controls_manager->get_control( $control['type'] );
|
257 |
+
|
258 |
+
// If the control isn't exist, like a plugin that creates the control but deactivated.
|
259 |
+
if ( ! $control_class ) {
|
260 |
+
return $element_data;
|
261 |
+
}
|
262 |
+
|
263 |
+
if ( method_exists( $control_class, $method ) ) {
|
264 |
+
$element_data['settings'][ $control['name'] ] = $control_class->{$method}( $element->get_settings( $control['name'] ) );
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
return $element_data;
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Import
|
273 |
+
*
|
274 |
+
* @since 1.0.14
|
275 |
+
* @return void
|
276 |
+
*/
|
277 |
+
public function import() {
|
278 |
+
|
279 |
+
\Astra_Sites_Image_Importer::log( '---- Processing WordPress Posts / Pages - for Elementor ----' );
|
280 |
+
|
281 |
+
$post_ids = \Astra_Sites_Batch_Processing::get_pages();
|
282 |
+
if ( is_array( $post_ids ) ) {
|
283 |
+
foreach ( $post_ids as $post_id ) {
|
284 |
+
$this->import_single_post( $post_id );
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Update post meta.
|
292 |
+
*
|
293 |
+
* @since 1.0.14
|
294 |
+
* @param integer $post_id Post ID.
|
295 |
+
* @return void
|
296 |
+
*/
|
297 |
+
public function import_single_post( $post_id = 0 ) {
|
298 |
+
|
299 |
+
\Astra_Sites_Image_Importer::log( 'Post ID: ' . $post_id );
|
300 |
+
|
301 |
+
if ( ! empty( $post_id ) ) {
|
302 |
+
|
303 |
+
$hotlink_imported = get_post_meta( $post_id, '_astra_sites_hotlink_imported', true );
|
304 |
+
|
305 |
+
if ( empty( $hotlink_imported ) ) {
|
306 |
+
|
307 |
+
$data = get_post_meta( $post_id, '_elementor_data', true );
|
308 |
+
|
309 |
+
if ( ! empty( $data ) ) {
|
310 |
+
|
311 |
+
$data = json_decode( $data, true );
|
312 |
+
|
313 |
+
$data = $this->replace_elements_ids( $data );
|
314 |
+
$data = $this->process_export_import_content( $data, 'on_import' );
|
315 |
+
|
316 |
+
// Update processed meta.
|
317 |
+
update_metadata( 'post', $post_id, '_elementor_data', $data );
|
318 |
+
update_metadata( 'post', $post_id, '_astra_sites_hotlink_imported', true );
|
319 |
+
|
320 |
+
// !important, Clear the cache after images import.
|
321 |
+
Plugin::$instance->posts_css_manager->clear_cache();
|
322 |
+
|
323 |
+
}
|
324 |
+
}
|
325 |
+
}
|
326 |
+
|
327 |
+
}
|
328 |
+
}
|
inc/importers/batch-processing/helpers/class-wp-async-request.php
CHANGED
@@ -1,164 +1,164 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WP Async Request
|
4 |
-
*
|
5 |
-
* @see https://github.com/A5hleyRich/wp-background-processing/
|
6 |
-
* @package WP-Background-Processing
|
7 |
-
*/
|
8 |
-
|
9 |
-
if ( ! class_exists( 'WP_Async_Request' ) ) {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Abstract WP_Async_Request class.
|
13 |
-
*
|
14 |
-
* @abstract
|
15 |
-
*/
|
16 |
-
abstract class WP_Async_Request {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Prefix
|
20 |
-
*
|
21 |
-
* (default value: 'wp')
|
22 |
-
*
|
23 |
-
* @var string
|
24 |
-
* @access protected
|
25 |
-
*/
|
26 |
-
protected $prefix = 'wp';
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Action
|
30 |
-
*
|
31 |
-
* (default value: 'async_request')
|
32 |
-
*
|
33 |
-
* @var string
|
34 |
-
* @access protected
|
35 |
-
*/
|
36 |
-
protected $action = 'async_request';
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Identifier
|
40 |
-
*
|
41 |
-
* @var mixed
|
42 |
-
* @access protected
|
43 |
-
*/
|
44 |
-
protected $identifier;
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Data
|
48 |
-
*
|
49 |
-
* (default value: array())
|
50 |
-
*
|
51 |
-
* @var array
|
52 |
-
* @access protected
|
53 |
-
*/
|
54 |
-
protected $data = array();
|
55 |
-
|
56 |
-
/**
|
57 |
-
* Initiate new async request
|
58 |
-
*/
|
59 |
-
public function __construct() {
|
60 |
-
$this->identifier = $this->prefix . '_' . $this->action;
|
61 |
-
|
62 |
-
add_action( 'wp_ajax_' . $this->identifier, array( $this, 'maybe_handle' ) );
|
63 |
-
add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) );
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Set data used during the request
|
68 |
-
*
|
69 |
-
* @param array $data Data.
|
70 |
-
*
|
71 |
-
* @return $this
|
72 |
-
*/
|
73 |
-
public function data( $data ) {
|
74 |
-
$this->data = $data;
|
75 |
-
|
76 |
-
return $this;
|
77 |
-
}
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Dispatch the async request
|
81 |
-
*
|
82 |
-
* @return array|WP_Error
|
83 |
-
*/
|
84 |
-
public function dispatch() {
|
85 |
-
$url = add_query_arg( $this->get_query_args(), $this->get_query_url() );
|
86 |
-
$args = $this->get_post_args();
|
87 |
-
|
88 |
-
return wp_remote_post( esc_url_raw( $url ), $args );
|
89 |
-
}
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Get query args
|
93 |
-
*
|
94 |
-
* @return array
|
95 |
-
*/
|
96 |
-
protected function get_query_args() {
|
97 |
-
if ( property_exists( $this, 'query_args' ) ) {
|
98 |
-
return $this->query_args;
|
99 |
-
}
|
100 |
-
|
101 |
-
return array(
|
102 |
-
'action' => $this->identifier,
|
103 |
-
'nonce' => wp_create_nonce( $this->identifier ),
|
104 |
-
);
|
105 |
-
}
|
106 |
-
|
107 |
-
/**
|
108 |
-
* Get query URL
|
109 |
-
*
|
110 |
-
* @return string
|
111 |
-
*/
|
112 |
-
protected function get_query_url() {
|
113 |
-
if ( property_exists( $this, 'query_url' ) ) {
|
114 |
-
return $this->query_url;
|
115 |
-
}
|
116 |
-
|
117 |
-
return admin_url( 'admin-ajax.php' );
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* Get post args
|
122 |
-
*
|
123 |
-
* @return array
|
124 |
-
*/
|
125 |
-
protected function get_post_args() {
|
126 |
-
if ( property_exists( $this, 'post_args' ) ) {
|
127 |
-
return $this->post_args;
|
128 |
-
}
|
129 |
-
|
130 |
-
return array(
|
131 |
-
'timeout' => 0.01,
|
132 |
-
'blocking' => false,
|
133 |
-
'body' => $this->data,
|
134 |
-
'cookies' => $_COOKIE,
|
135 |
-
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
|
136 |
-
);
|
137 |
-
}
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Maybe handle
|
141 |
-
*
|
142 |
-
* Check for correct nonce and pass to handler.
|
143 |
-
*/
|
144 |
-
public function maybe_handle() {
|
145 |
-
// Don't lock up other requests while processing.
|
146 |
-
session_write_close();
|
147 |
-
|
148 |
-
check_ajax_referer( $this->identifier, 'nonce' );
|
149 |
-
|
150 |
-
$this->handle();
|
151 |
-
|
152 |
-
wp_die();
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* Handle
|
157 |
-
*
|
158 |
-
* Override this method to perform any actions required
|
159 |
-
* during the async request.
|
160 |
-
*/
|
161 |
-
abstract protected function handle();
|
162 |
-
|
163 |
-
}
|
164 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WP Async Request
|
4 |
+
*
|
5 |
+
* @see https://github.com/A5hleyRich/wp-background-processing/
|
6 |
+
* @package WP-Background-Processing
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! class_exists( 'WP_Async_Request' ) ) {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Abstract WP_Async_Request class.
|
13 |
+
*
|
14 |
+
* @abstract
|
15 |
+
*/
|
16 |
+
abstract class WP_Async_Request {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Prefix
|
20 |
+
*
|
21 |
+
* (default value: 'wp')
|
22 |
+
*
|
23 |
+
* @var string
|
24 |
+
* @access protected
|
25 |
+
*/
|
26 |
+
protected $prefix = 'wp';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Action
|
30 |
+
*
|
31 |
+
* (default value: 'async_request')
|
32 |
+
*
|
33 |
+
* @var string
|
34 |
+
* @access protected
|
35 |
+
*/
|
36 |
+
protected $action = 'async_request';
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Identifier
|
40 |
+
*
|
41 |
+
* @var mixed
|
42 |
+
* @access protected
|
43 |
+
*/
|
44 |
+
protected $identifier;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Data
|
48 |
+
*
|
49 |
+
* (default value: array())
|
50 |
+
*
|
51 |
+
* @var array
|
52 |
+
* @access protected
|
53 |
+
*/
|
54 |
+
protected $data = array();
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Initiate new async request
|
58 |
+
*/
|
59 |
+
public function __construct() {
|
60 |
+
$this->identifier = $this->prefix . '_' . $this->action;
|
61 |
+
|
62 |
+
add_action( 'wp_ajax_' . $this->identifier, array( $this, 'maybe_handle' ) );
|
63 |
+
add_action( 'wp_ajax_nopriv_' . $this->identifier, array( $this, 'maybe_handle' ) );
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Set data used during the request
|
68 |
+
*
|
69 |
+
* @param array $data Data.
|
70 |
+
*
|
71 |
+
* @return $this
|
72 |
+
*/
|
73 |
+
public function data( $data ) {
|
74 |
+
$this->data = $data;
|
75 |
+
|
76 |
+
return $this;
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Dispatch the async request
|
81 |
+
*
|
82 |
+
* @return array|WP_Error
|
83 |
+
*/
|
84 |
+
public function dispatch() {
|
85 |
+
$url = add_query_arg( $this->get_query_args(), $this->get_query_url() );
|
86 |
+
$args = $this->get_post_args();
|
87 |
+
|
88 |
+
return wp_remote_post( esc_url_raw( $url ), $args );
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Get query args
|
93 |
+
*
|
94 |
+
* @return array
|
95 |
+
*/
|
96 |
+
protected function get_query_args() {
|
97 |
+
if ( property_exists( $this, 'query_args' ) ) {
|
98 |
+
return $this->query_args;
|
99 |
+
}
|
100 |
+
|
101 |
+
return array(
|
102 |
+
'action' => $this->identifier,
|
103 |
+
'nonce' => wp_create_nonce( $this->identifier ),
|
104 |
+
);
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Get query URL
|
109 |
+
*
|
110 |
+
* @return string
|
111 |
+
*/
|
112 |
+
protected function get_query_url() {
|
113 |
+
if ( property_exists( $this, 'query_url' ) ) {
|
114 |
+
return $this->query_url;
|
115 |
+
}
|
116 |
+
|
117 |
+
return admin_url( 'admin-ajax.php' );
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Get post args
|
122 |
+
*
|
123 |
+
* @return array
|
124 |
+
*/
|
125 |
+
protected function get_post_args() {
|
126 |
+
if ( property_exists( $this, 'post_args' ) ) {
|
127 |
+
return $this->post_args;
|
128 |
+
}
|
129 |
+
|
130 |
+
return array(
|
131 |
+
'timeout' => 0.01,
|
132 |
+
'blocking' => false,
|
133 |
+
'body' => $this->data,
|
134 |
+
'cookies' => $_COOKIE,
|
135 |
+
'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
|
136 |
+
);
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Maybe handle
|
141 |
+
*
|
142 |
+
* Check for correct nonce and pass to handler.
|
143 |
+
*/
|
144 |
+
public function maybe_handle() {
|
145 |
+
// Don't lock up other requests while processing.
|
146 |
+
session_write_close();
|
147 |
+
|
148 |
+
check_ajax_referer( $this->identifier, 'nonce' );
|
149 |
+
|
150 |
+
$this->handle();
|
151 |
+
|
152 |
+
wp_die();
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Handle
|
157 |
+
*
|
158 |
+
* Override this method to perform any actions required
|
159 |
+
* during the async request.
|
160 |
+
*/
|
161 |
+
abstract protected function handle();
|
162 |
+
|
163 |
+
}
|
164 |
+
}
|
inc/importers/batch-processing/helpers/class-wp-background-process.php
CHANGED
@@ -1,513 +1,513 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* WP Background Process
|
4 |
-
*
|
5 |
-
* @see https://github.com/A5hleyRich/wp-background-processing/
|
6 |
-
* @package WP-Background-Processing
|
7 |
-
*/
|
8 |
-
|
9 |
-
if ( ! class_exists( 'WP_Background_Process' ) ) {
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Abstract WP_Background_Process class.
|
13 |
-
*
|
14 |
-
* @abstract
|
15 |
-
* @extends WP_Async_Request
|
16 |
-
*/
|
17 |
-
abstract class WP_Background_Process extends WP_Async_Request {
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Action
|
21 |
-
*
|
22 |
-
* (default value: 'background_process')
|
23 |
-
*
|
24 |
-
* @var string
|
25 |
-
* @access protected
|
26 |
-
*/
|
27 |
-
protected $action = 'background_process';
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Start time of current process.
|
31 |
-
*
|
32 |
-
* (default value: 0)
|
33 |
-
*
|
34 |
-
* @var int
|
35 |
-
* @access protected
|
36 |
-
*/
|
37 |
-
protected $start_time = 0;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Cron_hook_identifier
|
41 |
-
*
|
42 |
-
* @var mixed
|
43 |
-
* @access protected
|
44 |
-
*/
|
45 |
-
protected $cron_hook_identifier;
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Cron_interval_identifier
|
49 |
-
*
|
50 |
-
* @var mixed
|
51 |
-
* @access protected
|
52 |
-
*/
|
53 |
-
protected $cron_interval_identifier;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Initiate new background process
|
57 |
-
*/
|
58 |
-
public function __construct() {
|
59 |
-
parent::__construct();
|
60 |
-
|
61 |
-
$this->cron_hook_identifier = $this->identifier . '_cron';
|
62 |
-
$this->cron_interval_identifier = $this->identifier . '_cron_interval';
|
63 |
-
|
64 |
-
add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
|
65 |
-
add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Dispatch
|
70 |
-
*
|
71 |
-
* @return mixed dispatch event.
|
72 |
-
*/
|
73 |
-
public function dispatch() {
|
74 |
-
// Schedule the cron healthcheck.
|
75 |
-
$this->schedule_event();
|
76 |
-
|
77 |
-
// Perform remote post.
|
78 |
-
return parent::dispatch();
|
79 |
-
}
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Push to queue
|
83 |
-
*
|
84 |
-
* @param mixed $data Data.
|
85 |
-
*
|
86 |
-
* @return $this
|
87 |
-
*/
|
88 |
-
public function push_to_queue( $data ) {
|
89 |
-
$this->data[] = $data;
|
90 |
-
|
91 |
-
return $this;
|
92 |
-
}
|
93 |
-
|
94 |
-
/**
|
95 |
-
* Save queue
|
96 |
-
*
|
97 |
-
* @return $this
|
98 |
-
*/
|
99 |
-
public function save() {
|
100 |
-
$key = $this->generate_key();
|
101 |
-
|
102 |
-
if ( ! empty( $this->data ) ) {
|
103 |
-
update_site_option( $key, $this->data );
|
104 |
-
}
|
105 |
-
|
106 |
-
return $this;
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Update queue
|
111 |
-
*
|
112 |
-
* @param string $key Key.
|
113 |
-
* @param array $data Data.
|
114 |
-
*
|
115 |
-
* @return $this
|
116 |
-
*/
|
117 |
-
public function update( $key, $data ) {
|
118 |
-
if ( ! empty( $data ) ) {
|
119 |
-
update_site_option( $key, $data );
|
120 |
-
}
|
121 |
-
|
122 |
-
return $this;
|
123 |
-
}
|
124 |
-
|
125 |
-
/**
|
126 |
-
* Delete queue
|
127 |
-
*
|
128 |
-
* @param string $key Key.
|
129 |
-
*
|
130 |
-
* @return $this
|
131 |
-
*/
|
132 |
-
public function delete( $key ) {
|
133 |
-
delete_site_option( $key );
|
134 |
-
|
135 |
-
return $this;
|
136 |
-
}
|
137 |
-
|
138 |
-
/**
|
139 |
-
* Generate key
|
140 |
-
*
|
141 |
-
* Generates a unique key based on microtime. Queue items are
|
142 |
-
* given a unique key so that they can be merged upon save.
|
143 |
-
*
|
144 |
-
* @param int $length Length.
|
145 |
-
*
|
146 |
-
* @return string
|
147 |
-
*/
|
148 |
-
protected function generate_key( $length = 64 ) {
|
149 |
-
$unique = md5( microtime() . rand() );
|
150 |
-
$prepend = $this->identifier . '_batch_';
|
151 |
-
|
152 |
-
return substr( $prepend . $unique, 0, $length );
|
153 |
-
}
|
154 |
-
|
155 |
-
/**
|
156 |
-
* Maybe process queue
|
157 |
-
*
|
158 |
-
* Checks whether data exists within the queue and that
|
159 |
-
* the process is not already running.
|
160 |
-
*/
|
161 |
-
public function maybe_handle() {
|
162 |
-
// Don't lock up other requests while processing.
|
163 |
-
session_write_close();
|
164 |
-
|
165 |
-
if ( $this->is_process_running() ) {
|
166 |
-
// Background process already running.
|
167 |
-
wp_die();
|
168 |
-
}
|
169 |
-
|
170 |
-
if ( $this->is_queue_empty() ) {
|
171 |
-
// No data to process.
|
172 |
-
wp_die();
|
173 |
-
}
|
174 |
-
|
175 |
-
check_ajax_referer( $this->identifier, 'nonce' );
|
176 |
-
|
177 |
-
$this->handle();
|
178 |
-
|
179 |
-
wp_die();
|
180 |
-
}
|
181 |
-
|
182 |
-
/**
|
183 |
-
* Is queue empty
|
184 |
-
*
|
185 |
-
* @return bool
|
186 |
-
*/
|
187 |
-
protected function is_queue_empty() {
|
188 |
-
global $wpdb;
|
189 |
-
|
190 |
-
$table = $wpdb->options;
|
191 |
-
$column = 'option_name';
|
192 |
-
|
193 |
-
if ( is_multisite() ) {
|
194 |
-
$table = $wpdb->sitemeta;
|
195 |
-
$column = 'meta_key';
|
196 |
-
}
|
197 |
-
|
198 |
-
$key = $this->identifier . '_batch_%';
|
199 |
-
|
200 |
-
$count = $wpdb->get_var(
|
201 |
-
$wpdb->prepare(
|
202 |
-
"
|
203 |
-
SELECT COUNT(*)
|
204 |
-
FROM {$table}
|
205 |
-
WHERE {$column} LIKE %s
|
206 |
-
", $key
|
207 |
-
)
|
208 |
-
);
|
209 |
-
|
210 |
-
return ( $count > 0 ) ? false : true;
|
211 |
-
}
|
212 |
-
|
213 |
-
/**
|
214 |
-
* Is process running
|
215 |
-
*
|
216 |
-
* Check whether the current process is already running
|
217 |
-
* in a background process.
|
218 |
-
*/
|
219 |
-
protected function is_process_running() {
|
220 |
-
if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
|
221 |
-
// Process already running.
|
222 |
-
return true;
|
223 |
-
}
|
224 |
-
|
225 |
-
return false;
|
226 |
-
}
|
227 |
-
|
228 |
-
/**
|
229 |
-
* Lock process
|
230 |
-
*
|
231 |
-
* Lock the process so that multiple instances can't run simultaneously.
|
232 |
-
* Override if applicable, but the duration should be greater than that
|
233 |
-
* defined in the time_exceeded() method.
|
234 |
-
*/
|
235 |
-
protected function lock_process() {
|
236 |
-
$this->start_time = time(); // Set start time of current process.
|
237 |
-
|
238 |
-
$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
|
239 |
-
$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
|
240 |
-
|
241 |
-
set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
|
242 |
-
}
|
243 |
-
|
244 |
-
/**
|
245 |
-
* Unlock process
|
246 |
-
*
|
247 |
-
* Unlock the process so that other instances can spawn.
|
248 |
-
*
|
249 |
-
* @return $this
|
250 |
-
*/
|
251 |
-
protected function unlock_process() {
|
252 |
-
delete_site_transient( $this->identifier . '_process_lock' );
|
253 |
-
|
254 |
-
return $this;
|
255 |
-
}
|
256 |
-
|
257 |
-
/**
|
258 |
-
* Get batch
|
259 |
-
*
|
260 |
-
* @return stdClass Return the first batch from the queue
|
261 |
-
*/
|
262 |
-
protected function get_batch() {
|
263 |
-
global $wpdb;
|
264 |
-
|
265 |
-
$table = $wpdb->options;
|
266 |
-
$column = 'option_name';
|
267 |
-
$key_column = 'option_id';
|
268 |
-
$value_column = 'option_value';
|
269 |
-
|
270 |
-
if ( is_multisite() ) {
|
271 |
-
$table = $wpdb->sitemeta;
|
272 |
-
$column = 'meta_key';
|
273 |
-
$key_column = 'meta_id';
|
274 |
-
$value_column = 'meta_value';
|
275 |
-
}
|
276 |
-
|
277 |
-
$key = $this->identifier . '_batch_%';
|
278 |
-
|
279 |
-
$query = $wpdb->get_row(
|
280 |
-
$wpdb->prepare(
|
281 |
-
"
|
282 |
-
SELECT *
|
283 |
-
FROM {$table}
|
284 |
-
WHERE {$column} LIKE %s
|
285 |
-
ORDER BY {$key_column} ASC
|
286 |
-
LIMIT 1
|
287 |
-
", $key
|
288 |
-
)
|
289 |
-
);
|
290 |
-
|
291 |
-
$batch = new stdClass();
|
292 |
-
$batch->key = $query->$column;
|
293 |
-
$batch->data = maybe_unserialize( $query->$value_column );
|
294 |
-
|
295 |
-
return $batch;
|
296 |
-
}
|
297 |
-
|
298 |
-
/**
|
299 |
-
* Handle
|
300 |
-
*
|
301 |
-
* Pass each queue item to the task handler, while remaining
|
302 |
-
* within server memory and time limit constraints.
|
303 |
-
*/
|
304 |
-
protected function handle() {
|
305 |
-
$this->lock_process();
|
306 |
-
|
307 |
-
do {
|
308 |
-
$batch = $this->get_batch();
|
309 |
-
|
310 |
-
foreach ( $batch->data as $key => $value ) {
|
311 |
-
$task = $this->task( $value );
|
312 |
-
|
313 |
-
if ( false !== $task ) {
|
314 |
-
$batch->data[ $key ] = $task;
|
315 |
-
} else {
|
316 |
-
unset( $batch->data[ $key ] );
|
317 |
-
}
|
318 |
-
|
319 |
-
if ( $this->time_exceeded() || $this->memory_exceeded() ) {
|
320 |
-
// Batch limits reached.
|
321 |
-
break;
|
322 |
-
}
|
323 |
-
}
|
324 |
-
|
325 |
-
// Update or delete current batch.
|
326 |
-
if ( ! empty( $batch->data ) ) {
|
327 |
-
$this->update( $batch->key, $batch->data );
|
328 |
-
} else {
|
329 |
-
$this->delete( $batch->key );
|
330 |
-
}
|
331 |
-
} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
|
332 |
-
|
333 |
-
$this->unlock_process();
|
334 |
-
|
335 |
-
// Start next batch or complete process.
|
336 |
-
if ( ! $this->is_queue_empty() ) {
|
337 |
-
$this->dispatch();
|
338 |
-
} else {
|
339 |
-
$this->complete();
|
340 |
-
}
|
341 |
-
|
342 |
-
wp_die();
|
343 |
-
}
|
344 |
-
|
345 |
-
/**
|
346 |
-
* Memory exceeded
|
347 |
-
*
|
348 |
-
* Ensures the batch process never exceeds 90%
|
349 |
-
* of the maximum WordPress memory.
|
350 |
-
*
|
351 |
-
* @return bool
|
352 |
-
*/
|
353 |
-
protected function memory_exceeded() {
|
354 |
-
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
|
355 |
-
$current_memory = memory_get_usage( true );
|
356 |
-
$return = false;
|
357 |
-
|
358 |
-
if ( $current_memory >= $memory_limit ) {
|
359 |
-
$return = true;
|
360 |
-
}
|
361 |
-
|
362 |
-
return apply_filters( $this->identifier . '_memory_exceeded', $return );
|
363 |
-
}
|
364 |
-
|
365 |
-
/**
|
366 |
-
* Get memory limit
|
367 |
-
*
|
368 |
-
* @return int
|
369 |
-
*/
|
370 |
-
protected function get_memory_limit() {
|
371 |
-
if ( function_exists( 'ini_get' ) ) {
|
372 |
-
$memory_limit = ini_get( 'memory_limit' );
|
373 |
-
} else {
|
374 |
-
// Sensible default.
|
375 |
-
$memory_limit = '128M';
|
376 |
-
}
|
377 |
-
|
378 |
-
if ( ! $memory_limit || -1 === $memory_limit ) {
|
379 |
-
// Unlimited, set to 32GB.
|
380 |
-
$memory_limit = '32000M';
|
381 |
-
}
|
382 |
-
|
383 |
-
return intval( $memory_limit ) * 1024 * 1024;
|
384 |
-
}
|
385 |
-
|
386 |
-
/**
|
387 |
-
* Time exceeded.
|
388 |
-
*
|
389 |
-
* Ensures the batch never exceeds a sensible time limit.
|
390 |
-
* A timeout limit of 30s is common on shared hosting.
|
391 |
-
*
|
392 |
-
* @return bool
|
393 |
-
*/
|
394 |
-
protected function time_exceeded() {
|
395 |
-
$finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
|
396 |
-
$return = false;
|
397 |
-
|
398 |
-
if ( time() >= $finish ) {
|
399 |
-
$return = true;
|
400 |
-
}
|
401 |
-
|
402 |
-
return apply_filters( $this->identifier . '_time_exceeded', $return );
|
403 |
-
}
|
404 |
-
|
405 |
-
/**
|
406 |
-
* Complete.
|
407 |
-
*
|
408 |
-
* Override if applicable, but ensure that the below actions are
|
409 |
-
* performed, or, call parent::complete().
|
410 |
-
*/
|
411 |
-
protected function complete() {
|
412 |
-
// Unschedule the cron healthcheck.
|
413 |
-
$this->clear_scheduled_event();
|
414 |
-
}
|
415 |
-
|
416 |
-
/**
|
417 |
-
* Schedule cron healthcheck
|
418 |
-
*
|
419 |
-
* @access public
|
420 |
-
* @param mixed $schedules Schedules.
|
421 |
-
* @return mixed
|
422 |
-
*/
|
423 |
-
public function schedule_cron_healthcheck( $schedules ) {
|
424 |
-
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
|
425 |
-
|
426 |
-
if ( property_exists( $this, 'cron_interval' ) ) {
|
427 |
-
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval_identifier );
|
428 |
-
}
|
429 |
-
|
430 |
-
// Adds every 5 minutes to the existing schedules.
|
431 |
-
$schedules[ $this->identifier . '_cron_interval' ] = array(
|
432 |
-
'interval' => MINUTE_IN_SECONDS * $interval,
|
433 |
-
'display' => sprintf( __( 'Every %d Minutes', 'astra-sites' ), $interval ),
|
434 |
-
);
|
435 |
-
|
436 |
-
return $schedules;
|
437 |
-
}
|
438 |
-
|
439 |
-
/**
|
440 |
-
* Handle cron healthcheck
|
441 |
-
*
|
442 |
-
* Restart the background process if not already running
|
443 |
-
* and data exists in the queue.
|
444 |
-
*/
|
445 |
-
public function handle_cron_healthcheck() {
|
446 |
-
if ( $this->is_process_running() ) {
|
447 |
-
// Background process already running.
|
448 |
-
exit;
|
449 |
-
}
|
450 |
-
|
451 |
-
if ( $this->is_queue_empty() ) {
|
452 |
-
// No data to process.
|
453 |
-
$this->clear_scheduled_event();
|
454 |
-
exit;
|
455 |
-
}
|
456 |
-
|
457 |
-
$this->handle();
|
458 |
-
|
459 |
-
exit;
|
460 |
-
}
|
461 |
-
|
462 |
-
/**
|
463 |
-
* Schedule event
|
464 |
-
*/
|
465 |
-
protected function schedule_event() {
|
466 |
-
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
|
467 |
-
wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
|
468 |
-
}
|
469 |
-
}
|
470 |
-
|
471 |
-
/**
|
472 |
-
* Clear scheduled event
|
473 |
-
*/
|
474 |
-
protected function clear_scheduled_event() {
|
475 |
-
$timestamp = wp_next_scheduled( $this->cron_hook_identifier );
|
476 |
-
|
477 |
-
if ( $timestamp ) {
|
478 |
-
wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
|
479 |
-
}
|
480 |
-
}
|
481 |
-
|
482 |
-
/**
|
483 |
-
* Cancel Process
|
484 |
-
*
|
485 |
-
* Stop processing queue items, clear cronjob and delete batch.
|
486 |
-
*/
|
487 |
-
public function cancel_process() {
|
488 |
-
if ( ! $this->is_queue_empty() ) {
|
489 |
-
$batch = $this->get_batch();
|
490 |
-
|
491 |
-
$this->delete( $batch->key );
|
492 |
-
|
493 |
-
wp_clear_scheduled_hook( $this->cron_hook_identifier );
|
494 |
-
}
|
495 |
-
|
496 |
-
}
|
497 |
-
|
498 |
-
/**
|
499 |
-
* Task
|
500 |
-
*
|
501 |
-
* Override this method to perform any actions required on each
|
502 |
-
* queue item. Return the modified item for further processing
|
503 |
-
* in the next pass through. Or, return false to remove the
|
504 |
-
* item from the queue.
|
505 |
-
*
|
506 |
-
* @param mixed $item Queue item to iterate over.
|
507 |
-
*
|
508 |
-
* @return mixed
|
509 |
-
*/
|
510 |
-
abstract protected function task( $item );
|
511 |
-
|
512 |
-
}
|
513 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* WP Background Process
|
4 |
+
*
|
5 |
+
* @see https://github.com/A5hleyRich/wp-background-processing/
|
6 |
+
* @package WP-Background-Processing
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! class_exists( 'WP_Background_Process' ) ) {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Abstract WP_Background_Process class.
|
13 |
+
*
|
14 |
+
* @abstract
|
15 |
+
* @extends WP_Async_Request
|
16 |
+
*/
|
17 |
+
abstract class WP_Background_Process extends WP_Async_Request {
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Action
|
21 |
+
*
|
22 |
+
* (default value: 'background_process')
|
23 |
+
*
|
24 |
+
* @var string
|
25 |
+
* @access protected
|
26 |
+
*/
|
27 |
+
protected $action = 'background_process';
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Start time of current process.
|
31 |
+
*
|
32 |
+
* (default value: 0)
|
33 |
+
*
|
34 |
+
* @var int
|
35 |
+
* @access protected
|
36 |
+
*/
|
37 |
+
protected $start_time = 0;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Cron_hook_identifier
|
41 |
+
*
|
42 |
+
* @var mixed
|
43 |
+
* @access protected
|
44 |
+
*/
|
45 |
+
protected $cron_hook_identifier;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Cron_interval_identifier
|
49 |
+
*
|
50 |
+
* @var mixed
|
51 |
+
* @access protected
|
52 |
+
*/
|
53 |
+
protected $cron_interval_identifier;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Initiate new background process
|
57 |
+
*/
|
58 |
+
public function __construct() {
|
59 |
+
parent::__construct();
|
60 |
+
|
61 |
+
$this->cron_hook_identifier = $this->identifier . '_cron';
|
62 |
+
$this->cron_interval_identifier = $this->identifier . '_cron_interval';
|
63 |
+
|
64 |
+
add_action( $this->cron_hook_identifier, array( $this, 'handle_cron_healthcheck' ) );
|
65 |
+
add_filter( 'cron_schedules', array( $this, 'schedule_cron_healthcheck' ) );
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Dispatch
|
70 |
+
*
|
71 |
+
* @return mixed dispatch event.
|
72 |
+
*/
|
73 |
+
public function dispatch() {
|
74 |
+
// Schedule the cron healthcheck.
|
75 |
+
$this->schedule_event();
|
76 |
+
|
77 |
+
// Perform remote post.
|
78 |
+
return parent::dispatch();
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Push to queue
|
83 |
+
*
|
84 |
+
* @param mixed $data Data.
|
85 |
+
*
|
86 |
+
* @return $this
|
87 |
+
*/
|
88 |
+
public function push_to_queue( $data ) {
|
89 |
+
$this->data[] = $data;
|
90 |
+
|
91 |
+
return $this;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Save queue
|
96 |
+
*
|
97 |
+
* @return $this
|
98 |
+
*/
|
99 |
+
public function save() {
|
100 |
+
$key = $this->generate_key();
|
101 |
+
|
102 |
+
if ( ! empty( $this->data ) ) {
|
103 |
+
update_site_option( $key, $this->data );
|
104 |
+
}
|
105 |
+
|
106 |
+
return $this;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Update queue
|
111 |
+
*
|
112 |
+
* @param string $key Key.
|
113 |
+
* @param array $data Data.
|
114 |
+
*
|
115 |
+
* @return $this
|
116 |
+
*/
|
117 |
+
public function update( $key, $data ) {
|
118 |
+
if ( ! empty( $data ) ) {
|
119 |
+
update_site_option( $key, $data );
|
120 |
+
}
|
121 |
+
|
122 |
+
return $this;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Delete queue
|
127 |
+
*
|
128 |
+
* @param string $key Key.
|
129 |
+
*
|
130 |
+
* @return $this
|
131 |
+
*/
|
132 |
+
public function delete( $key ) {
|
133 |
+
delete_site_option( $key );
|
134 |
+
|
135 |
+
return $this;
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Generate key
|
140 |
+
*
|
141 |
+
* Generates a unique key based on microtime. Queue items are
|
142 |
+
* given a unique key so that they can be merged upon save.
|
143 |
+
*
|
144 |
+
* @param int $length Length.
|
145 |
+
*
|
146 |
+
* @return string
|
147 |
+
*/
|
148 |
+
protected function generate_key( $length = 64 ) {
|
149 |
+
$unique = md5( microtime() . rand() );
|
150 |
+
$prepend = $this->identifier . '_batch_';
|
151 |
+
|
152 |
+
return substr( $prepend . $unique, 0, $length );
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Maybe process queue
|
157 |
+
*
|
158 |
+
* Checks whether data exists within the queue and that
|
159 |
+
* the process is not already running.
|
160 |
+
*/
|
161 |
+
public function maybe_handle() {
|
162 |
+
// Don't lock up other requests while processing.
|
163 |
+
session_write_close();
|
164 |
+
|
165 |
+
if ( $this->is_process_running() ) {
|
166 |
+
// Background process already running.
|
167 |
+
wp_die();
|
168 |
+
}
|
169 |
+
|
170 |
+
if ( $this->is_queue_empty() ) {
|
171 |
+
// No data to process.
|
172 |
+
wp_die();
|
173 |
+
}
|
174 |
+
|
175 |
+
check_ajax_referer( $this->identifier, 'nonce' );
|
176 |
+
|
177 |
+
$this->handle();
|
178 |
+
|
179 |
+
wp_die();
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Is queue empty
|
184 |
+
*
|
185 |
+
* @return bool
|
186 |
+
*/
|
187 |
+
protected function is_queue_empty() {
|
188 |
+
global $wpdb;
|
189 |
+
|
190 |
+
$table = $wpdb->options;
|
191 |
+
$column = 'option_name';
|
192 |
+
|
193 |
+
if ( is_multisite() ) {
|
194 |
+
$table = $wpdb->sitemeta;
|
195 |
+
$column = 'meta_key';
|
196 |
+
}
|
197 |
+
|
198 |
+
$key = $this->identifier . '_batch_%';
|
199 |
+
|
200 |
+
$count = $wpdb->get_var(
|
201 |
+
$wpdb->prepare(
|
202 |
+
"
|
203 |
+
SELECT COUNT(*)
|
204 |
+
FROM {$table}
|
205 |
+
WHERE {$column} LIKE %s
|
206 |
+
", $key
|
207 |
+
)
|
208 |
+
);
|
209 |
+
|
210 |
+
return ( $count > 0 ) ? false : true;
|
211 |
+
}
|
212 |
+
|
213 |
+
/**
|
214 |
+
* Is process running
|
215 |
+
*
|
216 |
+
* Check whether the current process is already running
|
217 |
+
* in a background process.
|
218 |
+
*/
|
219 |
+
protected function is_process_running() {
|
220 |
+
if ( get_site_transient( $this->identifier . '_process_lock' ) ) {
|
221 |
+
// Process already running.
|
222 |
+
return true;
|
223 |
+
}
|
224 |
+
|
225 |
+
return false;
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Lock process
|
230 |
+
*
|
231 |
+
* Lock the process so that multiple instances can't run simultaneously.
|
232 |
+
* Override if applicable, but the duration should be greater than that
|
233 |
+
* defined in the time_exceeded() method.
|
234 |
+
*/
|
235 |
+
protected function lock_process() {
|
236 |
+
$this->start_time = time(); // Set start time of current process.
|
237 |
+
|
238 |
+
$lock_duration = ( property_exists( $this, 'queue_lock_time' ) ) ? $this->queue_lock_time : 60; // 1 minute
|
239 |
+
$lock_duration = apply_filters( $this->identifier . '_queue_lock_time', $lock_duration );
|
240 |
+
|
241 |
+
set_site_transient( $this->identifier . '_process_lock', microtime(), $lock_duration );
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Unlock process
|
246 |
+
*
|
247 |
+
* Unlock the process so that other instances can spawn.
|
248 |
+
*
|
249 |
+
* @return $this
|
250 |
+
*/
|
251 |
+
protected function unlock_process() {
|
252 |
+
delete_site_transient( $this->identifier . '_process_lock' );
|
253 |
+
|
254 |
+
return $this;
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Get batch
|
259 |
+
*
|
260 |
+
* @return stdClass Return the first batch from the queue
|
261 |
+
*/
|
262 |
+
protected function get_batch() {
|
263 |
+
global $wpdb;
|
264 |
+
|
265 |
+
$table = $wpdb->options;
|
266 |
+
$column = 'option_name';
|
267 |
+
$key_column = 'option_id';
|
268 |
+
$value_column = 'option_value';
|
269 |
+
|
270 |
+
if ( is_multisite() ) {
|
271 |
+
$table = $wpdb->sitemeta;
|
272 |
+
$column = 'meta_key';
|
273 |
+
$key_column = 'meta_id';
|
274 |
+
$value_column = 'meta_value';
|
275 |
+
}
|
276 |
+
|
277 |
+
$key = $this->identifier . '_batch_%';
|
278 |
+
|
279 |
+
$query = $wpdb->get_row(
|
280 |
+
$wpdb->prepare(
|
281 |
+
"
|
282 |
+
SELECT *
|
283 |
+
FROM {$table}
|
284 |
+
WHERE {$column} LIKE %s
|
285 |
+
ORDER BY {$key_column} ASC
|
286 |
+
LIMIT 1
|
287 |
+
", $key
|
288 |
+
)
|
289 |
+
);
|
290 |
+
|
291 |
+
$batch = new stdClass();
|
292 |
+
$batch->key = $query->$column;
|
293 |
+
$batch->data = maybe_unserialize( $query->$value_column );
|
294 |
+
|
295 |
+
return $batch;
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Handle
|
300 |
+
*
|
301 |
+
* Pass each queue item to the task handler, while remaining
|
302 |
+
* within server memory and time limit constraints.
|
303 |
+
*/
|
304 |
+
protected function handle() {
|
305 |
+
$this->lock_process();
|
306 |
+
|
307 |
+
do {
|
308 |
+
$batch = $this->get_batch();
|
309 |
+
|
310 |
+
foreach ( $batch->data as $key => $value ) {
|
311 |
+
$task = $this->task( $value );
|
312 |
+
|
313 |
+
if ( false !== $task ) {
|
314 |
+
$batch->data[ $key ] = $task;
|
315 |
+
} else {
|
316 |
+
unset( $batch->data[ $key ] );
|
317 |
+
}
|
318 |
+
|
319 |
+
if ( $this->time_exceeded() || $this->memory_exceeded() ) {
|
320 |
+
// Batch limits reached.
|
321 |
+
break;
|
322 |
+
}
|
323 |
+
}
|
324 |
+
|
325 |
+
// Update or delete current batch.
|
326 |
+
if ( ! empty( $batch->data ) ) {
|
327 |
+
$this->update( $batch->key, $batch->data );
|
328 |
+
} else {
|
329 |
+
$this->delete( $batch->key );
|
330 |
+
}
|
331 |
+
} while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() );
|
332 |
+
|
333 |
+
$this->unlock_process();
|
334 |
+
|
335 |
+
// Start next batch or complete process.
|
336 |
+
if ( ! $this->is_queue_empty() ) {
|
337 |
+
$this->dispatch();
|
338 |
+
} else {
|
339 |
+
$this->complete();
|
340 |
+
}
|
341 |
+
|
342 |
+
wp_die();
|
343 |
+
}
|
344 |
+
|
345 |
+
/**
|
346 |
+
* Memory exceeded
|
347 |
+
*
|
348 |
+
* Ensures the batch process never exceeds 90%
|
349 |
+
* of the maximum WordPress memory.
|
350 |
+
*
|
351 |
+
* @return bool
|
352 |
+
*/
|
353 |
+
protected function memory_exceeded() {
|
354 |
+
$memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory
|
355 |
+
$current_memory = memory_get_usage( true );
|
356 |
+
$return = false;
|
357 |
+
|
358 |
+
if ( $current_memory >= $memory_limit ) {
|
359 |
+
$return = true;
|
360 |
+
}
|
361 |
+
|
362 |
+
return apply_filters( $this->identifier . '_memory_exceeded', $return );
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Get memory limit
|
367 |
+
*
|
368 |
+
* @return int
|
369 |
+
*/
|
370 |
+
protected function get_memory_limit() {
|
371 |
+
if ( function_exists( 'ini_get' ) ) {
|
372 |
+
$memory_limit = ini_get( 'memory_limit' );
|
373 |
+
} else {
|
374 |
+
// Sensible default.
|
375 |
+
$memory_limit = '128M';
|
376 |
+
}
|
377 |
+
|
378 |
+
if ( ! $memory_limit || -1 === $memory_limit ) {
|
379 |
+
// Unlimited, set to 32GB.
|
380 |
+
$memory_limit = '32000M';
|
381 |
+
}
|
382 |
+
|
383 |
+
return intval( $memory_limit ) * 1024 * 1024;
|
384 |
+
}
|
385 |
+
|
386 |
+
/**
|
387 |
+
* Time exceeded.
|
388 |
+
*
|
389 |
+
* Ensures the batch never exceeds a sensible time limit.
|
390 |
+
* A timeout limit of 30s is common on shared hosting.
|
391 |
+
*
|
392 |
+
* @return bool
|
393 |
+
*/
|
394 |
+
protected function time_exceeded() {
|
395 |
+
$finish = $this->start_time + apply_filters( $this->identifier . '_default_time_limit', 20 ); // 20 seconds
|
396 |
+
$return = false;
|
397 |
+
|
398 |
+
if ( time() >= $finish ) {
|
399 |
+
$return = true;
|
400 |
+
}
|
401 |
+
|
402 |
+
return apply_filters( $this->identifier . '_time_exceeded', $return );
|
403 |
+
}
|
404 |
+
|
405 |
+
/**
|
406 |
+
* Complete.
|
407 |
+
*
|
408 |
+
* Override if applicable, but ensure that the below actions are
|
409 |
+
* performed, or, call parent::complete().
|
410 |
+
*/
|
411 |
+
protected function complete() {
|
412 |
+
// Unschedule the cron healthcheck.
|
413 |
+
$this->clear_scheduled_event();
|
414 |
+
}
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Schedule cron healthcheck
|
418 |
+
*
|
419 |
+
* @access public
|
420 |
+
* @param mixed $schedules Schedules.
|
421 |
+
* @return mixed
|
422 |
+
*/
|
423 |
+
public function schedule_cron_healthcheck( $schedules ) {
|
424 |
+
$interval = apply_filters( $this->identifier . '_cron_interval', 5 );
|
425 |
+
|
426 |
+
if ( property_exists( $this, 'cron_interval' ) ) {
|
427 |
+
$interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval_identifier );
|
428 |
+
}
|
429 |
+
|
430 |
+
// Adds every 5 minutes to the existing schedules.
|
431 |
+
$schedules[ $this->identifier . '_cron_interval' ] = array(
|
432 |
+
'interval' => MINUTE_IN_SECONDS * $interval,
|
433 |
+
'display' => sprintf( __( 'Every %d Minutes', 'astra-sites' ), $interval ),
|
434 |
+
);
|
435 |
+
|
436 |
+
return $schedules;
|
437 |
+
}
|
438 |
+
|
439 |
+
/**
|
440 |
+
* Handle cron healthcheck
|
441 |
+
*
|
442 |
+
* Restart the background process if not already running
|
443 |
+
* and data exists in the queue.
|
444 |
+
*/
|
445 |
+
public function handle_cron_healthcheck() {
|
446 |
+
if ( $this->is_process_running() ) {
|
447 |
+
// Background process already running.
|
448 |
+
exit;
|
449 |
+
}
|
450 |
+
|
451 |
+
if ( $this->is_queue_empty() ) {
|
452 |
+
// No data to process.
|
453 |
+
$this->clear_scheduled_event();
|
454 |
+
exit;
|
455 |
+
}
|
456 |
+
|
457 |
+
$this->handle();
|
458 |
+
|
459 |
+
exit;
|
460 |
+
}
|
461 |
+
|
462 |
+
/**
|
463 |
+
* Schedule event
|
464 |
+
*/
|
465 |
+
protected function schedule_event() {
|
466 |
+
if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
|
467 |
+
wp_schedule_event( time(), $this->cron_interval_identifier, $this->cron_hook_identifier );
|
468 |
+
}
|
469 |
+
}
|
470 |
+
|
471 |
+
/**
|
472 |
+
* Clear scheduled event
|
473 |
+
*/
|
474 |
+
protected function clear_scheduled_event() {
|
475 |
+
$timestamp = wp_next_scheduled( $this->cron_hook_identifier );
|
476 |
+
|
477 |
+
if ( $timestamp ) {
|
478 |
+
wp_unschedule_event( $timestamp, $this->cron_hook_identifier );
|
479 |
+
}
|
480 |
+
}
|
481 |
+
|
482 |
+
/**
|
483 |
+
* Cancel Process
|
484 |
+
*
|
485 |
+
* Stop processing queue items, clear cronjob and delete batch.
|
486 |
+
*/
|
487 |
+
public function cancel_process() {
|
488 |
+
if ( ! $this->is_queue_empty() ) {
|
489 |
+
$batch = $this->get_batch();
|
490 |
+
|
491 |
+
$this->delete( $batch->key );
|
492 |
+
|
493 |
+
wp_clear_scheduled_hook( $this->cron_hook_identifier );
|
494 |
+
}
|
495 |
+
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
* Task
|
500 |
+
*
|
501 |
+
* Override this method to perform any actions required on each
|
502 |
+
* queue item. Return the modified item for further processing
|
503 |
+
* in the next pass through. Or, return false to remove the
|
504 |
+
* item from the queue.
|
505 |
+
*
|
506 |
+
* @param mixed $item Queue item to iterate over.
|
507 |
+
*
|
508 |
+
* @return mixed
|
509 |
+
*/
|
510 |
+
abstract protected function task( $item );
|
511 |
+
|
512 |
+
}
|
513 |
+
}
|
inc/importers/class-widgets-importer.php
CHANGED
@@ -1,278 +1,278 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Widget Data exporter class.
|
4 |
-
*
|
5 |
-
* @package Astra Addon
|
6 |
-
* @see - https://wordpress.org/plugins/widget-importer-exporter/
|
7 |
-
*/
|
8 |
-
|
9 |
-
defined( 'ABSPATH' ) or exit;
|
10 |
-
|
11 |
-
/**
|
12 |
-
* Widget Data exporter class.
|
13 |
-
*
|
14 |
-
* @see - https://wordpress.org/plugins/widget-importer-exporter/
|
15 |
-
*/
|
16 |
-
class Astra_Widget_Importer {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Instance of Astra_Widget_Importer
|
20 |
-
*
|
21 |
-
* @var Astra_Widget_Importer
|
22 |
-
*/
|
23 |
-
private static $_instance = null;
|
24 |
-
|
25 |
-
public static function instance() {
|
26 |
-
|
27 |
-
if ( ! isset( self::$_instance ) ) {
|
28 |
-
self::$_instance = new self;
|
29 |
-
}
|
30 |
-
|
31 |
-
return self::$_instance;
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Available widgets
|
36 |
-
*
|
37 |
-
* Gather site's widgets into array with ID base, name, etc.
|
38 |
-
* Used by export and import functions.
|
39 |
-
*
|
40 |
-
* @since 0.4
|
41 |
-
* @global array $wp_registered_widget_updates
|
42 |
-
* @return array Widget information
|
43 |
-
*/
|
44 |
-
function wie_available_widgets() {
|
45 |
-
|
46 |
-
global $wp_registered_widget_controls;
|
47 |
-
|
48 |
-
$widget_controls = $wp_registered_widget_controls;
|
49 |
-
|
50 |
-
$available_widgets = array();
|
51 |
-
|
52 |
-
foreach ( $widget_controls as $widget ) {
|
53 |
-
|
54 |
-
if ( ! empty( $widget['id_base'] ) && ! isset( $available_widgets[ $widget['id_base'] ] ) ) { // no dupes
|
55 |
-
|
56 |
-
$available_widgets[ $widget['id_base'] ]['id_base'] = $widget['id_base'];
|
57 |
-
$available_widgets[ $widget['id_base'] ]['name'] = $widget['name'];
|
58 |
-
|
59 |
-
}
|
60 |
-
}
|
61 |
-
|
62 |
-
return apply_filters( 'wie_available_widgets', $available_widgets );
|
63 |
-
}
|
64 |
-
|
65 |
-
/**
|
66 |
-
* Import widget JSON data
|
67 |
-
*
|
68 |
-
* @since 0.4
|
69 |
-
* @global array $wp_registered_sidebars
|
70 |
-
*
|
71 |
-
* @param object $data JSON widget data from .wie file
|
72 |
-
*
|
73 |
-
* @return array Results array
|
74 |
-
*/
|
75 |
-
function import_widgets_data( $data ) {
|
76 |
-
|
77 |
-
global $wp_registered_sidebars;
|
78 |
-
|
79 |
-
// Have valid data?
|
80 |
-
// If no data or could not decode
|
81 |
-
if ( empty( $data ) || ! is_object( $data ) ) {
|
82 |
-
wp_die(
|
83 |
-
esc_html__( 'Import data could not be read. Please try a different file.', 'astra-sites' ),
|
84 |
-
'',
|
85 |
-
array(
|
86 |
-
'back_link' => true,
|
87 |
-
)
|
88 |
-
);
|
89 |
-
}
|
90 |
-
|
91 |
-
// Hook before import
|
92 |
-
do_action( 'wie_before_import' );
|
93 |
-
$data = apply_filters( 'wie_import_data', $data );
|
94 |
-
|
95 |
-
// Get all available widgets site supports
|
96 |
-
$available_widgets = $this->wie_available_widgets();
|
97 |
-
|
98 |
-
// Get all existing widget instances
|
99 |
-
$widget_instances = array();
|
100 |
-
foreach ( $available_widgets as $widget_data ) {
|
101 |
-
$widget_instances[ $widget_data['id_base'] ] = get_option( 'widget_' . $widget_data['id_base'] );
|
102 |
-
}
|
103 |
-
|
104 |
-
// Begin results
|
105 |
-
$results = array();
|
106 |
-
|
107 |
-
// Loop import data's sidebars
|
108 |
-
foreach ( $data as $sidebar_id => $widgets ) {
|
109 |
-
|
110 |
-
// Skip inactive widgets
|
111 |
-
// (should not be in export file)
|
112 |
-
if ( 'wp_inactive_widgets' == $sidebar_id ) {
|
113 |
-
continue;
|
114 |
-
}
|
115 |
-
|
116 |
-
// Check if sidebar is available on this site
|
117 |
-
// Otherwise add widgets to inactive, and say so
|
118 |
-
if ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ) {
|
119 |
-
$sidebar_available = true;
|
120 |
-
$use_sidebar_id = $sidebar_id;
|
121 |
-
$sidebar_message_type = 'success';
|
122 |
-
$sidebar_message = '';
|
123 |
-
} else {
|
124 |
-
$sidebar_available = false;
|
125 |
-
$use_sidebar_id = 'wp_inactive_widgets'; // add to inactive if sidebar does not exist in theme
|
126 |
-
$sidebar_message_type = 'error';
|
127 |
-
$sidebar_message = esc_html__( 'Widget area does not exist in theme (using Inactive)', 'astra-sites' );
|
128 |
-
}
|
129 |
-
|
130 |
-
// Result for sidebar
|
131 |
-
$results[ $sidebar_id ]['name'] = ! empty( $wp_registered_sidebars[ $sidebar_id ]['name'] ) ? $wp_registered_sidebars[ $sidebar_id ]['name'] : $sidebar_id; // sidebar name if theme supports it; otherwise ID
|
132 |
-
$results[ $sidebar_id ]['message_type'] = $sidebar_message_type;
|
133 |
-
$results[ $sidebar_id ]['message'] = $sidebar_message;
|
134 |
-
$results[ $sidebar_id ]['widgets'] = array();
|
135 |
-
|
136 |
-
// Loop widgets
|
137 |
-
foreach ( $widgets as $widget_instance_id => $widget ) {
|
138 |
-
|
139 |
-
$fail = false;
|
140 |
-
|
141 |
-
// Get id_base (remove -# from end) and instance ID number
|
142 |
-
$id_base = preg_replace( '/-[0-9]+$/', '', $widget_instance_id );
|
143 |
-
$instance_id_number = str_replace( $id_base . '-', '', $widget_instance_id );
|
144 |
-
|
145 |
-
// Does site support this widget?
|
146 |
-
if ( ! $fail && ! isset( $available_widgets[ $id_base ] ) ) {
|
147 |
-
$fail = true;
|
148 |
-
$widget_message_type = 'error';
|
149 |
-
$widget_message = esc_html__( 'Site does not support widget', 'astra-sites' ); // explain why widget not imported
|
150 |
-
}
|
151 |
-
|
152 |
-
// Filter to modify settings object before conversion to array and import
|
153 |
-
// Leave this filter here for backwards compatibility with manipulating objects (before conversion to array below)
|
154 |
-
// Ideally the newer wie_widget_settings_array below will be used instead of this
|
155 |
-
$widget = apply_filters( 'wie_widget_settings', $widget ); // object
|
156 |
-
|
157 |
-
// Convert multidimensional objects to multidimensional arrays
|
158 |
-
// Some plugins like Jetpack Widget Visibility store settings as multidimensional arrays
|
159 |
-
// Without this, they are imported as objects and cause fatal error on Widgets page
|
160 |
-
// If this creates problems for plugins that do actually intend settings in objects then may need to consider other approach: https://wordpress.org/support/topic/problem-with-array-of-arrays
|
161 |
-
// It is probably much more likely that arrays are used than objects, however
|
162 |
-
$widget = json_decode( wp_json_encode( $widget ), true );
|
163 |
-
|
164 |
-
// Filter to modify settings array
|
165 |
-
// This is preferred over the older wie_widget_settings filter above
|
166 |
-
// Do before identical check because changes may make it identical to end result (such as URL replacements)
|
167 |
-
$widget = apply_filters( 'wie_widget_settings_array', $widget );
|
168 |
-
|
169 |
-
// Does widget with identical settings already exist in same sidebar?
|
170 |
-
if ( ! $fail && isset( $widget_instances[ $id_base ] ) ) {
|
171 |
-
|
172 |
-
// Get existing widgets in this sidebar
|
173 |
-
$sidebars_widgets = get_option( 'sidebars_widgets' );
|
174 |
-
$sidebar_widgets = isset( $sidebars_widgets[ $use_sidebar_id ] ) ? $sidebars_widgets[ $use_sidebar_id ] : array(); // check Inactive if that's where will go
|
175 |
-
|
176 |
-
// Loop widgets with ID base
|
177 |
-
$single_widget_instances = ! empty( $widget_instances[ $id_base ] ) ? $widget_instances[ $id_base ] : array();
|
178 |
-
foreach ( $single_widget_instances as $check_id => $check_widget ) {
|
179 |
-
|
180 |
-
// Is widget in same sidebar and has identical settings?
|
181 |
-
if ( in_array( "$id_base-$check_id", $sidebar_widgets ) && (array) $widget == $check_widget ) {
|
182 |
-
|
183 |
-
$fail = true;
|
184 |
-
$widget_message_type = 'warning';
|
185 |
-
$widget_message = esc_html__( 'Widget already exists', 'astra-sites' ); // explain why widget not imported
|
186 |
-
|
187 |
-
break;
|
188 |
-
|
189 |
-
}
|
190 |
-
}
|
191 |
-
}
|
192 |
-
|
193 |
-
// No failure
|
194 |
-
if ( ! $fail ) {
|
195 |
-
|
196 |
-
// Add widget instance
|
197 |
-
$single_widget_instances = get_option( 'widget_' . $id_base ); // all instances for that widget ID base, get fresh every time
|
198 |
-
$single_widget_instances = ! empty( $single_widget_instances ) ? $single_widget_instances : array(
|
199 |
-
'_multiwidget' => 1,
|
200 |
-
); // start fresh if have to
|
201 |
-
$single_widget_instances[] = $widget; // add it
|
202 |
-
|
203 |
-
// Get the key it was given
|
204 |
-
end( $single_widget_instances );
|
205 |
-
$new_instance_id_number = key( $single_widget_instances );
|
206 |
-
|
207 |
-
// If key is 0, make it 1
|
208 |
-
// When 0, an issue can occur where adding a widget causes data from other widget to load, and the widget doesn't stick (reload wipes it)
|
209 |
-
if ( '0' === strval( $new_instance_id_number ) ) {
|
210 |
-
$new_instance_id_number = 1;
|
211 |
-
$single_widget_instances[ $new_instance_id_number ] = $single_widget_instances[0];
|
212 |
-
unset( $single_widget_instances[0] );
|
213 |
-
}
|
214 |
-
|
215 |
-
// Move _multiwidget to end of array for uniformity
|
216 |
-
if ( isset( $single_widget_instances['_multiwidget'] ) ) {
|
217 |
-
$multiwidget = $single_widget_instances['_multiwidget'];
|
218 |
-
unset( $single_widget_instances['_multiwidget'] );
|
219 |
-
$single_widget_instances['_multiwidget'] = $multiwidget;
|
220 |
-
}
|
221 |
-
|
222 |
-
// Update option with new widget
|
223 |
-
$result = update_option( 'widget_' . $id_base, $single_widget_instances );
|
224 |
-
|
225 |
-
// Assign widget instance to sidebar
|
226 |
-
$sidebars_widgets = get_option( 'sidebars_widgets' ); // which sidebars have which widgets, get fresh every time
|
227 |
-
|
228 |
-
// Avoid rarely fatal error when the option is an empty string
|
229 |
-
// https://github.com/churchthemes/widget-importer-exporter/pull/11
|
230 |
-
if ( ! $sidebars_widgets ) {
|
231 |
-
$sidebars_widgets = array();
|
232 |
-
}
|
233 |
-
|
234 |
-
$new_instance_id = $id_base . '-' . $new_instance_id_number; // use ID number from new widget instance
|
235 |
-
$sidebars_widgets[ $use_sidebar_id ][] = $new_instance_id; // add new instance to sidebar
|
236 |
-
update_option( 'sidebars_widgets', $sidebars_widgets ); // save the amended data
|
237 |
-
|
238 |
-
// After widget import action
|
239 |
-
$after_widget_import = array(
|
240 |
-
'sidebar' => $use_sidebar_id,
|
241 |
-
'sidebar_old' => $sidebar_id,
|
242 |
-
'widget' => $widget,
|
243 |
-
'widget_type' => $id_base,
|
244 |
-
'widget_id' => $new_instance_id,
|
245 |
-
'widget_id_old' => $widget_instance_id,
|
246 |
-
'widget_id_num' => $new_instance_id_number,
|
247 |
-
'widget_id_num_old' => $instance_id_number,
|
248 |
-
);
|
249 |
-
do_action( 'wie_after_widget_import', $after_widget_import );
|
250 |
-
|
251 |
-
// Success message
|
252 |
-
if ( $sidebar_available ) {
|
253 |
-
$widget_message_type = 'success';
|
254 |
-
$widget_message = esc_html__( 'Imported', 'astra-sites' );
|
255 |
-
} else {
|
256 |
-
$widget_message_type = 'warning';
|
257 |
-
$widget_message = esc_html__( 'Imported to Inactive', 'astra-sites' );
|
258 |
-
}
|
259 |
-
}// End if().
|
260 |
-
|
261 |
-
// Result for widget instance
|
262 |
-
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['name'] = isset( $available_widgets[ $id_base ]['name'] ) ? $available_widgets[ $id_base ]['name'] : $id_base; // widget name or ID if name not available (not supported by site)
|
263 |
-
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['title'] = ! empty( $widget['title'] ) ? $widget['title'] : esc_html__( 'No Title', 'astra-sites' ); // show "No Title" if widget instance is untitled
|
264 |
-
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['message_type'] = $widget_message_type;
|
265 |
-
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['message'] = $widget_message;
|
266 |
-
|
267 |
-
}// End foreach().
|
268 |
-
}// End foreach().
|
269 |
-
|
270 |
-
// Hook after import
|
271 |
-
do_action( 'wie_after_import' );
|
272 |
-
|
273 |
-
// Return results
|
274 |
-
return apply_filters( 'wie_import_results', $results );
|
275 |
-
|
276 |
-
}
|
277 |
-
|
278 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Widget Data exporter class.
|
4 |
+
*
|
5 |
+
* @package Astra Addon
|
6 |
+
* @see - https://wordpress.org/plugins/widget-importer-exporter/
|
7 |
+
*/
|
8 |
+
|
9 |
+
defined( 'ABSPATH' ) or exit;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Widget Data exporter class.
|
13 |
+
*
|
14 |
+
* @see - https://wordpress.org/plugins/widget-importer-exporter/
|
15 |
+
*/
|
16 |
+
class Astra_Widget_Importer {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Instance of Astra_Widget_Importer
|
20 |
+
*
|
21 |
+
* @var Astra_Widget_Importer
|
22 |
+
*/
|
23 |
+
private static $_instance = null;
|
24 |
+
|
25 |
+
public static function instance() {
|
26 |
+
|
27 |
+
if ( ! isset( self::$_instance ) ) {
|
28 |
+
self::$_instance = new self;
|
29 |
+
}
|
30 |
+
|
31 |
+
return self::$_instance;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Available widgets
|
36 |
+
*
|
37 |
+
* Gather site's widgets into array with ID base, name, etc.
|
38 |
+
* Used by export and import functions.
|
39 |
+
*
|
40 |
+
* @since 0.4
|
41 |
+
* @global array $wp_registered_widget_updates
|
42 |
+
* @return array Widget information
|
43 |
+
*/
|
44 |
+
function wie_available_widgets() {
|
45 |
+
|
46 |
+
global $wp_registered_widget_controls;
|
47 |
+
|
48 |
+
$widget_controls = $wp_registered_widget_controls;
|
49 |
+
|
50 |
+
$available_widgets = array();
|
51 |
+
|
52 |
+
foreach ( $widget_controls as $widget ) {
|
53 |
+
|
54 |
+
if ( ! empty( $widget['id_base'] ) && ! isset( $available_widgets[ $widget['id_base'] ] ) ) { // no dupes
|
55 |
+
|
56 |
+
$available_widgets[ $widget['id_base'] ]['id_base'] = $widget['id_base'];
|
57 |
+
$available_widgets[ $widget['id_base'] ]['name'] = $widget['name'];
|
58 |
+
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
return apply_filters( 'wie_available_widgets', $available_widgets );
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Import widget JSON data
|
67 |
+
*
|
68 |
+
* @since 0.4
|
69 |
+
* @global array $wp_registered_sidebars
|
70 |
+
*
|
71 |
+
* @param object $data JSON widget data from .wie file
|
72 |
+
*
|
73 |
+
* @return array Results array
|
74 |
+
*/
|
75 |
+
function import_widgets_data( $data ) {
|
76 |
+
|
77 |
+
global $wp_registered_sidebars;
|
78 |
+
|
79 |
+
// Have valid data?
|
80 |
+
// If no data or could not decode
|
81 |
+
if ( empty( $data ) || ! is_object( $data ) ) {
|
82 |
+
wp_die(
|
83 |
+
esc_html__( 'Import data could not be read. Please try a different file.', 'astra-sites' ),
|
84 |
+
'',
|
85 |
+
array(
|
86 |
+
'back_link' => true,
|
87 |
+
)
|
88 |
+
);
|
89 |
+
}
|
90 |
+
|
91 |
+
// Hook before import
|
92 |
+
do_action( 'wie_before_import' );
|
93 |
+
$data = apply_filters( 'wie_import_data', $data );
|
94 |
+
|
95 |
+
// Get all available widgets site supports
|
96 |
+
$available_widgets = $this->wie_available_widgets();
|
97 |
+
|
98 |
+
// Get all existing widget instances
|
99 |
+
$widget_instances = array();
|
100 |
+
foreach ( $available_widgets as $widget_data ) {
|
101 |
+
$widget_instances[ $widget_data['id_base'] ] = get_option( 'widget_' . $widget_data['id_base'] );
|
102 |
+
}
|
103 |
+
|
104 |
+
// Begin results
|
105 |
+
$results = array();
|
106 |
+
|
107 |
+
// Loop import data's sidebars
|
108 |
+
foreach ( $data as $sidebar_id => $widgets ) {
|
109 |
+
|
110 |
+
// Skip inactive widgets
|
111 |
+
// (should not be in export file)
|
112 |
+
if ( 'wp_inactive_widgets' == $sidebar_id ) {
|
113 |
+
continue;
|
114 |
+
}
|
115 |
+
|
116 |
+
// Check if sidebar is available on this site
|
117 |
+
// Otherwise add widgets to inactive, and say so
|
118 |
+
if ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ) {
|
119 |
+
$sidebar_available = true;
|
120 |
+
$use_sidebar_id = $sidebar_id;
|
121 |
+
$sidebar_message_type = 'success';
|
122 |
+
$sidebar_message = '';
|
123 |
+
} else {
|
124 |
+
$sidebar_available = false;
|
125 |
+
$use_sidebar_id = 'wp_inactive_widgets'; // add to inactive if sidebar does not exist in theme
|
126 |
+
$sidebar_message_type = 'error';
|
127 |
+
$sidebar_message = esc_html__( 'Widget area does not exist in theme (using Inactive)', 'astra-sites' );
|
128 |
+
}
|
129 |
+
|
130 |
+
// Result for sidebar
|
131 |
+
$results[ $sidebar_id ]['name'] = ! empty( $wp_registered_sidebars[ $sidebar_id ]['name'] ) ? $wp_registered_sidebars[ $sidebar_id ]['name'] : $sidebar_id; // sidebar name if theme supports it; otherwise ID
|
132 |
+
$results[ $sidebar_id ]['message_type'] = $sidebar_message_type;
|
133 |
+
$results[ $sidebar_id ]['message'] = $sidebar_message;
|
134 |
+
$results[ $sidebar_id ]['widgets'] = array();
|
135 |
+
|
136 |
+
// Loop widgets
|
137 |
+
foreach ( $widgets as $widget_instance_id => $widget ) {
|
138 |
+
|
139 |
+
$fail = false;
|
140 |
+
|
141 |
+
// Get id_base (remove -# from end) and instance ID number
|
142 |
+
$id_base = preg_replace( '/-[0-9]+$/', '', $widget_instance_id );
|
143 |
+
$instance_id_number = str_replace( $id_base . '-', '', $widget_instance_id );
|
144 |
+
|
145 |
+
// Does site support this widget?
|
146 |
+
if ( ! $fail && ! isset( $available_widgets[ $id_base ] ) ) {
|
147 |
+
$fail = true;
|
148 |
+
$widget_message_type = 'error';
|
149 |
+
$widget_message = esc_html__( 'Site does not support widget', 'astra-sites' ); // explain why widget not imported
|
150 |
+
}
|
151 |
+
|
152 |
+
// Filter to modify settings object before conversion to array and import
|
153 |
+
// Leave this filter here for backwards compatibility with manipulating objects (before conversion to array below)
|
154 |
+
// Ideally the newer wie_widget_settings_array below will be used instead of this
|
155 |
+
$widget = apply_filters( 'wie_widget_settings', $widget ); // object
|
156 |
+
|
157 |
+
// Convert multidimensional objects to multidimensional arrays
|
158 |
+
// Some plugins like Jetpack Widget Visibility store settings as multidimensional arrays
|
159 |
+
// Without this, they are imported as objects and cause fatal error on Widgets page
|
160 |
+
// If this creates problems for plugins that do actually intend settings in objects then may need to consider other approach: https://wordpress.org/support/topic/problem-with-array-of-arrays
|
161 |
+
// It is probably much more likely that arrays are used than objects, however
|
162 |
+
$widget = json_decode( wp_json_encode( $widget ), true );
|
163 |
+
|
164 |
+
// Filter to modify settings array
|
165 |
+
// This is preferred over the older wie_widget_settings filter above
|
166 |
+
// Do before identical check because changes may make it identical to end result (such as URL replacements)
|
167 |
+
$widget = apply_filters( 'wie_widget_settings_array', $widget );
|
168 |
+
|
169 |
+
// Does widget with identical settings already exist in same sidebar?
|
170 |
+
if ( ! $fail && isset( $widget_instances[ $id_base ] ) ) {
|
171 |
+
|
172 |
+
// Get existing widgets in this sidebar
|
173 |
+
$sidebars_widgets = get_option( 'sidebars_widgets' );
|
174 |
+
$sidebar_widgets = isset( $sidebars_widgets[ $use_sidebar_id ] ) ? $sidebars_widgets[ $use_sidebar_id ] : array(); // check Inactive if that's where will go
|
175 |
+
|
176 |
+
// Loop widgets with ID base
|
177 |
+
$single_widget_instances = ! empty( $widget_instances[ $id_base ] ) ? $widget_instances[ $id_base ] : array();
|
178 |
+
foreach ( $single_widget_instances as $check_id => $check_widget ) {
|
179 |
+
|
180 |
+
// Is widget in same sidebar and has identical settings?
|
181 |
+
if ( in_array( "$id_base-$check_id", $sidebar_widgets ) && (array) $widget == $check_widget ) {
|
182 |
+
|
183 |
+
$fail = true;
|
184 |
+
$widget_message_type = 'warning';
|
185 |
+
$widget_message = esc_html__( 'Widget already exists', 'astra-sites' ); // explain why widget not imported
|
186 |
+
|
187 |
+
break;
|
188 |
+
|
189 |
+
}
|
190 |
+
}
|
191 |
+
}
|
192 |
+
|
193 |
+
// No failure
|
194 |
+
if ( ! $fail ) {
|
195 |
+
|
196 |
+
// Add widget instance
|
197 |
+
$single_widget_instances = get_option( 'widget_' . $id_base ); // all instances for that widget ID base, get fresh every time
|
198 |
+
$single_widget_instances = ! empty( $single_widget_instances ) ? $single_widget_instances : array(
|
199 |
+
'_multiwidget' => 1,
|
200 |
+
); // start fresh if have to
|
201 |
+
$single_widget_instances[] = $widget; // add it
|
202 |
+
|
203 |
+
// Get the key it was given
|
204 |
+
end( $single_widget_instances );
|
205 |
+
$new_instance_id_number = key( $single_widget_instances );
|
206 |
+
|
207 |
+
// If key is 0, make it 1
|
208 |
+
// When 0, an issue can occur where adding a widget causes data from other widget to load, and the widget doesn't stick (reload wipes it)
|
209 |
+
if ( '0' === strval( $new_instance_id_number ) ) {
|
210 |
+
$new_instance_id_number = 1;
|
211 |
+
$single_widget_instances[ $new_instance_id_number ] = $single_widget_instances[0];
|
212 |
+
unset( $single_widget_instances[0] );
|
213 |
+
}
|
214 |
+
|
215 |
+
// Move _multiwidget to end of array for uniformity
|
216 |
+
if ( isset( $single_widget_instances['_multiwidget'] ) ) {
|
217 |
+
$multiwidget = $single_widget_instances['_multiwidget'];
|
218 |
+
unset( $single_widget_instances['_multiwidget'] );
|
219 |
+
$single_widget_instances['_multiwidget'] = $multiwidget;
|
220 |
+
}
|
221 |
+
|
222 |
+
// Update option with new widget
|
223 |
+
$result = update_option( 'widget_' . $id_base, $single_widget_instances );
|
224 |
+
|
225 |
+
// Assign widget instance to sidebar
|
226 |
+
$sidebars_widgets = get_option( 'sidebars_widgets' ); // which sidebars have which widgets, get fresh every time
|
227 |
+
|
228 |
+
// Avoid rarely fatal error when the option is an empty string
|
229 |
+
// https://github.com/churchthemes/widget-importer-exporter/pull/11
|
230 |
+
if ( ! $sidebars_widgets ) {
|
231 |
+
$sidebars_widgets = array();
|
232 |
+
}
|
233 |
+
|
234 |
+
$new_instance_id = $id_base . '-' . $new_instance_id_number; // use ID number from new widget instance
|
235 |
+
$sidebars_widgets[ $use_sidebar_id ][] = $new_instance_id; // add new instance to sidebar
|
236 |
+
update_option( 'sidebars_widgets', $sidebars_widgets ); // save the amended data
|
237 |
+
|
238 |
+
// After widget import action
|
239 |
+
$after_widget_import = array(
|
240 |
+
'sidebar' => $use_sidebar_id,
|
241 |
+
'sidebar_old' => $sidebar_id,
|
242 |
+
'widget' => $widget,
|
243 |
+
'widget_type' => $id_base,
|
244 |
+
'widget_id' => $new_instance_id,
|
245 |
+
'widget_id_old' => $widget_instance_id,
|
246 |
+
'widget_id_num' => $new_instance_id_number,
|
247 |
+
'widget_id_num_old' => $instance_id_number,
|
248 |
+
);
|
249 |
+
do_action( 'wie_after_widget_import', $after_widget_import );
|
250 |
+
|
251 |
+
// Success message
|
252 |
+
if ( $sidebar_available ) {
|
253 |
+
$widget_message_type = 'success';
|
254 |
+
$widget_message = esc_html__( 'Imported', 'astra-sites' );
|
255 |
+
} else {
|
256 |
+
$widget_message_type = 'warning';
|
257 |
+
$widget_message = esc_html__( 'Imported to Inactive', 'astra-sites' );
|
258 |
+
}
|
259 |
+
}// End if().
|
260 |
+
|
261 |
+
// Result for widget instance
|
262 |
+
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['name'] = isset( $available_widgets[ $id_base ]['name'] ) ? $available_widgets[ $id_base ]['name'] : $id_base; // widget name or ID if name not available (not supported by site)
|
263 |
+
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['title'] = ! empty( $widget['title'] ) ? $widget['title'] : esc_html__( 'No Title', 'astra-sites' ); // show "No Title" if widget instance is untitled
|
264 |
+
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['message_type'] = $widget_message_type;
|
265 |
+
$results[ $sidebar_id ]['widgets'][ $widget_instance_id ]['message'] = $widget_message;
|
266 |
+
|
267 |
+
}// End foreach().
|
268 |
+
}// End foreach().
|
269 |
+
|
270 |
+
// Hook after import
|
271 |
+
do_action( 'wie_after_import' );
|
272 |
+
|
273 |
+
// Return results
|
274 |
+
return apply_filters( 'wie_import_results', $results );
|
275 |
+
|
276 |
+
}
|
277 |
+
|
278 |
+
}
|
inc/importers/wxr-importer/class-logger.php
CHANGED
@@ -1,140 +1,140 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Describes a logger instance
|
5 |
-
*
|
6 |
-
* Based on PSR-3: http://www.php-fig.org/psr/psr-3/
|
7 |
-
*
|
8 |
-
* The message MUST be a string or object implementing __toString().
|
9 |
-
*
|
10 |
-
* The message MAY contain placeholders in the form: {foo} where foo
|
11 |
-
* will be replaced by the context data in key "foo".
|
12 |
-
*
|
13 |
-
* The context array can contain arbitrary data, the only assumption that
|
14 |
-
* can be made by implementors is that if an Exception instance is given
|
15 |
-
* to produce a stack trace, it MUST be in a key named "exception".
|
16 |
-
*
|
17 |
-
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
|
18 |
-
* for the full interface specification.
|
19 |
-
*/
|
20 |
-
class WP_Importer_Logger {
|
21 |
-
/**
|
22 |
-
* System is unusable.
|
23 |
-
*
|
24 |
-
* @param string $message
|
25 |
-
* @param array $context
|
26 |
-
* @return null
|
27 |
-
*/
|
28 |
-
public function emergency( $message, array $context = array() ) {
|
29 |
-
return $this->log( 'emergency', $message, $context );
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Action must be taken immediately.
|
34 |
-
*
|
35 |
-
* Example: Entire website down, database unavailable, etc. This should
|
36 |
-
* trigger the SMS alerts and wake you up.
|
37 |
-
*
|
38 |
-
* @param string $message
|
39 |
-
* @param array $context
|
40 |
-
* @return null
|
41 |
-
*/
|
42 |
-
public function alert( $message, array $context = array() ) {
|
43 |
-
return $this->log( 'alert', $message, $context );
|
44 |
-
}
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Critical conditions.
|
48 |
-
*
|
49 |
-
* Example: Application component unavailable, unexpected exception.
|
50 |
-
*
|
51 |
-
* @param string $message
|
52 |
-
* @param array $context
|
53 |
-
* @return null
|
54 |
-
*/
|
55 |
-
public function critical( $message, array $context = array() ) {
|
56 |
-
return $this->log( 'critical', $message, $context );
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Runtime errors that do not require immediate action but should typically
|
61 |
-
* be logged and monitored.
|
62 |
-
*
|
63 |
-
* @param string $message
|
64 |
-
* @param array $context
|
65 |
-
* @return null
|
66 |
-
*/
|
67 |
-
public function error( $message, array $context = array() ) {
|
68 |
-
return $this->log( 'error', $message, $context );
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Exceptional occurrences that are not errors.
|
73 |
-
*
|
74 |
-
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
75 |
-
* that are not necessarily wrong.
|
76 |
-
*
|
77 |
-
* @param string $message
|
78 |
-
* @param array $context
|
79 |
-
* @return null
|
80 |
-
*/
|
81 |
-
public function warning( $message, array $context = array() ) {
|
82 |
-
return $this->log( 'warning', $message, $context );
|
83 |
-
}
|
84 |
-
|
85 |
-
/**
|
86 |
-
* Normal but significant events.
|
87 |
-
*
|
88 |
-
* @param string $message
|
89 |
-
* @param array $context
|
90 |
-
* @return null
|
91 |
-
*/
|
92 |
-
public function notice( $message, array $context = array() ) {
|
93 |
-
return $this->log( 'notice', $message, $context );
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* Interesting events.
|
98 |
-
*
|
99 |
-
* Example: User logs in, SQL logs.
|
100 |
-
*
|
101 |
-
* @param string $message
|
102 |
-
* @param array $context
|
103 |
-
* @return null
|
104 |
-
*/
|
105 |
-
public function info( $message, array $context = array() ) {
|
106 |
-
return $this->log( 'info', $message, $context );
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Detailed debug information.
|
111 |
-
*
|
112 |
-
* @param string $message
|
113 |
-
* @param array $context
|
114 |
-
* @return null
|
115 |
-
*/
|
116 |
-
public function debug( $message, array $context = array() ) {
|
117 |
-
return $this->log( 'debug', $message, $context );
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* Logs with an arbitrary level.
|
122 |
-
*
|
123 |
-
* @param mixed $level
|
124 |
-
* @param string $message
|
125 |
-
* @param array $context
|
126 |
-
* @return null
|
127 |
-
*/
|
128 |
-
public function log( $level, $message, array $context = array() ) {
|
129 |
-
|
130 |
-
// Log
|
131 |
-
do_action( 'astra_sites_import_xml_log', $level, $message, $context );
|
132 |
-
|
133 |
-
$this->messages[] = array(
|
134 |
-
'timestamp' => time(),
|
135 |
-
'level' => $level,
|
136 |
-
'message' => $message,
|
137 |
-
'context' => $context,
|
138 |
-
);
|
139 |
-
}
|
140 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Describes a logger instance
|
5 |
+
*
|
6 |
+
* Based on PSR-3: http://www.php-fig.org/psr/psr-3/
|
7 |
+
*
|
8 |
+
* The message MUST be a string or object implementing __toString().
|
9 |
+
*
|
10 |
+
* The message MAY contain placeholders in the form: {foo} where foo
|
11 |
+
* will be replaced by the context data in key "foo".
|
12 |
+
*
|
13 |
+
* The context array can contain arbitrary data, the only assumption that
|
14 |
+
* can be made by implementors is that if an Exception instance is given
|
15 |
+
* to produce a stack trace, it MUST be in a key named "exception".
|
16 |
+
*
|
17 |
+
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
|
18 |
+
* for the full interface specification.
|
19 |
+
*/
|
20 |
+
class WP_Importer_Logger {
|
21 |
+
/**
|
22 |
+
* System is unusable.
|
23 |
+
*
|
24 |
+
* @param string $message
|
25 |
+
* @param array $context
|
26 |
+
* @return null
|
27 |
+
*/
|
28 |
+
public function emergency( $message, array $context = array() ) {
|
29 |
+
return $this->log( 'emergency', $message, $context );
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Action must be taken immediately.
|
34 |
+
*
|
35 |
+
* Example: Entire website down, database unavailable, etc. This should
|
36 |
+
* trigger the SMS alerts and wake you up.
|
37 |
+
*
|
38 |
+
* @param string $message
|
39 |
+
* @param array $context
|
40 |
+
* @return null
|
41 |
+
*/
|
42 |
+
public function alert( $message, array $context = array() ) {
|
43 |
+
return $this->log( 'alert', $message, $context );
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Critical conditions.
|
48 |
+
*
|
49 |
+
* Example: Application component unavailable, unexpected exception.
|
50 |
+
*
|
51 |
+
* @param string $message
|
52 |
+
* @param array $context
|
53 |
+
* @return null
|
54 |
+
*/
|
55 |
+
public function critical( $message, array $context = array() ) {
|
56 |
+
return $this->log( 'critical', $message, $context );
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Runtime errors that do not require immediate action but should typically
|
61 |
+
* be logged and monitored.
|
62 |
+
*
|
63 |
+
* @param string $message
|
64 |
+
* @param array $context
|
65 |
+
* @return null
|
66 |
+
*/
|
67 |
+
public function error( $message, array $context = array() ) {
|
68 |
+
return $this->log( 'error', $message, $context );
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Exceptional occurrences that are not errors.
|
73 |
+
*
|
74 |
+
* Example: Use of deprecated APIs, poor use of an API, undesirable things
|
75 |
+
* that are not necessarily wrong.
|
76 |
+
*
|
77 |
+
* @param string $message
|
78 |
+
* @param array $context
|
79 |
+
* @return null
|
80 |
+
*/
|
81 |
+
public function warning( $message, array $context = array() ) {
|
82 |
+
return $this->log( 'warning', $message, $context );
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Normal but significant events.
|
87 |
+
*
|
88 |
+
* @param string $message
|
89 |
+
* @param array $context
|
90 |
+
* @return null
|
91 |
+
*/
|
92 |
+
public function notice( $message, array $context = array() ) {
|
93 |
+
return $this->log( 'notice', $message, $context );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Interesting events.
|
98 |
+
*
|
99 |
+
* Example: User logs in, SQL logs.
|
100 |
+
*
|
101 |
+
* @param string $message
|
102 |
+
* @param array $context
|
103 |
+
* @return null
|
104 |
+
*/
|
105 |
+
public function info( $message, array $context = array() ) {
|
106 |
+
return $this->log( 'info', $message, $context );
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Detailed debug information.
|
111 |
+
*
|
112 |
+
* @param string $message
|
113 |
+
* @param array $context
|
114 |
+
* @return null
|
115 |
+
*/
|
116 |
+
public function debug( $message, array $context = array() ) {
|
117 |
+
return $this->log( 'debug', $message, $context );
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Logs with an arbitrary level.
|
122 |
+
*
|
123 |
+
* @param mixed $level
|
124 |
+
* @param string $message
|
125 |
+
* @param array $context
|
126 |
+
* @return null
|
127 |
+
*/
|
128 |
+
public function log( $level, $message, array $context = array() ) {
|
129 |
+
|
130 |
+
// Log
|
131 |
+
do_action( 'astra_sites_import_xml_log', $level, $message, $context );
|
132 |
+
|
133 |
+
$this->messages[] = array(
|
134 |
+
'timestamp' => time(),
|
135 |
+
'level' => $level,
|
136 |
+
'message' => $message,
|
137 |
+
'context' => $context,
|
138 |
+
);
|
139 |
+
}
|
140 |
+
}
|
inc/importers/wxr-importer/class-wp-importer-logger-serversentevents.php
CHANGED
@@ -1,46 +1,46 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! class_exists( 'WP_Importer_Logger_ServerSentEvents' ) && class_exists( 'WP_Importer_Logger' ) ) {
|
4 |
-
|
5 |
-
class WP_Importer_Logger_ServerSentEvents extends WP_Importer_Logger {
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Logs with an arbitrary level.
|
9 |
-
*
|
10 |
-
* @param mixed $level
|
11 |
-
* @param string $message
|
12 |
-
* @param array $context
|
13 |
-
* @return null
|
14 |
-
*/
|
15 |
-
public function log( $level, $message, array $context = array() ) {
|
16 |
-
|
17 |
-
// Log
|
18 |
-
do_action( 'astra_sites_import_xml_log', $level, $message, $context );
|
19 |
-
|
20 |
-
$data = compact( 'level', 'message' );
|
21 |
-
|
22 |
-
switch ( $level ) {
|
23 |
-
case 'emergency':
|
24 |
-
case 'alert':
|
25 |
-
case 'critical':
|
26 |
-
case 'error':
|
27 |
-
case 'warning':
|
28 |
-
case 'notice':
|
29 |
-
case 'info':
|
30 |
-
echo "event: log\n";
|
31 |
-
echo 'data: ' . wp_json_encode( $data ) . "\n\n";
|
32 |
-
flush();
|
33 |
-
break;
|
34 |
-
|
35 |
-
case 'debug':
|
36 |
-
if ( defined( 'IMPORT_DEBUG' ) && IMPORT_DEBUG ) {
|
37 |
-
echo "event: log\n";
|
38 |
-
echo 'data: ' . wp_json_encode( $data ) . "\n\n";
|
39 |
-
flush();
|
40 |
-
break;
|
41 |
-
}
|
42 |
-
break;
|
43 |
-
}
|
44 |
-
}
|
45 |
-
}
|
46 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( ! class_exists( 'WP_Importer_Logger_ServerSentEvents' ) && class_exists( 'WP_Importer_Logger' ) ) {
|
4 |
+
|
5 |
+
class WP_Importer_Logger_ServerSentEvents extends WP_Importer_Logger {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Logs with an arbitrary level.
|
9 |
+
*
|
10 |
+
* @param mixed $level
|
11 |
+
* @param string $message
|
12 |
+
* @param array $context
|
13 |
+
* @return null
|
14 |
+
*/
|
15 |
+
public function log( $level, $message, array $context = array() ) {
|
16 |
+
|
17 |
+
// Log
|
18 |
+
do_action( 'astra_sites_import_xml_log', $level, $message, $context );
|
19 |
+
|
20 |
+
$data = compact( 'level', 'message' );
|
21 |
+
|
22 |
+
switch ( $level ) {
|
23 |
+
case 'emergency':
|
24 |
+
case 'alert':
|
25 |
+
case 'critical':
|
26 |
+
case 'error':
|
27 |
+
case 'warning':
|
28 |
+
case 'notice':
|
29 |
+
case 'info':
|
30 |
+
echo "event: log\n";
|
31 |
+
echo 'data: ' . wp_json_encode( $data ) . "\n\n";
|
32 |
+
flush();
|
33 |
+
break;
|
34 |
+
|
35 |
+
case 'debug':
|
36 |
+
if ( defined( 'IMPORT_DEBUG' ) && IMPORT_DEBUG ) {
|
37 |
+
echo "event: log\n";
|
38 |
+
echo 'data: ' . wp_json_encode( $data ) . "\n\n";
|
39 |
+
flush();
|
40 |
+
break;
|
41 |
+
}
|
42 |
+
break;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
}
|
46 |
+
}
|
inc/importers/wxr-importer/class-wxr-import-info.php
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! class_exists( 'WXR_Import_Info' ) ) {
|
4 |
-
|
5 |
-
class WXR_Import_Info {
|
6 |
-
public $home;
|
7 |
-
public $siteurl;
|
8 |
-
|
9 |
-
public $title;
|
10 |
-
|
11 |
-
public $users = array();
|
12 |
-
public $post_count = 0;
|
13 |
-
public $media_count = 0;
|
14 |
-
public $comment_count = 0;
|
15 |
-
public $term_count = 0;
|
16 |
-
|
17 |
-
public $generator = '';
|
18 |
-
public $version;
|
19 |
-
}
|
20 |
-
|
21 |
ย
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( ! class_exists( 'WXR_Import_Info' ) ) {
|
4 |
+
|
5 |
+
class WXR_Import_Info {
|
6 |
+
public $home;
|
7 |
+
public $siteurl;
|
8 |
+
|
9 |
+
public $title;
|
10 |
+
|
11 |
+
public $users = array();
|
12 |
+
public $post_count = 0;
|
13 |
+
public $media_count = 0;
|
14 |
+
public $comment_count = 0;
|
15 |
+
public $term_count = 0;
|
16 |
+
|
17 |
+
public $generator = '';
|
18 |
+
public $version;
|
19 |
+
}
|
20 |
+
|
21 |
ย
}
|
inc/importers/wxr-importer/class-wxr-importer.php
CHANGED
@@ -1,2299 +1,2299 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class WXR_Importer extends WP_Importer {
|
4 |
-
/**
|
5 |
-
* Maximum supported WXR version
|
6 |
-
*/
|
7 |
-
const MAX_WXR_VERSION = 1.2;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Regular expression for checking if a post references an attachment
|
11 |
-
*
|
12 |
-
* Note: This is a quick, weak check just to exclude text-only posts. More
|
13 |
-
* vigorous checking is done later to verify.
|
14 |
-
*/
|
15 |
-
const REGEX_HAS_ATTACHMENT_REFS = '!
|
16 |
-
(
|
17 |
-
# Match anything with an image or attachment class
|
18 |
-
class=[\'"].*?\b(wp-image-\d+|attachment-[\w\-]+)\b
|
19 |
-
|
|
20 |
-
# Match anything that looks like an upload URL
|
21 |
-
src=[\'"][^\'"]*(
|
22 |
-
[0-9]{4}/[0-9]{2}/[^\'"]+\.(jpg|jpeg|png|gif)
|
23 |
-
|
|
24 |
-
content/uploads[^\'"]+
|
25 |
-
)[\'"]
|
26 |
-
)!ix';
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Version of WXR we're importing.
|
30 |
-
*
|
31 |
-
* Defaults to 1.0 for compatibility. Typically overridden by a
|
32 |
-
* `<wp:wxr_version>` tag at the start of the file.
|
33 |
-
*
|
34 |
-
* @var string
|
35 |
-
*/
|
36 |
-
protected $version = '1.0';
|
37 |
-
|
38 |
-
// information to import from WXR file
|
39 |
-
protected $categories = array();
|
40 |
-
protected $tags = array();
|
41 |
-
protected $base_url = '';
|
42 |
-
|
43 |
-
// TODO: REMOVE THESE
|
44 |
-
protected $processed_terms = array();
|
45 |
-
protected $processed_posts = array();
|
46 |
-
protected $processed_menu_items = array();
|
47 |
-
protected $menu_item_orphans = array();
|
48 |
-
protected $missing_menu_items = array();
|
49 |
-
|
50 |
-
// NEW STYLE
|
51 |
-
protected $mapping = array();
|
52 |
-
protected $requires_remapping = array();
|
53 |
-
protected $exists = array();
|
54 |
-
protected $user_slug_override = array();
|
55 |
-
|
56 |
-
protected $url_remap = array();
|
57 |
-
protected $featured_images = array();
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Logger instance.
|
61 |
-
*
|
62 |
-
* @var WP_Importer_Logger
|
63 |
-
*/
|
64 |
-
protected $logger;
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Constructor
|
68 |
-
*
|
69 |
-
* @param array $options {
|
70 |
-
* @var bool $prefill_existing_posts Should we prefill `post_exists` calls? (True prefills and uses more memory, false checks once per imported post and takes longer. Default is true.)
|
71 |
-
* @var bool $prefill_existing_comments Should we prefill `comment_exists` calls? (True prefills and uses more memory, false checks once per imported comment and takes longer. Default is true.)
|
72 |
-
* @var bool $prefill_existing_terms Should we prefill `term_exists` calls? (True prefills and uses more memory, false checks once per imported term and takes longer. Default is true.)
|
73 |
-
* @var bool $update_attachment_guids Should attachment GUIDs be updated to the new URL? (True updates the GUID, which keeps compatibility with v1, false doesn't update, and allows deduplication and reimporting. Default is false.)
|
74 |
-
* @var bool $fetch_attachments Fetch attachments from the remote server. (True fetches and creates attachment posts, false skips attachments. Default is false.)
|
75 |
-
* @var bool $aggressive_url_search Should we search/replace for URLs aggressively? (True searches all posts' content for old URLs and replaces, false checks for `<img class="wp-image-*">` only. Default is false.)
|
76 |
-
* @var int $default_author User ID to use if author is missing or invalid. (Default is null, which leaves posts unassigned.)
|
77 |
-
* }
|
78 |
-
*/
|
79 |
-
public function __construct( $options = array() ) {
|
80 |
-
// Initialize some important variables
|
81 |
-
$empty_types = array(
|
82 |
-
'post' => array(),
|
83 |
-
'comment' => array(),
|
84 |
-
'term' => array(),
|
85 |
-
'user' => array(),
|
86 |
-
);
|
87 |
-
|
88 |
-
$this->mapping = $empty_types;
|
89 |
-
$this->mapping['user_slug'] = array();
|
90 |
-
$this->mapping['term_id'] = array();
|
91 |
-
$this->requires_remapping = $empty_types;
|
92 |
-
$this->exists = $empty_types;
|
93 |
-
|
94 |
-
$this->options = wp_parse_args( $options, array(
|
95 |
-
'prefill_existing_posts' => true,
|
96 |
-
'prefill_existing_comments' => true,
|
97 |
-
'prefill_existing_terms' => true,
|
98 |
-
'update_attachment_guids' => false,
|
99 |
-
'fetch_attachments' => false,
|
100 |
-
'aggressive_url_search' => false,
|
101 |
-
'default_author' => null,
|
102 |
-
) );
|
103 |
-
}
|
104 |
-
|
105 |
-
public function set_logger( $logger ) {
|
106 |
-
$this->logger = $logger;
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Get a stream reader for the file.
|
111 |
-
*
|
112 |
-
* @param string $file Path to the XML file.
|
113 |
-
* @return XMLReader|WP_Error Reader instance on success, error otherwise.
|
114 |
-
*/
|
115 |
-
protected function get_reader( $file ) {
|
116 |
-
// Avoid loading external entities for security
|
117 |
-
$old_value = null;
|
118 |
-
if ( function_exists( 'libxml_disable_entity_loader' ) ) {
|
119 |
-
// $old_value = libxml_disable_entity_loader( true );
|
120 |
-
}
|
121 |
-
|
122 |
-
$reader = new XMLReader();
|
123 |
-
$status = $reader->open( $file );
|
124 |
-
|
125 |
-
if ( ! is_null( $old_value ) ) {
|
126 |
-
// libxml_disable_entity_loader( $old_value );
|
127 |
-
}
|
128 |
-
|
129 |
-
if ( ! $status ) {
|
130 |
-
return new WP_Error( 'wxr_importer.cannot_parse', __( 'Could not open the file for parsing', 'wordpress-importer' ) );
|
131 |
-
}
|
132 |
-
|
133 |
-
return $reader;
|
134 |
-
}
|
135 |
-
|
136 |
-
/**
|
137 |
-
* The main controller for the actual import stage.
|
138 |
-
*
|
139 |
-
* @param string $file Path to the WXR file for importing
|
140 |
-
*/
|
141 |
-
public function get_preliminary_information( $file ) {
|
142 |
-
// Let's run the actual importer now, woot
|
143 |
-
$reader = $this->get_reader( $file );
|
144 |
-
if ( is_wp_error( $reader ) ) {
|
145 |
-
return $reader;
|
146 |
-
}
|
147 |
-
|
148 |
-
// Set the version to compatibility mode first
|
149 |
-
$this->version = '1.0';
|
150 |
-
|
151 |
-
// Start parsing!
|
152 |
-
$data = new WXR_Import_Info();
|
153 |
-
while ( $reader->read() ) {
|
154 |
-
// Only deal with element opens
|
155 |
-
if ( $reader->nodeType !== XMLReader::ELEMENT ) {
|
156 |
-
continue;
|
157 |
-
}
|
158 |
-
|
159 |
-
switch ( $reader->name ) {
|
160 |
-
case 'wp:wxr_version':
|
161 |
-
// Upgrade to the correct version
|
162 |
-
$this->version = $reader->readString();
|
163 |
-
|
164 |
-
if ( version_compare( $this->version, self::MAX_WXR_VERSION, '>' ) ) {
|
165 |
-
$this->logger->warning( sprintf(
|
166 |
-
__( 'This WXR file (version %1$s) is newer than the importer (version %2$s) and may not be supported. Please consider updating.', 'wordpress-importer' ),
|
167 |
-
$this->version,
|
168 |
-
self::MAX_WXR_VERSION
|
169 |
-
) );
|
170 |
-
}
|
171 |
-
|
172 |
-
// Handled everything in this node, move on to the next
|
173 |
-
$reader->next();
|
174 |
-
break;
|
175 |
-
|
176 |
-
case 'generator':
|
177 |
-
$data->generator = $reader->readString();
|
178 |
-
$reader->next();
|
179 |
-
break;
|
180 |
-
|
181 |
-
case 'title':
|
182 |
-
$data->title = $reader->readString();
|
183 |
-
$reader->next();
|
184 |
-
break;
|
185 |
-
|
186 |
-
case 'wp:base_site_url':
|
187 |
-
$data->siteurl = $reader->readString();
|
188 |
-
$reader->next();
|
189 |
-
break;
|
190 |
-
|
191 |
-
case 'wp:base_blog_url':
|
192 |
-
$data->home = $reader->readString();
|
193 |
-
$reader->next();
|
194 |
-
break;
|
195 |
-
|
196 |
-
case 'wp:author':
|
197 |
-
$node = $reader->expand();
|
198 |
-
|
199 |
-
$parsed = $this->parse_author_node( $node );
|
200 |
-
if ( is_wp_error( $parsed ) ) {
|
201 |
-
$this->log_error( $parsed );
|
202 |
-
|
203 |
-
// Skip the rest of this post
|
204 |
-
$reader->next();
|
205 |
-
break;
|
206 |
-
}
|
207 |
-
|
208 |
-
$data->users[] = $parsed;
|
209 |
-
|
210 |
-
// Handled everything in this node, move on to the next
|
211 |
-
$reader->next();
|
212 |
-
break;
|
213 |
-
|
214 |
-
case 'item':
|
215 |
-
$node = $reader->expand();
|
216 |
-
$parsed = $this->parse_post_node( $node );
|
217 |
-
if ( is_wp_error( $parsed ) ) {
|
218 |
-
$this->log_error( $parsed );
|
219 |
-
|
220 |
-
// Skip the rest of this post
|
221 |
-
$reader->next();
|
222 |
-
break;
|
223 |
-
}
|
224 |
-
|
225 |
-
if ( $parsed['data']['post_type'] === 'attachment' ) {
|
226 |
-
$data->media_count++;
|
227 |
-
} else {
|
228 |
-
$data->post_count++;
|
229 |
-
}
|
230 |
-
$data->comment_count += count( $parsed['comments'] );
|
231 |
-
|
232 |
-
// Handled everything in this node, move on to the next
|
233 |
-
$reader->next();
|
234 |
-
break;
|
235 |
-
|
236 |
-
case 'wp:category':
|
237 |
-
case 'wp:tag':
|
238 |
-
case 'wp:term':
|
239 |
-
$data->term_count++;
|
240 |
-
|
241 |
-
// Handled everything in this node, move on to the next
|
242 |
-
$reader->next();
|
243 |
-
break;
|
244 |
-
}// End switch().
|
245 |
-
}// End while().
|
246 |
-
|
247 |
-
$data->version = $this->version;
|
248 |
-
|
249 |
-
return $data;
|
250 |
-
}
|
251 |
-
|
252 |
-
/**
|
253 |
-
* The main controller for the actual import stage.
|
254 |
-
*
|
255 |
-
* @param string $file Path to the WXR file for importing
|
256 |
-
*/
|
257 |
-
public function parse_authors( $file ) {
|
258 |
-
// Let's run the actual importer now, woot
|
259 |
-
$reader = $this->get_reader( $file );
|
260 |
-
if ( is_wp_error( $reader ) ) {
|
261 |
-
return $reader;
|
262 |
-
}
|
263 |
-
|
264 |
-
// Set the version to compatibility mode first
|
265 |
-
$this->version = '1.0';
|
266 |
-
|
267 |
-
// Start parsing!
|
268 |
-
$authors = array();
|
269 |
-
while ( $reader->read() ) {
|
270 |
-
// Only deal with element opens
|
271 |
-
if ( $reader->nodeType !== XMLReader::ELEMENT ) {
|
272 |
-
continue;
|
273 |
-
}
|
274 |
-
|
275 |
-
switch ( $reader->name ) {
|
276 |
-
case 'wp:wxr_version':
|
277 |
-
// Upgrade to the correct version
|
278 |
-
$this->version = $reader->readString();
|
279 |
-
|
280 |
-
if ( version_compare( $this->version, self::MAX_WXR_VERSION, '>' ) ) {
|
281 |
-
$this->logger->warning( sprintf(
|
282 |
-
__( 'This WXR file (version %1$s) is newer than the importer (version %2$s) and may not be supported. Please consider updating.', 'wordpress-importer' ),
|
283 |
-
$this->version,
|
284 |
-
self::MAX_WXR_VERSION
|
285 |
-
) );
|
286 |
-
}
|
287 |
-
|
288 |
-
// Handled everything in this node, move on to the next
|
289 |
-
$reader->next();
|
290 |
-
break;
|
291 |
-
|
292 |
-
case 'wp:author':
|
293 |
-
$node = $reader->expand();
|
294 |
-
|
295 |
-
$parsed = $this->parse_author_node( $node );
|
296 |
-
if ( is_wp_error( $parsed ) ) {
|
297 |
-
$this->log_error( $parsed );
|
298 |
-
|
299 |
-
// Skip the rest of this post
|
300 |
-
$reader->next();
|
301 |
-
break;
|
302 |
-
}
|
303 |
-
|
304 |
-
$authors[] = $parsed;
|
305 |
-
|
306 |
-
// Handled everything in this node, move on to the next
|
307 |
-
$reader->next();
|
308 |
-
break;
|
309 |
-
}
|
310 |
-
}// End while().
|
311 |
-
|
312 |
-
return $authors;
|
313 |
-
}
|
314 |
-
|
315 |
-
/**
|
316 |
-
* The main controller for the actual import stage.
|
317 |
-
*
|
318 |
-
* @param string $file Path to the WXR file for importing
|
319 |
-
*/
|
320 |
-
public function import( $file ) {
|
321 |
-
add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' ) );
|
322 |
-
add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeout' ) );
|
323 |
-
|
324 |
-
$result = $this->import_start( $file );
|
325 |
-
if ( is_wp_error( $result ) ) {
|
326 |
-
return $result;
|
327 |
-
}
|
328 |
-
|
329 |
-
// Let's run the actual importer now, woot
|
330 |
-
$reader = $this->get_reader( $file );
|
331 |
-
if ( is_wp_error( $reader ) ) {
|
332 |
-
return $reader;
|
333 |
-
}
|
334 |
-
|
335 |
-
// Set the version to compatibility mode first
|
336 |
-
$this->version = '1.0';
|
337 |
-
|
338 |
-
// Reset other variables
|
339 |
-
$this->base_url = '';
|
340 |
-
|
341 |
-
// Start parsing!
|
342 |
-
while ( $reader->read() ) {
|
343 |
-
// Only deal with element opens
|
344 |
-
if ( $reader->nodeType !== XMLReader::ELEMENT ) {
|
345 |
-
continue;
|
346 |
-
}
|
347 |
-
|
348 |
-
switch ( $reader->name ) {
|
349 |
-
case 'wp:wxr_version':
|
350 |
-
// Upgrade to the correct version
|
351 |
-
$this->version = $reader->readString();
|
352 |
-
|
353 |
-
if ( version_compare( $this->version, self::MAX_WXR_VERSION, '>' ) ) {
|
354 |
-
$this->logger->warning( sprintf(
|
355 |
-
__( 'This WXR file (version %1$s) is newer than the importer (version %2$s) and may not be supported. Please consider updating.', 'wordpress-importer' ),
|
356 |
-
$this->version,
|
357 |
-
self::MAX_WXR_VERSION
|
358 |
-
) );
|
359 |
-
}
|
360 |
-
|
361 |
-
// Handled everything in this node, move on to the next
|
362 |
-
$reader->next();
|
363 |
-
break;
|
364 |
-
|
365 |
-
case 'wp:base_site_url':
|
366 |
-
$this->base_url = $reader->readString();
|
367 |
-
|
368 |
-
// Handled everything in this node, move on to the next
|
369 |
-
$reader->next();
|
370 |
-
break;
|
371 |
-
|
372 |
-
case 'item':
|
373 |
-
$node = $reader->expand();
|
374 |
-
$parsed = $this->parse_post_node( $node );
|
375 |
-
if ( is_wp_error( $parsed ) ) {
|
376 |
-
$this->log_error( $parsed );
|
377 |
-
|
378 |
-
// Skip the rest of this post
|
379 |
-
$reader->next();
|
380 |
-
break;
|
381 |
-
}
|
382 |
-
|
383 |
-
$this->process_post( $parsed['data'], $parsed['meta'], $parsed['comments'], $parsed['terms'] );
|
384 |
-
|
385 |
-
// Handled everything in this node, move on to the next
|
386 |
-
$reader->next();
|
387 |
-
break;
|
388 |
-
|
389 |
-
case 'wp:author':
|
390 |
-
$node = $reader->expand();
|
391 |
-
|
392 |
-
$parsed = $this->parse_author_node( $node );
|
393 |
-
if ( is_wp_error( $parsed ) ) {
|
394 |
-
$this->log_error( $parsed );
|
395 |
-
|
396 |
-
// Skip the rest of this post
|
397 |
-
$reader->next();
|
398 |
-
break;
|
399 |
-
}
|
400 |
-
|
401 |
-
$status = $this->process_author( $parsed['data'], $parsed['meta'] );
|
402 |
-
if ( is_wp_error( $status ) ) {
|
403 |
-
$this->log_error( $status );
|
404 |
-
}
|
405 |
-
|
406 |
-
// Handled everything in this node, move on to the next
|
407 |
-
$reader->next();
|
408 |
-
break;
|
409 |
-
|
410 |
-
case 'wp:category':
|
411 |
-
$node = $reader->expand();
|
412 |
-
|
413 |
-
$parsed = $this->parse_term_node( $node, 'category' );
|
414 |
-
if ( is_wp_error( $parsed ) ) {
|
415 |
-
$this->log_error( $parsed );
|
416 |
-
|
417 |
-
// Skip the rest of this post
|
418 |
-
$reader->next();
|
419 |
-
break;
|
420 |
-
}
|
421 |
-
|
422 |
-
$status = $this->process_term( $parsed['data'], $parsed['meta'] );
|
423 |
-
|
424 |
-
// Handled everything in this node, move on to the next
|
425 |
-
$reader->next();
|
426 |
-
break;
|
427 |
-
|
428 |
-
case 'wp:tag':
|
429 |
-
$node = $reader->expand();
|
430 |
-
|
431 |
-
$parsed = $this->parse_term_node( $node, 'tag' );
|
432 |
-
if ( is_wp_error( $parsed ) ) {
|
433 |
-
$this->log_error( $parsed );
|
434 |
-
|
435 |
-
// Skip the rest of this post
|
436 |
-
$reader->next();
|
437 |
-
break;
|
438 |
-
}
|
439 |
-
|
440 |
-
$status = $this->process_term( $parsed['data'], $parsed['meta'] );
|
441 |
-
|
442 |
-
// Handled everything in this node, move on to the next
|
443 |
-
$reader->next();
|
444 |
-
break;
|
445 |
-
|
446 |
-
case 'wp:term':
|
447 |
-
$node = $reader->expand();
|
448 |
-
|
449 |
-
$parsed = $this->parse_term_node( $node );
|
450 |
-
if ( is_wp_error( $parsed ) ) {
|
451 |
-
$this->log_error( $parsed );
|
452 |
-
|
453 |
-
// Skip the rest of this post
|
454 |
-
$reader->next();
|
455 |
-
break;
|
456 |
-
}
|
457 |
-
|
458 |
-
$status = $this->process_term( $parsed['data'], $parsed['meta'] );
|
459 |
-
|
460 |
-
// Handled everything in this node, move on to the next
|
461 |
-
$reader->next();
|
462 |
-
break;
|
463 |
-
|
464 |
-
default:
|
465 |
-
// Skip this node, probably handled by something already
|
466 |
-
break;
|
467 |
-
}// End switch().
|
468 |
-
}// End while().
|
469 |
-
|
470 |
-
// Now that we've done the main processing, do any required
|
471 |
-
// post-processing and remapping.
|
472 |
-
$this->post_process();
|
473 |
-
|
474 |
-
if ( $this->options['aggressive_url_search'] ) {
|
475 |
-
$this->replace_attachment_urls_in_content();
|
476 |
-
}
|
477 |
-
// $this->remap_featured_images();
|
478 |
-
$this->import_end();
|
479 |
-
}
|
480 |
-
|
481 |
-
/**
|
482 |
-
* Log an error instance to the logger.
|
483 |
-
*
|
484 |
-
* @param WP_Error $error Error instance to log.
|
485 |
-
*/
|
486 |
-
protected function log_error( WP_Error $error ) {
|
487 |
-
$this->logger->warning( $error->get_error_message() );
|
488 |
-
|
489 |
-
// Log the data as debug info too
|
490 |
-
$data = $error->get_error_data();
|
491 |
-
if ( ! empty( $data ) ) {
|
492 |
-
$this->logger->debug( var_export( $data, true ) );
|
493 |
-
}
|
494 |
-
}
|
495 |
-
|
496 |
-
/**
|
497 |
-
* Parses the WXR file and prepares us for the task of processing parsed data
|
498 |
-
*
|
499 |
-
* @param string $file Path to the WXR file for importing
|
500 |
-
*/
|
501 |
-
protected function import_start( $file ) {
|
502 |
-
if ( ! is_file( $file ) ) {
|
503 |
-
return new WP_Error( 'wxr_importer.file_missing', __( 'The file does not exist, please try again.', 'wordpress-importer' ) );
|
504 |
-
}
|
505 |
-
|
506 |
-
// Suspend bunches of stuff in WP core
|
507 |
-
wp_defer_term_counting( true );
|
508 |
-
wp_defer_comment_counting( true );
|
509 |
-
wp_suspend_cache_invalidation( true );
|
510 |
-
|
511 |
-
// Prefill exists calls if told to
|
512 |
-
if ( $this->options['prefill_existing_posts'] ) {
|
513 |
-
$this->prefill_existing_posts();
|
514 |
-
}
|
515 |
-
if ( $this->options['prefill_existing_comments'] ) {
|
516 |
-
$this->prefill_existing_comments();
|
517 |
-
}
|
518 |
-
if ( $this->options['prefill_existing_terms'] ) {
|
519 |
-
$this->prefill_existing_terms();
|
520 |
-
}
|
521 |
-
|
522 |
-
/**
|
523 |
-
* Begin the import.
|
524 |
-
*
|
525 |
-
* Fires before the import process has begun. If you need to suspend
|
526 |
-
* caching or heavy processing on hooks, do so here.
|
527 |
-
*/
|
528 |
-
do_action( 'import_start' );
|
529 |
-
}
|
530 |
-
|
531 |
-
/**
|
532 |
-
* Performs post-import cleanup of files and the cache
|
533 |
-
*/
|
534 |
-
protected function import_end() {
|
535 |
-
// Re-enable stuff in core
|
536 |
-
wp_suspend_cache_invalidation( false );
|
537 |
-
wp_cache_flush();
|
538 |
-
foreach ( get_taxonomies() as $tax ) {
|
539 |
-
delete_option( "{$tax}_children" );
|
540 |
-
_get_term_hierarchy( $tax );
|
541 |
-
}
|
542 |
-
|
543 |
-
wp_defer_term_counting( false );
|
544 |
-
wp_defer_comment_counting( false );
|
545 |
-
|
546 |
-
/**
|
547 |
-
* Complete the import.
|
548 |
-
*
|
549 |
-
* Fires after the import process has finished. If you need to update
|
550 |
-
* your cache or re-enable processing, do so here.
|
551 |
-
*/
|
552 |
-
do_action( 'import_end' );
|
553 |
-
}
|
554 |
-
|
555 |
-
/**
|
556 |
-
* Set the user mapping.
|
557 |
-
*
|
558 |
-
* @param array $mapping List of map arrays (containing `old_slug`, `old_id`, `new_id`)
|
559 |
-
*/
|
560 |
-
public function set_user_mapping( $mapping ) {
|
561 |
-
foreach ( $mapping as $map ) {
|
562 |
-
if ( empty( $map['old_slug'] ) || empty( $map['old_id'] ) || empty( $map['new_id'] ) ) {
|
563 |
-
$this->logger->warning( __( 'Invalid author mapping', 'wordpress-importer' ) );
|
564 |
-
$this->logger->debug( var_export( $map, true ) );
|
565 |
-
continue;
|
566 |
-
}
|
567 |
-
|
568 |
-
$old_slug = $map['old_slug'];
|
569 |
-
$old_id = $map['old_id'];
|
570 |
-
$new_id = $map['new_id'];
|
571 |
-
|
572 |
-
$this->mapping['user'][ $old_id ] = $new_id;
|
573 |
-
$this->mapping['user_slug'][ $old_slug ] = $new_id;
|
574 |
-
}
|
575 |
-
}
|
576 |
-
|
577 |
-
/**
|
578 |
-
* Set the user slug overrides.
|
579 |
-
*
|
580 |
-
* Allows overriding the slug in the import with a custom/renamed version.
|
581 |
-
*
|
582 |
-
* @param string[] $overrides Map of old slug to new slug.
|
583 |
-
*/
|
584 |
-
public function set_user_slug_overrides( $overrides ) {
|
585 |
-
foreach ( $overrides as $original => $renamed ) {
|
586 |
-
$this->user_slug_override[ $original ] = $renamed;
|
587 |
-
}
|
588 |
-
}
|
589 |
-
|
590 |
-
/**
|
591 |
-
* Parse a post node into post data.
|
592 |
-
*
|
593 |
-
* @param DOMElement $node Parent node of post data (typically `item`).
|
594 |
-
* @return array|WP_Error Post data array on success, error otherwise.
|
595 |
-
*/
|
596 |
-
protected function parse_post_node( $node ) {
|
597 |
-
$data = array();
|
598 |
-
$meta = array();
|
599 |
-
$comments = array();
|
600 |
-
$terms = array();
|
601 |
-
|
602 |
-
foreach ( $node->childNodes as $child ) {
|
603 |
-
// We only care about child elements
|
604 |
-
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
605 |
-
continue;
|
606 |
-
}
|
607 |
-
|
608 |
-
switch ( $child->tagName ) {
|
609 |
-
case 'wp:post_type':
|
610 |
-
$data['post_type'] = $child->textContent;
|
611 |
-
break;
|
612 |
-
|
613 |
-
case 'title':
|
614 |
-
$data['post_title'] = $child->textContent;
|
615 |
-
break;
|
616 |
-
|
617 |
-
case 'guid':
|
618 |
-
$data['guid'] = $child->textContent;
|
619 |
-
break;
|
620 |
-
|
621 |
-
case 'dc:creator':
|
622 |
-
$data['post_author'] = $child->textContent;
|
623 |
-
break;
|
624 |
-
|
625 |
-
case 'content:encoded':
|
626 |
-
$data['post_content'] = $child->textContent;
|
627 |
-
break;
|
628 |
-
|
629 |
-
case 'excerpt:encoded':
|
630 |
-
$data['post_excerpt'] = $child->textContent;
|
631 |
-
break;
|
632 |
-
|
633 |
-
case 'wp:post_id':
|
634 |
-
$data['post_id'] = $child->textContent;
|
635 |
-
break;
|
636 |
-
|
637 |
-
case 'wp:post_date':
|
638 |
-
$data['post_date'] = $child->textContent;
|
639 |
-
break;
|
640 |
-
|
641 |
-
case 'wp:post_date_gmt':
|
642 |
-
$data['post_date_gmt'] = $child->textContent;
|
643 |
-
break;
|
644 |
-
|
645 |
-
case 'wp:comment_status':
|
646 |
-
$data['comment_status'] = $child->textContent;
|
647 |
-
break;
|
648 |
-
|
649 |
-
case 'wp:ping_status':
|
650 |
-
$data['ping_status'] = $child->textContent;
|
651 |
-
break;
|
652 |
-
|
653 |
-
case 'wp:post_name':
|
654 |
-
$data['post_name'] = $child->textContent;
|
655 |
-
break;
|
656 |
-
|
657 |
-
case 'wp:status':
|
658 |
-
$data['post_status'] = $child->textContent;
|
659 |
-
|
660 |
-
if ( $data['post_status'] === 'auto-draft' ) {
|
661 |
-
// Bail now
|
662 |
-
return new WP_Error(
|
663 |
-
'wxr_importer.post.cannot_import_draft',
|
664 |
-
__( 'Cannot import auto-draft posts' ),
|
665 |
-
$data
|
666 |
-
);
|
667 |
-
}
|
668 |
-
break;
|
669 |
-
|
670 |
-
case 'wp:post_parent':
|
671 |
-
$data['post_parent'] = $child->textContent;
|
672 |
-
break;
|
673 |
-
|
674 |
-
case 'wp:menu_order':
|
675 |
-
$data['menu_order'] = $child->textContent;
|
676 |
-
break;
|
677 |
-
|
678 |
-
case 'wp:post_password':
|
679 |
-
$data['post_password'] = $child->textContent;
|
680 |
-
break;
|
681 |
-
|
682 |
-
case 'wp:is_sticky':
|
683 |
-
$data['is_sticky'] = $child->textContent;
|
684 |
-
break;
|
685 |
-
|
686 |
-
case 'wp:attachment_url':
|
687 |
-
$data['attachment_url'] = $child->textContent;
|
688 |
-
break;
|
689 |
-
|
690 |
-
case 'wp:postmeta':
|
691 |
-
$meta_item = $this->parse_meta_node( $child );
|
692 |
-
if ( ! empty( $meta_item ) ) {
|
693 |
-
$meta[] = $meta_item;
|
694 |
-
}
|
695 |
-
break;
|
696 |
-
|
697 |
-
case 'wp:comment':
|
698 |
-
$comment_item = $this->parse_comment_node( $child );
|
699 |
-
if ( ! empty( $comment_item ) ) {
|
700 |
-
$comments[] = $comment_item;
|
701 |
-
}
|
702 |
-
break;
|
703 |
-
|
704 |
-
case 'category':
|
705 |
-
$term_item = $this->parse_category_node( $child );
|
706 |
-
if ( ! empty( $term_item ) ) {
|
707 |
-
$terms[] = $term_item;
|
708 |
-
}
|
709 |
-
break;
|
710 |
-
}// End switch().
|
711 |
-
}// End foreach().
|
712 |
-
|
713 |
-
return compact( 'data', 'meta', 'comments', 'terms' );
|
714 |
-
}
|
715 |
-
|
716 |
-
/**
|
717 |
-
* Create new posts based on import information
|
718 |
-
*
|
719 |
-
* Posts marked as having a parent which doesn't exist will become top level items.
|
720 |
-
* Doesn't create a new post if: the post type doesn't exist, the given post ID
|
721 |
-
* is already noted as imported or a post with the same title and date already exists.
|
722 |
-
* Note that new/updated terms, comments and meta are imported for the last of the above.
|
723 |
-
*/
|
724 |
-
protected function process_post( $data, $meta, $comments, $terms ) {
|
725 |
-
/**
|
726 |
-
* Pre-process post data.
|
727 |
-
*
|
728 |
-
* @param array $data Post data. (Return empty to skip.)
|
729 |
-
* @param array $meta Meta data.
|
730 |
-
* @param array $comments Comments on the post.
|
731 |
-
* @param array $terms Terms on the post.
|
732 |
-
*/
|
733 |
-
$data = apply_filters( 'wxr_importer.pre_process.post', $data, $meta, $comments, $terms );
|
734 |
-
if ( empty( $data ) ) {
|
735 |
-
return false;
|
736 |
-
}
|
737 |
-
|
738 |
-
$original_id = isset( $data['post_id'] ) ? (int) $data['post_id'] : 0;
|
739 |
-
$parent_id = isset( $data['post_parent'] ) ? (int) $data['post_parent'] : 0;
|
740 |
-
$author_id = isset( $data['post_author'] ) ? (int) $data['post_author'] : 0;
|
741 |
-
|
742 |
-
// Have we already processed this?
|
743 |
-
if ( isset( $this->mapping['post'][ $original_id ] ) ) {
|
744 |
-
return;
|
745 |
-
}
|
746 |
-
|
747 |
-
$post_type_object = get_post_type_object( $data['post_type'] );
|
748 |
-
|
749 |
-
// Is this type even valid?
|
750 |
-
if ( ! $post_type_object ) {
|
751 |
-
$this->logger->warning( sprintf(
|
752 |
-
__( 'Failed to import "%1$s": Invalid post type %2$s', 'wordpress-importer' ),
|
753 |
-
$data['post_title'],
|
754 |
-
$data['post_type']
|
755 |
-
) );
|
756 |
-
return false;
|
757 |
-
}
|
758 |
-
|
759 |
-
$post_exists = $this->post_exists( $data );
|
760 |
-
if ( $post_exists ) {
|
761 |
-
$this->logger->info( sprintf(
|
762 |
-
__( '%1$s "%2$s" already exists.', 'wordpress-importer' ),
|
763 |
-
$post_type_object->labels->singular_name,
|
764 |
-
$data['post_title']
|
765 |
-
) );
|
766 |
-
|
767 |
-
/**
|
768 |
-
* Post processing already imported.
|
769 |
-
*
|
770 |
-
* @param array $data Raw data imported for the post.
|
771 |
-
*/
|
772 |
-
do_action( 'wxr_importer.process_already_imported.post', $data );
|
773 |
-
|
774 |
-
// Even though this post already exists, new comments might need importing
|
775 |
-
$this->process_comments( $comments, $original_id, $data, $post_exists );
|
776 |
-
|
777 |
-
return false;
|
778 |
-
}
|
779 |
-
|
780 |
-
// Map the parent post, or mark it as one we need to fix
|
781 |
-
$requires_remapping = false;
|
782 |
-
if ( $parent_id ) {
|
783 |
-
if ( isset( $this->mapping['post'][ $parent_id ] ) ) {
|
784 |
-
$data['post_parent'] = $this->mapping['post'][ $parent_id ];
|
785 |
-
} else {
|
786 |
-
$meta[] = array(
|
787 |
-
'key' => '_wxr_import_parent',
|
788 |
-
'value' => $parent_id,
|
789 |
-
);
|
790 |
-
$requires_remapping = true;
|
791 |
-
|
792 |
-
$data['post_parent'] = 0;
|
793 |
-
}
|
794 |
-
}
|
795 |
-
|
796 |
-
// Map the author, or mark it as one we need to fix
|
797 |
-
$author = sanitize_user( $data['post_author'], true );
|
798 |
-
if ( empty( $author ) ) {
|
799 |
-
// Missing or invalid author, use default if available.
|
800 |
-
$data['post_author'] = $this->options['default_author'];
|
801 |
-
} elseif ( isset( $this->mapping['user_slug'][ $author ] ) ) {
|
802 |
-
$data['post_author'] = $this->mapping['user_slug'][ $author ];
|
803 |
-
} else {
|
804 |
-
$meta[] = array(
|
805 |
-
'key' => '_wxr_import_user_slug',
|
806 |
-
'value' => $author,
|
807 |
-
);
|
808 |
-
$requires_remapping = true;
|
809 |
-
|
810 |
-
$data['post_author'] = (int) get_current_user_id();
|
811 |
-
}
|
812 |
-
|
813 |
-
// Does the post look like it contains attachment images?
|
814 |
-
if ( preg_match( self::REGEX_HAS_ATTACHMENT_REFS, $data['post_content'] ) ) {
|
815 |
-
$meta[] = array(
|
816 |
-
'key' => '_wxr_import_has_attachment_refs',
|
817 |
-
'value' => true,
|
818 |
-
);
|
819 |
-
$requires_remapping = true;
|
820 |
-
}
|
821 |
-
|
822 |
-
// Whitelist to just the keys we allow
|
823 |
-
$postdata = array(
|
824 |
-
'import_id' => $data['post_id'],
|
825 |
-
);
|
826 |
-
$allowed = array(
|
827 |
-
'post_author' => true,
|
828 |
-
'post_date' => true,
|
829 |
-
'post_date_gmt' => true,
|
830 |
-
'post_content' => true,
|
831 |
-
'post_excerpt' => true,
|
832 |
-
'post_title' => true,
|
833 |
-
'post_status' => true,
|
834 |
-
'post_name' => true,
|
835 |
-
'comment_status' => true,
|
836 |
-
'ping_status' => true,
|
837 |
-
'guid' => true,
|
838 |
-
'post_parent' => true,
|
839 |
-
'menu_order' => true,
|
840 |
-
'post_type' => true,
|
841 |
-
'post_password' => true,
|
842 |
-
);
|
843 |
-
foreach ( $data as $key => $value ) {
|
844 |
-
if ( ! isset( $allowed[ $key ] ) ) {
|
845 |
-
continue;
|
846 |
-
}
|
847 |
-
|
848 |
-
$postdata[ $key ] = $data[ $key ];
|
849 |
-
}
|
850 |
-
|
851 |
-
$postdata = apply_filters( 'wp_import_post_data_processed', $postdata, $data );
|
852 |
-
|
853 |
-
if ( 'attachment' === $postdata['post_type'] ) {
|
854 |
-
if ( ! $this->options['fetch_attachments'] ) {
|
855 |
-
$this->logger->notice( sprintf(
|
856 |
-
__( 'Skipping attachment "%s", fetching attachments disabled' ),
|
857 |
-
$data['post_title']
|
858 |
-
) );
|
859 |
-
/**
|
860 |
-
* Post processing skipped.
|
861 |
-
*
|
862 |
-
* @param array $data Raw data imported for the post.
|
863 |
-
* @param array $meta Raw meta data, already processed by {@see process_post_meta}.
|
864 |
-
*/
|
865 |
-
do_action( 'wxr_importer.process_skipped.post', $data, $meta );
|
866 |
-
return false;
|
867 |
-
}
|
868 |
-
$remote_url = ! empty( $data['attachment_url'] ) ? $data['attachment_url'] : $data['guid'];
|
869 |
-
$post_id = $this->process_attachment( $postdata, $meta, $remote_url );
|
870 |
-
} else {
|
871 |
-
$post_id = wp_insert_post( $postdata, true );
|
872 |
-
do_action( 'wp_import_insert_post', $post_id, $original_id, $postdata, $data );
|
873 |
-
}
|
874 |
-
|
875 |
-
if ( is_wp_error( $post_id ) ) {
|
876 |
-
$this->logger->error( sprintf(
|
877 |
-
__( 'Failed to import "%1$s" (%2$s)', 'wordpress-importer' ),
|
878 |
-
$data['post_title'],
|
879 |
-
$post_type_object->labels->singular_name
|
880 |
-
) );
|
881 |
-
$this->logger->debug( $post_id->get_error_message() );
|
882 |
-
|
883 |
-
/**
|
884 |
-
* Post processing failed.
|
885 |
-
*
|
886 |
-
* @param WP_Error $post_id Error object.
|
887 |
-
* @param array $data Raw data imported for the post.
|
888 |
-
* @param array $meta Raw meta data, already processed by {@see process_post_meta}.
|
889 |
-
* @param array $comments Raw comment data, already processed by {@see process_comments}.
|
890 |
-
* @param array $terms Raw term data, already processed.
|
891 |
-
*/
|
892 |
-
do_action( 'wxr_importer.process_failed.post', $post_id, $data, $meta, $comments, $terms );
|
893 |
-
return false;
|
894 |
-
}
|
895 |
-
|
896 |
-
// Ensure stickiness is handled correctly too
|
897 |
-
if ( $data['is_sticky'] === '1' ) {
|
898 |
-
stick_post( $post_id );
|
899 |
-
}
|
900 |
-
|
901 |
-
// map pre-import ID to local ID
|
902 |
-
$this->mapping['post'][ $original_id ] = (int) $post_id;
|
903 |
-
if ( $requires_remapping ) {
|
904 |
-
$this->requires_remapping['post'][ $post_id ] = true;
|
905 |
-
}
|
906 |
-
$this->mark_post_exists( $data, $post_id );
|
907 |
-
|
908 |
-
$this->logger->info( sprintf(
|
909 |
-
__( 'Imported "%1$s" (%2$s)', 'wordpress-importer' ),
|
910 |
-
$data['post_title'],
|
911 |
-
$post_type_object->labels->singular_name
|
912 |
-
) );
|
913 |
-
$this->logger->debug( sprintf(
|
914 |
-
__( 'Post %1$d remapped to %2$d', 'wordpress-importer' ),
|
915 |
-
$original_id,
|
916 |
-
$post_id
|
917 |
-
) );
|
918 |
-
|
919 |
-
// Handle the terms too
|
920 |
-
$terms = apply_filters( 'wp_import_post_terms', $terms, $post_id, $data );
|
921 |
-
|
922 |
-
if ( ! empty( $terms ) ) {
|
923 |
-
$term_ids = array();
|
924 |
-
foreach ( $terms as $term ) {
|
925 |
-
$taxonomy = $term['taxonomy'];
|
926 |
-
$key = sha1( $taxonomy . ':' . $term['slug'] );
|
927 |
-
|
928 |
-
if ( isset( $this->mapping['term'][ $key ] ) ) {
|
929 |
-
$term_ids[ $taxonomy ][] = (int) $this->mapping['term'][ $key ];
|
930 |
-
} else {
|
931 |
-
$meta[] = array(
|
932 |
-
'key' => '_wxr_import_term',
|
933 |
-
'value' => $term,
|
934 |
-
);
|
935 |
-
$requires_remapping = true;
|
936 |
-
}
|
937 |
-
}
|
938 |
-
|
939 |
-
foreach ( $term_ids as $tax => $ids ) {
|
940 |
-
$tt_ids = wp_set_post_terms( $post_id, $ids, $tax );
|
941 |
-
do_action( 'wp_import_set_post_terms', $tt_ids, $ids, $tax, $post_id, $data );
|
942 |
-
}
|
943 |
-
}
|
944 |
-
|
945 |
-
$this->process_comments( $comments, $post_id, $data );
|
946 |
-
$this->process_post_meta( $meta, $post_id, $data );
|
947 |
-
|
948 |
-
if ( 'nav_menu_item' === $data['post_type'] ) {
|
949 |
-
$this->process_menu_item_meta( $post_id, $data, $meta );
|
950 |
-
}
|
951 |
-
|
952 |
-
/**
|
953 |
-
* Post processing completed.
|
954 |
-
*
|
955 |
-
* @param int $post_id New post ID.
|
956 |
-
* @param array $data Raw data imported for the post.
|
957 |
-
* @param array $meta Raw meta data, already processed by {@see process_post_meta}.
|
958 |
-
* @param array $comments Raw comment data, already processed by {@see process_comments}.
|
959 |
-
* @param array $terms Raw term data, already processed.
|
960 |
-
*/
|
961 |
-
do_action( 'wxr_importer.processed.post', $post_id, $data, $meta, $comments, $terms );
|
962 |
-
}
|
963 |
-
|
964 |
-
/**
|
965 |
-
* Attempt to create a new menu item from import data
|
966 |
-
*
|
967 |
-
* Fails for draft, orphaned menu items and those without an associated nav_menu
|
968 |
-
* or an invalid nav_menu term. If the post type or term object which the menu item
|
969 |
-
* represents doesn't exist then the menu item will not be imported (waits until the
|
970 |
-
* end of the import to retry again before discarding).
|
971 |
-
*
|
972 |
-
* @param array $item Menu item details from WXR file
|
973 |
-
*/
|
974 |
-
protected function process_menu_item_meta( $post_id, $data, $meta ) {
|
975 |
-
|
976 |
-
$item_type = get_post_meta( $post_id, '_menu_item_type', true );
|
977 |
-
$original_object_id = get_post_meta( $post_id, '_menu_item_object_id', true );
|
978 |
-
$object_id = null;
|
979 |
-
|
980 |
-
$this->logger->debug( sprintf( 'Processing menu item %s', $item_type ) );
|
981 |
-
|
982 |
-
$requires_remapping = false;
|
983 |
-
switch ( $item_type ) {
|
984 |
-
case 'taxonomy':
|
985 |
-
if ( isset( $this->mapping['term_id'][ $original_object_id ] ) ) {
|
986 |
-
$object_id = $this->mapping['term_id'][ $original_object_id ];
|
987 |
-
} else {
|
988 |
-
add_post_meta( $post_id, '_wxr_import_menu_item', wp_slash( $original_object_id ) );
|
989 |
-
$requires_remapping = true;
|
990 |
-
}
|
991 |
-
break;
|
992 |
-
|
993 |
-
case 'post_type':
|
994 |
-
if ( isset( $this->mapping['post'][ $original_object_id ] ) ) {
|
995 |
-
$object_id = $this->mapping['post'][ $original_object_id ];
|
996 |
-
} else {
|
997 |
-
add_post_meta( $post_id, '_wxr_import_menu_item', wp_slash( $original_object_id ) );
|
998 |
-
$requires_remapping = true;
|
999 |
-
}
|
1000 |
-
break;
|
1001 |
-
|
1002 |
-
case 'custom':
|
1003 |
-
// Custom refers to itself, wonderfully easy.
|
1004 |
-
$object_id = $post_id;
|
1005 |
-
break;
|
1006 |
-
|
1007 |
-
default:
|
1008 |
-
// associated object is missing or not imported yet, we'll retry later
|
1009 |
-
$this->missing_menu_items[] = $item;
|
1010 |
-
$this->logger->debug( 'Unknown menu item type' );
|
1011 |
-
break;
|
1012 |
-
}
|
1013 |
-
|
1014 |
-
if ( $requires_remapping ) {
|
1015 |
-
$this->requires_remapping['post'][ $post_id ] = true;
|
1016 |
-
}
|
1017 |
-
|
1018 |
-
if ( empty( $object_id ) ) {
|
1019 |
-
// Nothing needed here.
|
1020 |
-
return;
|
1021 |
-
}
|
1022 |
-
|
1023 |
-
$this->logger->debug( sprintf( 'Menu item %d mapped to %d', $original_object_id, $object_id ) );
|
1024 |
-
update_post_meta( $post_id, '_menu_item_object_id', wp_slash( $object_id ) );
|
1025 |
-
}
|
1026 |
-
|
1027 |
-
/**
|
1028 |
-
* If fetching attachments is enabled then attempt to create a new attachment
|
1029 |
-
*
|
1030 |
-
* @param array $post Attachment post details from WXR
|
1031 |
-
* @param string $url URL to fetch attachment from
|
1032 |
-
* @return int|WP_Error Post ID on success, WP_Error otherwise
|
1033 |
-
*/
|
1034 |
-
protected function process_attachment( $post, $meta, $remote_url ) {
|
1035 |
-
// try to use _wp_attached file for upload folder placement to ensure the same location as the export site
|
1036 |
-
// e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
|
1037 |
-
$post['upload_date'] = $post['post_date'];
|
1038 |
-
foreach ( $meta as $meta_item ) {
|
1039 |
-
if ( $meta_item['key'] !== '_wp_attached_file' ) {
|
1040 |
-
continue;
|
1041 |
-
}
|
1042 |
-
|
1043 |
-
if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta_item['value'], $matches ) ) {
|
1044 |
-
$post['upload_date'] = $matches[0];
|
1045 |
-
}
|
1046 |
-
break;
|
1047 |
-
}
|
1048 |
-
|
1049 |
-
// if the URL is absolute, but does not contain address, then upload it assuming base_site_url
|
1050 |
-
if ( preg_match( '|^/[\w\W]+$|', $remote_url ) ) {
|
1051 |
-
$remote_url = rtrim( $this->base_url, '/' ) . $remote_url;
|
1052 |
-
}
|
1053 |
-
|
1054 |
-
$upload = $this->fetch_remote_file( $remote_url, $post );
|
1055 |
-
if ( is_wp_error( $upload ) ) {
|
1056 |
-
return $upload;
|
1057 |
-
}
|
1058 |
-
|
1059 |
-
$info = wp_check_filetype( $upload['file'] );
|
1060 |
-
if ( ! $info ) {
|
1061 |
-
return new WP_Error( 'attachment_processing_error', __( 'Invalid file type', 'wordpress-importer' ) );
|
1062 |
-
}
|
1063 |
-
|
1064 |
-
$post['post_mime_type'] = $info['type'];
|
1065 |
-
|
1066 |
-
// WP really likes using the GUID for display. Allow updating it.
|
1067 |
-
// See https://core.trac.wordpress.org/ticket/33386
|
1068 |
-
if ( $this->options['update_attachment_guids'] ) {
|
1069 |
-
$post['guid'] = $upload['url'];
|
1070 |
-
}
|
1071 |
-
|
1072 |
-
// as per wp-admin/includes/upload.php
|
1073 |
-
$post_id = wp_insert_attachment( $post, $upload['file'] );
|
1074 |
-
if ( is_wp_error( $post_id ) ) {
|
1075 |
-
return $post_id;
|
1076 |
-
}
|
1077 |
-
|
1078 |
-
$attachment_metadata = wp_generate_attachment_metadata( $post_id, $upload['file'] );
|
1079 |
-
wp_update_attachment_metadata( $post_id, $attachment_metadata );
|
1080 |
-
|
1081 |
-
// Map this image URL later if we need to
|
1082 |
-
$this->url_remap[ $remote_url ] = $upload['url'];
|
1083 |
-
|
1084 |
-
// If we have a HTTPS URL, ensure the HTTP URL gets replaced too
|
1085 |
-
if ( substr( $remote_url, 0, 8 ) === 'https://' ) {
|
1086 |
-
$insecure_url = 'http' . substr( $remote_url, 5 );
|
1087 |
-
$this->url_remap[ $insecure_url ] = $upload['url'];
|
1088 |
-
}
|
1089 |
-
|
1090 |
-
if ( $this->options['aggressive_url_search'] ) {
|
1091 |
-
// remap resized image URLs, works by stripping the extension and remapping the URL stub.
|
1092 |
-
/*
|
1093 |
-
if ( preg_match( '!^image/!', $info['type'] ) ) {
|
1094 |
-
$parts = pathinfo( $remote_url );
|
1095 |
-
$name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2
|
1096 |
-
|
1097 |
-
$parts_new = pathinfo( $upload['url'] );
|
1098 |
-
$name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" );
|
1099 |
-
|
1100 |
-
$this->url_remap[$parts['dirname'] . '/' . $name] = $parts_new['dirname'] . '/' . $name_new;
|
1101 |
-
}*/
|
1102 |
-
}
|
1103 |
-
|
1104 |
-
return $post_id;
|
1105 |
-
}
|
1106 |
-
|
1107 |
-
/**
|
1108 |
-
* Parse a meta node into meta data.
|
1109 |
-
*
|
1110 |
-
* @param DOMElement $node Parent node of meta data (typically `wp:postmeta` or `wp:commentmeta`).
|
1111 |
-
* @return array|null Meta data array on success, or null on error.
|
1112 |
-
*/
|
1113 |
-
protected function parse_meta_node( $node ) {
|
1114 |
-
foreach ( $node->childNodes as $child ) {
|
1115 |
-
// We only care about child elements
|
1116 |
-
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
1117 |
-
continue;
|
1118 |
-
}
|
1119 |
-
|
1120 |
-
switch ( $child->tagName ) {
|
1121 |
-
case 'wp:meta_key':
|
1122 |
-
$key = $child->textContent;
|
1123 |
-
break;
|
1124 |
-
|
1125 |
-
case 'wp:meta_value':
|
1126 |
-
$value = $child->textContent;
|
1127 |
-
break;
|
1128 |
-
}
|
1129 |
-
}
|
1130 |
-
|
1131 |
-
if ( empty( $key ) || empty( $value ) ) {
|
1132 |
-
return null;
|
1133 |
-
}
|
1134 |
-
|
1135 |
-
return compact( 'key', 'value' );
|
1136 |
-
}
|
1137 |
-
|
1138 |
-
/**
|
1139 |
-
* Process and import post meta items.
|
1140 |
-
*
|
1141 |
-
* @param array $meta List of meta data arrays
|
1142 |
-
* @param int $post_id Post to associate with
|
1143 |
-
* @param array $post Post data
|
1144 |
-
* @return int|WP_Error Number of meta items imported on success, error otherwise.
|
1145 |
-
*/
|
1146 |
-
protected function process_post_meta( $meta, $post_id, $post ) {
|
1147 |
-
if ( empty( $meta ) ) {
|
1148 |
-
return true;
|
1149 |
-
}
|
1150 |
-
|
1151 |
-
foreach ( $meta as $meta_item ) {
|
1152 |
-
/**
|
1153 |
-
* Pre-process post meta data.
|
1154 |
-
*
|
1155 |
-
* @param array $meta_item Meta data. (Return empty to skip.)
|
1156 |
-
* @param int $post_id Post the meta is attached to.
|
1157 |
-
*/
|
1158 |
-
$meta_item = apply_filters( 'wxr_importer.pre_process.post_meta', $meta_item, $post_id );
|
1159 |
-
if ( empty( $meta_item ) ) {
|
1160 |
-
return false;
|
1161 |
-
}
|
1162 |
-
|
1163 |
-
$key = apply_filters( 'import_post_meta_key', $meta_item['key'], $post_id, $post );
|
1164 |
-
$value = false;
|
1165 |
-
|
1166 |
-
if ( '_edit_last' === $key ) {
|
1167 |
-
$value = intval( $meta_item['value'] );
|
1168 |
-
if ( ! isset( $this->mapping['user'][ $value ] ) ) {
|
1169 |
-
// Skip!
|
1170 |
-
continue;
|
1171 |
-
}
|
1172 |
-
|
1173 |
-
$value = $this->mapping['user'][ $value ];
|
1174 |
-
}
|
1175 |
-
|
1176 |
-
if ( $key ) {
|
1177 |
-
// export gets meta straight from the DB so could have a serialized string
|
1178 |
-
if ( ! $value ) {
|
1179 |
-
$value = maybe_unserialize( $meta_item['value'] );
|
1180 |
-
}
|
1181 |
-
|
1182 |
-
add_post_meta( $post_id, $key, $value );
|
1183 |
-
do_action( 'import_post_meta', $post_id, $key, $value );
|
1184 |
-
|
1185 |
-
// if the post has a featured image, take note of this in case of remap
|
1186 |
-
if ( '_thumbnail_id' === $key ) {
|
1187 |
-
$this->featured_images[ $post_id ] = (int) $value;
|
1188 |
-
}
|
1189 |
-
}
|
1190 |
-
}// End foreach().
|
1191 |
-
|
1192 |
-
return true;
|
1193 |
-
}
|
1194 |
-
|
1195 |
-
/**
|
1196 |
-
* Parse a comment node into comment data.
|
1197 |
-
*
|
1198 |
-
* @param DOMElement $node Parent node of comment data (typically `wp:comment`).
|
1199 |
-
* @return array Comment data array.
|
1200 |
-
*/
|
1201 |
-
protected function parse_comment_node( $node ) {
|
1202 |
-
$data = array(
|
1203 |
-
'commentmeta' => array(),
|
1204 |
-
);
|
1205 |
-
|
1206 |
-
foreach ( $node->childNodes as $child ) {
|
1207 |
-
// We only care about child elements
|
1208 |
-
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
1209 |
-
continue;
|
1210 |
-
}
|
1211 |
-
|
1212 |
-
switch ( $child->tagName ) {
|
1213 |
-
case 'wp:comment_id':
|
1214 |
-
$data['comment_id'] = $child->textContent;
|
1215 |
-
break;
|
1216 |
-
case 'wp:comment_author':
|
1217 |
-
$data['comment_author'] = $child->textContent;
|
1218 |
-
break;
|
1219 |
-
|
1220 |
-
case 'wp:comment_author_email':
|
1221 |
-
$data['comment_author_email'] = $child->textContent;
|
1222 |
-
break;
|
1223 |
-
|
1224 |
-
case 'wp:comment_author_IP':
|
1225 |
-
$data['comment_author_IP'] = $child->textContent;
|
1226 |
-
break;
|
1227 |
-
|
1228 |
-
case 'wp:comment_author_url':
|
1229 |
-
$data['comment_author_url'] = $child->textContent;
|
1230 |
-
break;
|
1231 |
-
|
1232 |
-
case 'wp:comment_user_id':
|
1233 |
-
$data['comment_user_id'] = $child->textContent;
|
1234 |
-
break;
|
1235 |
-
|
1236 |
-
case 'wp:comment_date':
|
1237 |
-
$data['comment_date'] = $child->textContent;
|
1238 |
-
break;
|
1239 |
-
|
1240 |
-
case 'wp:comment_date_gmt':
|
1241 |
-
$data['comment_date_gmt'] = $child->textContent;
|
1242 |
-
break;
|
1243 |
-
|
1244 |
-
case 'wp:comment_content':
|
1245 |
-
$data['comment_content'] = $child->textContent;
|
1246 |
-
break;
|
1247 |
-
|
1248 |
-
case 'wp:comment_approved':
|
1249 |
-
$data['comment_approved'] = $child->textContent;
|
1250 |
-
break;
|
1251 |
-
|
1252 |
-
case 'wp:comment_type':
|
1253 |
-
$data['comment_type'] = $child->textContent;
|
1254 |
-
break;
|
1255 |
-
|
1256 |
-
case 'wp:comment_parent':
|
1257 |
-
$data['comment_parent'] = $child->textContent;
|
1258 |
-
break;
|
1259 |
-
|
1260 |
-
case 'wp:commentmeta':
|
1261 |
-
$meta_item = $this->parse_meta_node( $child );
|
1262 |
-
if ( ! empty( $meta_item ) ) {
|
1263 |
-
$data['commentmeta'][] = $meta_item;
|
1264 |
-
}
|
1265 |
-
break;
|
1266 |
-
}// End switch().
|
1267 |
-
}// End foreach().
|
1268 |
-
|
1269 |
-
return $data;
|
1270 |
-
}
|
1271 |
-
|
1272 |
-
/**
|
1273 |
-
* Process and import comment data.
|
1274 |
-
*
|
1275 |
-
* @param array $comments List of comment data arrays.
|
1276 |
-
* @param int $post_id Post to associate with.
|
1277 |
-
* @param array $post Post data.
|
1278 |
-
* @return int|WP_Error Number of comments imported on success, error otherwise.
|
1279 |
-
*/
|
1280 |
-
protected function process_comments( $comments, $post_id, $post, $post_exists = false ) {
|
1281 |
-
|
1282 |
-
$comments = apply_filters( 'wp_import_post_comments', $comments, $post_id, $post );
|
1283 |
-
if ( empty( $comments ) ) {
|
1284 |
-
return 0;
|
1285 |
-
}
|
1286 |
-
|
1287 |
-
$num_comments = 0;
|
1288 |
-
|
1289 |
-
// Sort by ID to avoid excessive remapping later
|
1290 |
-
usort( $comments, array( $this, 'sort_comments_by_id' ) );
|
1291 |
-
|
1292 |
-
foreach ( $comments as $key => $comment ) {
|
1293 |
-
/**
|
1294 |
-
* Pre-process comment data
|
1295 |
-
*
|
1296 |
-
* @param array $comment Comment data. (Return empty to skip.)
|
1297 |
-
* @param int $post_id Post the comment is attached to.
|
1298 |
-
*/
|
1299 |
-
$comment = apply_filters( 'wxr_importer.pre_process.comment', $comment, $post_id );
|
1300 |
-
if ( empty( $comment ) ) {
|
1301 |
-
return false;
|
1302 |
-
}
|
1303 |
-
|
1304 |
-
$original_id = isset( $comment['comment_id'] ) ? (int) $comment['comment_id'] : 0;
|
1305 |
-
$parent_id = isset( $comment['comment_parent'] ) ? (int) $comment['comment_parent'] : 0;
|
1306 |
-
$author_id = isset( $comment['comment_user_id'] ) ? (int) $comment['comment_user_id'] : 0;
|
1307 |
-
|
1308 |
-
// if this is a new post we can skip the comment_exists() check
|
1309 |
-
// TODO: Check comment_exists for performance
|
1310 |
-
if ( $post_exists ) {
|
1311 |
-
$existing = $this->comment_exists( $comment );
|
1312 |
-
if ( $existing ) {
|
1313 |
-
|
1314 |
-
/**
|
1315 |
-
* Comment processing already imported.
|
1316 |
-
*
|
1317 |
-
* @param array $comment Raw data imported for the comment.
|
1318 |
-
*/
|
1319 |
-
do_action( 'wxr_importer.process_already_imported.comment', $comment );
|
1320 |
-
|
1321 |
-
$this->mapping['comment'][ $original_id ] = $existing;
|
1322 |
-
continue;
|
1323 |
-
}
|
1324 |
-
}
|
1325 |
-
|
1326 |
-
// Remove meta from the main array
|
1327 |
-
$meta = isset( $comment['commentmeta'] ) ? $comment['commentmeta'] : array();
|
1328 |
-
unset( $comment['commentmeta'] );
|
1329 |
-
|
1330 |
-
// Map the parent comment, or mark it as one we need to fix
|
1331 |
-
$requires_remapping = false;
|
1332 |
-
if ( $parent_id ) {
|
1333 |
-
if ( isset( $this->mapping['comment'][ $parent_id ] ) ) {
|
1334 |
-
$comment['comment_parent'] = $this->mapping['comment'][ $parent_id ];
|
1335 |
-
} else {
|
1336 |
-
// Prepare for remapping later
|
1337 |
-
$meta[] = array(
|
1338 |
-
'key' => '_wxr_import_parent',
|
1339 |
-
'value' => $parent_id,
|
1340 |
-
);
|
1341 |
-
$requires_remapping = true;
|
1342 |
-
|
1343 |
-
// Wipe the parent for now
|
1344 |
-
$comment['comment_parent'] = 0;
|
1345 |
-
}
|
1346 |
-
}
|
1347 |
-
|
1348 |
-
// Map the author, or mark it as one we need to fix
|
1349 |
-
if ( $author_id ) {
|
1350 |
-
if ( isset( $this->mapping['user'][ $author_id ] ) ) {
|
1351 |
-
$comment['user_id'] = $this->mapping['user'][ $author_id ];
|
1352 |
-
} else {
|
1353 |
-
// Prepare for remapping later
|
1354 |
-
$meta[] = array(
|
1355 |
-
'key' => '_wxr_import_user',
|
1356 |
-
'value' => $author_id,
|
1357 |
-
);
|
1358 |
-
$requires_remapping = true;
|
1359 |
-
|
1360 |
-
// Wipe the user for now
|
1361 |
-
$comment['user_id'] = 0;
|
1362 |
-
}
|
1363 |
-
}
|
1364 |
-
|
1365 |
-
// Run standard core filters
|
1366 |
-
$comment['comment_post_ID'] = $post_id;
|
1367 |
-
$comment = wp_filter_comment( $comment );
|
1368 |
-
|
1369 |
-
// wp_insert_comment expects slashed data
|
1370 |
-
$comment_id = wp_insert_comment( wp_slash( $comment ) );
|
1371 |
-
$this->mapping['comment'][ $original_id ] = $comment_id;
|
1372 |
-
if ( $requires_remapping ) {
|
1373 |
-
$this->requires_remapping['comment'][ $comment_id ] = true;
|
1374 |
-
}
|
1375 |
-
$this->mark_comment_exists( $comment, $comment_id );
|
1376 |
-
|
1377 |
-
/**
|
1378 |
-
* Comment has been imported.
|
1379 |
-
*
|
1380 |
-
* @param int $comment_id New comment ID
|
1381 |
-
* @param array $comment Comment inserted (`comment_id` item refers to the original ID)
|
1382 |
-
* @param int $post_id Post parent of the comment
|
1383 |
-
* @param array $post Post data
|
1384 |
-
*/
|
1385 |
-
do_action( 'wp_import_insert_comment', $comment_id, $comment, $post_id, $post );
|
1386 |
-
|
1387 |
-
// Process the meta items
|
1388 |
-
foreach ( $meta as $meta_item ) {
|
1389 |
-
$value = maybe_unserialize( $meta_item['value'] );
|
1390 |
-
add_comment_meta( $comment_id, wp_slash( $meta_item['key'] ), wp_slash( $value ) );
|
1391 |
-
}
|
1392 |
-
|
1393 |
-
/**
|
1394 |
-
* Post processing completed.
|
1395 |
-
*
|
1396 |
-
* @param int $post_id New post ID.
|
1397 |
-
* @param array $comment Raw data imported for the comment.
|
1398 |
-
* @param array $meta Raw meta data, already processed by {@see process_post_meta}.
|
1399 |
-
* @param array $post_id Parent post ID.
|
1400 |
-
*/
|
1401 |
-
do_action( 'wxr_importer.processed.comment', $comment_id, $comment, $meta, $post_id );
|
1402 |
-
|
1403 |
-
$num_comments++;
|
1404 |
-
}// End foreach().
|
1405 |
-
|
1406 |
-
return $num_comments;
|
1407 |
-
}
|
1408 |
-
|
1409 |
-
protected function parse_category_node( $node ) {
|
1410 |
-
$data = array(
|
1411 |
-
// Default taxonomy to "category", since this is a `<category>` tag
|
1412 |
-
'taxonomy' => 'category',
|
1413 |
-
);
|
1414 |
-
$meta = array();
|
1415 |
-
|
1416 |
-
if ( $node->hasAttribute( 'domain' ) ) {
|
1417 |
-
$data['taxonomy'] = $node->getAttribute( 'domain' );
|
1418 |
-
}
|
1419 |
-
if ( $node->hasAttribute( 'nicename' ) ) {
|
1420 |
-
$data['slug'] = $node->getAttribute( 'nicename' );
|
1421 |
-
}
|
1422 |
-
|
1423 |
-
$data['name'] = $node->textContent;
|
1424 |
-
|
1425 |
-
if ( empty( $data['slug'] ) ) {
|
1426 |
-
return null;
|
1427 |
-
}
|
1428 |
-
|
1429 |
-
// Just for extra compatibility
|
1430 |
-
if ( $data['taxonomy'] === 'tag' ) {
|
1431 |
-
$data['taxonomy'] = 'post_tag';
|
1432 |
-
}
|
1433 |
-
|
1434 |
-
return $data;
|
1435 |
-
}
|
1436 |
-
|
1437 |
-
/**
|
1438 |
-
* Callback for `usort` to sort comments by ID
|
1439 |
-
*
|
1440 |
-
* @param array $a Comment data for the first comment
|
1441 |
-
* @param array $b Comment data for the second comment
|
1442 |
-
* @return int
|
1443 |
-
*/
|
1444 |
-
public static function sort_comments_by_id( $a, $b ) {
|
1445 |
-
if ( empty( $a['comment_id'] ) ) {
|
1446 |
-
return 1;
|
1447 |
-
}
|
1448 |
-
|
1449 |
-
if ( empty( $b['comment_id'] ) ) {
|
1450 |
-
return -1;
|
1451 |
-
}
|
1452 |
-
|
1453 |
-
return $a['comment_id'] - $b['comment_id'];
|
1454 |
-
}
|
1455 |
-
|
1456 |
-
protected function parse_author_node( $node ) {
|
1457 |
-
$data = array();
|
1458 |
-
$meta = array();
|
1459 |
-
foreach ( $node->childNodes as $child ) {
|
1460 |
-
// We only care about child elements
|
1461 |
-
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
1462 |
-
continue;
|
1463 |
-
}
|
1464 |
-
|
1465 |
-
switch ( $child->tagName ) {
|
1466 |
-
case 'wp:author_login':
|
1467 |
-
$data['user_login'] = $child->textContent;
|
1468 |
-
break;
|
1469 |
-
|
1470 |
-
case 'wp:author_id':
|
1471 |
-
$data['ID'] = $child->textContent;
|
1472 |
-
break;
|
1473 |
-
|
1474 |
-
case 'wp:author_email':
|
1475 |
-
$data['user_email'] = $child->textContent;
|
1476 |
-
break;
|
1477 |
-
|
1478 |
-
case 'wp:author_display_name':
|
1479 |
-
$data['display_name'] = $child->textContent;
|
1480 |
-
break;
|
1481 |
-
|
1482 |
-
case 'wp:author_first_name':
|
1483 |
-
$data['first_name'] = $child->textContent;
|
1484 |
-
break;
|
1485 |
-
|
1486 |
-
case 'wp:author_last_name':
|
1487 |
-
$data['last_name'] = $child->textContent;
|
1488 |
-
break;
|
1489 |
-
}
|
1490 |
-
}
|
1491 |
-
|
1492 |
-
return compact( 'data', 'meta' );
|
1493 |
-
}
|
1494 |
-
|
1495 |
-
protected function process_author( $data, $meta ) {
|
1496 |
-
/**
|
1497 |
-
* Pre-process user data.
|
1498 |
-
*
|
1499 |
-
* @param array $data User data. (Return empty to skip.)
|
1500 |
-
* @param array $meta Meta data.
|
1501 |
-
*/
|
1502 |
-
$data = apply_filters( 'wxr_importer.pre_process.user', $data, $meta );
|
1503 |
-
if ( empty( $data ) ) {
|
1504 |
-
return false;
|
1505 |
-
}
|
1506 |
-
|
1507 |
-
// Have we already handled this user?
|
1508 |
-
$original_id = isset( $data['ID'] ) ? $data['ID'] : 0;
|
1509 |
-
$original_slug = $data['user_login'];
|
1510 |
-
|
1511 |
-
if ( isset( $this->mapping['user'][ $original_id ] ) ) {
|
1512 |
-
$existing = $this->mapping['user'][ $original_id ];
|
1513 |
-
|
1514 |
-
// Note the slug mapping if we need to too
|
1515 |
-
if ( ! isset( $this->mapping['user_slug'][ $original_slug ] ) ) {
|
1516 |
-
$this->mapping['user_slug'][ $original_slug ] = $existing;
|
1517 |
-
}
|
1518 |
-
|
1519 |
-
return false;
|
1520 |
-
}
|
1521 |
-
|
1522 |
-
if ( isset( $this->mapping['user_slug'][ $original_slug ] ) ) {
|
1523 |
-
$existing = $this->mapping['user_slug'][ $original_slug ];
|
1524 |
-
|
1525 |
-
// Ensure we note the mapping too
|
1526 |
-
$this->mapping['user'][ $original_id ] = $existing;
|
1527 |
-
|
1528 |
-
return false;
|
1529 |
-
}
|
1530 |
-
|
1531 |
-
// Allow overriding the user's slug
|
1532 |
-
$login = $original_slug;
|
1533 |
-
if ( isset( $this->user_slug_override[ $login ] ) ) {
|
1534 |
-
$login = $this->user_slug_override[ $login ];
|
1535 |
-
}
|
1536 |
-
|
1537 |
-
$userdata = array(
|
1538 |
-
'user_login' => sanitize_user( $login, true ),
|
1539 |
-
'user_pass' => wp_generate_password(),
|
1540 |
-
);
|
1541 |
-
|
1542 |
-
$allowed = array(
|
1543 |
-
'user_email' => true,
|
1544 |
-
'display_name' => true,
|
1545 |
-
'first_name' => true,
|
1546 |
-
'last_name' => true,
|
1547 |
-
);
|
1548 |
-
foreach ( $data as $key => $value ) {
|
1549 |
-
if ( ! isset( $allowed[ $key ] ) ) {
|
1550 |
-
continue;
|
1551 |
-
}
|
1552 |
-
|
1553 |
-
$userdata[ $key ] = $data[ $key ];
|
1554 |
-
}
|
1555 |
-
|
1556 |
-
$user_id = wp_insert_user( wp_slash( $userdata ) );
|
1557 |
-
if ( is_wp_error( $user_id ) ) {
|
1558 |
-
$this->logger->error( sprintf(
|
1559 |
-
__( 'Failed to import user "%s"', 'wordpress-importer' ),
|
1560 |
-
$userdata['user_login']
|
1561 |
-
) );
|
1562 |
-
$this->logger->debug( $user_id->get_error_message() );
|
1563 |
-
|
1564 |
-
/**
|
1565 |
-
* User processing failed.
|
1566 |
-
*
|
1567 |
-
* @param WP_Error $user_id Error object.
|
1568 |
-
* @param array $userdata Raw data imported for the user.
|
1569 |
-
*/
|
1570 |
-
do_action( 'wxr_importer.process_failed.user', $user_id, $userdata );
|
1571 |
-
return false;
|
1572 |
-
}
|
1573 |
-
|
1574 |
-
if ( $original_id ) {
|
1575 |
-
$this->mapping['user'][ $original_id ] = $user_id;
|
1576 |
-
}
|
1577 |
-
$this->mapping['user_slug'][ $original_slug ] = $user_id;
|
1578 |
-
|
1579 |
-
$this->logger->info( sprintf(
|
1580 |
-
__( 'Imported user "%s"', 'wordpress-importer' ),
|
1581 |
-
$userdata['user_login']
|
1582 |
-
) );
|
1583 |
-
$this->logger->debug( sprintf(
|
1584 |
-
__( 'User %1$d remapped to %2$d', 'wordpress-importer' ),
|
1585 |
-
$original_id,
|
1586 |
-
$user_id
|
1587 |
-
) );
|
1588 |
-
|
1589 |
-
// TODO: Implement meta handling once WXR includes it
|
1590 |
-
/**
|
1591 |
-
* User processing completed.
|
1592 |
-
*
|
1593 |
-
* @param int $user_id New user ID.
|
1594 |
-
* @param array $userdata Raw data imported for the user.
|
1595 |
-
*/
|
1596 |
-
do_action( 'wxr_importer.processed.user', $user_id, $userdata );
|
1597 |
-
}
|
1598 |
-
|
1599 |
-
protected function parse_term_node( $node, $type = 'term' ) {
|
1600 |
-
$data = array();
|
1601 |
-
$meta = array();
|
1602 |
-
|
1603 |
-
$tag_name = array(
|
1604 |
-
'id' => 'wp:term_id',
|
1605 |
-
'taxonomy' => 'wp:term_taxonomy',
|
1606 |
-
'slug' => 'wp:term_slug',
|
1607 |
-
'parent' => 'wp:term_parent',
|
1608 |
-
'name' => 'wp:term_name',
|
1609 |
-
'description' => 'wp:term_description',
|
1610 |
-
);
|
1611 |
-
$taxonomy = null;
|
1612 |
-
|
1613 |
-
// Special casing!
|
1614 |
-
switch ( $type ) {
|
1615 |
-
case 'category':
|
1616 |
-
$tag_name['slug'] = 'wp:category_nicename';
|
1617 |
-
$tag_name['parent'] = 'wp:category_parent';
|
1618 |
-
$tag_name['name'] = 'wp:cat_name';
|
1619 |
-
$tag_name['description'] = 'wp:category_description';
|
1620 |
-
$tag_name['taxonomy'] = null;
|
1621 |
-
|
1622 |
-
$data['taxonomy'] = 'category';
|
1623 |
-
break;
|
1624 |
-
|
1625 |
-
case 'tag':
|
1626 |
-
$tag_name['slug'] = 'wp:tag_slug';
|
1627 |
-
$tag_name['parent'] = null;
|
1628 |
-
$tag_name['name'] = 'wp:tag_name';
|
1629 |
-
$tag_name['description'] = 'wp:tag_description';
|
1630 |
-
$tag_name['taxonomy'] = null;
|
1631 |
-
|
1632 |
-
$data['taxonomy'] = 'post_tag';
|
1633 |
-
break;
|
1634 |
-
}
|
1635 |
-
|
1636 |
-
foreach ( $node->childNodes as $child ) {
|
1637 |
-
// We only care about child elements
|
1638 |
-
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
1639 |
-
continue;
|
1640 |
-
}
|
1641 |
-
|
1642 |
-
$key = array_search( $child->tagName, $tag_name );
|
1643 |
-
if ( $key ) {
|
1644 |
-
$data[ $key ] = $child->textContent;
|
1645 |
-
}
|
1646 |
-
}
|
1647 |
-
|
1648 |
-
if ( empty( $data['taxonomy'] ) ) {
|
1649 |
-
return null;
|
1650 |
-
}
|
1651 |
-
|
1652 |
-
// Compatibility with WXR 1.0
|
1653 |
-
if ( $data['taxonomy'] === 'tag' ) {
|
1654 |
-
$data['taxonomy'] = 'post_tag';
|
1655 |
-
}
|
1656 |
-
|
1657 |
-
return compact( 'data', 'meta' );
|
1658 |
-
}
|
1659 |
-
|
1660 |
-
protected function process_term( $data, $meta ) {
|
1661 |
-
/**
|
1662 |
-
* Pre-process term data.
|
1663 |
-
*
|
1664 |
-
* @param array $data Term data. (Return empty to skip.)
|
1665 |
-
* @param array $meta Meta data.
|
1666 |
-
*/
|
1667 |
-
$data = apply_filters( 'wxr_importer.pre_process.term', $data, $meta );
|
1668 |
-
if ( empty( $data ) ) {
|
1669 |
-
return false;
|
1670 |
-
}
|
1671 |
-
|
1672 |
-
$original_id = isset( $data['id'] ) ? (int) $data['id'] : 0;
|
1673 |
-
$parent_id = isset( $data['parent'] ) ? (int) $data['parent'] : 0;
|
1674 |
-
|
1675 |
-
$mapping_key = sha1( $data['taxonomy'] . ':' . $data['slug'] );
|
1676 |
-
$existing = $this->term_exists( $data );
|
1677 |
-
if ( $existing ) {
|
1678 |
-
|
1679 |
-
/**
|
1680 |
-
* Term processing already imported.
|
1681 |
-
*
|
1682 |
-
* @param array $data Raw data imported for the term.
|
1683 |
-
*/
|
1684 |
-
do_action( 'wxr_importer.process_already_imported.term', $data );
|
1685 |
-
|
1686 |
-
$this->mapping['term'][ $mapping_key ] = $existing;
|
1687 |
-
$this->mapping['term_id'][ $original_id ] = $existing;
|
1688 |
-
return false;
|
1689 |
-
}
|
1690 |
-
|
1691 |
-
// WP really likes to repeat itself in export files
|
1692 |
-
if ( isset( $this->mapping['term'][ $mapping_key ] ) ) {
|
1693 |
-
return false;
|
1694 |
-
}
|
1695 |
-
|
1696 |
-
$termdata = array();
|
1697 |
-
$allowed = array(
|
1698 |
-
'slug' => true,
|
1699 |
-
'description' => true,
|
1700 |
-
);
|
1701 |
-
|
1702 |
-
// Map the parent comment, or mark it as one we need to fix
|
1703 |
-
// TODO: add parent mapping and remapping
|
1704 |
-
/*
|
1705 |
-
$requires_remapping = false;
|
1706 |
-
if ( $parent_id ) {
|
1707 |
-
if ( isset( $this->mapping['term'][ $parent_id ] ) ) {
|
1708 |
-
$data['parent'] = $this->mapping['term'][ $parent_id ];
|
1709 |
-
} else {
|
1710 |
-
// Prepare for remapping later
|
1711 |
-
$meta[] = array( 'key' => '_wxr_import_parent', 'value' => $parent_id );
|
1712 |
-
$requires_remapping = true;
|
1713 |
-
|
1714 |
-
// Wipe the parent for now
|
1715 |
-
$data['parent'] = 0;
|
1716 |
-
}
|
1717 |
-
}*/
|
1718 |
-
|
1719 |
-
foreach ( $data as $key => $value ) {
|
1720 |
-
if ( ! isset( $allowed[ $key ] ) ) {
|
1721 |
-
continue;
|
1722 |
-
}
|
1723 |
-
|
1724 |
-
$termdata[ $key ] = $data[ $key ];
|
1725 |
-
}
|
1726 |
-
|
1727 |
-
$result = wp_insert_term( $data['name'], $data['taxonomy'], $termdata );
|
1728 |
-
if ( is_wp_error( $result ) ) {
|
1729 |
-
$this->logger->warning( sprintf(
|
1730 |
-
__( 'Failed to import %1$s %2$s', 'wordpress-importer' ),
|
1731 |
-
$data['taxonomy'],
|
1732 |
-
$data['name']
|
1733 |
-
) );
|
1734 |
-
$this->logger->debug( $result->get_error_message() );
|
1735 |
-
do_action( 'wp_import_insert_term_failed', $result, $data );
|
1736 |
-
|
1737 |
-
/**
|
1738 |
-
* Term processing failed.
|
1739 |
-
*
|
1740 |
-
* @param WP_Error $result Error object.
|
1741 |
-
* @param array $data Raw data imported for the term.
|
1742 |
-
* @param array $meta Meta data supplied for the term.
|
1743 |
-
*/
|
1744 |
-
do_action( 'wxr_importer.process_failed.term', $result, $data, $meta );
|
1745 |
-
return false;
|
1746 |
-
}
|
1747 |
-
|
1748 |
-
$term_id = $result['term_id'];
|
1749 |
-
|
1750 |
-
$this->mapping['term'][ $mapping_key ] = $term_id;
|
1751 |
-
$this->mapping['term_id'][ $original_id ] = $term_id;
|
1752 |
-
|
1753 |
-
$this->logger->info( sprintf(
|
1754 |
-
__( 'Imported "%1$s" (%2$s)', 'wordpress-importer' ),
|
1755 |
-
$data['name'],
|
1756 |
-
$data['taxonomy']
|
1757 |
-
) );
|
1758 |
-
$this->logger->debug( sprintf(
|
1759 |
-
__( 'Term %1$d remapped to %2$d', 'wordpress-importer' ),
|
1760 |
-
$original_id,
|
1761 |
-
$term_id
|
1762 |
-
) );
|
1763 |
-
|
1764 |
-
do_action( 'wp_import_insert_term', $term_id, $data );
|
1765 |
-
|
1766 |
-
/**
|
1767 |
-
* Term processing completed.
|
1768 |
-
*
|
1769 |
-
* @param int $term_id New term ID.
|
1770 |
-
* @param array $data Raw data imported for the term.
|
1771 |
-
*/
|
1772 |
-
do_action( 'wxr_importer.processed.term', $term_id, $data );
|
1773 |
-
}
|
1774 |
-
|
1775 |
-
/**
|
1776 |
-
* Attempt to download a remote file attachment
|
1777 |
-
*
|
1778 |
-
* @param string $url URL of item to fetch
|
1779 |
-
* @param array $post Attachment details
|
1780 |
-
* @return array|WP_Error Local file location details on success, WP_Error otherwise
|
1781 |
-
*/
|
1782 |
-
protected function fetch_remote_file( $url, $post ) {
|
1783 |
-
// extract the file name and extension from the url
|
1784 |
-
$file_name = basename( $url );
|
1785 |
-
|
1786 |
-
// get placeholder file in the upload dir with a unique, sanitized filename
|
1787 |
-
$upload = wp_upload_bits( $file_name, 0, '', $post['upload_date'] );
|
1788 |
-
if ( $upload['error'] ) {
|
1789 |
-
return new WP_Error( 'upload_dir_error', $upload['error'] );
|
1790 |
-
}
|
1791 |
-
|
1792 |
-
// fetch the remote url and write it to the placeholder file
|
1793 |
-
$response = wp_remote_get( $url, array(
|
1794 |
-
'stream' => true,
|
1795 |
-
'filename' => $upload['file'],
|
1796 |
-
) );
|
1797 |
-
|
1798 |
-
// request failed
|
1799 |
-
if ( is_wp_error( $response ) ) {
|
1800 |
-
unlink( $upload['file'] );
|
1801 |
-
return $response;
|
1802 |
-
}
|
1803 |
-
|
1804 |
-
$code = (int) wp_remote_retrieve_response_code( $response );
|
1805 |
-
|
1806 |
-
// make sure the fetch was successful
|
1807 |
-
if ( $code !== 200 ) {
|
1808 |
-
unlink( $upload['file'] );
|
1809 |
-
return new WP_Error(
|
1810 |
-
'import_file_error',
|
1811 |
-
sprintf(
|
1812 |
-
__( 'Remote server returned %1$d %2$s for %3$s', 'wordpress-importer' ),
|
1813 |
-
$code,
|
1814 |
-
get_status_header_desc( $code ),
|
1815 |
-
$url
|
1816 |
-
)
|
1817 |
-
);
|
1818 |
-
}
|
1819 |
-
|
1820 |
-
$filesize = filesize( $upload['file'] );
|
1821 |
-
$headers = wp_remote_retrieve_headers( $response );
|
1822 |
-
|
1823 |
-
if ( isset( $headers['content-length'] ) && $filesize !== (int) $headers['content-length'] ) {
|
1824 |
-
unlink( $upload['file'] );
|
1825 |
-
return new WP_Error( 'import_file_error', __( 'Remote file is incorrect size', 'wordpress-importer' ) );
|
1826 |
-
}
|
1827 |
-
|
1828 |
-
if ( 0 === $filesize ) {
|
1829 |
-
unlink( $upload['file'] );
|
1830 |
-
return new WP_Error( 'import_file_error', __( 'Zero size file downloaded', 'wordpress-importer' ) );
|
1831 |
-
}
|
1832 |
-
|
1833 |
-
$max_size = (int) $this->max_attachment_size();
|
1834 |
-
if ( ! empty( $max_size ) && $filesize > $max_size ) {
|
1835 |
-
unlink( $upload['file'] );
|
1836 |
-
$message = sprintf( __( 'Remote file is too large, limit is %s', 'wordpress-importer' ), size_format( $max_size ) );
|
1837 |
-
return new WP_Error( 'import_file_error', $message );
|
1838 |
-
}
|
1839 |
-
|
1840 |
-
return $upload;
|
1841 |
-
}
|
1842 |
-
|
1843 |
-
protected function post_process() {
|
1844 |
-
// Time to tackle any left-over bits
|
1845 |
-
if ( ! empty( $this->requires_remapping['post'] ) ) {
|
1846 |
-
$this->post_process_posts( $this->requires_remapping['post'] );
|
1847 |
-
}
|
1848 |
-
if ( ! empty( $this->requires_remapping['comment'] ) ) {
|
1849 |
-
$this->post_process_comments( $this->requires_remapping['comment'] );
|
1850 |
-
}
|
1851 |
-
}
|
1852 |
-
|
1853 |
-
protected function post_process_posts( $todo ) {
|
1854 |
-
foreach ( $todo as $post_id => $_ ) {
|
1855 |
-
$this->logger->debug( sprintf(
|
1856 |
-
// Note: title intentionally not used to skip extra processing
|
1857 |
-
// for when debug logging is off
|
1858 |
-
__( 'Running post-processing for post %d', 'wordpress-importer' ),
|
1859 |
-
$post_id
|
1860 |
-
) );
|
1861 |
-
|
1862 |
-
$data = array();
|
1863 |
-
|
1864 |
-
$parent_id = get_post_meta( $post_id, '_wxr_import_parent', true );
|
1865 |
-
if ( ! empty( $parent_id ) ) {
|
1866 |
-
// Have we imported the parent now?
|
1867 |
-
if ( isset( $this->mapping['post'][ $parent_id ] ) ) {
|
1868 |
-
$data['post_parent'] = $this->mapping['post'][ $parent_id ];
|
1869 |
-
} else {
|
1870 |
-
$this->logger->warning( sprintf(
|
1871 |
-
__( 'Could not find the post parent for "%1$s" (post #%2$d)', 'wordpress-importer' ),
|
1872 |
-
get_the_title( $post_id ),
|
1873 |
-
$post_id
|
1874 |
-
) );
|
1875 |
-
$this->logger->debug( sprintf(
|
1876 |
-
__( 'Post %1$d was imported with parent %2$d, but could not be found', 'wordpress-importer' ),
|
1877 |
-
$post_id,
|
1878 |
-
$parent_id
|
1879 |
-
) );
|
1880 |
-
}
|
1881 |
-
}
|
1882 |
-
|
1883 |
-
$author_slug = get_post_meta( $post_id, '_wxr_import_user_slug', true );
|
1884 |
-
if ( ! empty( $author_slug ) ) {
|
1885 |
-
// Have we imported the user now?
|
1886 |
-
if ( isset( $this->mapping['user_slug'][ $author_slug ] ) ) {
|
1887 |
-
$data['post_author'] = $this->mapping['user_slug'][ $author_slug ];
|
1888 |
-
} else {
|
1889 |
-
$this->logger->warning( sprintf(
|
1890 |
-
__( 'Could not find the author for "%1$s" (post #%2$d)', 'wordpress-importer' ),
|
1891 |
-
get_the_title( $post_id ),
|
1892 |
-
$post_id
|
1893 |
-
) );
|
1894 |
-
$this->logger->debug( sprintf(
|
1895 |
-
__( 'Post %1$d was imported with author "%2$s", but could not be found', 'wordpress-importer' ),
|
1896 |
-
$post_id,
|
1897 |
-
$author_slug
|
1898 |
-
) );
|
1899 |
-
}
|
1900 |
-
}
|
1901 |
-
|
1902 |
-
$has_attachments = get_post_meta( $post_id, '_wxr_import_has_attachment_refs', true );
|
1903 |
-
if ( ! empty( $has_attachments ) ) {
|
1904 |
-
$post = get_post( $post_id );
|
1905 |
-
$content = $post->post_content;
|
1906 |
-
|
1907 |
-
// Replace all the URLs we've got
|
1908 |
-
$new_content = str_replace( array_keys( $this->url_remap ), $this->url_remap, $content );
|
1909 |
-
if ( $new_content !== $content ) {
|
1910 |
-
$data['post_content'] = $new_content;
|
1911 |
-
}
|
1912 |
-
}
|
1913 |
-
|
1914 |
-
if ( get_post_type( $post_id ) === 'nav_menu_item' ) {
|
1915 |
-
$this->post_process_menu_item( $post_id );
|
1916 |
-
}
|
1917 |
-
|
1918 |
-
// Do we have updates to make?
|
1919 |
-
if ( empty( $data ) ) {
|
1920 |
-
$this->logger->debug( sprintf(
|
1921 |
-
__( 'Post %d was marked for post-processing, but none was required.', 'wordpress-importer' ),
|
1922 |
-
$post_id
|
1923 |
-
) );
|
1924 |
-
continue;
|
1925 |
-
}
|
1926 |
-
|
1927 |
-
// Run the update
|
1928 |
-
$data['ID'] = $post_id;
|
1929 |
-
$result = wp_update_post( $data, true );
|
1930 |
-
if ( is_wp_error( $result ) ) {
|
1931 |
-
$this->logger->warning( sprintf(
|
1932 |
-
__( 'Could not update "%1$s" (post #%2$d) with mapped data', 'wordpress-importer' ),
|
1933 |
-
get_the_title( $post_id ),
|
1934 |
-
$post_id
|
1935 |
-
) );
|
1936 |
-
$this->logger->debug( $result->get_error_message() );
|
1937 |
-
continue;
|
1938 |
-
}
|
1939 |
-
|
1940 |
-
// Clear out our temporary meta keys
|
1941 |
-
delete_post_meta( $post_id, '_wxr_import_parent' );
|
1942 |
-
delete_post_meta( $post_id, '_wxr_import_user_slug' );
|
1943 |
-
delete_post_meta( $post_id, '_wxr_import_has_attachment_refs' );
|
1944 |
-
}// End foreach().
|
1945 |
-
}
|
1946 |
-
|
1947 |
-
protected function post_process_menu_item( $post_id ) {
|
1948 |
-
$menu_object_id = get_post_meta( $post_id, '_wxr_import_menu_item', true );
|
1949 |
-
if ( empty( $menu_object_id ) ) {
|
1950 |
-
// No processing needed!
|
1951 |
-
return;
|
1952 |
-
}
|
1953 |
-
|
1954 |
-
$menu_item_type = get_post_meta( $post_id, '_menu_item_type', true );
|
1955 |
-
switch ( $menu_item_type ) {
|
1956 |
-
case 'taxonomy':
|
1957 |
-
if ( isset( $this->mapping['term_id'][ $menu_object_id ] ) ) {
|
1958 |
-
$menu_object = $this->mapping['term_id'][ $menu_object_id ];
|
1959 |
-
}
|
1960 |
-
break;
|
1961 |
-
|
1962 |
-
case 'post_type':
|
1963 |
-
if ( isset( $this->mapping['post'][ $menu_object_id ] ) ) {
|
1964 |
-
$menu_object = $this->mapping['post'][ $menu_object_id ];
|
1965 |
-
}
|
1966 |
-
break;
|
1967 |
-
|
1968 |
-
default:
|
1969 |
-
// Cannot handle this.
|
1970 |
-
return;
|
1971 |
-
}
|
1972 |
-
|
1973 |
-
if ( ! empty( $menu_object ) ) {
|
1974 |
-
update_post_meta( $post_id, '_menu_item_object_id', wp_slash( $menu_object ) );
|
1975 |
-
} else {
|
1976 |
-
$this->logger->warning( sprintf(
|
1977 |
-
__( 'Could not find the menu object for "%1$s" (post #%2$d)', 'wordpress-importer' ),
|
1978 |
-
get_the_title( $post_id ),
|
1979 |
-
$post_id
|
1980 |
-
) );
|
1981 |
-
$this->logger->debug( sprintf(
|
1982 |
-
__( 'Post %1$d was imported with object "%2$d" of type "%3$s", but could not be found', 'wordpress-importer' ),
|
1983 |
-
$post_id,
|
1984 |
-
$menu_object_id,
|
1985 |
-
$menu_item_type
|
1986 |
-
) );
|
1987 |
-
}
|
1988 |
-
|
1989 |
-
delete_post_meta( $post_id, '_wxr_import_menu_item' );
|
1990 |
-
}
|
1991 |
-
|
1992 |
-
|
1993 |
-
protected function post_process_comments( $todo ) {
|
1994 |
-
foreach ( $todo as $comment_id => $_ ) {
|
1995 |
-
$data = array();
|
1996 |
-
|
1997 |
-
$parent_id = get_comment_meta( $comment_id, '_wxr_import_parent', true );
|
1998 |
-
if ( ! empty( $parent_id ) ) {
|
1999 |
-
// Have we imported the parent now?
|
2000 |
-
if ( isset( $this->mapping['comment'][ $parent_id ] ) ) {
|
2001 |
-
$data['comment_parent'] = $this->mapping['comment'][ $parent_id ];
|
2002 |
-
} else {
|
2003 |
-
$this->logger->warning( sprintf(
|
2004 |
-
__( 'Could not find the comment parent for comment #%d', 'wordpress-importer' ),
|
2005 |
-
$comment_id
|
2006 |
-
) );
|
2007 |
-
$this->logger->debug( sprintf(
|
2008 |
-
__( 'Comment %1$d was imported with parent %2$d, but could not be found', 'wordpress-importer' ),
|
2009 |
-
$comment_id,
|
2010 |
-
$parent_id
|
2011 |
-
) );
|
2012 |
-
}
|
2013 |
-
}
|
2014 |
-
|
2015 |
-
$author_id = get_comment_meta( $comment_id, '_wxr_import_user', true );
|
2016 |
-
if ( ! empty( $author_id ) ) {
|
2017 |
-
// Have we imported the user now?
|
2018 |
-
if ( isset( $this->mapping['user'][ $author_id ] ) ) {
|
2019 |
-
$data['user_id'] = $this->mapping['user'][ $author_id ];
|
2020 |
-
} else {
|
2021 |
-
$this->logger->warning( sprintf(
|
2022 |
-
__( 'Could not find the author for comment #%d', 'wordpress-importer' ),
|
2023 |
-
$comment_id
|
2024 |
-
) );
|
2025 |
-
$this->logger->debug( sprintf(
|
2026 |
-
__( 'Comment %1$d was imported with author %2$d, but could not be found', 'wordpress-importer' ),
|
2027 |
-
$comment_id,
|
2028 |
-
$author_id
|
2029 |
-
) );
|
2030 |
-
}
|
2031 |
-
}
|
2032 |
-
|
2033 |
-
// Do we have updates to make?
|
2034 |
-
if ( empty( $data ) ) {
|
2035 |
-
continue;
|
2036 |
-
}
|
2037 |
-
|
2038 |
-
// Run the update
|
2039 |
-
$data['comment_ID'] = $comment_ID;
|
2040 |
-
$result = wp_update_comment( wp_slash( $data ) );
|
2041 |
-
if ( empty( $result ) ) {
|
2042 |
-
$this->logger->warning( sprintf(
|
2043 |
-
__( 'Could not update comment #%d with mapped data', 'wordpress-importer' ),
|
2044 |
-
$comment_id
|
2045 |
-
) );
|
2046 |
-
continue;
|
2047 |
-
}
|
2048 |
-
|
2049 |
-
// Clear out our temporary meta keys
|
2050 |
-
delete_comment_meta( $comment_id, '_wxr_import_parent' );
|
2051 |
-
delete_comment_meta( $comment_id, '_wxr_import_user' );
|
2052 |
-
}// End foreach().
|
2053 |
-
}
|
2054 |
-
|
2055 |
-
/**
|
2056 |
-
* Use stored mapping information to update old attachment URLs
|
2057 |
-
*/
|
2058 |
-
protected function replace_attachment_urls_in_content() {
|
2059 |
-
global $wpdb;
|
2060 |
-
// make sure we do the longest urls first, in case one is a substring of another
|
2061 |
-
uksort( $this->url_remap, array( $this, 'cmpr_strlen' ) );
|
2062 |
-
|
2063 |
-
foreach ( $this->url_remap as $from_url => $to_url ) {
|
2064 |
-
// remap urls in post_content
|
2065 |
-
$query = $wpdb->prepare( "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url );
|
2066 |
-
$wpdb->query( $query );
|
2067 |
-
|
2068 |
-
// remap enclosure urls
|
2069 |
-
$query = $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url );
|
2070 |
-
$result = $wpdb->query( $query );
|
2071 |
-
}
|
2072 |
-
}
|
2073 |
-
|
2074 |
-
/**
|
2075 |
-
* Update _thumbnail_id meta to new, imported attachment IDs
|
2076 |
-
*/
|
2077 |
-
function remap_featured_images() {
|
2078 |
-
// cycle through posts that have a featured image
|
2079 |
-
foreach ( $this->featured_images as $post_id => $value ) {
|
2080 |
-
if ( isset( $this->processed_posts[ $value ] ) ) {
|
2081 |
-
$new_id = $this->processed_posts[ $value ];
|
2082 |
-
|
2083 |
-
// only update if there's a difference
|
2084 |
-
if ( $new_id !== $value ) {
|
2085 |
-
update_post_meta( $post_id, '_thumbnail_id', $new_id );
|
2086 |
-
}
|
2087 |
-
}
|
2088 |
-
}
|
2089 |
-
}
|
2090 |
-
|
2091 |
-
/**
|
2092 |
-
* Decide if the given meta key maps to information we will want to import
|
2093 |
-
*
|
2094 |
-
* @param string $key The meta key to check
|
2095 |
-
* @return string|bool The key if we do want to import, false if not
|
2096 |
-
*/
|
2097 |
-
public function is_valid_meta_key( $key ) {
|
2098 |
-
// skip attachment metadata since we'll regenerate it from scratch
|
2099 |
-
// skip _edit_lock as not relevant for import
|
2100 |
-
if ( in_array( $key, array( '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock' ) ) ) {
|
2101 |
-
return false;
|
2102 |
-
}
|
2103 |
-
|
2104 |
-
return $key;
|
2105 |
-
}
|
2106 |
-
|
2107 |
-
/**
|
2108 |
-
* Decide what the maximum file size for downloaded attachments is.
|
2109 |
-
* Default is 0 (unlimited), can be filtered via import_attachment_size_limit
|
2110 |
-
*
|
2111 |
-
* @return int Maximum attachment file size to import
|
2112 |
-
*/
|
2113 |
-
protected function max_attachment_size() {
|
2114 |
-
return apply_filters( 'import_attachment_size_limit', 0 );
|
2115 |
-
}
|
2116 |
-
|
2117 |
-
/**
|
2118 |
-
* Added to http_request_timeout filter to force timeout at 60 seconds during import
|
2119 |
-
*
|
2120 |
-
* @access protected
|
2121 |
-
* @return int 60
|
2122 |
-
*/
|
2123 |
-
function bump_request_timeout( $val ) {
|
2124 |
-
return 60;
|
2125 |
-
}
|
2126 |
-
|
2127 |
-
// return the difference in length between two strings
|
2128 |
-
function cmpr_strlen( $a, $b ) {
|
2129 |
-
return strlen( $b ) - strlen( $a );
|
2130 |
-
}
|
2131 |
-
|
2132 |
-
/**
|
2133 |
-
* Prefill existing post data.
|
2134 |
-
*
|
2135 |
-
* This preloads all GUIDs into memory, allowing us to avoid hitting the
|
2136 |
-
* database when we need to check for existence. With larger imports, this
|
2137 |
-
* becomes prohibitively slow to perform SELECT queries on each.
|
2138 |
-
*
|
2139 |
-
* By preloading all this data into memory, it's a constant-time lookup in
|
2140 |
-
* PHP instead. However, this does use a lot more memory, so for sites doing
|
2141 |
-
* small imports onto a large site, it may be a better tradeoff to use
|
2142 |
-
* on-the-fly checking instead.
|
2143 |
-
*/
|
2144 |
-
protected function prefill_existing_posts() {
|
2145 |
-
global $wpdb;
|
2146 |
-
$posts = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts}" );
|
2147 |
-
|
2148 |
-
foreach ( $posts as $item ) {
|
2149 |
-
$this->exists['post'][ $item->guid ] = $item->ID;
|
2150 |
-
}
|
2151 |
-
}
|
2152 |
-
|
2153 |
-
/**
|
2154 |
-
* Does the post exist?
|
2155 |
-
*
|
2156 |
-
* @param array $data Post data to check against.
|
2157 |
-
* @return int|bool Existing post ID if it exists, false otherwise.
|
2158 |
-
*/
|
2159 |
-
protected function post_exists( $data ) {
|
2160 |
-
// Constant-time lookup if we prefilled
|
2161 |
-
$exists_key = $data['guid'];
|
2162 |
-
|
2163 |
-
if ( $this->options['prefill_existing_posts'] ) {
|
2164 |
-
return isset( $this->exists['post'][ $exists_key ] ) ? $this->exists['post'][ $exists_key ] : false;
|
2165 |
-
}
|
2166 |
-
|
2167 |
-
// No prefilling, but might have already handled it
|
2168 |
-
if ( isset( $this->exists['post'][ $exists_key ] ) ) {
|
2169 |
-
return $this->exists['post'][ $exists_key ];
|
2170 |
-
}
|
2171 |
-
|
2172 |
-
// Still nothing, try post_exists, and cache it
|
2173 |
-
$exists = post_exists( $data['post_title'], $data['post_content'], $data['post_date'] );
|
2174 |
-
$this->exists['post'][ $exists_key ] = $exists;
|
2175 |
-
|
2176 |
-
return $exists;
|
2177 |
-
}
|
2178 |
-
|
2179 |
-
/**
|
2180 |
-
* Mark the post as existing.
|
2181 |
-
*
|
2182 |
-
* @param array $data Post data to mark as existing.
|
2183 |
-
* @param int $post_id Post ID.
|
2184 |
-
*/
|
2185 |
-
protected function mark_post_exists( $data, $post_id ) {
|
2186 |
-
$exists_key = $data['guid'];
|
2187 |
-
$this->exists['post'][ $exists_key ] = $post_id;
|
2188 |
-
}
|
2189 |
-
|
2190 |
-
/**
|
2191 |
-
* Prefill existing comment data.
|
2192 |
-
*
|
2193 |
-
* @see self::prefill_existing_posts() for justification of why this exists.
|
2194 |
-
*/
|
2195 |
-
protected function prefill_existing_comments() {
|
2196 |
-
global $wpdb;
|
2197 |
-
$posts = $wpdb->get_results( "SELECT comment_ID, comment_author, comment_date FROM {$wpdb->comments}" );
|
2198 |
-
|
2199 |
-
foreach ( $posts as $item ) {
|
2200 |
-
$exists_key = sha1( $item->comment_author . ':' . $item->comment_date );
|
2201 |
-
$this->exists['comment'][ $exists_key ] = $item->comment_ID;
|
2202 |
-
}
|
2203 |
-
}
|
2204 |
-
|
2205 |
-
/**
|
2206 |
-
* Does the comment exist?
|
2207 |
-
*
|
2208 |
-
* @param array $data Comment data to check against.
|
2209 |
-
* @return int|bool Existing comment ID if it exists, false otherwise.
|
2210 |
-
*/
|
2211 |
-
protected function comment_exists( $data ) {
|
2212 |
-
$exists_key = sha1( $data['comment_author'] . ':' . $data['comment_date'] );
|
2213 |
-
|
2214 |
-
// Constant-time lookup if we prefilled
|
2215 |
-
if ( $this->options['prefill_existing_comments'] ) {
|
2216 |
-
return isset( $this->exists['comment'][ $exists_key ] ) ? $this->exists['comment'][ $exists_key ] : false;
|
2217 |
-
}
|
2218 |
-
|
2219 |
-
// No prefilling, but might have already handled it
|
2220 |
-
if ( isset( $this->exists['comment'][ $exists_key ] ) ) {
|
2221 |
-
return $this->exists['comment'][ $exists_key ];
|
2222 |
-
}
|
2223 |
-
|
2224 |
-
// Still nothing, try comment_exists, and cache it
|
2225 |
-
$exists = comment_exists( $data['comment_author'], $data['comment_date'] );
|
2226 |
-
$this->exists['comment'][ $exists_key ] = $exists;
|
2227 |
-
|
2228 |
-
return $exists;
|
2229 |
-
}
|
2230 |
-
|
2231 |
-
/**
|
2232 |
-
* Mark the comment as existing.
|
2233 |
-
*
|
2234 |
-
* @param array $data Comment data to mark as existing.
|
2235 |
-
* @param int $comment_id Comment ID.
|
2236 |
-
*/
|
2237 |
-
protected function mark_comment_exists( $data, $comment_id ) {
|
2238 |
-
$exists_key = sha1( $data['comment_author'] . ':' . $data['comment_date'] );
|
2239 |
-
$this->exists['comment'][ $exists_key ] = $comment_id;
|
2240 |
-
}
|
2241 |
-
|
2242 |
-
/**
|
2243 |
-
* Prefill existing term data.
|
2244 |
-
*
|
2245 |
-
* @see self::prefill_existing_posts() for justification of why this exists.
|
2246 |
-
*/
|
2247 |
-
protected function prefill_existing_terms() {
|
2248 |
-
global $wpdb;
|
2249 |
-
$query = "SELECT t.term_id, tt.taxonomy, t.slug FROM {$wpdb->terms} AS t";
|
2250 |
-
$query .= " JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id";
|
2251 |
-
$terms = $wpdb->get_results( $query );
|
2252 |
-
|
2253 |
-
foreach ( $terms as $item ) {
|
2254 |
-
$exists_key = sha1( $item->taxonomy . ':' . $item->slug );
|
2255 |
-
$this->exists['term'][ $exists_key ] = $item->term_id;
|
2256 |
-
}
|
2257 |
-
}
|
2258 |
-
|
2259 |
-
/**
|
2260 |
-
* Does the term exist?
|
2261 |
-
*
|
2262 |
-
* @param array $data Term data to check against.
|
2263 |
-
* @return int|bool Existing term ID if it exists, false otherwise.
|
2264 |
-
*/
|
2265 |
-
protected function term_exists( $data ) {
|
2266 |
-
$exists_key = sha1( $data['taxonomy'] . ':' . $data['slug'] );
|
2267 |
-
|
2268 |
-
// Constant-time lookup if we prefilled
|
2269 |
-
if ( $this->options['prefill_existing_terms'] ) {
|
2270 |
-
return isset( $this->exists['term'][ $exists_key ] ) ? $this->exists['term'][ $exists_key ] : false;
|
2271 |
-
}
|
2272 |
-
|
2273 |
-
// No prefilling, but might have already handled it
|
2274 |
-
if ( isset( $this->exists['term'][ $exists_key ] ) ) {
|
2275 |
-
return $this->exists['term'][ $exists_key ];
|
2276 |
-
}
|
2277 |
-
|
2278 |
-
// Still nothing, try comment_exists, and cache it
|
2279 |
-
$exists = term_exists( $data['slug'], $data['taxonomy'] );
|
2280 |
-
if ( is_array( $exists ) ) {
|
2281 |
-
$exists = $exists['term_id'];
|
2282 |
-
}
|
2283 |
-
|
2284 |
-
$this->exists['term'][ $exists_key ] = $exists;
|
2285 |
-
|
2286 |
-
return $exists;
|
2287 |
-
}
|
2288 |
-
|
2289 |
-
/**
|
2290 |
-
* Mark the term as existing.
|
2291 |
-
*
|
2292 |
-
* @param array $data Term data to mark as existing.
|
2293 |
-
* @param int $term_id Term ID.
|
2294 |
-
*/
|
2295 |
-
protected function mark_term_exists( $data, $term_id ) {
|
2296 |
-
$exists_key = sha1( $data['taxonomy'] . ':' . $data['slug'] );
|
2297 |
-
$this->exists['term'][ $exists_key ] = $term_id;
|
2298 |
-
}
|
2299 |
ย
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class WXR_Importer extends WP_Importer {
|
4 |
+
/**
|
5 |
+
* Maximum supported WXR version
|
6 |
+
*/
|
7 |
+
const MAX_WXR_VERSION = 1.2;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Regular expression for checking if a post references an attachment
|
11 |
+
*
|
12 |
+
* Note: This is a quick, weak check just to exclude text-only posts. More
|
13 |
+
* vigorous checking is done later to verify.
|
14 |
+
*/
|
15 |
+
const REGEX_HAS_ATTACHMENT_REFS = '!
|
16 |
+
(
|
17 |
+
# Match anything with an image or attachment class
|
18 |
+
class=[\'"].*?\b(wp-image-\d+|attachment-[\w\-]+)\b
|
19 |
+
|
|
20 |
+
# Match anything that looks like an upload URL
|
21 |
+
src=[\'"][^\'"]*(
|
22 |
+
[0-9]{4}/[0-9]{2}/[^\'"]+\.(jpg|jpeg|png|gif)
|
23 |
+
|
|
24 |
+
content/uploads[^\'"]+
|
25 |
+
)[\'"]
|
26 |
+
)!ix';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Version of WXR we're importing.
|
30 |
+
*
|
31 |
+
* Defaults to 1.0 for compatibility. Typically overridden by a
|
32 |
+
* `<wp:wxr_version>` tag at the start of the file.
|
33 |
+
*
|
34 |
+
* @var string
|
35 |
+
*/
|
36 |
+
protected $version = '1.0';
|
37 |
+
|
38 |
+
// information to import from WXR file
|
39 |
+
protected $categories = array();
|
40 |
+
protected $tags = array();
|
41 |
+
protected $base_url = '';
|
42 |
+
|
43 |
+
// TODO: REMOVE THESE
|
44 |
+
protected $processed_terms = array();
|
45 |
+
protected $processed_posts = array();
|
46 |
+
protected $processed_menu_items = array();
|
47 |
+
protected $menu_item_orphans = array();
|
48 |
+
protected $missing_menu_items = array();
|
49 |
+
|
50 |
+
// NEW STYLE
|
51 |
+
protected $mapping = array();
|
52 |
+
protected $requires_remapping = array();
|
53 |
+
protected $exists = array();
|
54 |
+
protected $user_slug_override = array();
|
55 |
+
|
56 |
+
protected $url_remap = array();
|
57 |
+
protected $featured_images = array();
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Logger instance.
|
61 |
+
*
|
62 |
+
* @var WP_Importer_Logger
|
63 |
+
*/
|
64 |
+
protected $logger;
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Constructor
|
68 |
+
*
|
69 |
+
* @param array $options {
|
70 |
+
* @var bool $prefill_existing_posts Should we prefill `post_exists` calls? (True prefills and uses more memory, false checks once per imported post and takes longer. Default is true.)
|
71 |
+
* @var bool $prefill_existing_comments Should we prefill `comment_exists` calls? (True prefills and uses more memory, false checks once per imported comment and takes longer. Default is true.)
|
72 |
+
* @var bool $prefill_existing_terms Should we prefill `term_exists` calls? (True prefills and uses more memory, false checks once per imported term and takes longer. Default is true.)
|
73 |
+
* @var bool $update_attachment_guids Should attachment GUIDs be updated to the new URL? (True updates the GUID, which keeps compatibility with v1, false doesn't update, and allows deduplication and reimporting. Default is false.)
|
74 |
+
* @var bool $fetch_attachments Fetch attachments from the remote server. (True fetches and creates attachment posts, false skips attachments. Default is false.)
|
75 |
+
* @var bool $aggressive_url_search Should we search/replace for URLs aggressively? (True searches all posts' content for old URLs and replaces, false checks for `<img class="wp-image-*">` only. Default is false.)
|
76 |
+
* @var int $default_author User ID to use if author is missing or invalid. (Default is null, which leaves posts unassigned.)
|
77 |
+
* }
|
78 |
+
*/
|
79 |
+
public function __construct( $options = array() ) {
|
80 |
+
// Initialize some important variables
|
81 |
+
$empty_types = array(
|
82 |
+
'post' => array(),
|
83 |
+
'comment' => array(),
|
84 |
+
'term' => array(),
|
85 |
+
'user' => array(),
|
86 |
+
);
|
87 |
+
|
88 |
+
$this->mapping = $empty_types;
|
89 |
+
$this->mapping['user_slug'] = array();
|
90 |
+
$this->mapping['term_id'] = array();
|
91 |
+
$this->requires_remapping = $empty_types;
|
92 |
+
$this->exists = $empty_types;
|
93 |
+
|
94 |
+
$this->options = wp_parse_args( $options, array(
|
95 |
+
'prefill_existing_posts' => true,
|
96 |
+
'prefill_existing_comments' => true,
|
97 |
+
'prefill_existing_terms' => true,
|
98 |
+
'update_attachment_guids' => false,
|
99 |
+
'fetch_attachments' => false,
|
100 |
+
'aggressive_url_search' => false,
|
101 |
+
'default_author' => null,
|
102 |
+
) );
|
103 |
+
}
|
104 |
+
|
105 |
+
public function set_logger( $logger ) {
|
106 |
+
$this->logger = $logger;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Get a stream reader for the file.
|
111 |
+
*
|
112 |
+
* @param string $file Path to the XML file.
|
113 |
+
* @return XMLReader|WP_Error Reader instance on success, error otherwise.
|
114 |
+
*/
|
115 |
+
protected function get_reader( $file ) {
|
116 |
+
// Avoid loading external entities for security
|
117 |
+
$old_value = null;
|
118 |
+
if ( function_exists( 'libxml_disable_entity_loader' ) ) {
|
119 |
+
// $old_value = libxml_disable_entity_loader( true );
|
120 |
+
}
|
121 |
+
|
122 |
+
$reader = new XMLReader();
|
123 |
+
$status = $reader->open( $file );
|
124 |
+
|
125 |
+
if ( ! is_null( $old_value ) ) {
|
126 |
+
// libxml_disable_entity_loader( $old_value );
|
127 |
+
}
|
128 |
+
|
129 |
+
if ( ! $status ) {
|
130 |
+
return new WP_Error( 'wxr_importer.cannot_parse', __( 'Could not open the file for parsing', 'wordpress-importer' ) );
|
131 |
+
}
|
132 |
+
|
133 |
+
return $reader;
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* The main controller for the actual import stage.
|
138 |
+
*
|
139 |
+
* @param string $file Path to the WXR file for importing
|
140 |
+
*/
|
141 |
+
public function get_preliminary_information( $file ) {
|
142 |
+
// Let's run the actual importer now, woot
|
143 |
+
$reader = $this->get_reader( $file );
|
144 |
+
if ( is_wp_error( $reader ) ) {
|
145 |
+
return $reader;
|
146 |
+
}
|
147 |
+
|
148 |
+
// Set the version to compatibility mode first
|
149 |
+
$this->version = '1.0';
|
150 |
+
|
151 |
+
// Start parsing!
|
152 |
+
$data = new WXR_Import_Info();
|
153 |
+
while ( $reader->read() ) {
|
154 |
+
// Only deal with element opens
|
155 |
+
if ( $reader->nodeType !== XMLReader::ELEMENT ) {
|
156 |
+
continue;
|
157 |
+
}
|
158 |
+
|
159 |
+
switch ( $reader->name ) {
|
160 |
+
case 'wp:wxr_version':
|
161 |
+
// Upgrade to the correct version
|
162 |
+
$this->version = $reader->readString();
|
163 |
+
|
164 |
+
if ( version_compare( $this->version, self::MAX_WXR_VERSION, '>' ) ) {
|
165 |
+
$this->logger->warning( sprintf(
|
166 |
+
__( 'This WXR file (version %1$s) is newer than the importer (version %2$s) and may not be supported. Please consider updating.', 'wordpress-importer' ),
|
167 |
+
$this->version,
|
168 |
+
self::MAX_WXR_VERSION
|
169 |
+
) );
|
170 |
+
}
|
171 |
+
|
172 |
+
// Handled everything in this node, move on to the next
|
173 |
+
$reader->next();
|
174 |
+
break;
|
175 |
+
|
176 |
+
case 'generator':
|
177 |
+
$data->generator = $reader->readString();
|
178 |
+
$reader->next();
|
179 |
+
break;
|
180 |
+
|
181 |
+
case 'title':
|
182 |
+
$data->title = $reader->readString();
|
183 |
+
$reader->next();
|
184 |
+
break;
|
185 |
+
|
186 |
+
case 'wp:base_site_url':
|
187 |
+
$data->siteurl = $reader->readString();
|
188 |
+
$reader->next();
|
189 |
+
break;
|
190 |
+
|
191 |
+
case 'wp:base_blog_url':
|
192 |
+
$data->home = $reader->readString();
|
193 |
+
$reader->next();
|
194 |
+
break;
|
195 |
+
|
196 |
+
case 'wp:author':
|
197 |
+
$node = $reader->expand();
|
198 |
+
|
199 |
+
$parsed = $this->parse_author_node( $node );
|
200 |
+
if ( is_wp_error( $parsed ) ) {
|
201 |
+
$this->log_error( $parsed );
|
202 |
+
|
203 |
+
// Skip the rest of this post
|
204 |
+
$reader->next();
|
205 |
+
break;
|
206 |
+
}
|
207 |
+
|
208 |
+
$data->users[] = $parsed;
|
209 |
+
|
210 |
+
// Handled everything in this node, move on to the next
|
211 |
+
$reader->next();
|
212 |
+
break;
|
213 |
+
|
214 |
+
case 'item':
|
215 |
+
$node = $reader->expand();
|
216 |
+
$parsed = $this->parse_post_node( $node );
|
217 |
+
if ( is_wp_error( $parsed ) ) {
|
218 |
+
$this->log_error( $parsed );
|
219 |
+
|
220 |
+
// Skip the rest of this post
|
221 |
+
$reader->next();
|
222 |
+
break;
|
223 |
+
}
|
224 |
+
|
225 |
+
if ( $parsed['data']['post_type'] === 'attachment' ) {
|
226 |
+
$data->media_count++;
|
227 |
+
} else {
|
228 |
+
$data->post_count++;
|
229 |
+
}
|
230 |
+
$data->comment_count += count( $parsed['comments'] );
|
231 |
+
|
232 |
+
// Handled everything in this node, move on to the next
|
233 |
+
$reader->next();
|
234 |
+
break;
|
235 |
+
|
236 |
+
case 'wp:category':
|
237 |
+
case 'wp:tag':
|
238 |
+
case 'wp:term':
|
239 |
+
$data->term_count++;
|
240 |
+
|
241 |
+
// Handled everything in this node, move on to the next
|
242 |
+
$reader->next();
|
243 |
+
break;
|
244 |
+
}// End switch().
|
245 |
+
}// End while().
|
246 |
+
|
247 |
+
$data->version = $this->version;
|
248 |
+
|
249 |
+
return $data;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* The main controller for the actual import stage.
|
254 |
+
*
|
255 |
+
* @param string $file Path to the WXR file for importing
|
256 |
+
*/
|
257 |
+
public function parse_authors( $file ) {
|
258 |
+
// Let's run the actual importer now, woot
|
259 |
+
$reader = $this->get_reader( $file );
|
260 |
+
if ( is_wp_error( $reader ) ) {
|
261 |
+
return $reader;
|
262 |
+
}
|
263 |
+
|
264 |
+
// Set the version to compatibility mode first
|
265 |
+
$this->version = '1.0';
|
266 |
+
|
267 |
+
// Start parsing!
|
268 |
+
$authors = array();
|
269 |
+
while ( $reader->read() ) {
|
270 |
+
// Only deal with element opens
|
271 |
+
if ( $reader->nodeType !== XMLReader::ELEMENT ) {
|
272 |
+
continue;
|
273 |
+
}
|
274 |
+
|
275 |
+
switch ( $reader->name ) {
|
276 |
+
case 'wp:wxr_version':
|
277 |
+
// Upgrade to the correct version
|
278 |
+
$this->version = $reader->readString();
|
279 |
+
|
280 |
+
if ( version_compare( $this->version, self::MAX_WXR_VERSION, '>' ) ) {
|
281 |
+
$this->logger->warning( sprintf(
|
282 |
+
__( 'This WXR file (version %1$s) is newer than the importer (version %2$s) and may not be supported. Please consider updating.', 'wordpress-importer' ),
|
283 |
+
$this->version,
|
284 |
+
self::MAX_WXR_VERSION
|
285 |
+
) );
|
286 |
+
}
|
287 |
+
|
288 |
+
// Handled everything in this node, move on to the next
|
289 |
+
$reader->next();
|
290 |
+
break;
|
291 |
+
|
292 |
+
case 'wp:author':
|
293 |
+
$node = $reader->expand();
|
294 |
+
|
295 |
+
$parsed = $this->parse_author_node( $node );
|
296 |
+
if ( is_wp_error( $parsed ) ) {
|
297 |
+
$this->log_error( $parsed );
|
298 |
+
|
299 |
+
// Skip the rest of this post
|
300 |
+
$reader->next();
|
301 |
+
break;
|
302 |
+
}
|
303 |
+
|
304 |
+
$authors[] = $parsed;
|
305 |
+
|
306 |
+
// Handled everything in this node, move on to the next
|
307 |
+
$reader->next();
|
308 |
+
break;
|
309 |
+
}
|
310 |
+
}// End while().
|
311 |
+
|
312 |
+
return $authors;
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* The main controller for the actual import stage.
|
317 |
+
*
|
318 |
+
* @param string $file Path to the WXR file for importing
|
319 |
+
*/
|
320 |
+
public function import( $file ) {
|
321 |
+
add_filter( 'import_post_meta_key', array( $this, 'is_valid_meta_key' ) );
|
322 |
+
add_filter( 'http_request_timeout', array( &$this, 'bump_request_timeout' ) );
|
323 |
+
|
324 |
+
$result = $this->import_start( $file );
|
325 |
+
if ( is_wp_error( $result ) ) {
|
326 |
+
return $result;
|
327 |
+
}
|
328 |
+
|
329 |
+
// Let's run the actual importer now, woot
|
330 |
+
$reader = $this->get_reader( $file );
|
331 |
+
if ( is_wp_error( $reader ) ) {
|
332 |
+
return $reader;
|
333 |
+
}
|
334 |
+
|
335 |
+
// Set the version to compatibility mode first
|
336 |
+
$this->version = '1.0';
|
337 |
+
|
338 |
+
// Reset other variables
|
339 |
+
$this->base_url = '';
|
340 |
+
|
341 |
+
// Start parsing!
|
342 |
+
while ( $reader->read() ) {
|
343 |
+
// Only deal with element opens
|
344 |
+
if ( $reader->nodeType !== XMLReader::ELEMENT ) {
|
345 |
+
continue;
|
346 |
+
}
|
347 |
+
|
348 |
+
switch ( $reader->name ) {
|
349 |
+
case 'wp:wxr_version':
|
350 |
+
// Upgrade to the correct version
|
351 |
+
$this->version = $reader->readString();
|
352 |
+
|
353 |
+
if ( version_compare( $this->version, self::MAX_WXR_VERSION, '>' ) ) {
|
354 |
+
$this->logger->warning( sprintf(
|
355 |
+
__( 'This WXR file (version %1$s) is newer than the importer (version %2$s) and may not be supported. Please consider updating.', 'wordpress-importer' ),
|
356 |
+
$this->version,
|
357 |
+
self::MAX_WXR_VERSION
|
358 |
+
) );
|
359 |
+
}
|
360 |
+
|
361 |
+
// Handled everything in this node, move on to the next
|
362 |
+
$reader->next();
|
363 |
+
break;
|
364 |
+
|
365 |
+
case 'wp:base_site_url':
|
366 |
+
$this->base_url = $reader->readString();
|
367 |
+
|
368 |
+
// Handled everything in this node, move on to the next
|
369 |
+
$reader->next();
|
370 |
+
break;
|
371 |
+
|
372 |
+
case 'item':
|
373 |
+
$node = $reader->expand();
|
374 |
+
$parsed = $this->parse_post_node( $node );
|
375 |
+
if ( is_wp_error( $parsed ) ) {
|
376 |
+
$this->log_error( $parsed );
|
377 |
+
|
378 |
+
// Skip the rest of this post
|
379 |
+
$reader->next();
|
380 |
+
break;
|
381 |
+
}
|
382 |
+
|
383 |
+
$this->process_post( $parsed['data'], $parsed['meta'], $parsed['comments'], $parsed['terms'] );
|
384 |
+
|
385 |
+
// Handled everything in this node, move on to the next
|
386 |
+
$reader->next();
|
387 |
+
break;
|
388 |
+
|
389 |
+
case 'wp:author':
|
390 |
+
$node = $reader->expand();
|
391 |
+
|
392 |
+
$parsed = $this->parse_author_node( $node );
|
393 |
+
if ( is_wp_error( $parsed ) ) {
|
394 |
+
$this->log_error( $parsed );
|
395 |
+
|
396 |
+
// Skip the rest of this post
|
397 |
+
$reader->next();
|
398 |
+
break;
|
399 |
+
}
|
400 |
+
|
401 |
+
$status = $this->process_author( $parsed['data'], $parsed['meta'] );
|
402 |
+
if ( is_wp_error( $status ) ) {
|
403 |
+
$this->log_error( $status );
|
404 |
+
}
|
405 |
+
|
406 |
+
// Handled everything in this node, move on to the next
|
407 |
+
$reader->next();
|
408 |
+
break;
|
409 |
+
|
410 |
+
case 'wp:category':
|
411 |
+
$node = $reader->expand();
|
412 |
+
|
413 |
+
$parsed = $this->parse_term_node( $node, 'category' );
|
414 |
+
if ( is_wp_error( $parsed ) ) {
|
415 |
+
$this->log_error( $parsed );
|
416 |
+
|
417 |
+
// Skip the rest of this post
|
418 |
+
$reader->next();
|
419 |
+
break;
|
420 |
+
}
|
421 |
+
|
422 |
+
$status = $this->process_term( $parsed['data'], $parsed['meta'] );
|
423 |
+
|
424 |
+
// Handled everything in this node, move on to the next
|
425 |
+
$reader->next();
|
426 |
+
break;
|
427 |
+
|
428 |
+
case 'wp:tag':
|
429 |
+
$node = $reader->expand();
|
430 |
+
|
431 |
+
$parsed = $this->parse_term_node( $node, 'tag' );
|
432 |
+
if ( is_wp_error( $parsed ) ) {
|
433 |
+
$this->log_error( $parsed );
|
434 |
+
|
435 |
+
// Skip the rest of this post
|
436 |
+
$reader->next();
|
437 |
+
break;
|
438 |
+
}
|
439 |
+
|
440 |
+
$status = $this->process_term( $parsed['data'], $parsed['meta'] );
|
441 |
+
|
442 |
+
// Handled everything in this node, move on to the next
|
443 |
+
$reader->next();
|
444 |
+
break;
|
445 |
+
|
446 |
+
case 'wp:term':
|
447 |
+
$node = $reader->expand();
|
448 |
+
|
449 |
+
$parsed = $this->parse_term_node( $node );
|
450 |
+
if ( is_wp_error( $parsed ) ) {
|
451 |
+
$this->log_error( $parsed );
|
452 |
+
|
453 |
+
// Skip the rest of this post
|
454 |
+
$reader->next();
|
455 |
+
break;
|
456 |
+
}
|
457 |
+
|
458 |
+
$status = $this->process_term( $parsed['data'], $parsed['meta'] );
|
459 |
+
|
460 |
+
// Handled everything in this node, move on to the next
|
461 |
+
$reader->next();
|
462 |
+
break;
|
463 |
+
|
464 |
+
default:
|
465 |
+
// Skip this node, probably handled by something already
|
466 |
+
break;
|
467 |
+
}// End switch().
|
468 |
+
}// End while().
|
469 |
+
|
470 |
+
// Now that we've done the main processing, do any required
|
471 |
+
// post-processing and remapping.
|
472 |
+
$this->post_process();
|
473 |
+
|
474 |
+
if ( $this->options['aggressive_url_search'] ) {
|
475 |
+
$this->replace_attachment_urls_in_content();
|
476 |
+
}
|
477 |
+
// $this->remap_featured_images();
|
478 |
+
$this->import_end();
|
479 |
+
}
|
480 |
+
|
481 |
+
/**
|
482 |
+
* Log an error instance to the logger.
|
483 |
+
*
|
484 |
+
* @param WP_Error $error Error instance to log.
|
485 |
+
*/
|
486 |
+
protected function log_error( WP_Error $error ) {
|
487 |
+
$this->logger->warning( $error->get_error_message() );
|
488 |
+
|
489 |
+
// Log the data as debug info too
|
490 |
+
$data = $error->get_error_data();
|
491 |
+
if ( ! empty( $data ) ) {
|
492 |
+
$this->logger->debug( var_export( $data, true ) );
|
493 |
+
}
|
494 |
+
}
|
495 |
+
|
496 |
+
/**
|
497 |
+
* Parses the WXR file and prepares us for the task of processing parsed data
|
498 |
+
*
|
499 |
+
* @param string $file Path to the WXR file for importing
|
500 |
+
*/
|
501 |
+
protected function import_start( $file ) {
|
502 |
+
if ( ! is_file( $file ) ) {
|
503 |
+
return new WP_Error( 'wxr_importer.file_missing', __( 'The file does not exist, please try again.', 'wordpress-importer' ) );
|
504 |
+
}
|
505 |
+
|
506 |
+
// Suspend bunches of stuff in WP core
|
507 |
+
wp_defer_term_counting( true );
|
508 |
+
wp_defer_comment_counting( true );
|
509 |
+
wp_suspend_cache_invalidation( true );
|
510 |
+
|
511 |
+
// Prefill exists calls if told to
|
512 |
+
if ( $this->options['prefill_existing_posts'] ) {
|
513 |
+
$this->prefill_existing_posts();
|
514 |
+
}
|
515 |
+
if ( $this->options['prefill_existing_comments'] ) {
|
516 |
+
$this->prefill_existing_comments();
|
517 |
+
}
|
518 |
+
if ( $this->options['prefill_existing_terms'] ) {
|
519 |
+
$this->prefill_existing_terms();
|
520 |
+
}
|
521 |
+
|
522 |
+
/**
|
523 |
+
* Begin the import.
|
524 |
+
*
|
525 |
+
* Fires before the import process has begun. If you need to suspend
|
526 |
+
* caching or heavy processing on hooks, do so here.
|
527 |
+
*/
|
528 |
+
do_action( 'import_start' );
|
529 |
+
}
|
530 |
+
|
531 |
+
/**
|
532 |
+
* Performs post-import cleanup of files and the cache
|
533 |
+
*/
|
534 |
+
protected function import_end() {
|
535 |
+
// Re-enable stuff in core
|
536 |
+
wp_suspend_cache_invalidation( false );
|
537 |
+
wp_cache_flush();
|
538 |
+
foreach ( get_taxonomies() as $tax ) {
|
539 |
+
delete_option( "{$tax}_children" );
|
540 |
+
_get_term_hierarchy( $tax );
|
541 |
+
}
|
542 |
+
|
543 |
+
wp_defer_term_counting( false );
|
544 |
+
wp_defer_comment_counting( false );
|
545 |
+
|
546 |
+
/**
|
547 |
+
* Complete the import.
|
548 |
+
*
|
549 |
+
* Fires after the import process has finished. If you need to update
|
550 |
+
* your cache or re-enable processing, do so here.
|
551 |
+
*/
|
552 |
+
do_action( 'import_end' );
|
553 |
+
}
|
554 |
+
|
555 |
+
/**
|
556 |
+
* Set the user mapping.
|
557 |
+
*
|
558 |
+
* @param array $mapping List of map arrays (containing `old_slug`, `old_id`, `new_id`)
|
559 |
+
*/
|
560 |
+
public function set_user_mapping( $mapping ) {
|
561 |
+
foreach ( $mapping as $map ) {
|
562 |
+
if ( empty( $map['old_slug'] ) || empty( $map['old_id'] ) || empty( $map['new_id'] ) ) {
|
563 |
+
$this->logger->warning( __( 'Invalid author mapping', 'wordpress-importer' ) );
|
564 |
+
$this->logger->debug( var_export( $map, true ) );
|
565 |
+
continue;
|
566 |
+
}
|
567 |
+
|
568 |
+
$old_slug = $map['old_slug'];
|
569 |
+
$old_id = $map['old_id'];
|
570 |
+
$new_id = $map['new_id'];
|
571 |
+
|
572 |
+
$this->mapping['user'][ $old_id ] = $new_id;
|
573 |
+
$this->mapping['user_slug'][ $old_slug ] = $new_id;
|
574 |
+
}
|
575 |
+
}
|
576 |
+
|
577 |
+
/**
|
578 |
+
* Set the user slug overrides.
|
579 |
+
*
|
580 |
+
* Allows overriding the slug in the import with a custom/renamed version.
|
581 |
+
*
|
582 |
+
* @param string[] $overrides Map of old slug to new slug.
|
583 |
+
*/
|
584 |
+
public function set_user_slug_overrides( $overrides ) {
|
585 |
+
foreach ( $overrides as $original => $renamed ) {
|
586 |
+
$this->user_slug_override[ $original ] = $renamed;
|
587 |
+
}
|
588 |
+
}
|
589 |
+
|
590 |
+
/**
|
591 |
+
* Parse a post node into post data.
|
592 |
+
*
|
593 |
+
* @param DOMElement $node Parent node of post data (typically `item`).
|
594 |
+
* @return array|WP_Error Post data array on success, error otherwise.
|
595 |
+
*/
|
596 |
+
protected function parse_post_node( $node ) {
|
597 |
+
$data = array();
|
598 |
+
$meta = array();
|
599 |
+
$comments = array();
|
600 |
+
$terms = array();
|
601 |
+
|
602 |
+
foreach ( $node->childNodes as $child ) {
|
603 |
+
// We only care about child elements
|
604 |
+
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
605 |
+
continue;
|
606 |
+
}
|
607 |
+
|
608 |
+
switch ( $child->tagName ) {
|
609 |
+
case 'wp:post_type':
|
610 |
+
$data['post_type'] = $child->textContent;
|
611 |
+
break;
|
612 |
+
|
613 |
+
case 'title':
|
614 |
+
$data['post_title'] = $child->textContent;
|
615 |
+
break;
|
616 |
+
|
617 |
+
case 'guid':
|
618 |
+
$data['guid'] = $child->textContent;
|
619 |
+
break;
|
620 |
+
|
621 |
+
case 'dc:creator':
|
622 |
+
$data['post_author'] = $child->textContent;
|
623 |
+
break;
|
624 |
+
|
625 |
+
case 'content:encoded':
|
626 |
+
$data['post_content'] = $child->textContent;
|
627 |
+
break;
|
628 |
+
|
629 |
+
case 'excerpt:encoded':
|
630 |
+
$data['post_excerpt'] = $child->textContent;
|
631 |
+
break;
|
632 |
+
|
633 |
+
case 'wp:post_id':
|
634 |
+
$data['post_id'] = $child->textContent;
|
635 |
+
break;
|
636 |
+
|
637 |
+
case 'wp:post_date':
|
638 |
+
$data['post_date'] = $child->textContent;
|
639 |
+
break;
|
640 |
+
|
641 |
+
case 'wp:post_date_gmt':
|
642 |
+
$data['post_date_gmt'] = $child->textContent;
|
643 |
+
break;
|
644 |
+
|
645 |
+
case 'wp:comment_status':
|
646 |
+
$data['comment_status'] = $child->textContent;
|
647 |
+
break;
|
648 |
+
|
649 |
+
case 'wp:ping_status':
|
650 |
+
$data['ping_status'] = $child->textContent;
|
651 |
+
break;
|
652 |
+
|
653 |
+
case 'wp:post_name':
|
654 |
+
$data['post_name'] = $child->textContent;
|
655 |
+
break;
|
656 |
+
|
657 |
+
case 'wp:status':
|
658 |
+
$data['post_status'] = $child->textContent;
|
659 |
+
|
660 |
+
if ( $data['post_status'] === 'auto-draft' ) {
|
661 |
+
// Bail now
|
662 |
+
return new WP_Error(
|
663 |
+
'wxr_importer.post.cannot_import_draft',
|
664 |
+
__( 'Cannot import auto-draft posts' ),
|
665 |
+
$data
|
666 |
+
);
|
667 |
+
}
|
668 |
+
break;
|
669 |
+
|
670 |
+
case 'wp:post_parent':
|
671 |
+
$data['post_parent'] = $child->textContent;
|
672 |
+
break;
|
673 |
+
|
674 |
+
case 'wp:menu_order':
|
675 |
+
$data['menu_order'] = $child->textContent;
|
676 |
+
break;
|
677 |
+
|
678 |
+
case 'wp:post_password':
|
679 |
+
$data['post_password'] = $child->textContent;
|
680 |
+
break;
|
681 |
+
|
682 |
+
case 'wp:is_sticky':
|
683 |
+
$data['is_sticky'] = $child->textContent;
|
684 |
+
break;
|
685 |
+
|
686 |
+
case 'wp:attachment_url':
|
687 |
+
$data['attachment_url'] = $child->textContent;
|
688 |
+
break;
|
689 |
+
|
690 |
+
case 'wp:postmeta':
|
691 |
+
$meta_item = $this->parse_meta_node( $child );
|
692 |
+
if ( ! empty( $meta_item ) ) {
|
693 |
+
$meta[] = $meta_item;
|
694 |
+
}
|
695 |
+
break;
|
696 |
+
|
697 |
+
case 'wp:comment':
|
698 |
+
$comment_item = $this->parse_comment_node( $child );
|
699 |
+
if ( ! empty( $comment_item ) ) {
|
700 |
+
$comments[] = $comment_item;
|
701 |
+
}
|
702 |
+
break;
|
703 |
+
|
704 |
+
case 'category':
|
705 |
+
$term_item = $this->parse_category_node( $child );
|
706 |
+
if ( ! empty( $term_item ) ) {
|
707 |
+
$terms[] = $term_item;
|
708 |
+
}
|
709 |
+
break;
|
710 |
+
}// End switch().
|
711 |
+
}// End foreach().
|
712 |
+
|
713 |
+
return compact( 'data', 'meta', 'comments', 'terms' );
|
714 |
+
}
|
715 |
+
|
716 |
+
/**
|
717 |
+
* Create new posts based on import information
|
718 |
+
*
|
719 |
+
* Posts marked as having a parent which doesn't exist will become top level items.
|
720 |
+
* Doesn't create a new post if: the post type doesn't exist, the given post ID
|
721 |
+
* is already noted as imported or a post with the same title and date already exists.
|
722 |
+
* Note that new/updated terms, comments and meta are imported for the last of the above.
|
723 |
+
*/
|
724 |
+
protected function process_post( $data, $meta, $comments, $terms ) {
|
725 |
+
/**
|
726 |
+
* Pre-process post data.
|
727 |
+
*
|
728 |
+
* @param array $data Post data. (Return empty to skip.)
|
729 |
+
* @param array $meta Meta data.
|
730 |
+
* @param array $comments Comments on the post.
|
731 |
+
* @param array $terms Terms on the post.
|
732 |
+
*/
|
733 |
+
$data = apply_filters( 'wxr_importer.pre_process.post', $data, $meta, $comments, $terms );
|
734 |
+
if ( empty( $data ) ) {
|
735 |
+
return false;
|
736 |
+
}
|
737 |
+
|
738 |
+
$original_id = isset( $data['post_id'] ) ? (int) $data['post_id'] : 0;
|
739 |
+
$parent_id = isset( $data['post_parent'] ) ? (int) $data['post_parent'] : 0;
|
740 |
+
$author_id = isset( $data['post_author'] ) ? (int) $data['post_author'] : 0;
|
741 |
+
|
742 |
+
// Have we already processed this?
|
743 |
+
if ( isset( $this->mapping['post'][ $original_id ] ) ) {
|
744 |
+
return;
|
745 |
+
}
|
746 |
+
|
747 |
+
$post_type_object = get_post_type_object( $data['post_type'] );
|
748 |
+
|
749 |
+
// Is this type even valid?
|
750 |
+
if ( ! $post_type_object ) {
|
751 |
+
$this->logger->warning( sprintf(
|
752 |
+
__( 'Failed to import "%1$s": Invalid post type %2$s', 'wordpress-importer' ),
|
753 |
+
$data['post_title'],
|
754 |
+
$data['post_type']
|
755 |
+
) );
|
756 |
+
return false;
|
757 |
+
}
|
758 |
+
|
759 |
+
$post_exists = $this->post_exists( $data );
|
760 |
+
if ( $post_exists ) {
|
761 |
+
$this->logger->info( sprintf(
|
762 |
+
__( '%1$s "%2$s" already exists.', 'wordpress-importer' ),
|
763 |
+
$post_type_object->labels->singular_name,
|
764 |
+
$data['post_title']
|
765 |
+
) );
|
766 |
+
|
767 |
+
/**
|
768 |
+
* Post processing already imported.
|
769 |
+
*
|
770 |
+
* @param array $data Raw data imported for the post.
|
771 |
+
*/
|
772 |
+
do_action( 'wxr_importer.process_already_imported.post', $data );
|
773 |
+
|
774 |
+
// Even though this post already exists, new comments might need importing
|
775 |
+
$this->process_comments( $comments, $original_id, $data, $post_exists );
|
776 |
+
|
777 |
+
return false;
|
778 |
+
}
|
779 |
+
|
780 |
+
// Map the parent post, or mark it as one we need to fix
|
781 |
+
$requires_remapping = false;
|
782 |
+
if ( $parent_id ) {
|
783 |
+
if ( isset( $this->mapping['post'][ $parent_id ] ) ) {
|
784 |
+
$data['post_parent'] = $this->mapping['post'][ $parent_id ];
|
785 |
+
} else {
|
786 |
+
$meta[] = array(
|
787 |
+
'key' => '_wxr_import_parent',
|
788 |
+
'value' => $parent_id,
|
789 |
+
);
|
790 |
+
$requires_remapping = true;
|
791 |
+
|
792 |
+
$data['post_parent'] = 0;
|
793 |
+
}
|
794 |
+
}
|
795 |
+
|
796 |
+
// Map the author, or mark it as one we need to fix
|
797 |
+
$author = sanitize_user( $data['post_author'], true );
|
798 |
+
if ( empty( $author ) ) {
|
799 |
+
// Missing or invalid author, use default if available.
|
800 |
+
$data['post_author'] = $this->options['default_author'];
|
801 |
+
} elseif ( isset( $this->mapping['user_slug'][ $author ] ) ) {
|
802 |
+
$data['post_author'] = $this->mapping['user_slug'][ $author ];
|
803 |
+
} else {
|
804 |
+
$meta[] = array(
|
805 |
+
'key' => '_wxr_import_user_slug',
|
806 |
+
'value' => $author,
|
807 |
+
);
|
808 |
+
$requires_remapping = true;
|
809 |
+
|
810 |
+
$data['post_author'] = (int) get_current_user_id();
|
811 |
+
}
|
812 |
+
|
813 |
+
// Does the post look like it contains attachment images?
|
814 |
+
if ( preg_match( self::REGEX_HAS_ATTACHMENT_REFS, $data['post_content'] ) ) {
|
815 |
+
$meta[] = array(
|
816 |
+
'key' => '_wxr_import_has_attachment_refs',
|
817 |
+
'value' => true,
|
818 |
+
);
|
819 |
+
$requires_remapping = true;
|
820 |
+
}
|
821 |
+
|
822 |
+
// Whitelist to just the keys we allow
|
823 |
+
$postdata = array(
|
824 |
+
'import_id' => $data['post_id'],
|
825 |
+
);
|
826 |
+
$allowed = array(
|
827 |
+
'post_author' => true,
|
828 |
+
'post_date' => true,
|
829 |
+
'post_date_gmt' => true,
|
830 |
+
'post_content' => true,
|
831 |
+
'post_excerpt' => true,
|
832 |
+
'post_title' => true,
|
833 |
+
'post_status' => true,
|
834 |
+
'post_name' => true,
|
835 |
+
'comment_status' => true,
|
836 |
+
'ping_status' => true,
|
837 |
+
'guid' => true,
|
838 |
+
'post_parent' => true,
|
839 |
+
'menu_order' => true,
|
840 |
+
'post_type' => true,
|
841 |
+
'post_password' => true,
|
842 |
+
);
|
843 |
+
foreach ( $data as $key => $value ) {
|
844 |
+
if ( ! isset( $allowed[ $key ] ) ) {
|
845 |
+
continue;
|
846 |
+
}
|
847 |
+
|
848 |
+
$postdata[ $key ] = $data[ $key ];
|
849 |
+
}
|
850 |
+
|
851 |
+
$postdata = apply_filters( 'wp_import_post_data_processed', $postdata, $data );
|
852 |
+
|
853 |
+
if ( 'attachment' === $postdata['post_type'] ) {
|
854 |
+
if ( ! $this->options['fetch_attachments'] ) {
|
855 |
+
$this->logger->notice( sprintf(
|
856 |
+
__( 'Skipping attachment "%s", fetching attachments disabled' ),
|
857 |
+
$data['post_title']
|
858 |
+
) );
|
859 |
+
/**
|
860 |
+
* Post processing skipped.
|
861 |
+
*
|
862 |
+
* @param array $data Raw data imported for the post.
|
863 |
+
* @param array $meta Raw meta data, already processed by {@see process_post_meta}.
|
864 |
+
*/
|
865 |
+
do_action( 'wxr_importer.process_skipped.post', $data, $meta );
|
866 |
+
return false;
|
867 |
+
}
|
868 |
+
$remote_url = ! empty( $data['attachment_url'] ) ? $data['attachment_url'] : $data['guid'];
|
869 |
+
$post_id = $this->process_attachment( $postdata, $meta, $remote_url );
|
870 |
+
} else {
|
871 |
+
$post_id = wp_insert_post( $postdata, true );
|
872 |
+
do_action( 'wp_import_insert_post', $post_id, $original_id, $postdata, $data );
|
873 |
+
}
|
874 |
+
|
875 |
+
if ( is_wp_error( $post_id ) ) {
|
876 |
+
$this->logger->error( sprintf(
|
877 |
+
__( 'Failed to import "%1$s" (%2$s)', 'wordpress-importer' ),
|
878 |
+
$data['post_title'],
|
879 |
+
$post_type_object->labels->singular_name
|
880 |
+
) );
|
881 |
+
$this->logger->debug( $post_id->get_error_message() );
|
882 |
+
|
883 |
+
/**
|
884 |
+
* Post processing failed.
|
885 |
+
*
|
886 |
+
* @param WP_Error $post_id Error object.
|
887 |
+
* @param array $data Raw data imported for the post.
|
888 |
+
* @param array $meta Raw meta data, already processed by {@see process_post_meta}.
|
889 |
+
* @param array $comments Raw comment data, already processed by {@see process_comments}.
|
890 |
+
* @param array $terms Raw term data, already processed.
|
891 |
+
*/
|
892 |
+
do_action( 'wxr_importer.process_failed.post', $post_id, $data, $meta, $comments, $terms );
|
893 |
+
return false;
|
894 |
+
}
|
895 |
+
|
896 |
+
// Ensure stickiness is handled correctly too
|
897 |
+
if ( $data['is_sticky'] === '1' ) {
|
898 |
+
stick_post( $post_id );
|
899 |
+
}
|
900 |
+
|
901 |
+
// map pre-import ID to local ID
|
902 |
+
$this->mapping['post'][ $original_id ] = (int) $post_id;
|
903 |
+
if ( $requires_remapping ) {
|
904 |
+
$this->requires_remapping['post'][ $post_id ] = true;
|
905 |
+
}
|
906 |
+
$this->mark_post_exists( $data, $post_id );
|
907 |
+
|
908 |
+
$this->logger->info( sprintf(
|
909 |
+
__( 'Imported "%1$s" (%2$s)', 'wordpress-importer' ),
|
910 |
+
$data['post_title'],
|
911 |
+
$post_type_object->labels->singular_name
|
912 |
+
) );
|
913 |
+
$this->logger->debug( sprintf(
|
914 |
+
__( 'Post %1$d remapped to %2$d', 'wordpress-importer' ),
|
915 |
+
$original_id,
|
916 |
+
$post_id
|
917 |
+
) );
|
918 |
+
|
919 |
+
// Handle the terms too
|
920 |
+
$terms = apply_filters( 'wp_import_post_terms', $terms, $post_id, $data );
|
921 |
+
|
922 |
+
if ( ! empty( $terms ) ) {
|
923 |
+
$term_ids = array();
|
924 |
+
foreach ( $terms as $term ) {
|
925 |
+
$taxonomy = $term['taxonomy'];
|
926 |
+
$key = sha1( $taxonomy . ':' . $term['slug'] );
|
927 |
+
|
928 |
+
if ( isset( $this->mapping['term'][ $key ] ) ) {
|
929 |
+
$term_ids[ $taxonomy ][] = (int) $this->mapping['term'][ $key ];
|
930 |
+
} else {
|
931 |
+
$meta[] = array(
|
932 |
+
'key' => '_wxr_import_term',
|
933 |
+
'value' => $term,
|
934 |
+
);
|
935 |
+
$requires_remapping = true;
|
936 |
+
}
|
937 |
+
}
|
938 |
+
|
939 |
+
foreach ( $term_ids as $tax => $ids ) {
|
940 |
+
$tt_ids = wp_set_post_terms( $post_id, $ids, $tax );
|
941 |
+
do_action( 'wp_import_set_post_terms', $tt_ids, $ids, $tax, $post_id, $data );
|
942 |
+
}
|
943 |
+
}
|
944 |
+
|
945 |
+
$this->process_comments( $comments, $post_id, $data );
|
946 |
+
$this->process_post_meta( $meta, $post_id, $data );
|
947 |
+
|
948 |
+
if ( 'nav_menu_item' === $data['post_type'] ) {
|
949 |
+
$this->process_menu_item_meta( $post_id, $data, $meta );
|
950 |
+
}
|
951 |
+
|
952 |
+
/**
|
953 |
+
* Post processing completed.
|
954 |
+
*
|
955 |
+
* @param int $post_id New post ID.
|
956 |
+
* @param array $data Raw data imported for the post.
|
957 |
+
* @param array $meta Raw meta data, already processed by {@see process_post_meta}.
|
958 |
+
* @param array $comments Raw comment data, already processed by {@see process_comments}.
|
959 |
+
* @param array $terms Raw term data, already processed.
|
960 |
+
*/
|
961 |
+
do_action( 'wxr_importer.processed.post', $post_id, $data, $meta, $comments, $terms );
|
962 |
+
}
|
963 |
+
|
964 |
+
/**
|
965 |
+
* Attempt to create a new menu item from import data
|
966 |
+
*
|
967 |
+
* Fails for draft, orphaned menu items and those without an associated nav_menu
|
968 |
+
* or an invalid nav_menu term. If the post type or term object which the menu item
|
969 |
+
* represents doesn't exist then the menu item will not be imported (waits until the
|
970 |
+
* end of the import to retry again before discarding).
|
971 |
+
*
|
972 |
+
* @param array $item Menu item details from WXR file
|
973 |
+
*/
|
974 |
+
protected function process_menu_item_meta( $post_id, $data, $meta ) {
|
975 |
+
|
976 |
+
$item_type = get_post_meta( $post_id, '_menu_item_type', true );
|
977 |
+
$original_object_id = get_post_meta( $post_id, '_menu_item_object_id', true );
|
978 |
+
$object_id = null;
|
979 |
+
|
980 |
+
$this->logger->debug( sprintf( 'Processing menu item %s', $item_type ) );
|
981 |
+
|
982 |
+
$requires_remapping = false;
|
983 |
+
switch ( $item_type ) {
|
984 |
+
case 'taxonomy':
|
985 |
+
if ( isset( $this->mapping['term_id'][ $original_object_id ] ) ) {
|
986 |
+
$object_id = $this->mapping['term_id'][ $original_object_id ];
|
987 |
+
} else {
|
988 |
+
add_post_meta( $post_id, '_wxr_import_menu_item', wp_slash( $original_object_id ) );
|
989 |
+
$requires_remapping = true;
|
990 |
+
}
|
991 |
+
break;
|
992 |
+
|
993 |
+
case 'post_type':
|
994 |
+
if ( isset( $this->mapping['post'][ $original_object_id ] ) ) {
|
995 |
+
$object_id = $this->mapping['post'][ $original_object_id ];
|
996 |
+
} else {
|
997 |
+
add_post_meta( $post_id, '_wxr_import_menu_item', wp_slash( $original_object_id ) );
|
998 |
+
$requires_remapping = true;
|
999 |
+
}
|
1000 |
+
break;
|
1001 |
+
|
1002 |
+
case 'custom':
|
1003 |
+
// Custom refers to itself, wonderfully easy.
|
1004 |
+
$object_id = $post_id;
|
1005 |
+
break;
|
1006 |
+
|
1007 |
+
default:
|
1008 |
+
// associated object is missing or not imported yet, we'll retry later
|
1009 |
+
$this->missing_menu_items[] = $item;
|
1010 |
+
$this->logger->debug( 'Unknown menu item type' );
|
1011 |
+
break;
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
if ( $requires_remapping ) {
|
1015 |
+
$this->requires_remapping['post'][ $post_id ] = true;
|
1016 |
+
}
|
1017 |
+
|
1018 |
+
if ( empty( $object_id ) ) {
|
1019 |
+
// Nothing needed here.
|
1020 |
+
return;
|
1021 |
+
}
|
1022 |
+
|
1023 |
+
$this->logger->debug( sprintf( 'Menu item %d mapped to %d', $original_object_id, $object_id ) );
|
1024 |
+
update_post_meta( $post_id, '_menu_item_object_id', wp_slash( $object_id ) );
|
1025 |
+
}
|
1026 |
+
|
1027 |
+
/**
|
1028 |
+
* If fetching attachments is enabled then attempt to create a new attachment
|
1029 |
+
*
|
1030 |
+
* @param array $post Attachment post details from WXR
|
1031 |
+
* @param string $url URL to fetch attachment from
|
1032 |
+
* @return int|WP_Error Post ID on success, WP_Error otherwise
|
1033 |
+
*/
|
1034 |
+
protected function process_attachment( $post, $meta, $remote_url ) {
|
1035 |
+
// try to use _wp_attached file for upload folder placement to ensure the same location as the export site
|
1036 |
+
// e.g. location is 2003/05/image.jpg but the attachment post_date is 2010/09, see media_handle_upload()
|
1037 |
+
$post['upload_date'] = $post['post_date'];
|
1038 |
+
foreach ( $meta as $meta_item ) {
|
1039 |
+
if ( $meta_item['key'] !== '_wp_attached_file' ) {
|
1040 |
+
continue;
|
1041 |
+
}
|
1042 |
+
|
1043 |
+
if ( preg_match( '%^[0-9]{4}/[0-9]{2}%', $meta_item['value'], $matches ) ) {
|
1044 |
+
$post['upload_date'] = $matches[0];
|
1045 |
+
}
|
1046 |
+
break;
|
1047 |
+
}
|
1048 |
+
|
1049 |
+
// if the URL is absolute, but does not contain address, then upload it assuming base_site_url
|
1050 |
+
if ( preg_match( '|^/[\w\W]+$|', $remote_url ) ) {
|
1051 |
+
$remote_url = rtrim( $this->base_url, '/' ) . $remote_url;
|
1052 |
+
}
|
1053 |
+
|
1054 |
+
$upload = $this->fetch_remote_file( $remote_url, $post );
|
1055 |
+
if ( is_wp_error( $upload ) ) {
|
1056 |
+
return $upload;
|
1057 |
+
}
|
1058 |
+
|
1059 |
+
$info = wp_check_filetype( $upload['file'] );
|
1060 |
+
if ( ! $info ) {
|
1061 |
+
return new WP_Error( 'attachment_processing_error', __( 'Invalid file type', 'wordpress-importer' ) );
|
1062 |
+
}
|
1063 |
+
|
1064 |
+
$post['post_mime_type'] = $info['type'];
|
1065 |
+
|
1066 |
+
// WP really likes using the GUID for display. Allow updating it.
|
1067 |
+
// See https://core.trac.wordpress.org/ticket/33386
|
1068 |
+
if ( $this->options['update_attachment_guids'] ) {
|
1069 |
+
$post['guid'] = $upload['url'];
|
1070 |
+
}
|
1071 |
+
|
1072 |
+
// as per wp-admin/includes/upload.php
|
1073 |
+
$post_id = wp_insert_attachment( $post, $upload['file'] );
|
1074 |
+
if ( is_wp_error( $post_id ) ) {
|
1075 |
+
return $post_id;
|
1076 |
+
}
|
1077 |
+
|
1078 |
+
$attachment_metadata = wp_generate_attachment_metadata( $post_id, $upload['file'] );
|
1079 |
+
wp_update_attachment_metadata( $post_id, $attachment_metadata );
|
1080 |
+
|
1081 |
+
// Map this image URL later if we need to
|
1082 |
+
$this->url_remap[ $remote_url ] = $upload['url'];
|
1083 |
+
|
1084 |
+
// If we have a HTTPS URL, ensure the HTTP URL gets replaced too
|
1085 |
+
if ( substr( $remote_url, 0, 8 ) === 'https://' ) {
|
1086 |
+
$insecure_url = 'http' . substr( $remote_url, 5 );
|
1087 |
+
$this->url_remap[ $insecure_url ] = $upload['url'];
|
1088 |
+
}
|
1089 |
+
|
1090 |
+
if ( $this->options['aggressive_url_search'] ) {
|
1091 |
+
// remap resized image URLs, works by stripping the extension and remapping the URL stub.
|
1092 |
+
/*
|
1093 |
+
if ( preg_match( '!^image/!', $info['type'] ) ) {
|
1094 |
+
$parts = pathinfo( $remote_url );
|
1095 |
+
$name = basename( $parts['basename'], ".{$parts['extension']}" ); // PATHINFO_FILENAME in PHP 5.2
|
1096 |
+
|
1097 |
+
$parts_new = pathinfo( $upload['url'] );
|
1098 |
+
$name_new = basename( $parts_new['basename'], ".{$parts_new['extension']}" );
|
1099 |
+
|
1100 |
+
$this->url_remap[$parts['dirname'] . '/' . $name] = $parts_new['dirname'] . '/' . $name_new;
|
1101 |
+
}*/
|
1102 |
+
}
|
1103 |
+
|
1104 |
+
return $post_id;
|
1105 |
+
}
|
1106 |
+
|
1107 |
+
/**
|
1108 |
+
* Parse a meta node into meta data.
|
1109 |
+
*
|
1110 |
+
* @param DOMElement $node Parent node of meta data (typically `wp:postmeta` or `wp:commentmeta`).
|
1111 |
+
* @return array|null Meta data array on success, or null on error.
|
1112 |
+
*/
|
1113 |
+
protected function parse_meta_node( $node ) {
|
1114 |
+
foreach ( $node->childNodes as $child ) {
|
1115 |
+
// We only care about child elements
|
1116 |
+
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
1117 |
+
continue;
|
1118 |
+
}
|
1119 |
+
|
1120 |
+
switch ( $child->tagName ) {
|
1121 |
+
case 'wp:meta_key':
|
1122 |
+
$key = $child->textContent;
|
1123 |
+
break;
|
1124 |
+
|
1125 |
+
case 'wp:meta_value':
|
1126 |
+
$value = $child->textContent;
|
1127 |
+
break;
|
1128 |
+
}
|
1129 |
+
}
|
1130 |
+
|
1131 |
+
if ( empty( $key ) || empty( $value ) ) {
|
1132 |
+
return null;
|
1133 |
+
}
|
1134 |
+
|
1135 |
+
return compact( 'key', 'value' );
|
1136 |
+
}
|
1137 |
+
|
1138 |
+
/**
|
1139 |
+
* Process and import post meta items.
|
1140 |
+
*
|
1141 |
+
* @param array $meta List of meta data arrays
|
1142 |
+
* @param int $post_id Post to associate with
|
1143 |
+
* @param array $post Post data
|
1144 |
+
* @return int|WP_Error Number of meta items imported on success, error otherwise.
|
1145 |
+
*/
|
1146 |
+
protected function process_post_meta( $meta, $post_id, $post ) {
|
1147 |
+
if ( empty( $meta ) ) {
|
1148 |
+
return true;
|
1149 |
+
}
|
1150 |
+
|
1151 |
+
foreach ( $meta as $meta_item ) {
|
1152 |
+
/**
|
1153 |
+
* Pre-process post meta data.
|
1154 |
+
*
|
1155 |
+
* @param array $meta_item Meta data. (Return empty to skip.)
|
1156 |
+
* @param int $post_id Post the meta is attached to.
|
1157 |
+
*/
|
1158 |
+
$meta_item = apply_filters( 'wxr_importer.pre_process.post_meta', $meta_item, $post_id );
|
1159 |
+
if ( empty( $meta_item ) ) {
|
1160 |
+
return false;
|
1161 |
+
}
|
1162 |
+
|
1163 |
+
$key = apply_filters( 'import_post_meta_key', $meta_item['key'], $post_id, $post );
|
1164 |
+
$value = false;
|
1165 |
+
|
1166 |
+
if ( '_edit_last' === $key ) {
|
1167 |
+
$value = intval( $meta_item['value'] );
|
1168 |
+
if ( ! isset( $this->mapping['user'][ $value ] ) ) {
|
1169 |
+
// Skip!
|
1170 |
+
continue;
|
1171 |
+
}
|
1172 |
+
|
1173 |
+
$value = $this->mapping['user'][ $value ];
|
1174 |
+
}
|
1175 |
+
|
1176 |
+
if ( $key ) {
|
1177 |
+
// export gets meta straight from the DB so could have a serialized string
|
1178 |
+
if ( ! $value ) {
|
1179 |
+
$value = maybe_unserialize( $meta_item['value'] );
|
1180 |
+
}
|
1181 |
+
|
1182 |
+
add_post_meta( $post_id, $key, $value );
|
1183 |
+
do_action( 'import_post_meta', $post_id, $key, $value );
|
1184 |
+
|
1185 |
+
// if the post has a featured image, take note of this in case of remap
|
1186 |
+
if ( '_thumbnail_id' === $key ) {
|
1187 |
+
$this->featured_images[ $post_id ] = (int) $value;
|
1188 |
+
}
|
1189 |
+
}
|
1190 |
+
}// End foreach().
|
1191 |
+
|
1192 |
+
return true;
|
1193 |
+
}
|
1194 |
+
|
1195 |
+
/**
|
1196 |
+
* Parse a comment node into comment data.
|
1197 |
+
*
|
1198 |
+
* @param DOMElement $node Parent node of comment data (typically `wp:comment`).
|
1199 |
+
* @return array Comment data array.
|
1200 |
+
*/
|
1201 |
+
protected function parse_comment_node( $node ) {
|
1202 |
+
$data = array(
|
1203 |
+
'commentmeta' => array(),
|
1204 |
+
);
|
1205 |
+
|
1206 |
+
foreach ( $node->childNodes as $child ) {
|
1207 |
+
// We only care about child elements
|
1208 |
+
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
1209 |
+
continue;
|
1210 |
+
}
|
1211 |
+
|
1212 |
+
switch ( $child->tagName ) {
|
1213 |
+
case 'wp:comment_id':
|
1214 |
+
$data['comment_id'] = $child->textContent;
|
1215 |
+
break;
|
1216 |
+
case 'wp:comment_author':
|
1217 |
+
$data['comment_author'] = $child->textContent;
|
1218 |
+
break;
|
1219 |
+
|
1220 |
+
case 'wp:comment_author_email':
|
1221 |
+
$data['comment_author_email'] = $child->textContent;
|
1222 |
+
break;
|
1223 |
+
|
1224 |
+
case 'wp:comment_author_IP':
|
1225 |
+
$data['comment_author_IP'] = $child->textContent;
|
1226 |
+
break;
|
1227 |
+
|
1228 |
+
case 'wp:comment_author_url':
|
1229 |
+
$data['comment_author_url'] = $child->textContent;
|
1230 |
+
break;
|
1231 |
+
|
1232 |
+
case 'wp:comment_user_id':
|
1233 |
+
$data['comment_user_id'] = $child->textContent;
|
1234 |
+
break;
|
1235 |
+
|
1236 |
+
case 'wp:comment_date':
|
1237 |
+
$data['comment_date'] = $child->textContent;
|
1238 |
+
break;
|
1239 |
+
|
1240 |
+
case 'wp:comment_date_gmt':
|
1241 |
+
$data['comment_date_gmt'] = $child->textContent;
|
1242 |
+
break;
|
1243 |
+
|
1244 |
+
case 'wp:comment_content':
|
1245 |
+
$data['comment_content'] = $child->textContent;
|
1246 |
+
break;
|
1247 |
+
|
1248 |
+
case 'wp:comment_approved':
|
1249 |
+
$data['comment_approved'] = $child->textContent;
|
1250 |
+
break;
|
1251 |
+
|
1252 |
+
case 'wp:comment_type':
|
1253 |
+
$data['comment_type'] = $child->textContent;
|
1254 |
+
break;
|
1255 |
+
|
1256 |
+
case 'wp:comment_parent':
|
1257 |
+
$data['comment_parent'] = $child->textContent;
|
1258 |
+
break;
|
1259 |
+
|
1260 |
+
case 'wp:commentmeta':
|
1261 |
+
$meta_item = $this->parse_meta_node( $child );
|
1262 |
+
if ( ! empty( $meta_item ) ) {
|
1263 |
+
$data['commentmeta'][] = $meta_item;
|
1264 |
+
}
|
1265 |
+
break;
|
1266 |
+
}// End switch().
|
1267 |
+
}// End foreach().
|
1268 |
+
|
1269 |
+
return $data;
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
/**
|
1273 |
+
* Process and import comment data.
|
1274 |
+
*
|
1275 |
+
* @param array $comments List of comment data arrays.
|
1276 |
+
* @param int $post_id Post to associate with.
|
1277 |
+
* @param array $post Post data.
|
1278 |
+
* @return int|WP_Error Number of comments imported on success, error otherwise.
|
1279 |
+
*/
|
1280 |
+
protected function process_comments( $comments, $post_id, $post, $post_exists = false ) {
|
1281 |
+
|
1282 |
+
$comments = apply_filters( 'wp_import_post_comments', $comments, $post_id, $post );
|
1283 |
+
if ( empty( $comments ) ) {
|
1284 |
+
return 0;
|
1285 |
+
}
|
1286 |
+
|
1287 |
+
$num_comments = 0;
|
1288 |
+
|
1289 |
+
// Sort by ID to avoid excessive remapping later
|
1290 |
+
usort( $comments, array( $this, 'sort_comments_by_id' ) );
|
1291 |
+
|
1292 |
+
foreach ( $comments as $key => $comment ) {
|
1293 |
+
/**
|
1294 |
+
* Pre-process comment data
|
1295 |
+
*
|
1296 |
+
* @param array $comment Comment data. (Return empty to skip.)
|
1297 |
+
* @param int $post_id Post the comment is attached to.
|
1298 |
+
*/
|
1299 |
+
$comment = apply_filters( 'wxr_importer.pre_process.comment', $comment, $post_id );
|
1300 |
+
if ( empty( $comment ) ) {
|
1301 |
+
return false;
|
1302 |
+
}
|
1303 |
+
|
1304 |
+
$original_id = isset( $comment['comment_id'] ) ? (int) $comment['comment_id'] : 0;
|
1305 |
+
$parent_id = isset( $comment['comment_parent'] ) ? (int) $comment['comment_parent'] : 0;
|
1306 |
+
$author_id = isset( $comment['comment_user_id'] ) ? (int) $comment['comment_user_id'] : 0;
|
1307 |
+
|
1308 |
+
// if this is a new post we can skip the comment_exists() check
|
1309 |
+
// TODO: Check comment_exists for performance
|
1310 |
+
if ( $post_exists ) {
|
1311 |
+
$existing = $this->comment_exists( $comment );
|
1312 |
+
if ( $existing ) {
|
1313 |
+
|
1314 |
+
/**
|
1315 |
+
* Comment processing already imported.
|
1316 |
+
*
|
1317 |
+
* @param array $comment Raw data imported for the comment.
|
1318 |
+
*/
|
1319 |
+
do_action( 'wxr_importer.process_already_imported.comment', $comment );
|
1320 |
+
|
1321 |
+
$this->mapping['comment'][ $original_id ] = $existing;
|
1322 |
+
continue;
|
1323 |
+
}
|
1324 |
+
}
|
1325 |
+
|
1326 |
+
// Remove meta from the main array
|
1327 |
+
$meta = isset( $comment['commentmeta'] ) ? $comment['commentmeta'] : array();
|
1328 |
+
unset( $comment['commentmeta'] );
|
1329 |
+
|
1330 |
+
// Map the parent comment, or mark it as one we need to fix
|
1331 |
+
$requires_remapping = false;
|
1332 |
+
if ( $parent_id ) {
|
1333 |
+
if ( isset( $this->mapping['comment'][ $parent_id ] ) ) {
|
1334 |
+
$comment['comment_parent'] = $this->mapping['comment'][ $parent_id ];
|
1335 |
+
} else {
|
1336 |
+
// Prepare for remapping later
|
1337 |
+
$meta[] = array(
|
1338 |
+
'key' => '_wxr_import_parent',
|
1339 |
+
'value' => $parent_id,
|
1340 |
+
);
|
1341 |
+
$requires_remapping = true;
|
1342 |
+
|
1343 |
+
// Wipe the parent for now
|
1344 |
+
$comment['comment_parent'] = 0;
|
1345 |
+
}
|
1346 |
+
}
|
1347 |
+
|
1348 |
+
// Map the author, or mark it as one we need to fix
|
1349 |
+
if ( $author_id ) {
|
1350 |
+
if ( isset( $this->mapping['user'][ $author_id ] ) ) {
|
1351 |
+
$comment['user_id'] = $this->mapping['user'][ $author_id ];
|
1352 |
+
} else {
|
1353 |
+
// Prepare for remapping later
|
1354 |
+
$meta[] = array(
|
1355 |
+
'key' => '_wxr_import_user',
|
1356 |
+
'value' => $author_id,
|
1357 |
+
);
|
1358 |
+
$requires_remapping = true;
|
1359 |
+
|
1360 |
+
// Wipe the user for now
|
1361 |
+
$comment['user_id'] = 0;
|
1362 |
+
}
|
1363 |
+
}
|
1364 |
+
|
1365 |
+
// Run standard core filters
|
1366 |
+
$comment['comment_post_ID'] = $post_id;
|
1367 |
+
$comment = wp_filter_comment( $comment );
|
1368 |
+
|
1369 |
+
// wp_insert_comment expects slashed data
|
1370 |
+
$comment_id = wp_insert_comment( wp_slash( $comment ) );
|
1371 |
+
$this->mapping['comment'][ $original_id ] = $comment_id;
|
1372 |
+
if ( $requires_remapping ) {
|
1373 |
+
$this->requires_remapping['comment'][ $comment_id ] = true;
|
1374 |
+
}
|
1375 |
+
$this->mark_comment_exists( $comment, $comment_id );
|
1376 |
+
|
1377 |
+
/**
|
1378 |
+
* Comment has been imported.
|
1379 |
+
*
|
1380 |
+
* @param int $comment_id New comment ID
|
1381 |
+
* @param array $comment Comment inserted (`comment_id` item refers to the original ID)
|
1382 |
+
* @param int $post_id Post parent of the comment
|
1383 |
+
* @param array $post Post data
|
1384 |
+
*/
|
1385 |
+
do_action( 'wp_import_insert_comment', $comment_id, $comment, $post_id, $post );
|
1386 |
+
|
1387 |
+
// Process the meta items
|
1388 |
+
foreach ( $meta as $meta_item ) {
|
1389 |
+
$value = maybe_unserialize( $meta_item['value'] );
|
1390 |
+
add_comment_meta( $comment_id, wp_slash( $meta_item['key'] ), wp_slash( $value ) );
|
1391 |
+
}
|
1392 |
+
|
1393 |
+
/**
|
1394 |
+
* Post processing completed.
|
1395 |
+
*
|
1396 |
+
* @param int $post_id New post ID.
|
1397 |
+
* @param array $comment Raw data imported for the comment.
|
1398 |
+
* @param array $meta Raw meta data, already processed by {@see process_post_meta}.
|
1399 |
+
* @param array $post_id Parent post ID.
|
1400 |
+
*/
|
1401 |
+
do_action( 'wxr_importer.processed.comment', $comment_id, $comment, $meta, $post_id );
|
1402 |
+
|
1403 |
+
$num_comments++;
|
1404 |
+
}// End foreach().
|
1405 |
+
|
1406 |
+
return $num_comments;
|
1407 |
+
}
|
1408 |
+
|
1409 |
+
protected function parse_category_node( $node ) {
|
1410 |
+
$data = array(
|
1411 |
+
// Default taxonomy to "category", since this is a `<category>` tag
|
1412 |
+
'taxonomy' => 'category',
|
1413 |
+
);
|
1414 |
+
$meta = array();
|
1415 |
+
|
1416 |
+
if ( $node->hasAttribute( 'domain' ) ) {
|
1417 |
+
$data['taxonomy'] = $node->getAttribute( 'domain' );
|
1418 |
+
}
|
1419 |
+
if ( $node->hasAttribute( 'nicename' ) ) {
|
1420 |
+
$data['slug'] = $node->getAttribute( 'nicename' );
|
1421 |
+
}
|
1422 |
+
|
1423 |
+
$data['name'] = $node->textContent;
|
1424 |
+
|
1425 |
+
if ( empty( $data['slug'] ) ) {
|
1426 |
+
return null;
|
1427 |
+
}
|
1428 |
+
|
1429 |
+
// Just for extra compatibility
|
1430 |
+
if ( $data['taxonomy'] === 'tag' ) {
|
1431 |
+
$data['taxonomy'] = 'post_tag';
|
1432 |
+
}
|
1433 |
+
|
1434 |
+
return $data;
|
1435 |
+
}
|
1436 |
+
|
1437 |
+
/**
|
1438 |
+
* Callback for `usort` to sort comments by ID
|
1439 |
+
*
|
1440 |
+
* @param array $a Comment data for the first comment
|
1441 |
+
* @param array $b Comment data for the second comment
|
1442 |
+
* @return int
|
1443 |
+
*/
|
1444 |
+
public static function sort_comments_by_id( $a, $b ) {
|
1445 |
+
if ( empty( $a['comment_id'] ) ) {
|
1446 |
+
return 1;
|
1447 |
+
}
|
1448 |
+
|
1449 |
+
if ( empty( $b['comment_id'] ) ) {
|
1450 |
+
return -1;
|
1451 |
+
}
|
1452 |
+
|
1453 |
+
return $a['comment_id'] - $b['comment_id'];
|
1454 |
+
}
|
1455 |
+
|
1456 |
+
protected function parse_author_node( $node ) {
|
1457 |
+
$data = array();
|
1458 |
+
$meta = array();
|
1459 |
+
foreach ( $node->childNodes as $child ) {
|
1460 |
+
// We only care about child elements
|
1461 |
+
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
1462 |
+
continue;
|
1463 |
+
}
|
1464 |
+
|
1465 |
+
switch ( $child->tagName ) {
|
1466 |
+
case 'wp:author_login':
|
1467 |
+
$data['user_login'] = $child->textContent;
|
1468 |
+
break;
|
1469 |
+
|
1470 |
+
case 'wp:author_id':
|
1471 |
+
$data['ID'] = $child->textContent;
|
1472 |
+
break;
|
1473 |
+
|
1474 |
+
case 'wp:author_email':
|
1475 |
+
$data['user_email'] = $child->textContent;
|
1476 |
+
break;
|
1477 |
+
|
1478 |
+
case 'wp:author_display_name':
|
1479 |
+
$data['display_name'] = $child->textContent;
|
1480 |
+
break;
|
1481 |
+
|
1482 |
+
case 'wp:author_first_name':
|
1483 |
+
$data['first_name'] = $child->textContent;
|
1484 |
+
break;
|
1485 |
+
|
1486 |
+
case 'wp:author_last_name':
|
1487 |
+
$data['last_name'] = $child->textContent;
|
1488 |
+
break;
|
1489 |
+
}
|
1490 |
+
}
|
1491 |
+
|
1492 |
+
return compact( 'data', 'meta' );
|
1493 |
+
}
|
1494 |
+
|
1495 |
+
protected function process_author( $data, $meta ) {
|
1496 |
+
/**
|
1497 |
+
* Pre-process user data.
|
1498 |
+
*
|
1499 |
+
* @param array $data User data. (Return empty to skip.)
|
1500 |
+
* @param array $meta Meta data.
|
1501 |
+
*/
|
1502 |
+
$data = apply_filters( 'wxr_importer.pre_process.user', $data, $meta );
|
1503 |
+
if ( empty( $data ) ) {
|
1504 |
+
return false;
|
1505 |
+
}
|
1506 |
+
|
1507 |
+
// Have we already handled this user?
|
1508 |
+
$original_id = isset( $data['ID'] ) ? $data['ID'] : 0;
|
1509 |
+
$original_slug = $data['user_login'];
|
1510 |
+
|
1511 |
+
if ( isset( $this->mapping['user'][ $original_id ] ) ) {
|
1512 |
+
$existing = $this->mapping['user'][ $original_id ];
|
1513 |
+
|
1514 |
+
// Note the slug mapping if we need to too
|
1515 |
+
if ( ! isset( $this->mapping['user_slug'][ $original_slug ] ) ) {
|
1516 |
+
$this->mapping['user_slug'][ $original_slug ] = $existing;
|
1517 |
+
}
|
1518 |
+
|
1519 |
+
return false;
|
1520 |
+
}
|
1521 |
+
|
1522 |
+
if ( isset( $this->mapping['user_slug'][ $original_slug ] ) ) {
|
1523 |
+
$existing = $this->mapping['user_slug'][ $original_slug ];
|
1524 |
+
|
1525 |
+
// Ensure we note the mapping too
|
1526 |
+
$this->mapping['user'][ $original_id ] = $existing;
|
1527 |
+
|
1528 |
+
return false;
|
1529 |
+
}
|
1530 |
+
|
1531 |
+
// Allow overriding the user's slug
|
1532 |
+
$login = $original_slug;
|
1533 |
+
if ( isset( $this->user_slug_override[ $login ] ) ) {
|
1534 |
+
$login = $this->user_slug_override[ $login ];
|
1535 |
+
}
|
1536 |
+
|
1537 |
+
$userdata = array(
|
1538 |
+
'user_login' => sanitize_user( $login, true ),
|
1539 |
+
'user_pass' => wp_generate_password(),
|
1540 |
+
);
|
1541 |
+
|
1542 |
+
$allowed = array(
|
1543 |
+
'user_email' => true,
|
1544 |
+
'display_name' => true,
|
1545 |
+
'first_name' => true,
|
1546 |
+
'last_name' => true,
|
1547 |
+
);
|
1548 |
+
foreach ( $data as $key => $value ) {
|
1549 |
+
if ( ! isset( $allowed[ $key ] ) ) {
|
1550 |
+
continue;
|
1551 |
+
}
|
1552 |
+
|
1553 |
+
$userdata[ $key ] = $data[ $key ];
|
1554 |
+
}
|
1555 |
+
|
1556 |
+
$user_id = wp_insert_user( wp_slash( $userdata ) );
|
1557 |
+
if ( is_wp_error( $user_id ) ) {
|
1558 |
+
$this->logger->error( sprintf(
|
1559 |
+
__( 'Failed to import user "%s"', 'wordpress-importer' ),
|
1560 |
+
$userdata['user_login']
|
1561 |
+
) );
|
1562 |
+
$this->logger->debug( $user_id->get_error_message() );
|
1563 |
+
|
1564 |
+
/**
|
1565 |
+
* User processing failed.
|
1566 |
+
*
|
1567 |
+
* @param WP_Error $user_id Error object.
|
1568 |
+
* @param array $userdata Raw data imported for the user.
|
1569 |
+
*/
|
1570 |
+
do_action( 'wxr_importer.process_failed.user', $user_id, $userdata );
|
1571 |
+
return false;
|
1572 |
+
}
|
1573 |
+
|
1574 |
+
if ( $original_id ) {
|
1575 |
+
$this->mapping['user'][ $original_id ] = $user_id;
|
1576 |
+
}
|
1577 |
+
$this->mapping['user_slug'][ $original_slug ] = $user_id;
|
1578 |
+
|
1579 |
+
$this->logger->info( sprintf(
|
1580 |
+
__( 'Imported user "%s"', 'wordpress-importer' ),
|
1581 |
+
$userdata['user_login']
|
1582 |
+
) );
|
1583 |
+
$this->logger->debug( sprintf(
|
1584 |
+
__( 'User %1$d remapped to %2$d', 'wordpress-importer' ),
|
1585 |
+
$original_id,
|
1586 |
+
$user_id
|
1587 |
+
) );
|
1588 |
+
|
1589 |
+
// TODO: Implement meta handling once WXR includes it
|
1590 |
+
/**
|
1591 |
+
* User processing completed.
|
1592 |
+
*
|
1593 |
+
* @param int $user_id New user ID.
|
1594 |
+
* @param array $userdata Raw data imported for the user.
|
1595 |
+
*/
|
1596 |
+
do_action( 'wxr_importer.processed.user', $user_id, $userdata );
|
1597 |
+
}
|
1598 |
+
|
1599 |
+
protected function parse_term_node( $node, $type = 'term' ) {
|
1600 |
+
$data = array();
|
1601 |
+
$meta = array();
|
1602 |
+
|
1603 |
+
$tag_name = array(
|
1604 |
+
'id' => 'wp:term_id',
|
1605 |
+
'taxonomy' => 'wp:term_taxonomy',
|
1606 |
+
'slug' => 'wp:term_slug',
|
1607 |
+
'parent' => 'wp:term_parent',
|
1608 |
+
'name' => 'wp:term_name',
|
1609 |
+
'description' => 'wp:term_description',
|
1610 |
+
);
|
1611 |
+
$taxonomy = null;
|
1612 |
+
|
1613 |
+
// Special casing!
|
1614 |
+
switch ( $type ) {
|
1615 |
+
case 'category':
|
1616 |
+
$tag_name['slug'] = 'wp:category_nicename';
|
1617 |
+
$tag_name['parent'] = 'wp:category_parent';
|
1618 |
+
$tag_name['name'] = 'wp:cat_name';
|
1619 |
+
$tag_name['description'] = 'wp:category_description';
|
1620 |
+
$tag_name['taxonomy'] = null;
|
1621 |
+
|
1622 |
+
$data['taxonomy'] = 'category';
|
1623 |
+
break;
|
1624 |
+
|
1625 |
+
case 'tag':
|
1626 |
+
$tag_name['slug'] = 'wp:tag_slug';
|
1627 |
+
$tag_name['parent'] = null;
|
1628 |
+
$tag_name['name'] = 'wp:tag_name';
|
1629 |
+
$tag_name['description'] = 'wp:tag_description';
|
1630 |
+
$tag_name['taxonomy'] = null;
|
1631 |
+
|
1632 |
+
$data['taxonomy'] = 'post_tag';
|
1633 |
+
break;
|
1634 |
+
}
|
1635 |
+
|
1636 |
+
foreach ( $node->childNodes as $child ) {
|
1637 |
+
// We only care about child elements
|
1638 |
+
if ( $child->nodeType !== XML_ELEMENT_NODE ) {
|
1639 |
+
continue;
|
1640 |
+
}
|
1641 |
+
|
1642 |
+
$key = array_search( $child->tagName, $tag_name );
|
1643 |
+
if ( $key ) {
|
1644 |
+
$data[ $key ] = $child->textContent;
|
1645 |
+
}
|
1646 |
+
}
|
1647 |
+
|
1648 |
+
if ( empty( $data['taxonomy'] ) ) {
|
1649 |
+
return null;
|
1650 |
+
}
|
1651 |
+
|
1652 |
+
// Compatibility with WXR 1.0
|
1653 |
+
if ( $data['taxonomy'] === 'tag' ) {
|
1654 |
+
$data['taxonomy'] = 'post_tag';
|
1655 |
+
}
|
1656 |
+
|
1657 |
+
return compact( 'data', 'meta' );
|
1658 |
+
}
|
1659 |
+
|
1660 |
+
protected function process_term( $data, $meta ) {
|
1661 |
+
/**
|
1662 |
+
* Pre-process term data.
|
1663 |
+
*
|
1664 |
+
* @param array $data Term data. (Return empty to skip.)
|
1665 |
+
* @param array $meta Meta data.
|
1666 |
+
*/
|
1667 |
+
$data = apply_filters( 'wxr_importer.pre_process.term', $data, $meta );
|
1668 |
+
if ( empty( $data ) ) {
|
1669 |
+
return false;
|
1670 |
+
}
|
1671 |
+
|
1672 |
+
$original_id = isset( $data['id'] ) ? (int) $data['id'] : 0;
|
1673 |
+
$parent_id = isset( $data['parent'] ) ? (int) $data['parent'] : 0;
|
1674 |
+
|
1675 |
+
$mapping_key = sha1( $data['taxonomy'] . ':' . $data['slug'] );
|
1676 |
+
$existing = $this->term_exists( $data );
|
1677 |
+
if ( $existing ) {
|
1678 |
+
|
1679 |
+
/**
|
1680 |
+
* Term processing already imported.
|
1681 |
+
*
|
1682 |
+
* @param array $data Raw data imported for the term.
|
1683 |
+
*/
|
1684 |
+
do_action( 'wxr_importer.process_already_imported.term', $data );
|
1685 |
+
|
1686 |
+
$this->mapping['term'][ $mapping_key ] = $existing;
|
1687 |
+
$this->mapping['term_id'][ $original_id ] = $existing;
|
1688 |
+
return false;
|
1689 |
+
}
|
1690 |
+
|
1691 |
+
// WP really likes to repeat itself in export files
|
1692 |
+
if ( isset( $this->mapping['term'][ $mapping_key ] ) ) {
|
1693 |
+
return false;
|
1694 |
+
}
|
1695 |
+
|
1696 |
+
$termdata = array();
|
1697 |
+
$allowed = array(
|
1698 |
+
'slug' => true,
|
1699 |
+
'description' => true,
|
1700 |
+
);
|
1701 |
+
|
1702 |
+
// Map the parent comment, or mark it as one we need to fix
|
1703 |
+
// TODO: add parent mapping and remapping
|
1704 |
+
/*
|
1705 |
+
$requires_remapping = false;
|
1706 |
+
if ( $parent_id ) {
|
1707 |
+
if ( isset( $this->mapping['term'][ $parent_id ] ) ) {
|
1708 |
+
$data['parent'] = $this->mapping['term'][ $parent_id ];
|
1709 |
+
} else {
|
1710 |
+
// Prepare for remapping later
|
1711 |
+
$meta[] = array( 'key' => '_wxr_import_parent', 'value' => $parent_id );
|
1712 |
+
$requires_remapping = true;
|
1713 |
+
|
1714 |
+
// Wipe the parent for now
|
1715 |
+
$data['parent'] = 0;
|
1716 |
+
}
|
1717 |
+
}*/
|
1718 |
+
|
1719 |
+
foreach ( $data as $key => $value ) {
|
1720 |
+
if ( ! isset( $allowed[ $key ] ) ) {
|
1721 |
+
continue;
|
1722 |
+
}
|
1723 |
+
|
1724 |
+
$termdata[ $key ] = $data[ $key ];
|
1725 |
+
}
|
1726 |
+
|
1727 |
+
$result = wp_insert_term( $data['name'], $data['taxonomy'], $termdata );
|
1728 |
+
if ( is_wp_error( $result ) ) {
|
1729 |
+
$this->logger->warning( sprintf(
|
1730 |
+
__( 'Failed to import %1$s %2$s', 'wordpress-importer' ),
|
1731 |
+
$data['taxonomy'],
|
1732 |
+
$data['name']
|
1733 |
+
) );
|
1734 |
+
$this->logger->debug( $result->get_error_message() );
|
1735 |
+
do_action( 'wp_import_insert_term_failed', $result, $data );
|
1736 |
+
|
1737 |
+
/**
|
1738 |
+
* Term processing failed.
|
1739 |
+
*
|
1740 |
+
* @param WP_Error $result Error object.
|
1741 |
+
* @param array $data Raw data imported for the term.
|
1742 |
+
* @param array $meta Meta data supplied for the term.
|
1743 |
+
*/
|
1744 |
+
do_action( 'wxr_importer.process_failed.term', $result, $data, $meta );
|
1745 |
+
return false;
|
1746 |
+
}
|
1747 |
+
|
1748 |
+
$term_id = $result['term_id'];
|
1749 |
+
|
1750 |
+
$this->mapping['term'][ $mapping_key ] = $term_id;
|
1751 |
+
$this->mapping['term_id'][ $original_id ] = $term_id;
|
1752 |
+
|
1753 |
+
$this->logger->info( sprintf(
|
1754 |
+
__( 'Imported "%1$s" (%2$s)', 'wordpress-importer' ),
|
1755 |
+
$data['name'],
|
1756 |
+
$data['taxonomy']
|
1757 |
+
) );
|
1758 |
+
$this->logger->debug( sprintf(
|
1759 |
+
__( 'Term %1$d remapped to %2$d', 'wordpress-importer' ),
|
1760 |
+
$original_id,
|
1761 |
+
$term_id
|
1762 |
+
) );
|
1763 |
+
|
1764 |
+
do_action( 'wp_import_insert_term', $term_id, $data );
|
1765 |
+
|
1766 |
+
/**
|
1767 |
+
* Term processing completed.
|
1768 |
+
*
|
1769 |
+
* @param int $term_id New term ID.
|
1770 |
+
* @param array $data Raw data imported for the term.
|
1771 |
+
*/
|
1772 |
+
do_action( 'wxr_importer.processed.term', $term_id, $data );
|
1773 |
+
}
|
1774 |
+
|
1775 |
+
/**
|
1776 |
+
* Attempt to download a remote file attachment
|
1777 |
+
*
|
1778 |
+
* @param string $url URL of item to fetch
|
1779 |
+
* @param array $post Attachment details
|
1780 |
+
* @return array|WP_Error Local file location details on success, WP_Error otherwise
|
1781 |
+
*/
|
1782 |
+
protected function fetch_remote_file( $url, $post ) {
|
1783 |
+
// extract the file name and extension from the url
|
1784 |
+
$file_name = basename( $url );
|
1785 |
+
|
1786 |
+
// get placeholder file in the upload dir with a unique, sanitized filename
|
1787 |
+
$upload = wp_upload_bits( $file_name, 0, '', $post['upload_date'] );
|
1788 |
+
if ( $upload['error'] ) {
|
1789 |
+
return new WP_Error( 'upload_dir_error', $upload['error'] );
|
1790 |
+
}
|
1791 |
+
|
1792 |
+
// fetch the remote url and write it to the placeholder file
|
1793 |
+
$response = wp_remote_get( $url, array(
|
1794 |
+
'stream' => true,
|
1795 |
+
'filename' => $upload['file'],
|
1796 |
+
) );
|
1797 |
+
|
1798 |
+
// request failed
|
1799 |
+
if ( is_wp_error( $response ) ) {
|
1800 |
+
unlink( $upload['file'] );
|
1801 |
+
return $response;
|
1802 |
+
}
|
1803 |
+
|
1804 |
+
$code = (int) wp_remote_retrieve_response_code( $response );
|
1805 |
+
|
1806 |
+
// make sure the fetch was successful
|
1807 |
+
if ( $code !== 200 ) {
|
1808 |
+
unlink( $upload['file'] );
|
1809 |
+
return new WP_Error(
|
1810 |
+
'import_file_error',
|
1811 |
+
sprintf(
|
1812 |
+
__( 'Remote server returned %1$d %2$s for %3$s', 'wordpress-importer' ),
|
1813 |
+
$code,
|
1814 |
+
get_status_header_desc( $code ),
|
1815 |
+
$url
|
1816 |
+
)
|
1817 |
+
);
|
1818 |
+
}
|
1819 |
+
|
1820 |
+
$filesize = filesize( $upload['file'] );
|
1821 |
+
$headers = wp_remote_retrieve_headers( $response );
|
1822 |
+
|
1823 |
+
if ( isset( $headers['content-length'] ) && $filesize !== (int) $headers['content-length'] ) {
|
1824 |
+
unlink( $upload['file'] );
|
1825 |
+
return new WP_Error( 'import_file_error', __( 'Remote file is incorrect size', 'wordpress-importer' ) );
|
1826 |
+
}
|
1827 |
+
|
1828 |
+
if ( 0 === $filesize ) {
|
1829 |
+
unlink( $upload['file'] );
|
1830 |
+
return new WP_Error( 'import_file_error', __( 'Zero size file downloaded', 'wordpress-importer' ) );
|
1831 |
+
}
|
1832 |
+
|
1833 |
+
$max_size = (int) $this->max_attachment_size();
|
1834 |
+
if ( ! empty( $max_size ) && $filesize > $max_size ) {
|
1835 |
+
unlink( $upload['file'] );
|
1836 |
+
$message = sprintf( __( 'Remote file is too large, limit is %s', 'wordpress-importer' ), size_format( $max_size ) );
|
1837 |
+
return new WP_Error( 'import_file_error', $message );
|
1838 |
+
}
|
1839 |
+
|
1840 |
+
return $upload;
|
1841 |
+
}
|
1842 |
+
|
1843 |
+
protected function post_process() {
|
1844 |
+
// Time to tackle any left-over bits
|
1845 |
+
if ( ! empty( $this->requires_remapping['post'] ) ) {
|
1846 |
+
$this->post_process_posts( $this->requires_remapping['post'] );
|
1847 |
+
}
|
1848 |
+
if ( ! empty( $this->requires_remapping['comment'] ) ) {
|
1849 |
+
$this->post_process_comments( $this->requires_remapping['comment'] );
|
1850 |
+
}
|
1851 |
+
}
|
1852 |
+
|
1853 |
+
protected function post_process_posts( $todo ) {
|
1854 |
+
foreach ( $todo as $post_id => $_ ) {
|
1855 |
+
$this->logger->debug( sprintf(
|
1856 |
+
// Note: title intentionally not used to skip extra processing
|
1857 |
+
// for when debug logging is off
|
1858 |
+
__( 'Running post-processing for post %d', 'wordpress-importer' ),
|
1859 |
+
$post_id
|
1860 |
+
) );
|
1861 |
+
|
1862 |
+
$data = array();
|
1863 |
+
|
1864 |
+
$parent_id = get_post_meta( $post_id, '_wxr_import_parent', true );
|
1865 |
+
if ( ! empty( $parent_id ) ) {
|
1866 |
+
// Have we imported the parent now?
|
1867 |
+
if ( isset( $this->mapping['post'][ $parent_id ] ) ) {
|
1868 |
+
$data['post_parent'] = $this->mapping['post'][ $parent_id ];
|
1869 |
+
} else {
|
1870 |
+
$this->logger->warning( sprintf(
|
1871 |
+
__( 'Could not find the post parent for "%1$s" (post #%2$d)', 'wordpress-importer' ),
|
1872 |
+
get_the_title( $post_id ),
|
1873 |
+
$post_id
|
1874 |
+
) );
|
1875 |
+
$this->logger->debug( sprintf(
|
1876 |
+
__( 'Post %1$d was imported with parent %2$d, but could not be found', 'wordpress-importer' ),
|
1877 |
+
$post_id,
|
1878 |
+
$parent_id
|
1879 |
+
) );
|
1880 |
+
}
|
1881 |
+
}
|
1882 |
+
|
1883 |
+
$author_slug = get_post_meta( $post_id, '_wxr_import_user_slug', true );
|
1884 |
+
if ( ! empty( $author_slug ) ) {
|
1885 |
+
// Have we imported the user now?
|
1886 |
+
if ( isset( $this->mapping['user_slug'][ $author_slug ] ) ) {
|
1887 |
+
$data['post_author'] = $this->mapping['user_slug'][ $author_slug ];
|
1888 |
+
} else {
|
1889 |
+
$this->logger->warning( sprintf(
|
1890 |
+
__( 'Could not find the author for "%1$s" (post #%2$d)', 'wordpress-importer' ),
|
1891 |
+
get_the_title( $post_id ),
|
1892 |
+
$post_id
|
1893 |
+
) );
|
1894 |
+
$this->logger->debug( sprintf(
|
1895 |
+
__( 'Post %1$d was imported with author "%2$s", but could not be found', 'wordpress-importer' ),
|
1896 |
+
$post_id,
|
1897 |
+
$author_slug
|
1898 |
+
) );
|
1899 |
+
}
|
1900 |
+
}
|
1901 |
+
|
1902 |
+
$has_attachments = get_post_meta( $post_id, '_wxr_import_has_attachment_refs', true );
|
1903 |
+
if ( ! empty( $has_attachments ) ) {
|
1904 |
+
$post = get_post( $post_id );
|
1905 |
+
$content = $post->post_content;
|
1906 |
+
|
1907 |
+
// Replace all the URLs we've got
|
1908 |
+
$new_content = str_replace( array_keys( $this->url_remap ), $this->url_remap, $content );
|
1909 |
+
if ( $new_content !== $content ) {
|
1910 |
+
$data['post_content'] = $new_content;
|
1911 |
+
}
|
1912 |
+
}
|
1913 |
+
|
1914 |
+
if ( get_post_type( $post_id ) === 'nav_menu_item' ) {
|
1915 |
+
$this->post_process_menu_item( $post_id );
|
1916 |
+
}
|
1917 |
+
|
1918 |
+
// Do we have updates to make?
|
1919 |
+
if ( empty( $data ) ) {
|
1920 |
+
$this->logger->debug( sprintf(
|
1921 |
+
__( 'Post %d was marked for post-processing, but none was required.', 'wordpress-importer' ),
|
1922 |
+
$post_id
|
1923 |
+
) );
|
1924 |
+
continue;
|
1925 |
+
}
|
1926 |
+
|
1927 |
+
// Run the update
|
1928 |
+
$data['ID'] = $post_id;
|
1929 |
+
$result = wp_update_post( $data, true );
|
1930 |
+
if ( is_wp_error( $result ) ) {
|
1931 |
+
$this->logger->warning( sprintf(
|
1932 |
+
__( 'Could not update "%1$s" (post #%2$d) with mapped data', 'wordpress-importer' ),
|
1933 |
+
get_the_title( $post_id ),
|
1934 |
+
$post_id
|
1935 |
+
) );
|
1936 |
+
$this->logger->debug( $result->get_error_message() );
|
1937 |
+
continue;
|
1938 |
+
}
|
1939 |
+
|
1940 |
+
// Clear out our temporary meta keys
|
1941 |
+
delete_post_meta( $post_id, '_wxr_import_parent' );
|
1942 |
+
delete_post_meta( $post_id, '_wxr_import_user_slug' );
|
1943 |
+
delete_post_meta( $post_id, '_wxr_import_has_attachment_refs' );
|
1944 |
+
}// End foreach().
|
1945 |
+
}
|
1946 |
+
|
1947 |
+
protected function post_process_menu_item( $post_id ) {
|
1948 |
+
$menu_object_id = get_post_meta( $post_id, '_wxr_import_menu_item', true );
|
1949 |
+
if ( empty( $menu_object_id ) ) {
|
1950 |
+
// No processing needed!
|
1951 |
+
return;
|
1952 |
+
}
|
1953 |
+
|
1954 |
+
$menu_item_type = get_post_meta( $post_id, '_menu_item_type', true );
|
1955 |
+
switch ( $menu_item_type ) {
|
1956 |
+
case 'taxonomy':
|
1957 |
+
if ( isset( $this->mapping['term_id'][ $menu_object_id ] ) ) {
|
1958 |
+
$menu_object = $this->mapping['term_id'][ $menu_object_id ];
|
1959 |
+
}
|
1960 |
+
break;
|
1961 |
+
|
1962 |
+
case 'post_type':
|
1963 |
+
if ( isset( $this->mapping['post'][ $menu_object_id ] ) ) {
|
1964 |
+
$menu_object = $this->mapping['post'][ $menu_object_id ];
|
1965 |
+
}
|
1966 |
+
break;
|
1967 |
+
|
1968 |
+
default:
|
1969 |
+
// Cannot handle this.
|
1970 |
+
return;
|
1971 |
+
}
|
1972 |
+
|
1973 |
+
if ( ! empty( $menu_object ) ) {
|
1974 |
+
update_post_meta( $post_id, '_menu_item_object_id', wp_slash( $menu_object ) );
|
1975 |
+
} else {
|
1976 |
+
$this->logger->warning( sprintf(
|
1977 |
+
__( 'Could not find the menu object for "%1$s" (post #%2$d)', 'wordpress-importer' ),
|
1978 |
+
get_the_title( $post_id ),
|
1979 |
+
$post_id
|
1980 |
+
) );
|
1981 |
+
$this->logger->debug( sprintf(
|
1982 |
+
__( 'Post %1$d was imported with object "%2$d" of type "%3$s", but could not be found', 'wordpress-importer' ),
|
1983 |
+
$post_id,
|
1984 |
+
$menu_object_id,
|
1985 |
+
$menu_item_type
|
1986 |
+
) );
|
1987 |
+
}
|
1988 |
+
|
1989 |
+
delete_post_meta( $post_id, '_wxr_import_menu_item' );
|
1990 |
+
}
|
1991 |
+
|
1992 |
+
|
1993 |
+
protected function post_process_comments( $todo ) {
|
1994 |
+
foreach ( $todo as $comment_id => $_ ) {
|
1995 |
+
$data = array();
|
1996 |
+
|
1997 |
+
$parent_id = get_comment_meta( $comment_id, '_wxr_import_parent', true );
|
1998 |
+
if ( ! empty( $parent_id ) ) {
|
1999 |
+
// Have we imported the parent now?
|
2000 |
+
if ( isset( $this->mapping['comment'][ $parent_id ] ) ) {
|
2001 |
+
$data['comment_parent'] = $this->mapping['comment'][ $parent_id ];
|
2002 |
+
} else {
|
2003 |
+
$this->logger->warning( sprintf(
|
2004 |
+
__( 'Could not find the comment parent for comment #%d', 'wordpress-importer' ),
|
2005 |
+
$comment_id
|
2006 |
+
) );
|
2007 |
+
$this->logger->debug( sprintf(
|
2008 |
+
__( 'Comment %1$d was imported with parent %2$d, but could not be found', 'wordpress-importer' ),
|
2009 |
+
$comment_id,
|
2010 |
+
$parent_id
|
2011 |
+
) );
|
2012 |
+
}
|
2013 |
+
}
|
2014 |
+
|
2015 |
+
$author_id = get_comment_meta( $comment_id, '_wxr_import_user', true );
|
2016 |
+
if ( ! empty( $author_id ) ) {
|
2017 |
+
// Have we imported the user now?
|
2018 |
+
if ( isset( $this->mapping['user'][ $author_id ] ) ) {
|
2019 |
+
$data['user_id'] = $this->mapping['user'][ $author_id ];
|
2020 |
+
} else {
|
2021 |
+
$this->logger->warning( sprintf(
|
2022 |
+
__( 'Could not find the author for comment #%d', 'wordpress-importer' ),
|
2023 |
+
$comment_id
|
2024 |
+
) );
|
2025 |
+
$this->logger->debug( sprintf(
|
2026 |
+
__( 'Comment %1$d was imported with author %2$d, but could not be found', 'wordpress-importer' ),
|
2027 |
+
$comment_id,
|
2028 |
+
$author_id
|
2029 |
+
) );
|
2030 |
+
}
|
2031 |
+
}
|
2032 |
+
|
2033 |
+
// Do we have updates to make?
|
2034 |
+
if ( empty( $data ) ) {
|
2035 |
+
continue;
|
2036 |
+
}
|
2037 |
+
|
2038 |
+
// Run the update
|
2039 |
+
$data['comment_ID'] = $comment_ID;
|
2040 |
+
$result = wp_update_comment( wp_slash( $data ) );
|
2041 |
+
if ( empty( $result ) ) {
|
2042 |
+
$this->logger->warning( sprintf(
|
2043 |
+
__( 'Could not update comment #%d with mapped data', 'wordpress-importer' ),
|
2044 |
+
$comment_id
|
2045 |
+
) );
|
2046 |
+
continue;
|
2047 |
+
}
|
2048 |
+
|
2049 |
+
// Clear out our temporary meta keys
|
2050 |
+
delete_comment_meta( $comment_id, '_wxr_import_parent' );
|
2051 |
+
delete_comment_meta( $comment_id, '_wxr_import_user' );
|
2052 |
+
}// End foreach().
|
2053 |
+
}
|
2054 |
+
|
2055 |
+
/**
|
2056 |
+
* Use stored mapping information to update old attachment URLs
|
2057 |
+
*/
|
2058 |
+
protected function replace_attachment_urls_in_content() {
|
2059 |
+
global $wpdb;
|
2060 |
+
// make sure we do the longest urls first, in case one is a substring of another
|
2061 |
+
uksort( $this->url_remap, array( $this, 'cmpr_strlen' ) );
|
2062 |
+
|
2063 |
+
foreach ( $this->url_remap as $from_url => $to_url ) {
|
2064 |
+
// remap urls in post_content
|
2065 |
+
$query = $wpdb->prepare( "UPDATE {$wpdb->posts} SET post_content = REPLACE(post_content, %s, %s)", $from_url, $to_url );
|
2066 |
+
$wpdb->query( $query );
|
2067 |
+
|
2068 |
+
// remap enclosure urls
|
2069 |
+
$query = $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = REPLACE(meta_value, %s, %s) WHERE meta_key='enclosure'", $from_url, $to_url );
|
2070 |
+
$result = $wpdb->query( $query );
|
2071 |
+
}
|
2072 |
+
}
|
2073 |
+
|
2074 |
+
/**
|
2075 |
+
* Update _thumbnail_id meta to new, imported attachment IDs
|
2076 |
+
*/
|
2077 |
+
function remap_featured_images() {
|
2078 |
+
// cycle through posts that have a featured image
|
2079 |
+
foreach ( $this->featured_images as $post_id => $value ) {
|
2080 |
+
if ( isset( $this->processed_posts[ $value ] ) ) {
|
2081 |
+
$new_id = $this->processed_posts[ $value ];
|
2082 |
+
|
2083 |
+
// only update if there's a difference
|
2084 |
+
if ( $new_id !== $value ) {
|
2085 |
+
update_post_meta( $post_id, '_thumbnail_id', $new_id );
|
2086 |
+
}
|
2087 |
+
}
|
2088 |
+
}
|
2089 |
+
}
|
2090 |
+
|
2091 |
+
/**
|
2092 |
+
* Decide if the given meta key maps to information we will want to import
|
2093 |
+
*
|
2094 |
+
* @param string $key The meta key to check
|
2095 |
+
* @return string|bool The key if we do want to import, false if not
|
2096 |
+
*/
|
2097 |
+
public function is_valid_meta_key( $key ) {
|
2098 |
+
// skip attachment metadata since we'll regenerate it from scratch
|
2099 |
+
// skip _edit_lock as not relevant for import
|
2100 |
+
if ( in_array( $key, array( '_wp_attached_file', '_wp_attachment_metadata', '_edit_lock' ) ) ) {
|
2101 |
+
return false;
|
2102 |
+
}
|
2103 |
+
|
2104 |
+
return $key;
|
2105 |
+
}
|
2106 |
+
|
2107 |
+
/**
|
2108 |
+
* Decide what the maximum file size for downloaded attachments is.
|
2109 |
+
* Default is 0 (unlimited), can be filtered via import_attachment_size_limit
|
2110 |
+
*
|
2111 |
+
* @return int Maximum attachment file size to import
|
2112 |
+
*/
|
2113 |
+
protected function max_attachment_size() {
|
2114 |
+
return apply_filters( 'import_attachment_size_limit', 0 );
|
2115 |
+
}
|
2116 |
+
|
2117 |
+
/**
|
2118 |
+
* Added to http_request_timeout filter to force timeout at 60 seconds during import
|
2119 |
+
*
|
2120 |
+
* @access protected
|
2121 |
+
* @return int 60
|
2122 |
+
*/
|
2123 |
+
function bump_request_timeout( $val ) {
|
2124 |
+
return 60;
|
2125 |
+
}
|
2126 |
+
|
2127 |
+
// return the difference in length between two strings
|
2128 |
+
function cmpr_strlen( $a, $b ) {
|
2129 |
+
return strlen( $b ) - strlen( $a );
|
2130 |
+
}
|
2131 |
+
|
2132 |
+
/**
|
2133 |
+
* Prefill existing post data.
|
2134 |
+
*
|
2135 |
+
* This preloads all GUIDs into memory, allowing us to avoid hitting the
|
2136 |
+
* database when we need to check for existence. With larger imports, this
|
2137 |
+
* becomes prohibitively slow to perform SELECT queries on each.
|
2138 |
+
*
|
2139 |
+
* By preloading all this data into memory, it's a constant-time lookup in
|
2140 |
+
* PHP instead. However, this does use a lot more memory, so for sites doing
|
2141 |
+
* small imports onto a large site, it may be a better tradeoff to use
|
2142 |
+
* on-the-fly checking instead.
|
2143 |
+
*/
|
2144 |
+
protected function prefill_existing_posts() {
|
2145 |
+
global $wpdb;
|
2146 |
+
$posts = $wpdb->get_results( "SELECT ID, guid FROM {$wpdb->posts}" );
|
2147 |
+
|
2148 |
+
foreach ( $posts as $item ) {
|
2149 |
+
$this->exists['post'][ $item->guid ] = $item->ID;
|
2150 |
+
}
|
2151 |
+
}
|
2152 |
+
|
2153 |
+
/**
|
2154 |
+
* Does the post exist?
|
2155 |
+
*
|
2156 |
+
* @param array $data Post data to check against.
|
2157 |
+
* @return int|bool Existing post ID if it exists, false otherwise.
|
2158 |
+
*/
|
2159 |
+
protected function post_exists( $data ) {
|
2160 |
+
// Constant-time lookup if we prefilled
|
2161 |
+
$exists_key = $data['guid'];
|
2162 |
+
|
2163 |
+
if ( $this->options['prefill_existing_posts'] ) {
|
2164 |
+
return isset( $this->exists['post'][ $exists_key ] ) ? $this->exists['post'][ $exists_key ] : false;
|
2165 |
+
}
|
2166 |
+
|
2167 |
+
// No prefilling, but might have already handled it
|
2168 |
+
if ( isset( $this->exists['post'][ $exists_key ] ) ) {
|
2169 |
+
return $this->exists['post'][ $exists_key ];
|
2170 |
+
}
|
2171 |
+
|
2172 |
+
// Still nothing, try post_exists, and cache it
|
2173 |
+
$exists = post_exists( $data['post_title'], $data['post_content'], $data['post_date'] );
|
2174 |
+
$this->exists['post'][ $exists_key ] = $exists;
|
2175 |
+
|
2176 |
+
return $exists;
|
2177 |
+
}
|
2178 |
+
|
2179 |
+
/**
|
2180 |
+
* Mark the post as existing.
|
2181 |
+
*
|
2182 |
+
* @param array $data Post data to mark as existing.
|
2183 |
+
* @param int $post_id Post ID.
|
2184 |
+
*/
|
2185 |
+
protected function mark_post_exists( $data, $post_id ) {
|
2186 |
+
$exists_key = $data['guid'];
|
2187 |
+
$this->exists['post'][ $exists_key ] = $post_id;
|
2188 |
+
}
|
2189 |
+
|
2190 |
+
/**
|
2191 |
+
* Prefill existing comment data.
|
2192 |
+
*
|
2193 |
+
* @see self::prefill_existing_posts() for justification of why this exists.
|
2194 |
+
*/
|
2195 |
+
protected function prefill_existing_comments() {
|
2196 |
+
global $wpdb;
|
2197 |
+
$posts = $wpdb->get_results( "SELECT comment_ID, comment_author, comment_date FROM {$wpdb->comments}" );
|
2198 |
+
|
2199 |
+
foreach ( $posts as $item ) {
|
2200 |
+
$exists_key = sha1( $item->comment_author . ':' . $item->comment_date );
|
2201 |
+
$this->exists['comment'][ $exists_key ] = $item->comment_ID;
|
2202 |
+
}
|
2203 |
+
}
|
2204 |
+
|
2205 |
+
/**
|
2206 |
+
* Does the comment exist?
|
2207 |
+
*
|
2208 |
+
* @param array $data Comment data to check against.
|
2209 |
+
* @return int|bool Existing comment ID if it exists, false otherwise.
|
2210 |
+
*/
|
2211 |
+
protected function comment_exists( $data ) {
|
2212 |
+
$exists_key = sha1( $data['comment_author'] . ':' . $data['comment_date'] );
|
2213 |
+
|
2214 |
+
// Constant-time lookup if we prefilled
|
2215 |
+
if ( $this->options['prefill_existing_comments'] ) {
|
2216 |
+
return isset( $this->exists['comment'][ $exists_key ] ) ? $this->exists['comment'][ $exists_key ] : false;
|
2217 |
+
}
|
2218 |
+
|
2219 |
+
// No prefilling, but might have already handled it
|
2220 |
+
if ( isset( $this->exists['comment'][ $exists_key ] ) ) {
|
2221 |
+
return $this->exists['comment'][ $exists_key ];
|
2222 |
+
}
|
2223 |
+
|
2224 |
+
// Still nothing, try comment_exists, and cache it
|
2225 |
+
$exists = comment_exists( $data['comment_author'], $data['comment_date'] );
|
2226 |
+
$this->exists['comment'][ $exists_key ] = $exists;
|
2227 |
+
|
2228 |
+
return $exists;
|
2229 |
+
}
|
2230 |
+
|
2231 |
+
/**
|
2232 |
+
* Mark the comment as existing.
|
2233 |
+
*
|
2234 |
+
* @param array $data Comment data to mark as existing.
|
2235 |
+
* @param int $comment_id Comment ID.
|
2236 |
+
*/
|
2237 |
+
protected function mark_comment_exists( $data, $comment_id ) {
|
2238 |
+
$exists_key = sha1( $data['comment_author'] . ':' . $data['comment_date'] );
|
2239 |
+
$this->exists['comment'][ $exists_key ] = $comment_id;
|
2240 |
+
}
|
2241 |
+
|
2242 |
+
/**
|
2243 |
+
* Prefill existing term data.
|
2244 |
+
*
|
2245 |
+
* @see self::prefill_existing_posts() for justification of why this exists.
|
2246 |
+
*/
|
2247 |
+
protected function prefill_existing_terms() {
|
2248 |
+
global $wpdb;
|
2249 |
+
$query = "SELECT t.term_id, tt.taxonomy, t.slug FROM {$wpdb->terms} AS t";
|
2250 |
+
$query .= " JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id";
|
2251 |
+
$terms = $wpdb->get_results( $query );
|
2252 |
+
|
2253 |
+
foreach ( $terms as $item ) {
|
2254 |
+
$exists_key = sha1( $item->taxonomy . ':' . $item->slug );
|
2255 |
+
$this->exists['term'][ $exists_key ] = $item->term_id;
|
2256 |
+
}
|
2257 |
+
}
|
2258 |
+
|
2259 |
+
/**
|
2260 |
+
* Does the term exist?
|
2261 |
+
*
|
2262 |
+
* @param array $data Term data to check against.
|
2263 |
+
* @return int|bool Existing term ID if it exists, false otherwise.
|
2264 |
+
*/
|
2265 |
+
protected function term_exists( $data ) {
|
2266 |
+
$exists_key = sha1( $data['taxonomy'] . ':' . $data['slug'] );
|
2267 |
+
|
2268 |
+
// Constant-time lookup if we prefilled
|
2269 |
+
if ( $this->options['prefill_existing_terms'] ) {
|
2270 |
+
return isset( $this->exists['term'][ $exists_key ] ) ? $this->exists['term'][ $exists_key ] : false;
|
2271 |
+
}
|
2272 |
+
|
2273 |
+
// No prefilling, but might have already handled it
|
2274 |
+
if ( isset( $this->exists['term'][ $exists_key ] ) ) {
|
2275 |
+
return $this->exists['term'][ $exists_key ];
|
2276 |
+
}
|
2277 |
+
|
2278 |
+
// Still nothing, try comment_exists, and cache it
|
2279 |
+
$exists = term_exists( $data['slug'], $data['taxonomy'] );
|
2280 |
+
if ( is_array( $exists ) ) {
|
2281 |
+
$exists = $exists['term_id'];
|
2282 |
+
}
|
2283 |
+
|
2284 |
+
$this->exists['term'][ $exists_key ] = $exists;
|
2285 |
+
|
2286 |
+
return $exists;
|
2287 |
+
}
|
2288 |
+
|
2289 |
+
/**
|
2290 |
+
* Mark the term as existing.
|
2291 |
+
*
|
2292 |
+
* @param array $data Term data to mark as existing.
|
2293 |
+
* @param int $term_id Term ID.
|
2294 |
+
*/
|
2295 |
+
protected function mark_term_exists( $data, $term_id ) {
|
2296 |
+
$exists_key = sha1( $data['taxonomy'] . ':' . $data['slug'] );
|
2297 |
+
$this->exists['term'][ $exists_key ] = $term_id;
|
2298 |
+
}
|
2299 |
ย
}
|
inc/includes/admin-page.php
CHANGED
@@ -52,6 +52,20 @@ defined( 'ABSPATH' ) or exit;
|
|
52 |
ย
<div id="astra-sites" class="themes wp-clearfix"></div>
|
53 |
ย
</div>
|
54 |
ย
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
55 |
ย
<div class="select-page-builder">
|
56 |
ย
<div class="note-wrap">
|
57 |
ย
<h3>
|
@@ -61,14 +75,7 @@ defined( 'ABSPATH' ) or exit;
|
|
61 |
ย
</div>
|
62 |
ย
<img src="<?php echo esc_url( ASTRA_SITES_URI . 'inc/assets/images/sites-screenshot.jpg' ); ?>" alt="<?php _e( 'Sites List..', 'astra-sites' ); ?>" title="<?php _e( 'Sites List..', 'astra-sites' ); ?>" />
|
63 |
ย
</div>
|
64 |
-
|
65 |
-
<div class="spinner-wrap">
|
66 |
-
<span class="spinner"></span>
|
67 |
-
</div>
|
68 |
-
|
69 |
-
<?php do_action( 'astra_sites_after_site_grid' ); ?>
|
70 |
-
|
71 |
-
</div>
|
72 |
ย
|
73 |
ย
<?php
|
74 |
ย
/**
|
52 |
ย
<div id="astra-sites" class="themes wp-clearfix"></div>
|
53 |
ย
</div>
|
54 |
ย
|
55 |
+
<div class="spinner-wrap">
|
56 |
+
<span class="spinner"></span>
|
57 |
+
</div>
|
58 |
+
|
59 |
+
<?php do_action( 'astra_sites_after_site_grid' ); ?>
|
60 |
+
|
61 |
+
</div>
|
62 |
+
|
63 |
+
<?php
|
64 |
+
/**
|
65 |
+
* TMPL - Single Demo Preview
|
66 |
+
*/
|
67 |
+
?>
|
68 |
+
<script type="text/template" id="tmpl-astra-site-select-page-builder">
|
69 |
ย
<div class="select-page-builder">
|
70 |
ย
<div class="note-wrap">
|
71 |
ย
<h3>
|
75 |
ย
</div>
|
76 |
ย
<img src="<?php echo esc_url( ASTRA_SITES_URI . 'inc/assets/images/sites-screenshot.jpg' ); ?>" alt="<?php _e( 'Sites List..', 'astra-sites' ); ?>" title="<?php _e( 'Sites List..', 'astra-sites' ); ?>" />
|
77 |
ย
</div>
|
78 |
+
</script>
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
ย
|
|
79 |
ย
|
80 |
ย
<?php
|
81 |
ย
/**
|
languages/astra-sites.pot
CHANGED
@@ -1,631 +1,631 @@
|
|
1 |
-
# Copyright (C) 2018 Brainstorm Force
|
2 |
-
# This file is distributed under the same license as the Astra Starter Sites package.
|
3 |
-
msgid ""
|
4 |
-
msgstr ""
|
5 |
-
"Project-Id-Version: Astra Starter Sites 1.2.
|
6 |
-
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/astra-sites\n"
|
7 |
-
"POT-Creation-Date: 2018-06-
|
8 |
-
"MIME-Version: 1.0\n"
|
9 |
-
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
-
"Content-Transfer-Encoding: 8bit\n"
|
11 |
-
"PO-Revision-Date: 2018-MO-DA HO:MI+ZONE\n"
|
12 |
-
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
-
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
-
"Language: en\n"
|
15 |
-
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
16 |
-
"X-Poedit-Country: United States\n"
|
17 |
-
"X-Poedit-SourceCharset: UTF-8\n"
|
18 |
-
"X-Poedit-KeywordsList: "
|
19 |
-
"__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_"
|
20 |
-
"attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n"
|
21 |
-
"X-Poedit-Basepath: ../\n"
|
22 |
-
"X-Poedit-SearchPath-0: .\n"
|
23 |
-
"X-Poedit-Bookmarks: \n"
|
24 |
-
"X-Textdomain-Support: yes\n"
|
25 |
-
"X-Generator: grunt-wp-i18n1.0.0\n"
|
26 |
-
|
27 |
-
#: astra-sites.php:18 inc/classes/class-astra-sites-page.php:85
|
28 |
-
msgid "Astra Sites"
|
29 |
-
msgstr ""
|
30 |
-
|
31 |
-
#: inc/classes/class-astra-sites-importer-log.php:351
|
32 |
-
msgid "Enabled"
|
33 |
-
msgstr ""
|
34 |
-
|
35 |
-
#: inc/classes/class-astra-sites-importer-log.php:354
|
36 |
-
msgid "Disabled"
|
37 |
-
msgstr ""
|
38 |
-
|
39 |
-
#: inc/classes/class-astra-sites-importer-log.php:481
|
40 |
-
msgid "Yes"
|
41 |
-
msgstr ""
|
42 |
-
|
43 |
-
#: inc/classes/class-astra-sites-importer-log.php:484
|
44 |
-
msgid "No"
|
45 |
-
msgstr ""
|
46 |
-
|
47 |
-
#: inc/classes/class-astra-sites-importer.php:87
|
48 |
-
msgid "You have not \"customize\" access to import the Astra site."
|
49 |
-
msgstr ""
|
50 |
-
|
51 |
-
#: inc/classes/class-astra-sites-importer.php:111
|
52 |
-
msgid "Request site API URL is empty. Try again!"
|
53 |
-
msgstr ""
|
54 |
-
|
55 |
-
#: inc/classes/class-astra-sites-importer.php:134
|
56 |
-
msgid "Customizer data is empty!"
|
57 |
-
msgstr ""
|
58 |
-
|
59 |
-
#: inc/classes/class-astra-sites-importer.php:163
|
60 |
-
msgid "There was an error downloading the XML file."
|
61 |
-
msgstr ""
|
62 |
-
|
63 |
-
#: inc/classes/class-astra-sites-importer.php:169
|
64 |
-
msgid "Invalid site XML file!"
|
65 |
-
msgstr ""
|
66 |
-
|
67 |
-
#: inc/classes/class-astra-sites-importer.php:191
|
68 |
-
msgid "Site options are empty!"
|
69 |
-
msgstr ""
|
70 |
-
|
71 |
-
#: inc/classes/class-astra-sites-importer.php:213
|
72 |
-
msgid "Widget data is empty!"
|
73 |
-
msgstr ""
|
74 |
-
|
75 |
-
#: inc/classes/class-astra-sites-page.php:192
|
76 |
-
msgid "Settings saved successfully."
|
77 |
-
msgstr ""
|
78 |
-
|
79 |
-
#: inc/classes/class-astra-sites-white-label.php:176
|
80 |
-
#. translators: %1$s product name
|
81 |
-
msgid "%1$s Branding"
|
82 |
-
msgstr ""
|
83 |
-
|
84 |
-
#: inc/classes/class-astra-sites.php:81
|
85 |
-
#. translators: 1: theme.php file
|
86 |
-
msgid ""
|
87 |
-
"Astra Theme needs to be active for you to use currently installed \"%1$s\" "
|
88 |
-
"plugin. <a href=\"%2$s\">Install & Activate Now</a>"
|
89 |
-
msgstr ""
|
90 |
-
|
91 |
-
#: inc/classes/class-astra-sites.php:121
|
92 |
-
msgid "See Library"
|
93 |
-
msgstr ""
|
94 |
-
|
95 |
-
#: inc/classes/class-astra-sites.php:172
|
96 |
-
msgid "Page Builder"
|
97 |
-
msgstr ""
|
98 |
-
|
99 |
-
#: inc/classes/class-astra-sites.php:177
|
100 |
-
msgid "Categories"
|
101 |
-
msgstr ""
|
102 |
-
|
103 |
-
#: inc/classes/class-astra-sites.php:210
|
104 |
-
msgid "Purchase"
|
105 |
-
msgstr ""
|
106 |
-
|
107 |
-
#: inc/classes/class-astra-sites.php:212
|
108 |
-
msgid "Upgrade"
|
109 |
-
msgstr ""
|
110 |
-
|
111 |
-
#: inc/classes/class-astra-sites.php:217
|
112 |
-
msgid ""
|
113 |
-
"Warning! Astra Site Import process is not complete. Don't close the window "
|
114 |
-
"until import process complete. Do you still want to leave the window?"
|
115 |
-
msgstr ""
|
116 |
-
|
117 |
-
#: inc/classes/class-astra-sites.php:218
|
118 |
-
msgid "Error!"
|
119 |
-
msgstr ""
|
120 |
-
|
121 |
-
#: inc/classes/class-astra-sites.php:219
|
122 |
-
msgid "Error! Read Possibilities."
|
123 |
-
msgstr ""
|
124 |
-
|
125 |
-
#: inc/classes/class-astra-sites.php:221
|
126 |
-
msgid "Done! View Site"
|
127 |
-
msgstr ""
|
128 |
-
|
129 |
-
#: inc/classes/class-astra-sites.php:222
|
130 |
-
msgid "Activating"
|
131 |
-
msgstr ""
|
132 |
-
|
133 |
-
#: inc/classes/class-astra-sites.php:223
|
134 |
-
msgid "Active"
|
135 |
-
msgstr ""
|
136 |
-
|
137 |
-
#: inc/classes/class-astra-sites.php:224
|
138 |
-
msgid "Import failed."
|
139 |
-
msgstr ""
|
140 |
-
|
141 |
-
#: inc/classes/class-astra-sites.php:225
|
142 |
-
msgid "Import failed. See error log."
|
143 |
-
msgstr ""
|
144 |
-
|
145 |
-
#: inc/classes/class-astra-sites.php:226
|
146 |
-
msgid "Import This Site"
|
147 |
-
msgstr ""
|
148 |
-
|
149 |
-
#: inc/classes/class-astra-sites.php:227 inc/classes/class-astra-sites.php:244
|
150 |
-
msgid "Importing.."
|
151 |
-
msgstr ""
|
152 |
-
|
153 |
-
#: inc/classes/class-astra-sites.php:228 inc/includes/admin-page.php:
|
154 |
-
msgid "Read more"
|
155 |
-
msgstr ""
|
156 |
-
|
157 |
-
#: inc/classes/class-astra-sites.php:229
|
158 |
-
msgid "Hide"
|
159 |
-
msgstr ""
|
160 |
-
|
161 |
-
#: inc/classes/class-astra-sites.php:230
|
162 |
-
msgid "There was a problem receiving a response from server."
|
163 |
-
msgstr ""
|
164 |
-
|
165 |
-
#: inc/classes/class-astra-sites.php:231 inc/includes/admin-page.php:
|
166 |
-
msgid "No Demos found, Try a different search."
|
167 |
-
msgstr ""
|
168 |
-
|
169 |
-
#: inc/classes/class-astra-sites.php:232
|
170 |
-
msgid ""
|
171 |
-
"Executing Demo Import will make your site similar as ours. Please bear in "
|
172 |
-
"mind -\n"
|
173 |
-
"\n"
|
174 |
-
"1. It is recommended to run import on a fresh WordPress installation.\n"
|
175 |
-
"\n"
|
176 |
-
"2. Importing site does not delete any pages or posts. However, it can "
|
177 |
-
"overwrite your existing content.\n"
|
178 |
-
"\n"
|
179 |
-
"3. Copyrighted media will not be imported. Instead it will be replaced with "
|
180 |
-
"placeholders."
|
181 |
-
msgstr ""
|
182 |
-
|
183 |
-
#: inc/classes/class-astra-sites.php:235
|
184 |
-
msgid "Installing plugin "
|
185 |
-
msgstr ""
|
186 |
-
|
187 |
-
#: inc/classes/class-astra-sites.php:236
|
188 |
-
msgid "Successfully plugin installed!"
|
189 |
-
msgstr ""
|
190 |
-
|
191 |
-
#: inc/classes/class-astra-sites.php:237
|
192 |
-
msgid "Activating plugin "
|
193 |
-
msgstr ""
|
194 |
-
|
195 |
-
#: inc/classes/class-astra-sites.php:238
|
196 |
-
msgid "Successfully plugin activated "
|
197 |
-
msgstr ""
|
198 |
-
|
199 |
-
#: inc/classes/class-astra-sites.php:239
|
200 |
-
msgid "Bulk plugin activation..."
|
201 |
-
msgstr ""
|
202 |
-
|
203 |
-
#: inc/classes/class-astra-sites.php:240
|
204 |
-
msgid "Successfully plugin activate - "
|
205 |
-
msgstr ""
|
206 |
-
|
207 |
-
#: inc/classes/class-astra-sites.php:241
|
208 |
-
msgid "Error! While activating plugin - "
|
209 |
-
msgstr ""
|
210 |
-
|
211 |
-
#: inc/classes/class-astra-sites.php:242
|
212 |
-
msgid "Bulk plugin installation..."
|
213 |
-
msgstr ""
|
214 |
-
|
215 |
-
#: inc/classes/class-astra-sites.php:243
|
216 |
-
msgid "Site API "
|
217 |
-
msgstr ""
|
218 |
-
|
219 |
-
#: inc/classes/class-astra-sites.php:245
|
220 |
-
msgid "Processing requests..."
|
221 |
-
msgstr ""
|
222 |
-
|
223 |
-
#: inc/classes/class-astra-sites.php:246
|
224 |
-
msgid "1) Importing \"Customizer Settings\"..."
|
225 |
-
msgstr ""
|
226 |
-
|
227 |
-
#: inc/classes/class-astra-sites.php:247
|
228 |
-
msgid "Successfully imported customizer settings!"
|
229 |
-
msgstr ""
|
230 |
-
|
231 |
-
#: inc/classes/class-astra-sites.php:248
|
232 |
-
msgid "2) Preparing \"XML\" Data..."
|
233 |
-
msgstr ""
|
234 |
-
|
235 |
-
#: inc/classes/class-astra-sites.php:249
|
236 |
-
msgid "Successfully set XML data!"
|
237 |
-
msgstr ""
|
238 |
-
|
239 |
-
#: inc/classes/class-astra-sites.php:250
|
240 |
-
msgid "3) Importing \"XML\"..."
|
241 |
-
msgstr ""
|
242 |
-
|
243 |
-
#: inc/classes/class-astra-sites.php:251
|
244 |
-
msgid "Successfully imported XML!"
|
245 |
-
msgstr ""
|
246 |
-
|
247 |
-
#: inc/classes/class-astra-sites.php:252
|
248 |
-
msgid "4) Importing \"Options\"..."
|
249 |
-
msgstr ""
|
250 |
-
|
251 |
-
#: inc/classes/class-astra-sites.php:253
|
252 |
-
msgid "Successfully imported Options!"
|
253 |
-
msgstr ""
|
254 |
-
|
255 |
-
#: inc/classes/class-astra-sites.php:254
|
256 |
-
msgid "5) Importing \"Widgets\"..."
|
257 |
-
msgstr ""
|
258 |
-
|
259 |
-
#: inc/classes/class-astra-sites.php:255
|
260 |
-
msgid "Successfully imported Widgets!"
|
261 |
-
msgstr ""
|
262 |
-
|
263 |
-
#: inc/classes/class-astra-sites.php:257
|
264 |
-
msgid "Site imported successfully! visit : "
|
265 |
-
msgstr ""
|
266 |
-
|
267 |
-
#: inc/classes/class-astra-sites.php:258
|
268 |
-
msgid "Getting Site Information.."
|
269 |
-
msgstr ""
|
270 |
-
|
271 |
-
#: inc/classes/class-astra-sites.php:259
|
272 |
-
msgid "Importing Customizer Settings.."
|
273 |
-
msgstr ""
|
274 |
-
|
275 |
-
#: inc/classes/class-astra-sites.php:260
|
276 |
-
msgid "Setting up import data.."
|
277 |
-
msgstr ""
|
278 |
-
|
279 |
-
#: inc/classes/class-astra-sites.php:261
|
280 |
-
msgid "Importing Pages, Posts & Media.."
|
281 |
-
msgstr ""
|
282 |
-
|
283 |
-
#: inc/classes/class-astra-sites.php:262
|
284 |
-
msgid "Importing Site Options.."
|
285 |
-
msgstr ""
|
286 |
-
|
287 |
-
#: inc/classes/class-astra-sites.php:263
|
288 |
-
msgid "Importing Widgets.."
|
289 |
-
msgstr ""
|
290 |
-
|
291 |
-
#: inc/classes/class-astra-sites.php:264
|
292 |
-
msgid "Import Complete.."
|
293 |
-
msgstr ""
|
294 |
-
|
295 |
-
#: inc/classes/class-astra-sites.php:265
|
296 |
-
msgid "Previewing "
|
297 |
-
msgstr ""
|
298 |
-
|
299 |
-
#: inc/classes/class-astra-sites.php:266
|
300 |
-
msgid "See Error Log →"
|
301 |
-
msgstr ""
|
302 |
-
|
303 |
-
#: inc/classes/class-astra-sites.php:301
|
304 |
-
msgid "No plugin specified"
|
305 |
-
msgstr ""
|
306 |
-
|
307 |
-
#: inc/classes/class-astra-sites.php:330
|
308 |
-
msgid "Plugin Successfully Activated"
|
309 |
-
msgstr ""
|
310 |
-
|
311 |
-
#: inc/importers/batch-processing/class-astra-sites-batch-processing-elementor-v2.php:60
|
312 |
-
#: inc/importers/batch-processing/class-astra-sites-batch-processing-elementor.php:59
|
313 |
-
msgid "Remote"
|
314 |
-
msgstr ""
|
315 |
-
|
316 |
-
#: inc/importers/batch-processing/helpers/class-wp-background-process.php:433
|
317 |
-
msgid "Every %d Minutes"
|
318 |
-
msgstr ""
|
319 |
-
|
320 |
-
#: inc/importers/class-widgets-importer.php:83
|
321 |
-
msgid "Import data could not be read. Please try a different file."
|
322 |
-
msgstr ""
|
323 |
-
|
324 |
-
#: inc/importers/class-widgets-importer.php:127
|
325 |
-
msgid "Widget area does not exist in theme (using Inactive)"
|
326 |
-
msgstr ""
|
327 |
-
|
328 |
-
#: inc/importers/class-widgets-importer.php:149
|
329 |
-
msgid "Site does not support widget"
|
330 |
-
msgstr ""
|
331 |
-
|
332 |
-
#: inc/importers/class-widgets-importer.php:185
|
333 |
-
msgid "Widget already exists"
|
334 |
-
msgstr ""
|
335 |
-
|
336 |
-
#: inc/importers/class-widgets-importer.php:254
|
337 |
-
msgid "Imported"
|
338 |
-
msgstr ""
|
339 |
-
|
340 |
-
#: inc/importers/class-widgets-importer.php:257
|
341 |
-
msgid "Imported to Inactive"
|
342 |
-
msgstr ""
|
343 |
-
|
344 |
-
#: inc/importers/class-widgets-importer.php:263
|
345 |
-
msgid "No Title"
|
346 |
-
msgstr ""
|
347 |
-
|
348 |
-
#: inc/importers/wxr-importer/class-astra-wxr-importer.php:194
|
349 |
-
msgid "Import complete!"
|
350 |
-
msgstr ""
|
351 |
-
|
352 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:130
|
353 |
-
msgid "Could not open the file for parsing"
|
354 |
-
msgstr ""
|
355 |
-
|
356 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:166
|
357 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:282
|
358 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:355
|
359 |
-
msgid ""
|
360 |
-
"This WXR file (version %1$s) is newer than the importer (version %2$s) and "
|
361 |
-
"may not be supported. Please consider updating."
|
362 |
-
msgstr ""
|
363 |
-
|
364 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:503
|
365 |
-
msgid "The file does not exist, please try again."
|
366 |
-
msgstr ""
|
367 |
-
|
368 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:563
|
369 |
-
msgid "Invalid author mapping"
|
370 |
-
msgstr ""
|
371 |
-
|
372 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:664
|
373 |
-
msgid "Cannot import auto-draft posts"
|
374 |
-
msgstr ""
|
375 |
-
|
376 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:752
|
377 |
-
msgid "Failed to import \"%1$s\": Invalid post type %2$s"
|
378 |
-
msgstr ""
|
379 |
-
|
380 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:762
|
381 |
-
msgid "%1$s \"%2$s\" already exists."
|
382 |
-
msgstr ""
|
383 |
-
|
384 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:856
|
385 |
-
msgid "Skipping attachment \"%s\", fetching attachments disabled"
|
386 |
-
msgstr ""
|
387 |
-
|
388 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:877
|
389 |
-
msgid "Failed to import \"%1$s\" (%2$s)"
|
390 |
-
msgstr ""
|
391 |
-
|
392 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:909
|
393 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1754
|
394 |
-
msgid "Imported \"%1$s\" (%2$s)"
|
395 |
-
msgstr ""
|
396 |
-
|
397 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:914
|
398 |
-
msgid "Post %1$d remapped to %2$d"
|
399 |
-
msgstr ""
|
400 |
-
|
401 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1061
|
402 |
-
msgid "Invalid file type"
|
403 |
-
msgstr ""
|
404 |
-
|
405 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1559
|
406 |
-
msgid "Failed to import user \"%s\""
|
407 |
-
msgstr ""
|
408 |
-
|
409 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1580
|
410 |
-
msgid "Imported user \"%s\""
|
411 |
-
msgstr ""
|
412 |
-
|
413 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1584
|
414 |
-
msgid "User %1$d remapped to %2$d"
|
415 |
-
msgstr ""
|
416 |
-
|
417 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1730
|
418 |
-
msgid "Failed to import %1$s %2$s"
|
419 |
-
msgstr ""
|
420 |
-
|
421 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1759
|
422 |
-
msgid "Term %1$d remapped to %2$d"
|
423 |
-
msgstr ""
|
424 |
-
|
425 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1812
|
426 |
-
msgid "Remote server returned %1$d %2$s for %3$s"
|
427 |
-
msgstr ""
|
428 |
-
|
429 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1825
|
430 |
-
msgid "Remote file is incorrect size"
|
431 |
-
msgstr ""
|
432 |
-
|
433 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1830
|
434 |
-
msgid "Zero size file downloaded"
|
435 |
-
msgstr ""
|
436 |
-
|
437 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1836
|
438 |
-
msgid "Remote file is too large, limit is %s"
|
439 |
-
msgstr ""
|
440 |
-
|
441 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1858
|
442 |
-
msgid "Running post-processing for post %d"
|
443 |
-
msgstr ""
|
444 |
-
|
445 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1871
|
446 |
-
msgid "Could not find the post parent for \"%1$s\" (post #%2$d)"
|
447 |
-
msgstr ""
|
448 |
-
|
449 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1876
|
450 |
-
msgid "Post %1$d was imported with parent %2$d, but could not be found"
|
451 |
-
msgstr ""
|
452 |
-
|
453 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1890
|
454 |
-
msgid "Could not find the author for \"%1$s\" (post #%2$d)"
|
455 |
-
msgstr ""
|
456 |
-
|
457 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1895
|
458 |
-
msgid "Post %1$d was imported with author \"%2$s\", but could not be found"
|
459 |
-
msgstr ""
|
460 |
-
|
461 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1921
|
462 |
-
msgid "Post %d was marked for post-processing, but none was required."
|
463 |
-
msgstr ""
|
464 |
-
|
465 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1932
|
466 |
-
msgid "Could not update \"%1$s\" (post #%2$d) with mapped data"
|
467 |
-
msgstr ""
|
468 |
-
|
469 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1977
|
470 |
-
msgid "Could not find the menu object for \"%1$s\" (post #%2$d)"
|
471 |
-
msgstr ""
|
472 |
-
|
473 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:1982
|
474 |
-
msgid ""
|
475 |
-
"Post %1$d was imported with object \"%2$d\" of type \"%3$s\", but could not "
|
476 |
-
"be found"
|
477 |
-
msgstr ""
|
478 |
-
|
479 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:2004
|
480 |
-
msgid "Could not find the comment parent for comment #%d"
|
481 |
-
msgstr ""
|
482 |
-
|
483 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:2008
|
484 |
-
msgid "Comment %1$d was imported with parent %2$d, but could not be found"
|
485 |
-
msgstr ""
|
486 |
-
|
487 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:2022
|
488 |
-
msgid "Could not find the author for comment #%d"
|
489 |
-
msgstr ""
|
490 |
-
|
491 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:2026
|
492 |
-
msgid "Comment %1$d was imported with author %2$d, but could not be found"
|
493 |
-
msgstr ""
|
494 |
-
|
495 |
-
#: inc/importers/wxr-importer/class-wxr-importer.php:2043
|
496 |
-
msgid "Could not update comment #%d with mapped data"
|
497 |
-
msgstr ""
|
498 |
-
|
499 |
-
#: inc/includes/admin-page.php:41
|
500 |
-
msgid "Search Sites"
|
501 |
-
msgstr ""
|
502 |
-
|
503 |
-
#: inc/includes/admin-page.php:42
|
504 |
-
msgid "Search Sites..."
|
505 |
-
msgstr ""
|
506 |
-
|
507 |
-
#: inc/includes/admin-page.php:
|
508 |
-
msgid "Select Your Favorite Page Builder"
|
509 |
-
msgstr ""
|
510 |
-
|
511 |
-
#: inc/includes/admin-page.php:
|
512 |
-
msgid "Sites List.."
|
513 |
-
msgstr ""
|
514 |
-
|
515 |
-
#: inc/includes/admin-page.php:
|
516 |
-
msgid "Close"
|
517 |
-
msgstr ""
|
518 |
-
|
519 |
-
#: inc/includes/admin-page.php:
|
520 |
-
msgid "Previous"
|
521 |
-
msgstr ""
|
522 |
-
|
523 |
-
#: inc/includes/admin-page.php:
|
524 |
-
msgid "Next"
|
525 |
-
msgstr ""
|
526 |
-
|
527 |
-
#: inc/includes/admin-page.php:
|
528 |
-
msgid "Install Plugins"
|
529 |
-
msgstr ""
|
530 |
-
|
531 |
-
#: inc/includes/admin-page.php:
|
532 |
-
msgid "Required Plugins"
|
533 |
-
msgstr ""
|
534 |
-
|
535 |
-
#: inc/includes/admin-page.php:
|
536 |
-
msgid "Collapse"
|
537 |
-
msgstr ""
|
538 |
-
|
539 |
-
#: inc/includes/admin-page.php:
|
540 |
-
msgid "Enter desktop preview mode"
|
541 |
-
msgstr ""
|
542 |
-
|
543 |
-
#: inc/includes/admin-page.php:
|
544 |
-
msgid "Enter tablet preview mode"
|
545 |
-
msgstr ""
|
546 |
-
|
547 |
-
#: inc/includes/admin-page.php:
|
548 |
-
msgid "Enter mobile preview mode"
|
549 |
-
msgstr ""
|
550 |
-
|
551 |
-
#: inc/includes/admin-page.php:
|
552 |
-
msgid "Preview"
|
553 |
-
msgstr ""
|
554 |
-
|
555 |
-
#: inc/includes/admin-page.php:
|
556 |
-
#. translators: %1$s & %2$s are a Demo API URL
|
557 |
-
msgid ""
|
558 |
-
"<p> It seems the demo data server, <i><a href=\"%1$s\">%2$s</a></i> is "
|
559 |
-
"unreachable from your site.</p>"
|
560 |
-
msgstr ""
|
561 |
-
|
562 |
-
#: inc/includes/admin-page.php:
|
563 |
-
msgid ""
|
564 |
-
"<p class=\"left-margin\"> 1. Sometimes, simple page reload fixes any "
|
565 |
-
"temporary issues. No kidding!</p>"
|
566 |
-
msgstr ""
|
567 |
-
|
568 |
-
#: inc/includes/admin-page.php:
|
569 |
-
msgid ""
|
570 |
-
"<p class=\"left-margin\"> 2. If that does not work, you will need to talk "
|
571 |
-
"to your server administrator and check if demo server is being blocked by "
|
572 |
-
"the firewall!</p>"
|
573 |
-
msgstr ""
|
574 |
-
|
575 |
-
#: inc/includes/admin-page.php:
|
576 |
-
#. translators: %1$s is a support link
|
577 |
-
msgid ""
|
578 |
-
"<p>If that does not help, please open up a <a href=\"%1$s\" "
|
579 |
-
"target=\"_blank\">Support Ticket</a> and we will be glad take a closer look "
|
580 |
-
"for you.</p>"
|
581 |
-
msgstr ""
|
582 |
-
|
583 |
-
#: inc/includes/admin-page.php:
|
584 |
-
msgid "Details & Preview"
|
585 |
-
msgstr ""
|
586 |
-
|
587 |
-
#: inc/includes/admin-page.php:
|
588 |
-
#. translators: %1$s External Link
|
589 |
-
msgid ""
|
590 |
-
"Don't see a site that you would like to import?<br><a target=\"_blank\" "
|
591 |
-
"href=\"%1$s\">Please suggest us!</a>"
|
592 |
-
msgstr ""
|
593 |
-
|
594 |
-
#: inc/includes/white-label.php:23
|
595 |
-
msgid "Plugin Name:"
|
596 |
-
msgstr ""
|
597 |
-
|
598 |
-
#: inc/includes/white-label.php:28
|
599 |
-
msgid "Plugin Description:"
|
600 |
-
msgstr ""
|
601 |
-
|
602 |
-
#. Plugin Name of the plugin/theme
|
603 |
-
msgid "Astra Starter Sites"
|
604 |
-
msgstr ""
|
605 |
-
|
606 |
-
#. Plugin URI of the plugin/theme
|
607 |
-
msgid "http://www.wpastra.com/pro/"
|
608 |
-
msgstr ""
|
609 |
-
|
610 |
-
#. Description of the plugin/theme
|
611 |
-
msgid "Import free sites build with Astra theme."
|
612 |
-
msgstr ""
|
613 |
-
|
614 |
-
#. Author of the plugin/theme
|
615 |
-
msgid "Brainstorm Force"
|
616 |
-
msgstr ""
|
617 |
-
|
618 |
-
#. Author URI of the plugin/theme
|
619 |
-
msgid "http://www.brainstormforce.com"
|
620 |
-
msgstr ""
|
621 |
-
|
622 |
-
#: inc/classes/class-astra-sites-importer-log.php:372
|
623 |
-
#. translators: %1$s Memory Limit, %2$s Recommended memory limit.
|
624 |
-
msgctxt "Recommended Memory Limit"
|
625 |
-
msgid "Current memory limit %1$s. We recommend setting memory to at least %2$s."
|
626 |
-
msgstr ""
|
627 |
-
|
628 |
-
#: inc/classes/class-astra-sites-importer-log.php:438
|
629 |
-
msgctxt "PHP Version"
|
630 |
-
msgid "We recommend to use php 5.4 or higher"
|
631 |
ย
msgstr ""
|
1 |
+
# Copyright (C) 2018 Brainstorm Force
|
2 |
+
# This file is distributed under the same license as the Astra Starter Sites package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"Project-Id-Version: Astra Starter Sites 1.2.4\n"
|
6 |
+
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/astra-sites\n"
|
7 |
+
"POT-Creation-Date: 2018-06-29 12:12:52+00:00\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2018-MO-DA HO:MI+ZONE\n"
|
12 |
+
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
+
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
+
"Language: en\n"
|
15 |
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
16 |
+
"X-Poedit-Country: United States\n"
|
17 |
+
"X-Poedit-SourceCharset: UTF-8\n"
|
18 |
+
"X-Poedit-KeywordsList: "
|
19 |
+
"__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_"
|
20 |
+
"attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n"
|
21 |
+
"X-Poedit-Basepath: ../\n"
|
22 |
+
"X-Poedit-SearchPath-0: .\n"
|
23 |
+
"X-Poedit-Bookmarks: \n"
|
24 |
+
"X-Textdomain-Support: yes\n"
|
25 |
+
"X-Generator: grunt-wp-i18n1.0.0\n"
|
26 |
+
|
27 |
+
#: astra-sites.php:18 inc/classes/class-astra-sites-page.php:85
|
28 |
+
msgid "Astra Sites"
|
29 |
+
msgstr ""
|
30 |
+
|
31 |
+
#: inc/classes/class-astra-sites-importer-log.php:351
|
32 |
+
msgid "Enabled"
|
33 |
+
msgstr ""
|
34 |
+
|
35 |
+
#: inc/classes/class-astra-sites-importer-log.php:354
|
36 |
+
msgid "Disabled"
|
37 |
+
msgstr ""
|
38 |
+
|
39 |
+
#: inc/classes/class-astra-sites-importer-log.php:481
|
40 |
+
msgid "Yes"
|
41 |
+
msgstr ""
|
42 |
+
|
43 |
+
#: inc/classes/class-astra-sites-importer-log.php:484
|
44 |
+
msgid "No"
|
45 |
+
msgstr ""
|
46 |
+
|
47 |
+
#: inc/classes/class-astra-sites-importer.php:87
|
48 |
+
msgid "You have not \"customize\" access to import the Astra site."
|
49 |
+
msgstr ""
|
50 |
+
|
51 |
+
#: inc/classes/class-astra-sites-importer.php:111
|
52 |
+
msgid "Request site API URL is empty. Try again!"
|
53 |
+
msgstr ""
|
54 |
+
|
55 |
+
#: inc/classes/class-astra-sites-importer.php:134
|
56 |
+
msgid "Customizer data is empty!"
|
57 |
+
msgstr ""
|
58 |
+
|
59 |
+
#: inc/classes/class-astra-sites-importer.php:163
|
60 |
+
msgid "There was an error downloading the XML file."
|
61 |
+
msgstr ""
|
62 |
+
|
63 |
+
#: inc/classes/class-astra-sites-importer.php:169
|
64 |
+
msgid "Invalid site XML file!"
|
65 |
+
msgstr ""
|
66 |
+
|
67 |
+
#: inc/classes/class-astra-sites-importer.php:191
|
68 |
+
msgid "Site options are empty!"
|
69 |
+
msgstr ""
|
70 |
+
|
71 |
+
#: inc/classes/class-astra-sites-importer.php:213
|
72 |
+
msgid "Widget data is empty!"
|
73 |
+
msgstr ""
|
74 |
+
|
75 |
+
#: inc/classes/class-astra-sites-page.php:192
|
76 |
+
msgid "Settings saved successfully."
|
77 |
+
msgstr ""
|
78 |
+
|
79 |
+
#: inc/classes/class-astra-sites-white-label.php:176
|
80 |
+
#. translators: %1$s product name
|
81 |
+
msgid "%1$s Branding"
|
82 |
+
msgstr ""
|
83 |
+
|
84 |
+
#: inc/classes/class-astra-sites.php:81
|
85 |
+
#. translators: 1: theme.php file
|
86 |
+
msgid ""
|
87 |
+
"Astra Theme needs to be active for you to use currently installed \"%1$s\" "
|
88 |
+
"plugin. <a href=\"%2$s\">Install & Activate Now</a>"
|
89 |
+
msgstr ""
|
90 |
+
|
91 |
+
#: inc/classes/class-astra-sites.php:121
|
92 |
+
msgid "See Library"
|
93 |
+
msgstr ""
|
94 |
+
|
95 |
+
#: inc/classes/class-astra-sites.php:172
|
96 |
+
msgid "Page Builder"
|
97 |
+
msgstr ""
|
98 |
+
|
99 |
+
#: inc/classes/class-astra-sites.php:177
|
100 |
+
msgid "Categories"
|
101 |
+
msgstr ""
|
102 |
+
|
103 |
+
#: inc/classes/class-astra-sites.php:210
|
104 |
+
msgid "Purchase"
|
105 |
+
msgstr ""
|
106 |
+
|
107 |
+
#: inc/classes/class-astra-sites.php:212
|
108 |
+
msgid "Upgrade"
|
109 |
+
msgstr ""
|
110 |
+
|
111 |
+
#: inc/classes/class-astra-sites.php:217
|
112 |
+
msgid ""
|
113 |
+
"Warning! Astra Site Import process is not complete. Don't close the window "
|
114 |
+
"until import process complete. Do you still want to leave the window?"
|
115 |
+
msgstr ""
|
116 |
+
|
117 |
+
#: inc/classes/class-astra-sites.php:218
|
118 |
+
msgid "Error!"
|
119 |
+
msgstr ""
|
120 |
+
|
121 |
+
#: inc/classes/class-astra-sites.php:219
|
122 |
+
msgid "Error! Read Possibilities."
|
123 |
+
msgstr ""
|
124 |
+
|
125 |
+
#: inc/classes/class-astra-sites.php:221
|
126 |
+
msgid "Done! View Site"
|
127 |
+
msgstr ""
|
128 |
+
|
129 |
+
#: inc/classes/class-astra-sites.php:222
|
130 |
+
msgid "Activating"
|
131 |
+
msgstr ""
|
132 |
+
|
133 |
+
#: inc/classes/class-astra-sites.php:223
|
134 |
+
msgid "Active"
|
135 |
+
msgstr ""
|
136 |
+
|
137 |
+
#: inc/classes/class-astra-sites.php:224
|
138 |
+
msgid "Import failed."
|
139 |
+
msgstr ""
|
140 |
+
|
141 |
+
#: inc/classes/class-astra-sites.php:225
|
142 |
+
msgid "Import failed. See error log."
|
143 |
+
msgstr ""
|
144 |
+
|
145 |
+
#: inc/classes/class-astra-sites.php:226
|
146 |
+
msgid "Import This Site"
|
147 |
+
msgstr ""
|
148 |
+
|
149 |
+
#: inc/classes/class-astra-sites.php:227 inc/classes/class-astra-sites.php:244
|
150 |
+
msgid "Importing.."
|
151 |
+
msgstr ""
|
152 |
+
|
153 |
+
#: inc/classes/class-astra-sites.php:228 inc/includes/admin-page.php:119
|
154 |
+
msgid "Read more"
|
155 |
+
msgstr ""
|
156 |
+
|
157 |
+
#: inc/classes/class-astra-sites.php:229
|
158 |
+
msgid "Hide"
|
159 |
+
msgstr ""
|
160 |
+
|
161 |
+
#: inc/classes/class-astra-sites.php:230
|
162 |
+
msgid "There was a problem receiving a response from server."
|
163 |
+
msgstr ""
|
164 |
+
|
165 |
+
#: inc/classes/class-astra-sites.php:231 inc/includes/admin-page.php:266
|
166 |
+
msgid "No Demos found, Try a different search."
|
167 |
+
msgstr ""
|
168 |
+
|
169 |
+
#: inc/classes/class-astra-sites.php:232
|
170 |
+
msgid ""
|
171 |
+
"Executing Demo Import will make your site similar as ours. Please bear in "
|
172 |
+
"mind -\n"
|
173 |
+
"\n"
|
174 |
+
"1. It is recommended to run import on a fresh WordPress installation.\n"
|
175 |
+
"\n"
|
176 |
+
"2. Importing site does not delete any pages or posts. However, it can "
|
177 |
+
"overwrite your existing content.\n"
|
178 |
+
"\n"
|
179 |
+
"3. Copyrighted media will not be imported. Instead it will be replaced with "
|
180 |
+
"placeholders."
|
181 |
+
msgstr ""
|
182 |
+
|
183 |
+
#: inc/classes/class-astra-sites.php:235
|
184 |
+
msgid "Installing plugin "
|
185 |
+
msgstr ""
|
186 |
+
|
187 |
+
#: inc/classes/class-astra-sites.php:236
|
188 |
+
msgid "Successfully plugin installed!"
|
189 |
+
msgstr ""
|
190 |
+
|
191 |
+
#: inc/classes/class-astra-sites.php:237
|
192 |
+
msgid "Activating plugin "
|
193 |
+
msgstr ""
|
194 |
+
|
195 |
+
#: inc/classes/class-astra-sites.php:238
|
196 |
+
msgid "Successfully plugin activated "
|
197 |
+
msgstr ""
|
198 |
+
|
199 |
+
#: inc/classes/class-astra-sites.php:239
|
200 |
+
msgid "Bulk plugin activation..."
|
201 |
+
msgstr ""
|
202 |
+
|
203 |
+
#: inc/classes/class-astra-sites.php:240
|
204 |
+
msgid "Successfully plugin activate - "
|
205 |
+
msgstr ""
|
206 |
+
|
207 |
+
#: inc/classes/class-astra-sites.php:241
|
208 |
+
msgid "Error! While activating plugin - "
|
209 |
+
msgstr ""
|
210 |
+
|
211 |
+
#: inc/classes/class-astra-sites.php:242
|
212 |
+
msgid "Bulk plugin installation..."
|
213 |
+
msgstr ""
|
214 |
+
|
215 |
+
#: inc/classes/class-astra-sites.php:243
|
216 |
+
msgid "Site API "
|
217 |
+
msgstr ""
|
218 |
+
|
219 |
+
#: inc/classes/class-astra-sites.php:245
|
220 |
+
msgid "Processing requests..."
|
221 |
+
msgstr ""
|
222 |
+
|
223 |
+
#: inc/classes/class-astra-sites.php:246
|
224 |
+
msgid "1) Importing \"Customizer Settings\"..."
|
225 |
+
msgstr ""
|
226 |
+
|
227 |
+
#: inc/classes/class-astra-sites.php:247
|
228 |
+
msgid "Successfully imported customizer settings!"
|
229 |
+
msgstr ""
|
230 |
+
|
231 |
+
#: inc/classes/class-astra-sites.php:248
|
232 |
+
msgid "2) Preparing \"XML\" Data..."
|
233 |
+
msgstr ""
|
234 |
+
|
235 |
+
#: inc/classes/class-astra-sites.php:249
|
236 |
+
msgid "Successfully set XML data!"
|
237 |
+
msgstr ""
|
238 |
+
|
239 |
+
#: inc/classes/class-astra-sites.php:250
|
240 |
+
msgid "3) Importing \"XML\"..."
|
241 |
+
msgstr ""
|
242 |
+
|
243 |
+
#: inc/classes/class-astra-sites.php:251
|
244 |
+
msgid "Successfully imported XML!"
|
245 |
+
msgstr ""
|
246 |
+
|
247 |
+
#: inc/classes/class-astra-sites.php:252
|
248 |
+
msgid "4) Importing \"Options\"..."
|
249 |
+
msgstr ""
|
250 |
+
|
251 |
+
#: inc/classes/class-astra-sites.php:253
|
252 |
+
msgid "Successfully imported Options!"
|
253 |
+
msgstr ""
|
254 |
+
|
255 |
+
#: inc/classes/class-astra-sites.php:254
|
256 |
+
msgid "5) Importing \"Widgets\"..."
|
257 |
+
msgstr ""
|
258 |
+
|
259 |
+
#: inc/classes/class-astra-sites.php:255
|
260 |
+
msgid "Successfully imported Widgets!"
|
261 |
+
msgstr ""
|
262 |
+
|
263 |
+
#: inc/classes/class-astra-sites.php:257
|
264 |
+
msgid "Site imported successfully! visit : "
|
265 |
+
msgstr ""
|
266 |
+
|
267 |
+
#: inc/classes/class-astra-sites.php:258
|
268 |
+
msgid "Getting Site Information.."
|
269 |
+
msgstr ""
|
270 |
+
|
271 |
+
#: inc/classes/class-astra-sites.php:259
|
272 |
+
msgid "Importing Customizer Settings.."
|
273 |
+
msgstr ""
|
274 |
+
|
275 |
+
#: inc/classes/class-astra-sites.php:260
|
276 |
+
msgid "Setting up import data.."
|
277 |
+
msgstr ""
|
278 |
+
|
279 |
+
#: inc/classes/class-astra-sites.php:261
|
280 |
+
msgid "Importing Pages, Posts & Media.."
|
281 |
+
msgstr ""
|
282 |
+
|
283 |
+
#: inc/classes/class-astra-sites.php:262
|
284 |
+
msgid "Importing Site Options.."
|
285 |
+
msgstr ""
|
286 |
+
|
287 |
+
#: inc/classes/class-astra-sites.php:263
|
288 |
+
msgid "Importing Widgets.."
|
289 |
+
msgstr ""
|
290 |
+
|
291 |
+
#: inc/classes/class-astra-sites.php:264
|
292 |
+
msgid "Import Complete.."
|
293 |
+
msgstr ""
|
294 |
+
|
295 |
+
#: inc/classes/class-astra-sites.php:265
|
296 |
+
msgid "Previewing "
|
297 |
+
msgstr ""
|
298 |
+
|
299 |
+
#: inc/classes/class-astra-sites.php:266
|
300 |
+
msgid "See Error Log →"
|
301 |
+
msgstr ""
|
302 |
+
|
303 |
+
#: inc/classes/class-astra-sites.php:301
|
304 |
+
msgid "No plugin specified"
|
305 |
+
msgstr ""
|
306 |
+
|
307 |
+
#: inc/classes/class-astra-sites.php:330
|
308 |
+
msgid "Plugin Successfully Activated"
|
309 |
+
msgstr ""
|
310 |
+
|
311 |
+
#: inc/importers/batch-processing/class-astra-sites-batch-processing-elementor-v2.php:60
|
312 |
+
#: inc/importers/batch-processing/class-astra-sites-batch-processing-elementor.php:59
|
313 |
+
msgid "Remote"
|
314 |
+
msgstr ""
|
315 |
+
|
316 |
+
#: inc/importers/batch-processing/helpers/class-wp-background-process.php:433
|
317 |
+
msgid "Every %d Minutes"
|
318 |
+
msgstr ""
|
319 |
+
|
320 |
+
#: inc/importers/class-widgets-importer.php:83
|
321 |
+
msgid "Import data could not be read. Please try a different file."
|
322 |
+
msgstr ""
|
323 |
+
|
324 |
+
#: inc/importers/class-widgets-importer.php:127
|
325 |
+
msgid "Widget area does not exist in theme (using Inactive)"
|
326 |
+
msgstr ""
|
327 |
+
|
328 |
+
#: inc/importers/class-widgets-importer.php:149
|
329 |
+
msgid "Site does not support widget"
|
330 |
+
msgstr ""
|
331 |
+
|
332 |
+
#: inc/importers/class-widgets-importer.php:185
|
333 |
+
msgid "Widget already exists"
|
334 |
+
msgstr ""
|
335 |
+
|
336 |
+
#: inc/importers/class-widgets-importer.php:254
|
337 |
+
msgid "Imported"
|
338 |
+
msgstr ""
|
339 |
+
|
340 |
+
#: inc/importers/class-widgets-importer.php:257
|
341 |
+
msgid "Imported to Inactive"
|
342 |
+
msgstr ""
|
343 |
+
|
344 |
+
#: inc/importers/class-widgets-importer.php:263
|
345 |
+
msgid "No Title"
|
346 |
+
msgstr ""
|
347 |
+
|
348 |
+
#: inc/importers/wxr-importer/class-astra-wxr-importer.php:194
|
349 |
+
msgid "Import complete!"
|
350 |
+
msgstr ""
|
351 |
+
|
352 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:130
|
353 |
+
msgid "Could not open the file for parsing"
|
354 |
+
msgstr ""
|
355 |
+
|
356 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:166
|
357 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:282
|
358 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:355
|
359 |
+
msgid ""
|
360 |
+
"This WXR file (version %1$s) is newer than the importer (version %2$s) and "
|
361 |
+
"may not be supported. Please consider updating."
|
362 |
+
msgstr ""
|
363 |
+
|
364 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:503
|
365 |
+
msgid "The file does not exist, please try again."
|
366 |
+
msgstr ""
|
367 |
+
|
368 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:563
|
369 |
+
msgid "Invalid author mapping"
|
370 |
+
msgstr ""
|
371 |
+
|
372 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:664
|
373 |
+
msgid "Cannot import auto-draft posts"
|
374 |
+
msgstr ""
|
375 |
+
|
376 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:752
|
377 |
+
msgid "Failed to import \"%1$s\": Invalid post type %2$s"
|
378 |
+
msgstr ""
|
379 |
+
|
380 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:762
|
381 |
+
msgid "%1$s \"%2$s\" already exists."
|
382 |
+
msgstr ""
|
383 |
+
|
384 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:856
|
385 |
+
msgid "Skipping attachment \"%s\", fetching attachments disabled"
|
386 |
+
msgstr ""
|
387 |
+
|
388 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:877
|
389 |
+
msgid "Failed to import \"%1$s\" (%2$s)"
|
390 |
+
msgstr ""
|
391 |
+
|
392 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:909
|
393 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1754
|
394 |
+
msgid "Imported \"%1$s\" (%2$s)"
|
395 |
+
msgstr ""
|
396 |
+
|
397 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:914
|
398 |
+
msgid "Post %1$d remapped to %2$d"
|
399 |
+
msgstr ""
|
400 |
+
|
401 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1061
|
402 |
+
msgid "Invalid file type"
|
403 |
+
msgstr ""
|
404 |
+
|
405 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1559
|
406 |
+
msgid "Failed to import user \"%s\""
|
407 |
+
msgstr ""
|
408 |
+
|
409 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1580
|
410 |
+
msgid "Imported user \"%s\""
|
411 |
+
msgstr ""
|
412 |
+
|
413 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1584
|
414 |
+
msgid "User %1$d remapped to %2$d"
|
415 |
+
msgstr ""
|
416 |
+
|
417 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1730
|
418 |
+
msgid "Failed to import %1$s %2$s"
|
419 |
+
msgstr ""
|
420 |
+
|
421 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1759
|
422 |
+
msgid "Term %1$d remapped to %2$d"
|
423 |
+
msgstr ""
|
424 |
+
|
425 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1812
|
426 |
+
msgid "Remote server returned %1$d %2$s for %3$s"
|
427 |
+
msgstr ""
|
428 |
+
|
429 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1825
|
430 |
+
msgid "Remote file is incorrect size"
|
431 |
+
msgstr ""
|
432 |
+
|
433 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1830
|
434 |
+
msgid "Zero size file downloaded"
|
435 |
+
msgstr ""
|
436 |
+
|
437 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1836
|
438 |
+
msgid "Remote file is too large, limit is %s"
|
439 |
+
msgstr ""
|
440 |
+
|
441 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1858
|
442 |
+
msgid "Running post-processing for post %d"
|
443 |
+
msgstr ""
|
444 |
+
|
445 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1871
|
446 |
+
msgid "Could not find the post parent for \"%1$s\" (post #%2$d)"
|
447 |
+
msgstr ""
|
448 |
+
|
449 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1876
|
450 |
+
msgid "Post %1$d was imported with parent %2$d, but could not be found"
|
451 |
+
msgstr ""
|
452 |
+
|
453 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1890
|
454 |
+
msgid "Could not find the author for \"%1$s\" (post #%2$d)"
|
455 |
+
msgstr ""
|
456 |
+
|
457 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1895
|
458 |
+
msgid "Post %1$d was imported with author \"%2$s\", but could not be found"
|
459 |
+
msgstr ""
|
460 |
+
|
461 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1921
|
462 |
+
msgid "Post %d was marked for post-processing, but none was required."
|
463 |
+
msgstr ""
|
464 |
+
|
465 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1932
|
466 |
+
msgid "Could not update \"%1$s\" (post #%2$d) with mapped data"
|
467 |
+
msgstr ""
|
468 |
+
|
469 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1977
|
470 |
+
msgid "Could not find the menu object for \"%1$s\" (post #%2$d)"
|
471 |
+
msgstr ""
|
472 |
+
|
473 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:1982
|
474 |
+
msgid ""
|
475 |
+
"Post %1$d was imported with object \"%2$d\" of type \"%3$s\", but could not "
|
476 |
+
"be found"
|
477 |
+
msgstr ""
|
478 |
+
|
479 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:2004
|
480 |
+
msgid "Could not find the comment parent for comment #%d"
|
481 |
+
msgstr ""
|
482 |
+
|
483 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:2008
|
484 |
+
msgid "Comment %1$d was imported with parent %2$d, but could not be found"
|
485 |
+
msgstr ""
|
486 |
+
|
487 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:2022
|
488 |
+
msgid "Could not find the author for comment #%d"
|
489 |
+
msgstr ""
|
490 |
+
|
491 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:2026
|
492 |
+
msgid "Comment %1$d was imported with author %2$d, but could not be found"
|
493 |
+
msgstr ""
|
494 |
+
|
495 |
+
#: inc/importers/wxr-importer/class-wxr-importer.php:2043
|
496 |
+
msgid "Could not update comment #%d with mapped data"
|
497 |
+
msgstr ""
|
498 |
+
|
499 |
+
#: inc/includes/admin-page.php:41
|
500 |
+
msgid "Search Sites"
|
501 |
+
msgstr ""
|
502 |
+
|
503 |
+
#: inc/includes/admin-page.php:42
|
504 |
+
msgid "Search Sites..."
|
505 |
+
msgstr ""
|
506 |
+
|
507 |
+
#: inc/includes/admin-page.php:73
|
508 |
+
msgid "Select Your Favorite Page Builder"
|
509 |
+
msgstr ""
|
510 |
+
|
511 |
+
#: inc/includes/admin-page.php:76
|
512 |
+
msgid "Sites List.."
|
513 |
+
msgstr ""
|
514 |
+
|
515 |
+
#: inc/includes/admin-page.php:100
|
516 |
+
msgid "Close"
|
517 |
+
msgstr ""
|
518 |
+
|
519 |
+
#: inc/includes/admin-page.php:101
|
520 |
+
msgid "Previous"
|
521 |
+
msgstr ""
|
522 |
+
|
523 |
+
#: inc/includes/admin-page.php:102
|
524 |
+
msgid "Next"
|
525 |
+
msgstr ""
|
526 |
+
|
527 |
+
#: inc/includes/admin-page.php:103 inc/includes/admin-page.php:131
|
528 |
+
msgid "Install Plugins"
|
529 |
+
msgstr ""
|
530 |
+
|
531 |
+
#: inc/includes/admin-page.php:122
|
532 |
+
msgid "Required Plugins"
|
533 |
+
msgstr ""
|
534 |
+
|
535 |
+
#: inc/includes/admin-page.php:137
|
536 |
+
msgid "Collapse"
|
537 |
+
msgstr ""
|
538 |
+
|
539 |
+
#: inc/includes/admin-page.php:143
|
540 |
+
msgid "Enter desktop preview mode"
|
541 |
+
msgstr ""
|
542 |
+
|
543 |
+
#: inc/includes/admin-page.php:146
|
544 |
+
msgid "Enter tablet preview mode"
|
545 |
+
msgstr ""
|
546 |
+
|
547 |
+
#: inc/includes/admin-page.php:149
|
548 |
+
msgid "Enter mobile preview mode"
|
549 |
+
msgstr ""
|
550 |
+
|
551 |
+
#: inc/includes/admin-page.php:157 inc/includes/admin-page.php:258
|
552 |
+
msgid "Preview"
|
553 |
+
msgstr ""
|
554 |
+
|
555 |
+
#: inc/includes/admin-page.php:172
|
556 |
+
#. translators: %1$s & %2$s are a Demo API URL
|
557 |
+
msgid ""
|
558 |
+
"<p> It seems the demo data server, <i><a href=\"%1$s\">%2$s</a></i> is "
|
559 |
+
"unreachable from your site.</p>"
|
560 |
+
msgstr ""
|
561 |
+
|
562 |
+
#: inc/includes/admin-page.php:174
|
563 |
+
msgid ""
|
564 |
+
"<p class=\"left-margin\"> 1. Sometimes, simple page reload fixes any "
|
565 |
+
"temporary issues. No kidding!</p>"
|
566 |
+
msgstr ""
|
567 |
+
|
568 |
+
#: inc/includes/admin-page.php:176
|
569 |
+
msgid ""
|
570 |
+
"<p class=\"left-margin\"> 2. If that does not work, you will need to talk "
|
571 |
+
"to your server administrator and check if demo server is being blocked by "
|
572 |
+
"the firewall!</p>"
|
573 |
+
msgstr ""
|
574 |
+
|
575 |
+
#: inc/includes/admin-page.php:179
|
576 |
+
#. translators: %1$s is a support link
|
577 |
+
msgid ""
|
578 |
+
"<p>If that does not help, please open up a <a href=\"%1$s\" "
|
579 |
+
"target=\"_blank\">Support Ticket</a> and we will be glad take a closer look "
|
580 |
+
"for you.</p>"
|
581 |
+
msgstr ""
|
582 |
+
|
583 |
+
#: inc/includes/admin-page.php:247
|
584 |
+
msgid "Details & Preview"
|
585 |
+
msgstr ""
|
586 |
+
|
587 |
+
#: inc/includes/admin-page.php:270 inc/includes/admin-page.php:288
|
588 |
+
#. translators: %1$s External Link
|
589 |
+
msgid ""
|
590 |
+
"Don't see a site that you would like to import?<br><a target=\"_blank\" "
|
591 |
+
"href=\"%1$s\">Please suggest us!</a>"
|
592 |
+
msgstr ""
|
593 |
+
|
594 |
+
#: inc/includes/white-label.php:23
|
595 |
+
msgid "Plugin Name:"
|
596 |
+
msgstr ""
|
597 |
+
|
598 |
+
#: inc/includes/white-label.php:28
|
599 |
+
msgid "Plugin Description:"
|
600 |
+
msgstr ""
|
601 |
+
|
602 |
+
#. Plugin Name of the plugin/theme
|
603 |
+
msgid "Astra Starter Sites"
|
604 |
+
msgstr ""
|
605 |
+
|
606 |
+
#. Plugin URI of the plugin/theme
|
607 |
+
msgid "http://www.wpastra.com/pro/"
|
608 |
+
msgstr ""
|
609 |
+
|
610 |
+
#. Description of the plugin/theme
|
611 |
+
msgid "Import free sites build with Astra theme."
|
612 |
+
msgstr ""
|
613 |
+
|
614 |
+
#. Author of the plugin/theme
|
615 |
+
msgid "Brainstorm Force"
|
616 |
+
msgstr ""
|
617 |
+
|
618 |
+
#. Author URI of the plugin/theme
|
619 |
+
msgid "http://www.brainstormforce.com"
|
620 |
+
msgstr ""
|
621 |
+
|
622 |
+
#: inc/classes/class-astra-sites-importer-log.php:372
|
623 |
+
#. translators: %1$s Memory Limit, %2$s Recommended memory limit.
|
624 |
+
msgctxt "Recommended Memory Limit"
|
625 |
+
msgid "Current memory limit %1$s. We recommend setting memory to at least %2$s."
|
626 |
+
msgstr ""
|
627 |
+
|
628 |
+
#: inc/classes/class-astra-sites-importer-log.php:438
|
629 |
+
msgctxt "PHP Version"
|
630 |
+
msgid "We recommend to use php 5.4 or higher"
|
631 |
ย
msgstr ""
|
readme.txt
CHANGED
@@ -1,186 +1,190 @@
|
|
1 |
-
=== Astra Starter Sites ===
|
2 |
-
Contributors: brainstormforce
|
3 |
-
Donate link: https://wpastra.com/pro/
|
4 |
-
Tags: demo, theme demos, one click import
|
5 |
-
Requires at least: 4.4
|
6 |
-
Requires PHP: 5.3
|
7 |
-
Tested up to: 4.9.6
|
8 |
-
Stable tag: 1.2.
|
9 |
-
License: GPLv2 or later
|
10 |
-
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
-
|
12 |
-
Import Astra Starter Sites with just one click.
|
13 |
-
|
14 |
-
== Description ==
|
15 |
-
|
16 |
-
This plugin is an add-on for the Astra WordPress Theme. It offers a library of ready sites that can be imported for your website easily. Here is how it works:
|
17 |
-
|
18 |
-
1. Browse through the library of ready sites right from your WordPress backend.
|
19 |
-
2. Pick a site you like.
|
20 |
-
3. Install required plugins in one click
|
21 |
-
4. Import the site data.
|
22 |
-
5. Done ;)
|
23 |
-
|
24 |
-
|
25 |
-
Use this imported site as a base for your project and don't waste time starting from scratch!
|
26 |
-
|
27 |
-
_<a href="https://wpastra.com/ready-websites/">See list of all available sites to import ยป</a>_
|
28 |
-
|
29 |
-
#### Video Walkthrough by Adam from WPCrafter:
|
30 |
-
[youtube https://www.youtube.com/watch?v=zYbz-jxE9_Q]
|
31 |
-
|
32 |
-
== Installation ==
|
33 |
-
|
34 |
-
1. Upload the plugin files to the `/wp-content/plugins/astra-sites` directory, or install the plugin through the WordPress plugins screen directly.
|
35 |
-
2. Activate the plugin through the 'Plugins' screen in WordPress
|
36 |
-
3. Use the Appearance->Astra->Astra Free Sites to select the page to be displayed as header and footer.
|
37 |
-
|
38 |
-
== Frequently Asked Questions ==
|
39 |
-
|
40 |
-
= Is this really free? =
|
41 |
-
|
42 |
-
Yup, we have dozens of free websites ready to import! We have a premium version as well that is required for importing premium sites.
|
43 |
-
|
44 |
-
Learn More: https://wpastra.com/agency/
|
45 |
-
|
46 |
-
= Can I suggest new websites that you I add? =
|
47 |
-
|
48 |
-
Sure. We love suggestions! Please submit them here -
|
49 |
-
https://wpastra.com/sites-suggestions/
|
50 |
-
|
51 |
-
|
52 |
-
== Screenshots ==
|
53 |
-
|
54 |
-
1. Select the demo you want to import.
|
55 |
-
2. Install and activate the required plugins.
|
56 |
-
3. Import the demo.
|
57 |
-
|
58 |
-
== Changelog ==
|
59 |
-
|
60 |
-
v1.2.
|
61 |
-
* Improvement:
|
62 |
-
* Improvement:
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
* Fix:
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
*
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
* Improvements:
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
*
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
*
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
*
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
* Improvement: Retain WooCommerce
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
* New:
|
112 |
-
|
113 |
-
|
114 |
-
*
|
115 |
-
*
|
116 |
-
|
117 |
-
|
118 |
-
*
|
119 |
-
*
|
120 |
-
|
121 |
-
|
122 |
-
*
|
123 |
-
*
|
124 |
-
|
125 |
-
|
126 |
-
*
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
*
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
*
|
135 |
-
*
|
136 |
-
|
137 |
-
|
138 |
-
*
|
139 |
-
|
140 |
-
|
141 |
-
* Improvement:
|
142 |
-
* Fix:
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
*
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
*
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
*
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
* Fix:
|
159 |
-
|
160 |
-
v1.0.
|
161 |
-
* New:
|
162 |
-
*
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
*
|
167 |
-
*
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
*
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
*
|
176 |
-
|
177 |
-
v1.0.
|
178 |
-
*
|
179 |
-
*
|
180 |
-
|
181 |
-
|
182 |
-
*
|
183 |
-
*
|
184 |
-
|
185 |
-
|
186 |
-
*
|
ย
|
|
ย
|
|
ย
|
|
ย
|
1 |
+
=== Astra Starter Sites ===
|
2 |
+
Contributors: brainstormforce
|
3 |
+
Donate link: https://wpastra.com/pro/
|
4 |
+
Tags: demo, theme demos, one click import
|
5 |
+
Requires at least: 4.4
|
6 |
+
Requires PHP: 5.3
|
7 |
+
Tested up to: 4.9.6
|
8 |
+
Stable tag: 1.2.4
|
9 |
+
License: GPLv2 or later
|
10 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
+
|
12 |
+
Import Astra Starter Sites with just one click.
|
13 |
+
|
14 |
+
== Description ==
|
15 |
+
|
16 |
+
This plugin is an add-on for the Astra WordPress Theme. It offers a library of ready sites that can be imported for your website easily. Here is how it works:
|
17 |
+
|
18 |
+
1. Browse through the library of ready sites right from your WordPress backend.
|
19 |
+
2. Pick a site you like.
|
20 |
+
3. Install required plugins in one click
|
21 |
+
4. Import the site data.
|
22 |
+
5. Done ;)
|
23 |
+
|
24 |
+
|
25 |
+
Use this imported site as a base for your project and don't waste time starting from scratch!
|
26 |
+
|
27 |
+
_<a href="https://wpastra.com/ready-websites/">See list of all available sites to import ยป</a>_
|
28 |
+
|
29 |
+
#### Video Walkthrough by Adam from WPCrafter:
|
30 |
+
[youtube https://www.youtube.com/watch?v=zYbz-jxE9_Q]
|
31 |
+
|
32 |
+
== Installation ==
|
33 |
+
|
34 |
+
1. Upload the plugin files to the `/wp-content/plugins/astra-sites` directory, or install the plugin through the WordPress plugins screen directly.
|
35 |
+
2. Activate the plugin through the 'Plugins' screen in WordPress
|
36 |
+
3. Use the Appearance->Astra->Astra Free Sites to select the page to be displayed as header and footer.
|
37 |
+
|
38 |
+
== Frequently Asked Questions ==
|
39 |
+
|
40 |
+
= Is this really free? =
|
41 |
+
|
42 |
+
Yup, we have dozens of free websites ready to import! We have a premium version as well that is required for importing premium sites.
|
43 |
+
|
44 |
+
Learn More: https://wpastra.com/agency/
|
45 |
+
|
46 |
+
= Can I suggest new websites that you I add? =
|
47 |
+
|
48 |
+
Sure. We love suggestions! Please submit them here -
|
49 |
+
https://wpastra.com/sites-suggestions/
|
50 |
+
|
51 |
+
|
52 |
+
== Screenshots ==
|
53 |
+
|
54 |
+
1. Select the demo you want to import.
|
55 |
+
2. Install and activate the required plugins.
|
56 |
+
3. Import the demo.
|
57 |
+
|
58 |
+
== Changelog ==
|
59 |
+
|
60 |
+
v1.2.4 - 29-June-2018
|
61 |
+
* Improvement: Removed custom license validation form and used Graupi in-build license validation form.
|
62 |
+
* Improvement: Set default page builders depends on the packaged purchase.
|
63 |
+
|
64 |
+
v1.2.3 - 13-June-2018
|
65 |
+
* Improvement: Added windows EDGE browser support for importing the sites.
|
66 |
+
* Improvement: The log file was not created if server does not support the file handling functions.
|
67 |
+
* Fix: Load WXR importer on init to avoid redirect loop when loading WooCommerce importer.
|
68 |
+
* Fix: Clear the Astra Pro plugin cache after site import.
|
69 |
+
|
70 |
+
v1.2.2 - 26-March-2018
|
71 |
+
* Fix: Correctly load the Elementor Pro 2.0 compatibility class for beta versions.
|
72 |
+
|
73 |
+
v1.2.1 - 23-March-2018
|
74 |
+
* Improvement: Clear the Astra Pro plugin cache after site import.
|
75 |
+
|
76 |
+
v1.2.0 - 22-March-2018
|
77 |
+
* Improvement: Added compatibility for Elemetor version 2.0.0. Older versions throw the PHP warning for function process_element_export_import_content().
|
78 |
+
|
79 |
+
v1.1.9 - 12-March-2018
|
80 |
+
* Fix: String `Select Your Favorite Page Builder` jerk while loading the sites.
|
81 |
+
|
82 |
+
v1.1.8 - 5-March-2018
|
83 |
+
* Improvements: Updated processing button animation while installation/activating plugin and importing site.
|
84 |
+
* Improvements: Updated suggestion box message.
|
85 |
+
* Fix: PHP fatal errors for WXR importer classes `WXR_Import_Info`, `WXR_Importer`, `WP_Importer_Logger_ServerSentEvents` and `WP_Importer_Logger`.
|
86 |
+
|
87 |
+
v1.1.7 - 2-February-2018
|
88 |
+
* Improvements: Some users reported confusion in the default option of choosing page builder. We have made UX improvements so users now must select the Page Builder first before selecting any website.
|
89 |
+
|
90 |
+
v1.1.6 - 22-January-2018
|
91 |
+
* New: Added filter `astra_sites_xml_import_options` to change the XML import options.
|
92 |
+
* Fix: Astra Pro plugin 'Custom Layouts' & 'Page Headers' not setting right display location due to different page, tax, category ids.
|
93 |
+
* Fix: WooCommerce shop, checkout cart page ids not setting issue.
|
94 |
+
* Fix: After site import updated demo url from the nav menus.
|
95 |
+
|
96 |
+
v1.1.5 - 11-January-2018
|
97 |
+
* New: Added SVG file support for importing the SVG images.
|
98 |
+
|
99 |
+
v1.1.4 - 28-Dec-2017
|
100 |
+
* Improvement: Importing WooCommerce product category images.
|
101 |
+
* Improvement: Retain WooCommerce cart, checkout & my account pages when importing the ready WooCommerce sites.
|
102 |
+
* Fix: Disabled WooCommerce plugin setup wizard after plugin install & activate.
|
103 |
+
|
104 |
+
v1.1.3 - 20-Dec-2017
|
105 |
+
* Improvement: Retain WooCommerce shop page when importing the ready WooCommerce sites.
|
106 |
+
|
107 |
+
v1.1.2 - 24-Nov-2017
|
108 |
+
* Fix: Handling plugin installation errors.
|
109 |
+
|
110 |
+
v1.1.1 - 23-Nov-2017
|
111 |
+
* New: Change the api url for Astra sites to https://websitedemos.net/ from https://sites.wpastra.com/
|
112 |
+
|
113 |
+
v1.1.0 - 21-Nov-2017
|
114 |
+
* New: Import the site content using Event Source (SSE) which ensures faithful imports.
|
115 |
+
* New: Divided the site import process in separate AJAX calls to reduce the possibility of timeouts.
|
116 |
+
* New: Generated the import log file. It will be displayed in the UI if the import fails.
|
117 |
+
* Improvement: Validate all the possible errors.
|
118 |
+
* Improvement: Updated Astra sites HTML grid structure for WordPress v4.9 compatibility.
|
119 |
+
* Enhancement: Updated plugin name from Astra Sites - Lite with Astra Starter Sites.
|
120 |
+
|
121 |
+
v1.0.14 - 9-Nov-2017
|
122 |
+
* New: All the linked images on the Astra Sites will be downloaded to your site, No more loading images from external URLs.
|
123 |
+
* New: Added suggestion box at as the last column in when listing sites so that you can add a suggest the sites you want.
|
124 |
+
* New: Added site responsive preview buttons.
|
125 |
+
* Improvement: Search string will not be removed when switching the page builder when scrolling through sites.
|
126 |
+
* Improvement: Loading 15 sites instead of 6 Astra sites in the first load.
|
127 |
+
* Improvement: Removed LazyLoad which is not useful in admin back-end for showing Astra Sites.
|
128 |
+
|
129 |
+
v1.0.13 - 9-Oct-2017
|
130 |
+
* New: Browsing the Astra Sites in the Admin panel is not faster with JS rendering.
|
131 |
+
|
132 |
+
v1.0.12 - 29-Sept-2017
|
133 |
+
* New: Added White Label support from <a href="https://wpastra.com/pro/">Astra Pro</a>.
|
134 |
+
* Improvement: Don't display sites from both the page builders in the same view.
|
135 |
+
* Fix: Astra Sites admin area not working in the Firefox.
|
136 |
+
|
137 |
+
v1.0.11 - 22-Sept-2017
|
138 |
+
* New: Single click Install & activate required plugins.
|
139 |
+
* New: Added filter `astra_sites_menu_item` for adding extra tabs in admin page.
|
140 |
+
* New: Added back image import feature for `elementor` page builder. In batch image import we import all images from astra site into client site.
|
141 |
+
* Improvement: Updated JS code with object prototype.
|
142 |
+
* Fix: Screen bounce on retina devices.
|
143 |
+
|
144 |
+
v1.0.10 - 11-Sept-2017
|
145 |
+
* Improvement: Added support for retina logo import.
|
146 |
+
* Fix: Site logo image not displayed in customizer.
|
147 |
+
* Fix: Updated `Astra Agency` purchase link.
|
148 |
+
|
149 |
+
v1.0.9 - 8-Sept-2017
|
150 |
+
* New: Added page builder categories for listing sites as per page builder.
|
151 |
+
|
152 |
+
v1.0.8 - 6-Sept-2017
|
153 |
+
* Fix: Beaver Builder option import.
|
154 |
+
* Enhancement: Disabled dismiss-able notice visible once for each user.
|
155 |
+
* Enhancement: Showing error message for for user who have not `manage_plugins` capability.
|
156 |
+
|
157 |
+
v1.0.7 - 1-Sept-2017
|
158 |
+
* Fix: Custom Menu widget not setting imported widget.
|
159 |
+
|
160 |
+
v1.0.6 - 30-Aug-2017
|
161 |
+
* New: Addd custom menu for Astra Sites.
|
162 |
+
* Fix: Validate site options before storing in database.
|
163 |
+
|
164 |
+
v1.0.5 - 29-Aug-2017
|
165 |
+
* New: Added filter `astra_sites_api_args` for adding extra arguments in api call.
|
166 |
+
* Enhancement: Plugin name updated from `Astra Sites` with `Astra Free Sites`.
|
167 |
+
* Fix: PHP error while ignoring users.
|
168 |
+
|
169 |
+
v1.0.4 - 21-Aug-2017
|
170 |
+
* New: Added filter `astra_sites_api_params` for adding extra params in api call.
|
171 |
+
* New: Added filter `astra_sites_api_args` for adding extra arguments in api call.
|
172 |
+
* New: Added filter `astra_sites_category_hide_empty` for showing categories which are not set for any site.
|
173 |
+
|
174 |
+
v1.0.3 - 11-Aug-2017
|
175 |
+
* Fix: Avoided Astra users from site import process.
|
176 |
+
|
177 |
+
v1.0.2 - 09-Aug-2017
|
178 |
+
* Fix: Listing appropriate next and previous Astra sites.
|
179 |
+
* Enhancement: Listing Astra sites though AJAX API call.
|
180 |
+
|
181 |
+
v1.0.1 - 04-Aug-2017
|
182 |
+
* New: Added Elementor plugin options support.
|
183 |
+
* New: Added Customizer CSS support.
|
184 |
+
* Enhancement: Avoided Lite Plugin version if Pro version is Installed. Now added support for Beaver Builder Plugin (Lite Version).
|
185 |
+
* Enhancement: Astra sites API call validated before import.
|
186 |
+
* Enhancement: Site logo imported from Astra sites.
|
187 |
+
* Fix: Bug where widgets created with SiteOrigin plugin were not being imported.
|
188 |
+
|
189 |
+
v1.0.0
|
190 |
+
* Initial release
|