Gallery – Photo Gallery and Images Gallery - Version 1.7.0

Version Description

  • Added new gallery backup functionality
  • Implemented galleries export mode
  • Implemented galleries import mode
Download this release

Release Info

Developer robosoft
Plugin Icon 128x128 Gallery – Photo Gallery and Images Gallery
Version 1.7.0
Comparing to
See all releases

Code changes from version 1.6.9 to 1.7.0

includes/extensions/backup/class_backup.php ADDED
@@ -0,0 +1,1083 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Robo Gallery
4
+ * Version: 1.6
5
+ * By Robosoft
6
+ *
7
+ * Contact: http://robosoft.co
8
+ * Created: 2015
9
+ * Licensed under the GPLv2 license - http://opensource.org/licenses/gpl-2.0.php
10
+ *
11
+ * Copyright (c) 2014-2015, Robosoft. All rights reserved.
12
+ * Available only in http://robosoft.co/
13
+ */
14
+
15
+ class rbsGalleryExport {
16
+ const ATTACHMENT_MAX_AMOUNT = 1000;
17
+ const DUPLICATE_PREFIX = 'copy_';
18
+ const MODE_EXPORT_XML = 'xml';
19
+ const MODE_EXPORT_ZIP = 'zip';
20
+ const MODE_IMPORT_XML = 'xml';
21
+ const MODE_IMPORT_ZIP = 'zip';
22
+ const POSTMETA_ATTACHED_FILE = '_wp_attached_file';
23
+ const POSTMETA_ATTACHMENT_METADATA = '_wp_attachment_metadata';
24
+ const POSTMETA_IMAGES = 'rsg_galleryImages';
25
+ const SPACE4 = ' ';
26
+ const SPACE8 = ' ';
27
+ const TAG_POST_DATA = 'post_data';
28
+ const XML_DECLARATION = '<?xml version="1.0" encoding="utf-8" ?>';
29
+
30
+ /**
31
+ * Database connection
32
+ *
33
+ * @var wpdb
34
+ */
35
+ protected $wpdb;
36
+
37
+ /**
38
+ * Mode of importing/exporting posts
39
+ *
40
+ * @var string
41
+ */
42
+ protected $mode;
43
+
44
+ /**
45
+ * Base url of uploaded files
46
+ *
47
+ * @var string
48
+ */
49
+ protected $baseFileUrl;
50
+
51
+ /**
52
+ * Bath path of uploaded files
53
+ *
54
+ * @var string
55
+ */
56
+ protected $baseFilePath;
57
+
58
+ /**
59
+ * Base archive directory
60
+ *
61
+ * @var string
62
+ */
63
+ protected $archiveDir = ABSPATH;
64
+
65
+ /**
66
+ * Size(bytes) of chunk archive for splitting
67
+ *
68
+ * @var int
69
+ */
70
+ protected $archiveChunkSize = 0;
71
+
72
+ /**
73
+ * List files for exporting
74
+ *
75
+ * @var array
76
+ */
77
+ protected $exportFiles = [];
78
+
79
+ /**
80
+ * Duplicate mode of importing posts data.
81
+ *
82
+ * @var int
83
+ */
84
+ public $duplicate = 0;
85
+
86
+ /**
87
+ * Mapping archives
88
+ * key: archive key
89
+ * value: ZipArchive object
90
+ *
91
+ * @var ZipArchive[]
92
+ */
93
+ protected $archives = [];
94
+
95
+ /**
96
+ * Mapping archive files
97
+ * key: file path
98
+ * value: archive key
99
+ *
100
+ * @var array
101
+ */
102
+ protected $archiveFiles = [];
103
+
104
+ /**
105
+ * Mapping post ID
106
+ * key: old post ID
107
+ * value: new new ID
108
+ *
109
+ * @var array
110
+ */
111
+ protected $mappingPostIds = [];
112
+
113
+ /**
114
+ * Mapping attachment IDs
115
+ * key: old attachment ID
116
+ * value: new attachment ID
117
+ *
118
+ * @var array
119
+ */
120
+ protected $mappingAttachmentIds = [];
121
+
122
+ /**
123
+ * Shared error
124
+ *
125
+ * @var string
126
+ */
127
+ protected $error;
128
+
129
+ /**
130
+ * Import posts response
131
+ *
132
+ * @var array
133
+ */
134
+ protected $response;
135
+
136
+ /**
137
+ * @constructor
138
+ */
139
+ public function __construct()
140
+ {
141
+ global $wpdb;
142
+ $uploadDir = wp_upload_dir();
143
+
144
+ $this->wpdb = $wpdb;
145
+ $this->baseFileUrl = $uploadDir['baseurl'];
146
+ $this->baseFilePath = $uploadDir['basedir'] . DIRECTORY_SEPARATOR;
147
+ }
148
+
149
+ /**
150
+ * Get error
151
+ *
152
+ * @return string
153
+ */
154
+ public function getError()
155
+ {
156
+ return $this->error;
157
+ }
158
+
159
+ /**
160
+ * Set path for archive directory
161
+ *
162
+ * @param string $dir
163
+ * @return void
164
+ */
165
+ public function setArchiveDir($dir)
166
+ {
167
+ $this->archiveDir = rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
168
+ }
169
+
170
+ /**
171
+ * Get path for archive directory
172
+ *
173
+ * @return string
174
+ */
175
+ public function getArchiveDir()
176
+ {
177
+ return $this->archiveDir;
178
+ }
179
+
180
+ /**
181
+ * Set archive chunk size in byte
182
+ *
183
+ * @param int $size
184
+ * @return void
185
+ */
186
+ public function setArchiveChunkSize($size)
187
+ {
188
+ $this->archiveChunkSize = abs((int)$size);
189
+ }
190
+
191
+ /**
192
+ * Get archive chunk size in byte
193
+ *
194
+ * @return int
195
+ */
196
+ public function getArchiveChunkSize()
197
+ {
198
+ return $this->archiveChunkSize;
199
+ }
200
+
201
+
202
+ /**
203
+ * Get export posts xml data for downloading
204
+ *
205
+ * @param array $args
206
+ * @param string $fileName
207
+ * @return bool
208
+ */
209
+ public function exportPostsXml(array $args = [], $fileName = 'export.xml')
210
+ {
211
+ $this->mode = self::MODE_EXPORT_XML;
212
+
213
+ $postsXml = $this->exportPosts($args);
214
+ if ($this->error) {
215
+ return false;
216
+ }
217
+
218
+ $this->sendDownloadHeader($fileName);
219
+ echo $postsXml;
220
+ return true;
221
+ }
222
+
223
+ /**
224
+ * Send headers for force file download
225
+ *
226
+ * @param string $fileName
227
+ * @return void
228
+ */
229
+ protected function sendDownloadHeader($fileName)
230
+ {
231
+ header('Content-Description: File Transfer');
232
+ header('Content-type: text/xml; charset=utf-8');
233
+ header('Content-Disposition: attachment; filename="' . $fileName . '"');
234
+ header('Content-Transfer-Encoding: binary');
235
+ header('Expires: 0');
236
+ header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
237
+ header('Pragma: public');
238
+ }
239
+
240
+ public function exportPostsZip(array $args = [], $fileName = 'export.xml')
241
+ {
242
+ $this->mode = self::MODE_EXPORT_ZIP;
243
+
244
+ $postsXml = $this->exportPosts($args);
245
+ if ($this->error) {
246
+ return false;
247
+ }
248
+
249
+ $archiveRootName = str_replace('.xml' , '', $fileName);
250
+ $this->clearArchive($archiveRootName);
251
+ if ($this->error) {
252
+ return false;
253
+ }
254
+
255
+ $zip = new ZipArchive();
256
+ if (0 == $this->archiveChunkSize) {
257
+ $archivePath = "{$this->archiveDir}{$archiveRootName}.zip";
258
+ $zip->open($archivePath, ZipArchive::CREATE);
259
+
260
+ $zip->addFromString($fileName, $postsXml);
261
+ foreach ($this->exportFiles as $exportFile) {
262
+ $zip->addFile($this->baseFilePath . $exportFile, $exportFile);
263
+ }
264
+ } else {
265
+ $count = 1;
266
+ $size = 0;
267
+ $archivePath = "{$this->archiveDir}{$archiveRootName}.{$count}.zip";
268
+ $zip->open($archivePath, ZipArchive::CREATE);
269
+
270
+ $zip->addFromString($fileName, $postsXml);
271
+ foreach ($this->exportFiles as $exportFile) {
272
+ $fileSize = filesize($this->baseFilePath . $exportFile);
273
+ if ($this->archiveChunkSize < $size + $fileSize) {
274
+ $zip->close();
275
+ $this->isCreatedArchive($archivePath);
276
+ if ($this->error) {
277
+ break;
278
+ }
279
+
280
+ $count++;
281
+ $size = 0;
282
+ $archivePath = "{$this->archiveDir}{$archiveRootName}.{$count}.zip";
283
+ $zip->open($archivePath, ZipArchive::CREATE);
284
+ }
285
+
286
+ $zip->addFile($this->baseFilePath . $exportFile, $exportFile);
287
+ $size += strlen(gzcompress(file_get_contents($this->baseFilePath . $exportFile)));
288
+ }
289
+ }
290
+ $zip->close();
291
+ $this->isCreatedArchive($archivePath);
292
+ if ($this->error) {
293
+ return false;
294
+ }
295
+
296
+ return true;
297
+ }
298
+
299
+ /**
300
+ * Clear archive files by root name
301
+ *
302
+ * @param string $archiveRootName
303
+ * @return bool|string
304
+ */
305
+ protected function clearArchive($archiveRootName)
306
+ {
307
+ $patternName = "{$archiveRootName}.*.zip";
308
+ $chunks = glob($this->archiveDir . $patternName, GLOB_ERR);
309
+ $chunks[] = $this->archiveDir . $archiveRootName . '.zip';
310
+
311
+ foreach ($chunks as $chunk) {
312
+ if (file_exists($chunk) && !unlink($chunk)) {
313
+ $this->error = sprintf(__('Can not clear archive\'s file: "%s".'), $chunk);
314
+ return false;
315
+ }
316
+ }
317
+ return true;
318
+ }
319
+
320
+ /**
321
+ * Check whether created archive
322
+ *
323
+ * @param string $archivePath
324
+ * @return bool
325
+ */
326
+ protected function isCreatedArchive($archivePath)
327
+ {
328
+ if (!file_exists($archivePath)) {
329
+ $this->error = sprintf(__("Didn't save archive with files \"%s\"."), basename($archivePath));
330
+ return false;
331
+ }
332
+ return true;
333
+ }
334
+
335
+ /**
336
+ * Get export posts data
337
+ *
338
+ * @param array $args
339
+ * @return string
340
+ */
341
+ protected function exportPosts(array $args)
342
+ {
343
+ $args = array_merge(
344
+ [
345
+ 'posts_per_page' => 200,
346
+ 'offset' => 0,
347
+ 'post_type' => 'post',
348
+ 'post_status' => 'publish',
349
+ ],
350
+ $args,
351
+ [
352
+ 'orderby' => 'post_parent ID',
353
+ 'order' => 'ASC'
354
+ ]
355
+ );
356
+ $step = 0;
357
+ $out = '';
358
+
359
+ $out .= self::XML_DECLARATION . PHP_EOL;
360
+ $out .= '<posts>' . PHP_EOL;
361
+ do {
362
+ $args['offset'] = $args['posts_per_page'] * $step;
363
+ $posts = get_posts($args);
364
+
365
+ foreach ($posts as $post) {
366
+ // convert stdClass to array
367
+ $post = (array)$post;
368
+
369
+ $out .= self::SPACE4 . '<' . self::TAG_POST_DATA . ' id="' . $post['ID'] . '">' . PHP_EOL;
370
+ $out .= $this->getPostData($post, self::SPACE8);
371
+ $out .= $this->getPostMetaData($post['ID'], self::SPACE8);
372
+ $out .= $this->getAttachmentsData($post['ID'], self::SPACE8);
373
+ $out .= self::SPACE4 . '</' . self::TAG_POST_DATA . '>' . PHP_EOL;
374
+
375
+ if ($this->error) {
376
+ break;
377
+ }
378
+ }
379
+
380
+ $step += 1;
381
+ } while (count($posts) == $args['posts_per_page']);
382
+ $out .= '</posts>' . PHP_EOL;
383
+
384
+ if ($this->error) {
385
+ return null;
386
+ }
387
+ return $out;
388
+ }
389
+
390
+ /**
391
+ * Get export post data
392
+ *
393
+ * @param array $post
394
+ * @param string $indent
395
+ * @return string
396
+ */
397
+ protected function getPostData(array $post, $indent = '')
398
+ {
399
+ $post = $this->prepareExportData($post);
400
+ return $this->getContent($post, 'post', $indent);
401
+ }
402
+
403
+ /**
404
+ * Get export post meta data
405
+ *
406
+ * @param int $postId
407
+ * @param string $indent
408
+ * @return string
409
+ */
410
+ protected function getPostMetaData($postId, $indent = '')
411
+ {
412
+ $rows = get_post_meta($postId, '', true);
413
+ $postMeta = [];
414
+
415
+ foreach ($rows as $metaKey => $metaValues) {
416
+ if($metaKey!='rbs_gallery_id') $postMeta[$metaKey] = $metaValues[0];
417
+ }
418
+ $postMeta = $this->prepareExportData($postMeta);
419
+
420
+ return $this->getContent($postMeta, 'postmeta', $indent);
421
+ }
422
+
423
+ /**
424
+ * Get export post attachments data
425
+ *
426
+ * @param int $postId
427
+ * @param string $indent
428
+ * @return string
429
+ */
430
+ protected function getAttachmentsData($postId, $indent = '')
431
+ {
432
+ $images = $this->getMetaImages($postId);
433
+ $attachments = $this->getAttachments($images);
434
+
435
+ $out = $indent . '<attachments>' . PHP_EOL;
436
+ foreach ($attachments as $attachment) {
437
+ $out .= $indent .self::SPACE4 . '<post_data id="' . $attachment['ID'] . '">' . PHP_EOL;
438
+ $out .= $this->getPostData($attachment, $indent . self::SPACE8);
439
+ $out .= $this->getPostMetaData($attachment['ID'], $indent . self::SPACE8);
440
+ $out .= $indent .self::SPACE4 . '</post_data>' . PHP_EOL;
441
+
442
+ if (self::MODE_EXPORT_ZIP == $this->mode) {
443
+ $this->exportFiles[] = trim(str_replace($this->baseFileUrl, '', $attachment['guid']), '/');
444
+ }
445
+ }
446
+ $out .= self::SPACE8 . '</attachments>' . PHP_EOL;
447
+
448
+ return $out;
449
+ }
450
+
451
+ /**
452
+ * Get export data content
453
+ *
454
+ * @param array $fields
455
+ * @param string $wrapper
456
+ * @param string $indent
457
+ * @return string
458
+ */
459
+ protected function getContent(array $fields, $wrapper = '', $indent = '')
460
+ {
461
+ $out = '';
462
+ $innerIndent = '';
463
+
464
+ if ($wrapper) {
465
+ $out = $wrapper ? ($indent . '<' . $wrapper . '>' . PHP_EOL) : '';
466
+ $innerIndent = self::SPACE4;
467
+ }
468
+ foreach ($fields as $name => $value) {
469
+ $out .= $indent . $innerIndent . '<' . $name . '>' . $value . '</' . $name . '>' . PHP_EOL;
470
+ }
471
+ if ($wrapper) {
472
+ $out .= $indent . '</' . $wrapper . '>' . PHP_EOL;
473
+ }
474
+
475
+ return $out;
476
+ }
477
+
478
+ /**
479
+ * Get post meta images
480
+ *
481
+ * @param int $postId
482
+ * @return array
483
+ */
484
+ protected function getMetaImages($postId)
485
+ {
486
+ $images = get_post_meta($postId, self::POSTMETA_IMAGES, true);
487
+ return is_array($images) ? $images : [];
488
+ }
489
+
490
+ /**
491
+ * Get post attachments by ids
492
+ *
493
+ * @param array $ids
494
+ * @return array
495
+ */
496
+ protected function getAttachments(array $ids)
497
+ {
498
+ $args =[
499
+ 'post__in' => $ids,
500
+ 'post_type' => 'attachment',
501
+ 'posts_per_page' => self::ATTACHMENT_MAX_AMOUNT
502
+ ];
503
+ $attachments = [];
504
+ $result = [];
505
+
506
+ // indexing by ID and convert stdClass to array
507
+ foreach (get_posts($args) as $post) {
508
+ $attachments[$post->ID] = (array)$post;
509
+ }
510
+ // sort to ids order
511
+ foreach ($ids as $id) {
512
+ if (!isset($attachments[$id])) {
513
+ continue;
514
+ }
515
+ $result[$id] = $attachments[$id];
516
+ }
517
+
518
+ return $result;
519
+ }
520
+
521
+ /**
522
+ * Prepare data for exporting:
523
+ * - replacing html entities corresponding xml format
524
+ *
525
+ * @param array $data
526
+ * @return array
527
+ */
528
+ protected function prepareExportData(array $data)
529
+ {
530
+ foreach ($data as $key => $value) {
531
+ if (is_string($value)) {
532
+ $data[$key] = htmlentities($value, ENT_XML1);
533
+ }
534
+ }
535
+ return $data;
536
+ }
537
+
538
+
539
+ /**
540
+ * Import posts, postmeta, attachments from *.xml file
541
+ *
542
+ * @param string $fileXmlPath
543
+ * @return array
544
+ */
545
+ public function importPostsXml($fileXmlPath)
546
+ {
547
+ $this->mode = self::MODE_IMPORT_XML;
548
+
549
+ $xml = file_get_contents($fileXmlPath);
550
+ return $this->importPosts($xml);
551
+ }
552
+
553
+ /**
554
+ * Import posts, postmeta, attachments from archive
555
+ *
556
+ * @param string $archivePath
557
+ * @return array
558
+ */
559
+ public function importPostsZip($archivePath)
560
+ {
561
+ $this->mode = self::MODE_IMPORT_ZIP;
562
+
563
+ $this->response = [
564
+ 'import' => [
565
+ 'post' => 0,
566
+ 'element' => 0,
567
+ 'file' => 0,
568
+ ],
569
+ 'duplicate' => [
570
+ 'post' => 0,
571
+ 'element' => 0,
572
+ 'file' => 0,
573
+ ],
574
+ 'skipped' => [
575
+ 'post' => 0,
576
+ 'element' => 0,
577
+ 'file' => 0,
578
+ ],
579
+ 'errors' => []
580
+ ];
581
+
582
+ $this->readArchive($archivePath);
583
+ if ($this->error) {
584
+ $this->response['errors'][] = $this->error;
585
+ return $this->response;
586
+ }
587
+
588
+ $archiveRootName = preg_replace('/(\.[0-9]+)?\.zip$/', '', basename($archivePath));
589
+ $postsXmlFile = "{$archiveRootName}.xml";
590
+ if (!isset($this->archiveFiles[$postsXmlFile])) {
591
+ $this->response['errors'][] = __("Can't find import xml file in archive.");
592
+ }
593
+ $archiveKey = $this->archiveFiles[$postsXmlFile];
594
+ $archive = $this->archives[$archiveKey];
595
+ $postsXml = $archive->getFromName($postsXmlFile);
596
+
597
+ return $this->importPosts($postsXml);
598
+ }
599
+
600
+ /**
601
+ * Import posts, postmeta, attachments from xml
602
+ *
603
+ * @param string $xml
604
+ * @return array
605
+ */
606
+ public function importPosts($xml)
607
+ {
608
+ $this->response = [
609
+ 'import' => [
610
+ 'post' => 0,
611
+ 'element' => 0,
612
+ 'file' => 0,
613
+ ],
614
+ 'duplicate' => [
615
+ 'post' => 0,
616
+ 'element' => 0,
617
+ 'file' => 0,
618
+ ],
619
+ 'skipped' => [
620
+ 'post' => 0,
621
+ 'element' => 0,
622
+ 'file' => 0,
623
+ ],
624
+ 'errors' => []
625
+ ];
626
+
627
+ if (!$this->validateXml($xml)) {
628
+ $this->response['errors'][] = $this->error;
629
+ return $this->response;
630
+ }
631
+
632
+ $xmlReader = new XMLReader();
633
+ if(false === $xmlReader->xml($xml)) {
634
+ $this->response['errors'][] = __("Can't set xml content for reading.");
635
+ return $this->response;
636
+ }
637
+
638
+ while ($xmlReader->read() && self::TAG_POST_DATA != $xmlReader->localName);
639
+ if (self::TAG_POST_DATA != $xmlReader->localName) {
640
+ $this->response['errors'][] = __('Invalid document of import');
641
+ return $this->response;
642
+ }
643
+
644
+ while (self::TAG_POST_DATA == $xmlReader->localName) {
645
+ $xmlPostData = new SimpleXMLElement($xmlReader->readOuterXML());
646
+ $postData = $this->convertPostData($xmlPostData);
647
+
648
+ // reset shared error
649
+ $this->error = null;
650
+ $this->importPostData($postData);
651
+
652
+ if ($this->error) {
653
+ $this->response['errors'][] = $this->error;
654
+ return $this->response;
655
+ }
656
+
657
+ $xmlReader->next(self::TAG_POST_DATA);
658
+ }
659
+
660
+ return $this->response;
661
+ }
662
+
663
+ /**
664
+ * Import single post with postmeta, attachments
665
+ *
666
+ * @param array $postData
667
+ * @return void
668
+ */
669
+ protected function importPostData(array $postData)
670
+ {
671
+ $post = $postData['post'];
672
+ $postId = $this->findPost($post);
673
+
674
+ if (null === $postId) {
675
+ $newPostId = $this->insertPostData($postData);
676
+ $newPostId && ($this->response['import']['post'] += 1);
677
+ } elseif ($postId && 1 == $this->duplicate) {
678
+ $newPostId = $this->duplicatePostData($postData);
679
+ $newPostId && ($this->response['duplicate']['post'] += 1);
680
+ } else {
681
+ $this->response['skipped']['post'] += 1;
682
+ }
683
+ }
684
+
685
+ /**
686
+ * Insert post with postmeta, attachments
687
+ *
688
+ * @param array $postData
689
+ * @return int|null
690
+ */
691
+ protected function insertPostData(array $postData)
692
+ {
693
+ $post = $postData['post'];
694
+ $postMeta = isset($postData['postmeta']) ? $postData['postmeta'] : [];
695
+ $attachments = isset($postData['attachments']) ? $postData['attachments'] : [];
696
+ $attachmentIds = [];
697
+
698
+ $postId = $this->insertPost($post);
699
+ if (null === $postId) {
700
+ return null;
701
+ }
702
+
703
+ foreach ($attachments as $attachmentData) {
704
+ $attachmentId = $this->importAttachmentData($attachmentData);
705
+ if ($attachmentId) {
706
+ $attachmentIds[] = $attachmentId;
707
+ }
708
+ }
709
+
710
+ if (!empty($attachmentIds)) {
711
+ $postMeta[self::POSTMETA_IMAGES] = $attachmentIds;
712
+ }
713
+ $this->addPostMeta($postId, $postMeta);
714
+
715
+ return $postId;
716
+ }
717
+
718
+ /**
719
+ * Duplicate post with postmeta, attachments
720
+ *
721
+ * @param array $postData
722
+ * @return int|null
723
+ */
724
+ protected function duplicatePostData(array $postData)
725
+ {
726
+ $post = $postData['post'];
727
+ $postName = $post['post_name'];
728
+ $postTitle = $post['post_title'];
729
+ $count = 0;
730
+
731
+ $post['post_name'] = self::DUPLICATE_PREFIX . $postName;
732
+ $post['post_title'] = self::DUPLICATE_PREFIX . $postTitle;
733
+ while ($postId = $this->findPost($post)) {
734
+ $count++;
735
+ $post['post_name'] = self::DUPLICATE_PREFIX . "{$count}_{$postName}";
736
+ $post['post_title'] = self::DUPLICATE_PREFIX . "{$count}_{$postTitle}";
737
+ }
738
+
739
+ $postData['post'] = $post;
740
+ return $this->insertPostData($postData);
741
+ }
742
+
743
+ /**
744
+ * Import attachment post with postmeta
745
+ *
746
+ * @param array $attachmentData
747
+ * @return int|null
748
+ */
749
+ protected function importAttachmentData(array $attachmentData)
750
+ {
751
+ $attachment = $attachmentData['post'];
752
+
753
+ if (isset($this->mappingAttachmentIds[$attachment['ID']])) {
754
+ $this->response['skipped']['element'] += 1;
755
+ return $this->mappingAttachmentIds[$attachment['ID']];
756
+ }
757
+
758
+ $attachmentId = $this->findPost($attachment);
759
+ if (null === $attachmentId) {
760
+ $newAttachmentId = $this->insertAttachmentData($attachmentData);
761
+ $newAttachmentId && ($this->response['import']['element'] += 1);
762
+ } elseif ($attachmentId && 1 == $this->duplicate) {
763
+ $newAttachmentId = $this->duplicateAttachmentData($attachmentData);
764
+ $newAttachmentId && ($this->response['duplicate']['element'] += 1);
765
+ } else {
766
+ $this->response['skipped']['element'] += 1;
767
+ $newAttachmentId = null;
768
+ }
769
+
770
+ return $newAttachmentId;
771
+ }
772
+
773
+ /**
774
+ * Insert attachment post with postmeta
775
+ *
776
+ * @param array $attachmentData
777
+ * @return int|null
778
+ */
779
+ protected function insertAttachmentData(array $attachmentData)
780
+ {
781
+ $post = $attachmentData['post'];
782
+ $oldPostId = $post['ID'];
783
+ $postMeta = isset($attachmentData['postmeta']) ? $attachmentData['postmeta'] : [];
784
+ $oldAttachmentFile = null;
785
+ $newAttachmentFile = null;
786
+
787
+ if (self::MODE_IMPORT_ZIP == $this->mode && isset($postMeta[self::POSTMETA_ATTACHED_FILE])) {
788
+ $oldAttachmentFile = $postMeta[self::POSTMETA_ATTACHED_FILE];
789
+ $newAttachmentFile = $this->importFile($oldAttachmentFile);
790
+
791
+ if (!$newAttachmentFile) {
792
+ return null;
793
+ }
794
+ }
795
+
796
+ unset($post['ID']);
797
+ $post['guid'] = $newAttachmentFile
798
+ ? str_replace($oldAttachmentFile, $newAttachmentFile, $post['guid'])
799
+ : $post['guid'];
800
+ $result = wp_insert_post($post, true);
801
+ if (is_wp_error($result)) {
802
+ $this->error = sprintf(
803
+ __('Error insert post attachment with ID: "%d" and guid: "%s". %s'),
804
+ $oldPostId,
805
+ $post['guid'],
806
+ $result->get_error_message()
807
+ );
808
+ return null;
809
+ }
810
+ $post['ID'] = $result;
811
+ $this->mappingAttachmentIds[$oldPostId] = $post['ID'];
812
+
813
+ if ($newAttachmentFile) {
814
+ $postMeta[self::POSTMETA_ATTACHED_FILE] = $newAttachmentFile;
815
+ $postMeta[self::POSTMETA_ATTACHMENT_METADATA] = serialize(wp_generate_attachment_metadata(
816
+ $post['ID'],
817
+ $this->baseFilePath . $newAttachmentFile
818
+ ));
819
+ }
820
+ $this->addPostMeta($post['ID'], $postMeta);
821
+
822
+ return $post['ID'];
823
+ }
824
+
825
+ /**
826
+ * Duplicate attachment post with postmeta
827
+ *
828
+ * @param array $attachmentData
829
+ * @return int|null
830
+ */
831
+ protected function duplicateAttachmentData(array $attachmentData)
832
+ {
833
+ $post = $attachmentData['post'];
834
+ $postName = $post['post_name'];
835
+ $postTitle = $post['post_title'];
836
+ $count = 0;
837
+
838
+ $post['post_name'] = self::DUPLICATE_PREFIX . $postName;
839
+ $post['post_title'] = self::DUPLICATE_PREFIX . $postTitle;
840
+ while ($post['ID'] = $this->findPost($post)) {
841
+ $count++;
842
+ $post['post_name'] = self::DUPLICATE_PREFIX . "{$count}_{$postName}";
843
+ $post['post_title'] = self::DUPLICATE_PREFIX . "{$count}_{$postTitle}";
844
+ }
845
+
846
+ $attachmentData['post'] = $post;
847
+ return $this->insertAttachmentData($attachmentData);
848
+ }
849
+
850
+ /**
851
+ * Check whether correcting xml
852
+ *
853
+ * @param string $xml
854
+ * @return bool
855
+ */
856
+ protected function validateXml($xml)
857
+ {
858
+ if (0 !== strpos($xml, self::XML_DECLARATION)) {
859
+ $this->error = __('Invalid xml content.');
860
+ return false;
861
+ }
862
+ return true;
863
+ }
864
+
865
+ /**
866
+ * Convert xml element of post data to array
867
+ *
868
+ * @param SimpleXMLElement $postData
869
+ * @return array
870
+ */
871
+ protected function convertPostData(SimpleXMLElement $postData)
872
+ {
873
+ $result = [];
874
+
875
+ foreach ($postData->post[0] as $name => $value) {
876
+ $result['post'][$name] = (string)$value;
877
+ }
878
+
879
+ if (isset($postData->postmeta)) {
880
+ foreach ($postData->postmeta[0] as $name => $value) {
881
+ $result['postmeta'][$name] = (string)$value;
882
+ }
883
+ }
884
+
885
+ if (isset($postData->attachments)) {
886
+ for ($i = 0, $count = count($postData->attachments->post_data); $i < $count; $i++ ) {
887
+ $attachment = $postData->attachments->post_data[$i];
888
+ $attachmentId = (string)$attachment->attributes()['id'];
889
+
890
+ $result['attachments'][$attachmentId] = $this->convertPostData($attachment);
891
+ }
892
+ }
893
+
894
+ return $result;
895
+ }
896
+
897
+ /**
898
+ * Get post ID by post_name or post_title
899
+ *
900
+ * @param array $post
901
+ * @return int|null
902
+ */
903
+ protected function findPost(array $post)
904
+ {
905
+ $query = $this->wpdb->prepare(
906
+ 'select ID from `' . $this->wpdb->prefix . 'posts`
907
+ where post_type="%s" and post_status="%s" and (post_name="%s" or post_title="%s")',
908
+ $post['post_type'],
909
+ $post['post_status'],
910
+ $post['post_name'],
911
+ $post['post_title']
912
+ );
913
+ return $this->wpdb->get_var($query);
914
+ }
915
+
916
+ /**
917
+ * Prepare and insert post
918
+ *
919
+ * @param array $post
920
+ * @return int|null
921
+ */
922
+ protected function insertPost(array $post)
923
+ {
924
+ $oldPostId = $post['ID'];
925
+
926
+ unset($post['ID']);
927
+ unset($post['guid']);
928
+ if (isset($this->mappingPostIds[$post['post_parent']])) {
929
+ $post['post_parent'] = $this->mappingPostIds[$post['post_parent']];
930
+ }
931
+
932
+ $result = wp_insert_post($post, true);
933
+ if (is_wp_error($result)) {
934
+ $this->response['errors'][] = sprintf(
935
+ __('Error insert post with ID: "%d" and title: "%s". %s'),
936
+ $oldPostId,
937
+ $post['post_title'],
938
+ $result->get_error_message()
939
+ );
940
+ return null;
941
+ }
942
+
943
+ $this->mappingPostIds[$oldPostId] = $result;
944
+ return $result;
945
+ }
946
+
947
+ /**
948
+ * Add post meta values
949
+ *
950
+ * @param int $postId
951
+ * @param array $postMeta
952
+ * @return void
953
+ */
954
+ protected function addPostMeta($postId, array $postMeta)
955
+ {
956
+ foreach ($postMeta as $metaKey => $metaValue) {
957
+ // check whether meta value is serialized
958
+ $value = @unserialize($metaValue);
959
+ if (false !== $value) {
960
+ $metaValue = $value;
961
+ }
962
+
963
+ $result = add_post_meta($postId, $metaKey, $metaValue);
964
+ if (false === $result) {
965
+ $this->response['errors'][] = sprintf(
966
+ __('Error insert postmeta for post with ID %d. Meta key: "%s", meta value: "%s"'),
967
+ $postId,
968
+ $metaKey,
969
+ $metaValue
970
+ );
971
+ continue;
972
+ }
973
+ }
974
+ }
975
+
976
+ protected function readArchive($archivePath)
977
+ {
978
+ $archiveDir = dirname($archivePath) . DIRECTORY_SEPARATOR;
979
+ $archiveName = basename($archivePath);
980
+ $archives = [];
981
+
982
+ if (preg_match('/^(.+)\.([0-9]+)\.zip$/', $archiveName, $match)) {
983
+ $archiveRootName = $match[1];
984
+ $archiveIndex = $match[2];
985
+
986
+ $archiveChunkPath = "{$archiveDir}{$archiveRootName}.{$archiveIndex}.zip";
987
+ while(file_exists($archiveChunkPath)) {
988
+ $archives[] = $archiveChunkPath;
989
+ $archiveIndex++;
990
+ $archiveChunkPath = "{$archiveDir}{$archiveRootName}.{$archiveIndex}.zip";
991
+ }
992
+ } else {
993
+ $archives[] = $archivePath;
994
+ }
995
+
996
+ foreach ($archives as $index => $archive) {
997
+ $this->readSingleArchive("archive-{$index}", $archive);
998
+ if ($this->error) {
999
+ break;
1000
+ }
1001
+ }
1002
+
1003
+ return $this->error ? false : true;
1004
+ }
1005
+
1006
+ /**
1007
+ * Read list files from single archive
1008
+ *
1009
+ * @param string $key
1010
+ * @param string $path
1011
+ * @return bool
1012
+ */
1013
+ protected function readSingleArchive($key, $path)
1014
+ {
1015
+ $zip = new ZipArchive();
1016
+
1017
+ if(true !== $zip->open($path)) {
1018
+ $this->error = sprintf(__("Can't open archive \"%s\"."), basename($path));
1019
+ return false;
1020
+ }
1021
+ $this->archives[$key] = $zip;
1022
+
1023
+ for ($i = 0; $i < $zip->numFiles; $i++) {
1024
+ $stat = $zip->statIndex($i);
1025
+ $this->archiveFiles[$stat['name']] = $key;
1026
+ }
1027
+
1028
+ return true;
1029
+ }
1030
+
1031
+ /**
1032
+ * Import single file from archive to upload directory
1033
+ *
1034
+ * @param string $file
1035
+ * @return bool|string
1036
+ */
1037
+ protected function importFile($file)
1038
+ {
1039
+ if (!isset($this->archiveFiles[$file])) {
1040
+ $this->error = sprintf(__("Can't import file \"%s\". File is absent in archive"), $file);
1041
+ return false;
1042
+ }
1043
+
1044
+ $archiveKey = $this->archiveFiles[$file];
1045
+ $archive = $this->archives[$archiveKey];
1046
+ $uploadDir = dirname($file) . DIRECTORY_SEPARATOR;
1047
+ $fileName = basename($file);
1048
+ $filePath = $this->baseFilePath . $uploadDir . $fileName;
1049
+
1050
+ if (file_exists($filePath) && 0 == $this->duplicate) {
1051
+ $this->response['skipped']['file'] += 1;
1052
+ return $file;
1053
+ }
1054
+ if (file_exists($filePath) && 1 == $this->duplicate) {
1055
+ $count = 0;
1056
+ $duplicateFileName = self::DUPLICATE_PREFIX . $fileName;
1057
+ $duplicateFilePath = $this->baseFilePath . $uploadDir . $fileName;
1058
+ while (file_exists($duplicateFilePath)) {
1059
+ $count++;
1060
+ $duplicateFileName = self::DUPLICATE_PREFIX . "{$count}_{$fileName}";
1061
+ $duplicateFilePath = $this->baseFilePath . $uploadDir . $duplicateFileName;
1062
+ }
1063
+
1064
+ $fileName = $duplicateFileName;
1065
+ $filePath = $duplicateFilePath;
1066
+ $this->response['duplicate']['file'] += 1;
1067
+ } else {
1068
+ $this->response['import']['file'] += 1;
1069
+ }
1070
+
1071
+ if (!file_exists($this->baseFilePath . $uploadDir) && mkdir($this->baseFilePath . $uploadDir, 0777, true)) {
1072
+ $this->error = sprintf(__("Can't create directory \"%s\" during import file."), $this->baseFilePath . $uploadDir);
1073
+ return false;
1074
+ }
1075
+ if (!touch($filePath) || !chmod($filePath, 0777)) {
1076
+ $this->error = sprintf(__("Can't create file \"%s\" during import file."), $file);
1077
+ return false;
1078
+ }
1079
+ file_put_contents($filePath, $archive->getFromName($file));
1080
+
1081
+ return $uploadDir . $fileName;
1082
+ }
1083
+ }
includes/extensions/backup/index.html ADDED
File without changes
includes/rbs_gallery_backup.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Robo Gallery
4
+ * Version: 1.2
5
+ * By Robosoft
6
+ *
7
+ * Contact: http://robosoft.co
8
+ * Created: 2015
9
+ * Licensed under the GPLv2 license - http://opensource.org/licenses/gpl-2.0.php
10
+ *
11
+ * Copyright (c) 2014-2015, Robosoft. All rights reserved.
12
+ * Available only in http://robosoft.co/
13
+ */
14
+
15
+
16
+
17
+ wp_enqueue_style ( 'toolbox-gallery-about', ROBO_GALLERY_URL.'css/admin/about.css', array( ), ROBO_GALLERY_VERSION );
18
+
19
+
20
+ if(isset($_POST['rbsSubmitBackup'])){
21
+ if( check_admin_referer( 'rbs-gallery-backup-import' ) ){
22
+ if ( $_FILES['rbsBackupFile']['error'] == UPLOAD_ERR_OK && is_uploaded_file($_FILES['rbsBackupFile']['tmp_name'])) {
23
+ $tmp_name = $_FILES['rbsBackupFile']['tmp_name'];
24
+ rbs_gallery_include('class_backup.php', ROBO_GALLERY_EXTENSIONS_PATH.'/backup/');
25
+
26
+ $wordPressExport = new rbsGalleryExport();
27
+ //$wordPressExport->setArchiveDir(ABSPATH . 'tmp');
28
+ //$wordPressExport->setArchiveChunkSize(2000000);
29
+ //$wordPressExport->exportPostsZip(['post_type' => $postType], 'export.xml');
30
+ //$wordPressExport->duplicate = $duplicate;
31
+
32
+
33
+
34
+ $export = new rbsGalleryExport('robo_gallery_table');
35
+ $result = $export->importPostsXml($tmp_name);
36
+ echo "<h2>".__('Success Import ', 'rbs_gallery')."</h2>";
37
+ //print_r($result);
38
+ }
39
+ } else {
40
+ echo "check secrete error ";
41
+ }
42
+
43
+ }
44
+ ?>
45
+ <div class="wrap">
46
+ <h1 class="rbs-nobackup">
47
+ <?php _e('Robo Gallery Backup', 'rbs_gallery'); ?>
48
+ </h1>
49
+ <table class="form-table">
50
+ <tbody>
51
+ <tr>
52
+ <th scope="row"><label for="blogname"><?php _e('Export Gallery', 'rbs_gallery'); ?></label></th>
53
+ <td>
54
+ <form method="post" enctype="multipart/form-data" class="wp-upload-form" action="<?php echo admin_url().'edit.php?post_type=robo_gallery_table&page=robo-gallery-backup'; ?>">
55
+ <a href="<?php echo admin_url(); ?>edit.php?post_type=robo_gallery_table&page=robo-gallery-backup&rbsGalleryExport=1" class="button button-primary">Download Backup</a>
56
+ </form></td>
57
+ </tr>
58
+ <tr>
59
+ <th scope="row"><label for="blogname"><?php _e('Import Gallery', 'rbs_gallery'); ?></label></th>
60
+ <td>
61
+ <form method="post" enctype="multipart/form-data" class="wp-upload-form" action="<?php echo admin_url().'edit.php?post_type=robo_gallery_table&page=robo-gallery-backup'; ?>">
62
+
63
+ <input id="_wpnonce" name="_wpnonce" value="75248da724" type="hidden">
64
+ <input name="_wp_http_referer" value="/site/w5/wp-admin/plugin-install.php?tab=upload" type="hidden">
65
+ <?php wp_nonce_field( 'rbs-gallery-backup-import' ); ?>
66
+
67
+ <label class="screen-reader-text" for="pluginzip">Import xml file</label>
68
+ <input type="file" name="rbsBackupFile" id="rbsBackupFile">
69
+ <input type="submit" class="button button-primary " value="<?php _e('Upload XML'); ?>" name="rbsSubmitBackup">
70
+
71
+
72
+ </form>
73
+ </td>
74
+ </tr>
75
+ <tr>
76
+ <td colspan="2"><p class="description" id="rbsBackupFile-description"><?php _e('After backup of the galleries settings with EXPORT option, copy images from server folder: {Wordpress folder}/wp-content/uploads to the new location by FTP'); ?></p></td>
77
+
78
+ </tr>
79
+ </tbody>
80
+ </table>
81
+
82
+ </div>
83
+ <?php
includes/rbs_gallery_config.php CHANGED
@@ -50,7 +50,6 @@ if( !class_exists('RoboGalleryConfig') ){
50
  'text'=> 'How to create shortcode?',
51
  'class'=> 'green'
52
  ),
