PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / Destination / Tree.php
backup / src / JetBackup / Destination Last commit date
Integration 1 year ago Vendors 1 month ago .htaccess 1 year ago Destination.php 1 month ago DestinationDiskUsage.php 1 year ago DestinationFile.php 1 year ago DestinationWrapper.php 1 year ago ScanDirIterator.php 1 year ago ScanDirIteratorFile.php 8 months ago Tree.php 1 year ago index.html 1 year ago web.config 1 year ago
Tree.php
143 lines
1 <?php
2
3 namespace JetBackup\Destination;
4
5 use JetBackup\Exception\DestinationException;
6 use JetBackup\Exception\IOVanishedException;
7 use JetBackup\Factory;
8 use JetBackup\JetBackup;
9 use JetBackup\Queue\QueueItem;
10 use SleekDB\Exceptions\InvalidArgumentException;
11 use SleekDB\Exceptions\IOException;
12
13 if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
14
15 class Tree {
16
17 const TREE_FILE = '%s' . JetBackup::SEP . '%d_tree.ini';
18
19 private Destination $_destination;
20 private QueueItem $_queue_item;
21 private string $_source;
22 private string $_tree_file;
23
24 /**
25 * @param Destination $destination
26 * @param QueueItem $item
27 * @param string $source
28 */
29 public function __construct(Destination $destination, QueueItem $item, string $source) {
30 $this->_destination = $destination;
31 $this->_queue_item = $item;
32 $this->_source = $source;
33 $this->_tree_file = sprintf(self::TREE_FILE, $source, $destination->getId());
34 }
35
36 /**
37 * @return void
38 * @throws DestinationException
39 * @throws IOVanishedException
40 * @throws IOException
41 * @throws InvalidArgumentException
42 */
43 private function _build():void {
44
45 if(file_exists($this->_tree_file)) return;
46
47 $excludes = [
48 '*' . JetBackup::SEP . '.htaccess',
49 '*' . JetBackup::SEP . 'web.config',
50 '*' . JetBackup::SEP . 'index.html',
51 JetBackup::SEP . 'tree.php_done',
52 JetBackup::SEP . '*_tree.ini',
53 JetBackup::SEP . 'tmp',
54 JetBackup::SEP . 'tmp' . JetBackup::SEP . '*',
55 JetBackup::SEP . 'logs',
56 JetBackup::SEP . 'logs' . JetBackup::SEP . '*',
57 JetBackup::SEP . basename($this->_tree_file),
58 ];
59
60 $fd = fopen($this->_tree_file, 'w');
61 if(!$fd) throw new DestinationException("Cannot open tree file: $this->_tree_file");
62
63 // We must build the tree with directories first, we must create the directory before uploading files to that directory
64 $scan = new ScanDirIterator($this->_source);
65
66 $total_size = 0;
67 while($entry = $scan->next()) {
68 $filename = substr($entry->getFullPath(), strlen($this->_source));
69 foreach($excludes as $exclude) if(fnmatch($exclude, $filename)) continue 2;
70 fwrite($fd, $filename . PHP_EOL);
71 if(!$entry->isDir()) $total_size += $entry->getSize();
72 }
73
74 fclose($fd);
75
76 $progress = $this->_queue_item->getProgress();
77 $progress->setTotalSubItems($total_size);
78 $progress->setCurrentSubItem(0);
79 $this->_queue_item->save();
80
81 }
82
83 /**
84 * @param callable $callback
85 *
86 * @return void
87 * @throws DestinationException
88 * @throws IOVanishedException
89 */
90 public function process(callable $callback) {
91
92 $this->_build();
93
94 $fp = fopen($this->_tree_file, 'r+');
95 if (!$fp) throw new DestinationException("Cannot open tree file: $this->_tree_file");
96
97 fseek($fp, 0, SEEK_END);
98 $fileSize = ftell($fp); // Get the initial size of the file
99 $position = $fileSize;
100 $buffer = '';
101 $_chunk_size = $this->_destination->getChunkSizeBytes() ?: Factory::getSettingsPerformance()->getReadChunkSizeBytes();
102
103 while ($position > 0) {
104
105 $readSize = min($position, $_chunk_size);
106 $position -= $readSize; // Adjust position for the next read
107 fseek($fp, $position);
108 $chunk = fread($fp, $readSize) . $buffer; // Prepend previously buffered data
109
110 while (($eolPos = strrpos($chunk, PHP_EOL)) !== false) {
111 $lineStartPos = $eolPos + strlen(PHP_EOL);
112 $line = substr($chunk, $lineStartPos);
113 $chunk = substr($chunk, 0, $eolPos);
114
115 if (!empty($line)/* && basename($line) != basename(self::TREE_FILE)*/) call_user_func($callback, $line);
116
117 // Update the position for truncating the file
118 $newSize = $position + $eolPos + strlen(PHP_EOL);
119 ftruncate($fp, $newSize);
120 fflush($fp); // Ensure changes are written
121 fseek($fp, $newSize); // Set the pointer for the next operation
122 }
123
124 $buffer = $chunk; // Save any remaining data not followed by PHP_EOL
125
126 if ($position === 0 && !empty($buffer)) {
127 // If there's buffered data left when we reach the start of the file, process it
128 call_user_func($callback, $buffer);
129 ftruncate($fp, 0); // Truncate the file if the entire content has been processed
130 }
131
132
133 }
134
135 fclose($fp);
136
137 // At this point, if tree file is empty we know we finished with the current destination
138 // tree upload, we need this if using multiple uploads to multiple destinations.
139
140 // Do not delete tree file here
141 //unlink($_tree_file);
142 }
143 }