53
-
54
  );
55
 
56
  return $guides[ array_rand( $guides ) ];
50
  'text'=> 'How to create shortcode?',
51
  'class'=> 'green'
52
  ),
 
53
  );
54
 
55
  return $guides[ array_rand( $guides ) ];
includes/rbs_gallery_init.php CHANGED
@@ -144,4 +144,29 @@ rbs_gallery_include(array('rbs_gallery_source.php', 'rbs_gallery_helper.php', 'r
144
 
145
  /* AJAX */
146
  rbs_gallery_include('rbs_gallery_ajax.php', ROBO_GALLERY_INCLUDES_PATH);
147
- rbs_gallery_include('rbs_create_post_ajax.php', ROBO_GALLERY_EXTENSIONS_PATH);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
  /* AJAX */
146
  rbs_gallery_include('rbs_gallery_ajax.php', ROBO_GALLERY_INCLUDES_PATH);
147
+ rbs_gallery_include('rbs_create_post_ajax.php', ROBO_GALLERY_EXTENSIONS_PATH);
148
+
149
+ /* Init function */
150
+
151
+ /* backup export + */
152
+ if(!function_exists('rbs_gallery_export')){
153
+ function rbs_gallery_export(){
154
+ if(isset($_GET['rbsGalleryExport']) && $_GET['rbsGalleryExport']==1 ){
155
+ rbs_gallery_include('class_backup.php', ROBO_GALLERY_EXTENSIONS_PATH.'/backup/');
156
+ $export = new rbsGalleryExport('robo_gallery_table');
157
+ $export->setArchiveDir(ABSPATH . 'tmp');
158
+ $export->isExportFiles = true;
159
+ $isExport = $export->exportPostsXml(['post_type' => ROBO_GALLERY_TYPE_POST] , 'export.xml');
160
+ if(!$isExport) {
161
+ // show pretty error
162
+ var_dump($export->getError());
163
+ } else {
164
+ wp_redirect(get_permalink( 'edit.php?post_type=robo_gallery_table&page=robo-gallery-backup' ));
165
+ }
166
+
167
+ die();
168
+ }
169
+ }
170
+ add_action( 'init', 'rbs_gallery_export' );
171
+ }
172
+ /* backup export - */
includes/rbs_gallery_list.php CHANGED
@@ -55,19 +55,15 @@ if(!function_exists('add_rbs_table_columns')){
55
  add_filter('manage_'.ROBO_GALLERY_TYPE_POST.'_posts_columns' , 'add_rbs_table_columns');
56
  }
57
 
 
58
  if(!function_exists('rbs_gallery_robogalleryList')){
59
  function rbs_gallery_robogalleryList (){
60
- echo '
61
- <script type="text/javascript">
62
  jQuery(document).ready( function($){
63
- jQuery(jQuery(".wrap h2")[0]).append("<a id=\'rbs_backup_button\' class=\'page-title-action\'>'.__('BackUp').'</a>");
64
- jQuery("#rbs_backup_button").click(function(event){
65
- event.preventDefault();
66
- alert("'.__('This function is coming soon!').'");
67
- })
68
  });
69
- </script>
70
- ';
71
  wp_enqueue_style ('robo-gallery-list', ROBO_GALLERY_URL.'css/admin/list.css', array( ), ROBO_GALLERY_VERSION );
72
  }
73
  add_action( 'in_admin_header', 'rbs_gallery_robogalleryList' );
55
  add_filter('manage_'.ROBO_GALLERY_TYPE_POST.'_posts_columns' , 'add_rbs_table_columns');
56
  }
57
 
58
+
59
  if(!function_exists('rbs_gallery_robogalleryList')){
60
  function rbs_gallery_robogalleryList (){
61
+ /* echo '<script type="text/javascript">
 
62
  jQuery(document).ready( function($){
63
+ var rbsButtonBackup = jQuery("<a href=\''.admin_url().'edit.php?post_type=robo_gallery_table&page=robo-gallery-backup\' id=\'rbs_backup_button\' class=\'page-title-action\'>'.__('BackUp').'</a>").appendTo(jQuery(".wrap h1")[0]);
64
+ //rbsButtonBackup.attr("href", "'.admin_url().'edit.php?post_type=robo_gallery_table&rbsGalleryExport=1");
 
 
 
65
  });
66
+ </script>';*/
 
67
  wp_enqueue_style ('robo-gallery-list', ROBO_GALLERY_URL.'css/admin/list.css', array( ), ROBO_GALLERY_VERSION );
68
  }
69
  add_action( 'in_admin_header', 'rbs_gallery_robogalleryList' );
includes/rbs_gallery_menu.php CHANGED
@@ -54,6 +54,16 @@ if(!function_exists('robo_gallery_settings_submenu_page')){
54
 
55
  }
56
 
 
 
 
 
 
 
 
 
 
 
57
  if(!function_exists('robo_gallery_about_submenu_page')){
58
  add_action('admin_menu', 'robo_gallery_about_submenu_page');
59
  function robo_gallery_about_submenu_page() {
54
 
55
  }
56
 
57
+ if(!function_exists('robo_gallery_backup_submenu_page')){
58
+ add_action('admin_menu', 'robo_gallery_backup_submenu_page');
59
+ function robo_gallery_backup_submenu_page() {
60
+ add_submenu_page( 'edit.php?post_type=robo_gallery_table', 'Backup', 'Backup', 'manage_options', 'robo-gallery-backup', 'robo_gallery_backup_submenu_page_render' );
61
+ }
62
+ function robo_gallery_backup_submenu_page_render(){
63
+ rbs_gallery_include('rbs_gallery_backup.php', ROBO_GALLERY_INCLUDES_PATH);
64
+ }
65
+ }
66
+
67
  if(!function_exists('robo_gallery_about_submenu_page')){
68
  add_action('admin_menu', 'robo_gallery_about_submenu_page');
69
  function robo_gallery_about_submenu_page() {
js/admin/backup.js ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Robo Gallery
3
+ * Version: 1.0
4
+ * By Robosoft
5
+ *
6
+ * Contact: http://robosoft.co
7
+ * Created: 2015
8
+ * Licensed under the GPLv2 license - http://opensource.org/licenses/gpl-2.0.php
9
+ *
10
+ * Copyright (c) 2014-2015, Robosoft. All rights reserved.
11
+ * Available only in http://robosoft.co/
12
+ */
13
+
14
+ jQuery(function(){
15
+ var roboBackupGalleryDialog = jQuery("#rbsBackUpBlock")/*.appendTo("body")*/;
16
+
17
+ var bodyClass = roboBackupGalleryDialog.data("body");
18
+ if(bodyClass) jQuery("body").addClass(bodyClass);
19
+ roboBackupGalleryDialog.dialog({
20
+ 'dialogClass' : 'wp-dialog',
21
+ 'title': roboBackupGalleryDialog.data('title'),
22
+ 'modal' : true,
23
+ 'autoOpen' : roboBackupGalleryDialog.data('open'),
24
+ 'width': '450', // overcomes width:'auto' and maxWidth bug
25
+ 'maxWidth': 450,
26
+ 'height': 'auto',
27
+ 'fluid': true,
28
+ 'resizable': false,
29
+ 'responsive': true,
30
+ 'draggable': false,
31
+ 'closeOnEscape' : true,
32
+ 'buttons' : [{
33
+ 'text' : roboBackupGalleryDialog.data('close'),
34
+ 'class' : 'button button-default rbs_dialog_close',
35
+ 'click' : function() { jQuery(this).dialog('close'); }
36
+ },
37
+ {
38
+ 'text' : roboBackupGalleryDialog.data('info'),
39
+ 'class' : 'button-primary rbs_getproversion_blank rbs_close_dialog',
40
+ 'click' : function(){}
41
+ }
42
+ ],
43
+ open: function( event, ui ) {}
44
+ });
45
+ window['roboBackupGalleryDialog'] = roboBackupGalleryDialog;
46
+ });
languages/rbs_gallery-ru_RU.mo CHANGED
Binary file
languages/rbs_gallery-ru_RU.po CHANGED
@@ -1,15 +1,15 @@
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: Robo Gallery v 1.0.0\n"
4
- "POT-Creation-Date: 2015-12-11 11:51+0100\n"
5
- "PO-Revision-Date: 2015-12-11 11:52+0100\n"
6
  "Last-Translator: RoboSoft Team <team@robosoft.co>\n"
7
  "Language-Team: RoboSoft Team <team@robosoft.co>\n"
8
  "Language: ru_RU\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.2\n"
13
  "X-Poedit-Basepath: ../includes\n"
14
  "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
  "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
@@ -17,6 +17,41 @@ msgstr ""
17
  "X-Poedit-KeywordsList: __;_e\n"
18
  "X-Poedit-SearchPath-0: .\n"
19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  #: extensions/rbs_create_post.php:10
21
  msgid "Post manager"
22
  msgstr ""
@@ -47,7 +82,7 @@ msgid "Empty gallery ID"
47
  msgstr "Пустое id галереи "
48
 
49
  #: extensions/rbs_create_post_ajax.php:37
50
- #: extensions/rbs_create_post_ajax.php:170
51
  msgid "Incorrect gallery ID"
52
  msgstr ""
53
 
@@ -89,14 +124,14 @@ msgid " created"
89
  msgstr ""
90
 
91
  #: extensions/rbs_create_post_ajax.php:129
92
- #: extensions/rbs_create_post_ajax.php:182
93
  #: extensions/rbs_create_post_ajax.php:183
 
94
  msgid "Edit"
95
  msgstr ""
96
 
97
  #: extensions/rbs_create_post_ajax.php:132
98
- #: extensions/rbs_create_post_ajax.php:187
99
  #: extensions/rbs_create_post_ajax.php:188
 
100
  msgid "Preview"
101
  msgstr ""
102
 
@@ -105,7 +140,7 @@ msgid "Error: input value"
105
  msgstr "Ошибка: входящее значение"
106
 
107
  #: extensions/rbs_create_post_ajax.php:150
108
- #: extensions/rbs_create_post_ajax.php:170
109
  msgid "Error: "
110
  msgstr "Ошибка:"
111
 
@@ -113,7 +148,7 @@ msgstr "Ошибка:"
113
  msgid "Status"
114
  msgstr ""
115
 
116
- #: extensions/rbs_create_post_ajax.php:178
117
  msgid "publish"
118
  msgstr ""
119
 
@@ -416,8 +451,7 @@ msgstr ""
416
  #: options/rbs_gallery_options_info.php:18
417
  #: options/rbs_gallery_options_info.php:31
418
  #: options/rbs_gallery_options_infowide.php:18 rbs_gallery_about.php:63
419
- #: rbs_gallery_about.php:64 rbs_gallery_list.php:29
420
- #: rbs_gallery_topblock.php:20
421
  msgid "Get Pro version"
422
  msgstr "Получить PRO версию"
423
 
@@ -728,6 +762,18 @@ msgstr "Дополнительные настройки описания изо
728
  msgid "All Rights Reserved"
729
  msgstr "All Rights Reserved."
730
 
 
 
 
 
 
 
 
 
 
 
 
 
731
  #: rbs_gallery_button.php:22 rbs_gallery_media.php:43
732
  msgid "Robo Gallery"
733
  msgstr "Robo Gallery"
@@ -787,10 +833,6 @@ msgstr "Shortcode"
787
  msgid "BackUp"
788
  msgstr "Резервная копия "
789
 
790
- #: rbs_gallery_list.php:66
791
- msgid "This function is coming soon!"
792
- msgstr ""
793
-
794
  #: rbs_gallery_media.php:58
795
  msgid "Column"
796
  msgstr "Колонка (и)"
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: Robo Gallery v 1.0.0\n"
4
+ "POT-Creation-Date: 2015-12-18 12:00+0100\n"
5
+ "PO-Revision-Date: 2015-12-18 12:00+0100\n"
6
  "Last-Translator: RoboSoft Team <team@robosoft.co>\n"
7
  "Language-Team: RoboSoft Team <team@robosoft.co>\n"
8
  "Language: ru_RU\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 1.8.6\n"
13
  "X-Poedit-Basepath: ../includes\n"
14
  "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
15
  "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
17
  "X-Poedit-KeywordsList: __;_e\n"
18
  "X-Poedit-SearchPath-0: .\n"
19
 
20
+ #: extensions/backup/class_backup.php:294
21
+ msgid "Invalid document of import"
22
+ msgstr ""
23
+
24
+ #: extensions/backup/class_backup.php:436
25
+ #, php-format
26
+ msgid "Error insert post attachment with ID: \"%d\" and guid: \"%s\". %s"
27
+ msgstr ""
28
+
29
+ #: extensions/backup/class_backup.php:488
30
+ #, php-format
31
+ msgid "Wrong post type \"%s\""
32
+ msgstr ""
33
+
34
+ #: extensions/backup/class_backup.php:502
35
+ #, php-format
36
+ msgid "File \"%s\" does not exist."
37
+ msgstr ""
38
+
39
+ #: extensions/backup/class_backup.php:511
40
+ msgid "Wrong type of file. Allowed use only *.xml file type."
41
+ msgstr ""
42
+
43
+ #: extensions/backup/class_backup.php:617
44
+ #, php-format
45
+ msgid "Error insert post with ID: \"%d\" and title: \"%s\". %s"
46
+ msgstr ""
47
+
48
+ #: extensions/backup/class_backup.php:648
49
+ #, php-format
50
+ msgid ""
51
+ "Error insert postmeta for post with ID %d. Meta key: \"%s\", meta value: \"%s"
52
+ "\""
53
+ msgstr ""
54
+
55
  #: extensions/rbs_create_post.php:10
56
  msgid "Post manager"
57
  msgstr ""
82
  msgstr "Пустое id галереи "
83
 
84
  #: extensions/rbs_create_post_ajax.php:37
85
+ #: extensions/rbs_create_post_ajax.php:171
86
  msgid "Incorrect gallery ID"
87
  msgstr ""
88
 
124
  msgstr ""
125
 
126
  #: extensions/rbs_create_post_ajax.php:129
 
127
  #: extensions/rbs_create_post_ajax.php:183
128
+ #: extensions/rbs_create_post_ajax.php:184
129
  msgid "Edit"
130
  msgstr ""
131
 
132
  #: extensions/rbs_create_post_ajax.php:132
 
133
  #: extensions/rbs_create_post_ajax.php:188
134
+ #: extensions/rbs_create_post_ajax.php:189
135
  msgid "Preview"
136
  msgstr ""
137
 
140
  msgstr "Ошибка: входящее значение"
141
 
142
  #: extensions/rbs_create_post_ajax.php:150
143
+ #: extensions/rbs_create_post_ajax.php:171
144
  msgid "Error: "
145
  msgstr "Ошибка:"
146
 
148
  msgid "Status"
149
  msgstr ""
150
 
151
+ #: extensions/rbs_create_post_ajax.php:179
152
  msgid "publish"
153
  msgstr ""
154
 
451
  #: options/rbs_gallery_options_info.php:18
452
  #: options/rbs_gallery_options_info.php:31
453
  #: options/rbs_gallery_options_infowide.php:18 rbs_gallery_about.php:63
454
+ #: rbs_gallery_about.php:64 rbs_gallery_list.php:29 rbs_gallery_topblock.php:20
 
455
  msgid "Get Pro version"
456
  msgstr "Получить PRO версию"
457
 
762
  msgid "All Rights Reserved"
763
  msgstr "All Rights Reserved."
764
 
765
+ #: rbs_gallery_backup.php:36
766
+ msgid "Robo Gallery Backup"
767
+ msgstr ""
768
+
769
+ #: rbs_gallery_backup.php:37
770
+ msgid "Import Gallery"
771
+ msgstr ""
772
+
773
+ #: rbs_gallery_backup.php:55
774
+ msgid "Export Gallery"
775
+ msgstr ""
776
+
777
  #: rbs_gallery_button.php:22 rbs_gallery_media.php:43
778
  msgid "Robo Gallery"
779
  msgstr "Robo Gallery"
833
  msgid "BackUp"
834
  msgstr "Резервная копия "
835
 
 
 
 
 
836
  #: rbs_gallery_media.php:58
837
  msgid "Column"
838
  msgstr "Колонка (и)"
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://www.robosoft.co/robogallery
4
  Tags: gallery, add gallery, photo gallery, images gallery, media gallery, responsive gallery, gallery image, gallery lightbox, Polaroid gallery, Gallery Plugin, plugin gallery, video gallery, gallery shortcode, responsive images gallery, website gallery, widget gallery, wordpress gallery, wordpress gallery plugin, wordpress photo gallery plugin, wp gallery, wp gallery plugin, wp gallery plugins, multi categories gallery, add galleries, add picture, add pictures, album, best gallery, best gallery plugin, responsive galleries, mobile gallery, mobile galleries, responsive photo gallery, best portfolio, easy media gallery, filterable gallery, filterable portfolio, foto, fotoalbum, fotogalerie, sortable gallery, sortable galleries, free photo gallery, fullscreen gallery, galary, galeri, galerie, galerij, galery, gallary, Galleria, gallerie, galleries, gallery decription, gallery slider, gelary, gellary, gellery, google, grid gallery, image, image album, image gallery, image gallery plugin, image lightbox, image slider, image slideshow, images, jquery, jquery gallery, links, media, multiple pictures, page, pagination gallery, pagination portfolio, photo, photo album, photo albums, photoalbum, photogallery, photos, photoset, picture, pictures, plugin, plugin for gallery, portfolio, portfolio gallery, portfolio plugin, Post, posts, responsive slideshow, responsive wordpress photo gallery, seo image, slide show, slideshow, thumbnail, upload images, upload photos, batch upload, multiply images upload, view images, view pictures, wordpress portfolio plugin, multi-categories gallery, multi categories galleries, robo gallery
5
  Requires at least: 3.3
6
  Tested up to: 4.4
7
- Stable tag: 1.6.9
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -575,6 +575,11 @@ If any problem occurs, please contact us.
575
 
576
  == Changelog ==
577
 
 
 
 
 
 
578
  = 1.6.9 =
579
  * Added new content to video guides section
580
  * Added link to gallery shortcode tools video guide
@@ -854,6 +859,9 @@ If any problem occurs, please contact us.
854
 
855
  == Upgrade Notice ==
856
 
 
 
 
857
  = 1.6.9 =
858
  Added new content to video guides section, added link to gallery shortcode tools video guide
859
 
4
  Tags: gallery, add gallery, photo gallery, images gallery, media gallery, responsive gallery, gallery image, gallery lightbox, Polaroid gallery, Gallery Plugin, plugin gallery, video gallery, gallery shortcode, responsive images gallery, website gallery, widget gallery, wordpress gallery, wordpress gallery plugin, wordpress photo gallery plugin, wp gallery, wp gallery plugin, wp gallery plugins, multi categories gallery, add galleries, add picture, add pictures, album, best gallery, best gallery plugin, responsive galleries, mobile gallery, mobile galleries, responsive photo gallery, best portfolio, easy media gallery, filterable gallery, filterable portfolio, foto, fotoalbum, fotogalerie, sortable gallery, sortable galleries, free photo gallery, fullscreen gallery, galary, galeri, galerie, galerij, galery, gallary, Galleria, gallerie, galleries, gallery decription, gallery slider, gelary, gellary, gellery, google, grid gallery, image, image album, image gallery, image gallery plugin, image lightbox, image slider, image slideshow, images, jquery, jquery gallery, links, media, multiple pictures, page, pagination gallery, pagination portfolio, photo, photo album, photo albums, photoalbum, photogallery, photos, photoset, picture, pictures, plugin, plugin for gallery, portfolio, portfolio gallery, portfolio plugin, Post, posts, responsive slideshow, responsive wordpress photo gallery, seo image, slide show, slideshow, thumbnail, upload images, upload photos, batch upload, multiply images upload, view images, view pictures, wordpress portfolio plugin, multi-categories gallery, multi categories galleries, robo gallery
5
  Requires at least: 3.3
6
  Tested up to: 4.4
7
+ Stable tag: 1.7.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
575
 
576
  == Changelog ==
577
 
578
+ = 1.7.0 =
579
+ * Added new gallery backup functionality
580
+ * Implemented galleries export mode
581
+ * Implemented galleries import mode
582
+
583
  = 1.6.9 =
584
  * Added new content to video guides section
585
  * Added link to gallery shortcode tools video guide
859
 
860
  == Upgrade Notice ==
861
 
862
+ = 1.7.0 =
863
+ Added new gallery backup functionality, Implemented galleries export/import mode
864
+
865
  = 1.6.9 =
866
  Added new content to video guides section, added link to gallery shortcode tools video guide
867
 
robogallery.php CHANGED
@@ -8,7 +8,7 @@
8
  * Plugin Name: Robo Gallery
9
  * Plugin URI: http://robosoft.co/robogallery
10
  * Description: A responsive, easy and elegant way to show gallery.
11
- * Version: 1.6.9
12
  * Author: RoboSoft (c)
13
  * Author URI: http://robosoft.co/robogallery
14
  * License: GPL-2.0+
@@ -19,7 +19,7 @@
19
 
20
  if ( ! defined( 'WPINC' ) ) die;
21
  define("ROBO_GALLERY", 1);
22
- define("ROBO_GALLERY_VERSION", '1.6.9');
23
  define("ROBO_GALLERY_PATH", plugin_dir_path( __FILE__ ));
24
  define("ROBO_GALLERY_SPECIAL", 0);
25
 
8
  * Plugin Name: Robo Gallery
9
  * Plugin URI: http://robosoft.co/robogallery
10
  * Description: A responsive, easy and elegant way to show gallery.
11
+ * Version: 1.7.0
12
  * Author: RoboSoft (c)
13
  * Author URI: http://robosoft.co/robogallery
14
  * License: GPL-2.0+
19
 
20
  if ( ! defined( 'WPINC' ) ) die;
21
  define("ROBO_GALLERY", 1);
22
+ define("ROBO_GALLERY_VERSION", '1.7.0');
23
  define("ROBO_GALLERY_PATH", plugin_dir_path( __FILE__ ));
24
  define("ROBO_GALLERY_SPECIAL", 0);
25