]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/protected/Pages/RestoreWizard.php
baculum: Support for mobile web browsers in restore wizard
[bacula/bacula] / gui / baculum / protected / Pages / RestoreWizard.php
1 <?php
2 /**
3  * Bacula® - The Network Backup Solution
4  * Baculum - Bacula web interface
5  *
6  * Copyright (C) 2013-2015 Marcin Haba
7  *
8  * The main author of Baculum is Marcin Haba.
9  * The main author of Bacula is Kern Sibbald, with contributions from many
10  * others, a complete list can be found in the file AUTHORS.
11  *
12  * You may use this file and others of this release according to the
13  * license defined in the LICENSE file, which includes the Affero General
14  * Public License, v3.0 ("AGPLv3") and some additional permissions and
15  * terms pursuant to its AGPLv3 Section 7.
16  *
17  * Bacula® is a registered trademark of Kern Sibbald.
18  */
19  
20 Prado::using('System.Exceptions.TException');
21 Prado::using('System.Web.UI.ActiveControls.TActiveDropDownList');
22 Prado::using('System.Web.UI.ActiveControls.TActivePanel');
23 Prado::using('System.Web.UI.ActiveControls.TActiveLinkButton');
24 Prado::using('System.Web.UI.ActiveControls.TActiveImageButton');
25 Prado::using('System.Web.UI.ActiveControls.TDropContainer');
26 Prado::using('System.Web.UI.ActiveControls.TDraggable');
27 Prado::using('System.Web.UI.ActiveControls.TActiveRadioButton');
28 Prado::using('System.Web.UI.ActiveControls.TActiveDataGrid');
29 Prado::using('System.Web.UI.ActiveControls.TCallback');
30
31 class RestoreWizard extends BaculumPage
32 {
33         private $jobLevelsToRestore = array('F' => 'Full', 'I' => 'Incremental', 'D'=> 'Differential');
34         private $jobs = null;
35         private $filesets = null;
36         private $storages = null;
37         private $clients = null;
38         private $browserRootDir = array('name' => '.', 'type' => 'dir');
39         private $browserUpDir = array('name' => '..', 'type' => 'dir');
40
41         public $excludedElementsFromAdd = array('.', '..');
42
43         const BVFS_PATH_PREFIX = 'b2';
44
45         public function onInit($param) {
46                 parent::onInit($param);
47                 if(!$this->IsPostBack && !$this->IsCallBack) {
48                         $this->setBrowserFiles(array());
49                         $this->setFileVersions(array());
50                         $this->setFilesToRestore(array());
51                         $this->markFileToRestore(null, null);
52                         $_SESSION['restore_path'] = array();
53                 }
54         }
55
56         public function onLoad($param) {
57                 parent::onLoad($param);
58                         if($this->RestoreWizard->ActiveStepIndex == 0) {
59                                 $this->jobs = $this->getModule('api')->get(array('jobs'))->output;
60                                 $this->filesets = $this->getModule('api')->get(array('filesets'))->output;
61                         }
62                         $this->clients = $this->getModule('api')->get(array('clients'))->output;
63
64                         if(!$this->IsCallBack && (($this->RestoreWizard->ActiveStepIndex == 1 && $this->getPage()->BackupToRestore->ItemCount > 0) || $this->RestoreWizard->ActiveStepIndex == 3)) {
65                                 $this->setFileVersions(array());
66                                 $this->setBrowserPath('');
67                                 $this->prepareFilesToRestore();
68                                 $this->prepareVersionsToRestore();
69                         }
70         }
71
72         public function addFileToRestore($sender, $param) {
73                 $fileid = null;
74                 if (isset($param->callbackParameter)) {
75                         list(, , , $sourceElementID, , ) = explode('_', $sender->ClientID, 6);
76                         $fileid = $param->callbackParameter;
77                 } else {
78                         $control = $param->getDroppedControl();
79                         $item = $control->getNamingContainer();
80                         list(, , , $sourceElementID, , ) = explode('_', $param->getDragElementID(), 6); // I know that it is ugly.
81                 }
82                 if($sourceElementID == $this->VersionsDataGrid->ID) {
83                         if (is_null($fileid)) {
84                                 $fileid = $this->VersionsDataGrid->getDataKeys()->itemAt($item->getItemIndex());
85                         }
86                         $fileProperties = $this->getFileVersions($fileid);
87                 } else {
88                         if (is_null($fileid)) {
89                                 $fileid = $this->DataGridFiles->getDataKeys()->itemAt($item->getItemIndex());
90                         }
91                         $fileProperties = $this->getBrowserFile($fileid);
92                 }
93                 if($fileProperties['name'] != $this->browserRootDir['name'] && $fileProperties['name'] != $this->browserUpDir['name']) {
94                         $this->markFileToRestore($fileid, $fileProperties);
95                         $this->prepareFilesToRestore();
96                 }
97         }
98
99         public function removeSelectedFile($sender, $param) {
100                 $fileid = $param->CallbackParameter;
101                 $this->unmarkFileToRestore($fileid);
102                 $this->prepareFilesToRestore();
103         }
104
105         public function getVersions($sender, $param) {
106                 list($filename, $pathid, $filenameid, $jobid) = explode('|', $param->CallbackParameter, 4);
107                 if($filenameid == 0) {
108                         $this->setBrowserPath($filename);
109                         return;
110                 }
111                 $clientname = null;
112                 foreach($this->clients as $client) {
113                         if($client->clientid == $this->BackupClientName->SelectedValue) {
114                                 $clientname = $client->name;
115                                 break;
116                         }
117                 }
118                 $versions = $this->getModule('api')->get(array('bvfs', 'versions', $clientname, $jobid, $pathid, $filenameid))->output;
119                 $fileVersions = $this->getModule('misc')->parseFileVersions($filename, $versions);
120                 $this->setFileVersions($fileVersions);
121                 $this->VersionsDataGrid->dataSource = $fileVersions;
122                 $this->VersionsDataGrid->dataBind();
123                 $this->prepareFilesToRestore();
124         }
125
126         public function refreshSelectedFiles($sender, $param) {
127                 $this->prepareFilesToRestore();
128                 $this->SelectedVersionsDropper->render($param->NewWriter);
129         }
130
131         public function NextStep($sender, $param) {
132         }
133         
134         public function PreviousStep($sender, $param) {
135         }
136
137         public function wizardStop($sender, $param) {
138                 $this->goToDefaultPage();
139         }
140
141         public function setJobs($sender, $param) {
142                 $jobsList = $jobsGroupList = $fileSetsList = array();
143                 if(is_array($this->jobs)) {
144                         foreach($this->jobs as $job) {
145                                 if(array_key_exists($job->level, $this->jobLevelsToRestore) && $job->type == 'B' && $job->jobstatus == 'T' && $job->clientid == $this->BackupClientName->SelectedValue) {
146                                         $jobsList[$job->jobid] = sprintf('[%s] %s, %s, %s', $job->jobid, $job->name, $this->jobLevelsToRestore[$job->level], $job->endtime);
147                                         $jobsGroupList[$job->name] = $job->name;
148                                         //$fileSetsList[$job->filesetid] = $this->getFileSet($job->filesetid)->fileset;
149                                 }
150                         }
151                 }
152                 
153                 foreach($this->filesets as $director => $filesets) {
154                         $fileSetsList = array_merge($filesets, $fileSetsList);
155                 }
156
157                 $this->BackupToRestore->dataSource = $jobsList;
158                 $this->BackupToRestore->dataBind();
159                 $this->GroupBackupToRestore->dataSource = $jobsGroupList;
160                 $this->GroupBackupToRestore->dataBind();
161                 $this->GroupBackupFileSet->dataSource = array_combine($fileSetsList, $fileSetsList);
162                 $this->GroupBackupFileSet->dataBind();
163                 $this->setRestoreClients($sender, $param);
164         }
165
166         public function setBackupClients($sender, $param) {
167                 if(!$this->IsPostBack) {
168                         $clientsList = array();
169                         foreach($this->clients as $client) {
170                                 $clientsList[$client->clientid] = $client->name;
171                         }
172                         $this->BackupClientName->dataSource = $clientsList;
173                         $this->BackupClientName->dataBind();
174                 }
175         }
176
177         public function setRestoreClients($sender, $param) {
178                 if(!$this->IsPostBack || $sender->ID == $this->BackupClientName->ID) {
179                         $clientsList = array();
180                         foreach($this->clients as $client) {
181                                 $clientsList[$client->clientid] = $client->name;
182                         }
183                         $this->RestoreClient->SelectedValue = $this->BackupClientName->SelectedValue;
184                         $this->RestoreClient->dataSource = $clientsList;
185                         $this->RestoreClient->dataBind();
186                 }
187         }
188
189         public function getFileSet($filesetId) {
190                 $filesetObj = null;
191                 foreach($this->filesets as $fileset) {
192                         if($fileset->filesetid == $filesetId) {
193                                 $filesetObj = $fileset;
194                                 break;
195                         }
196                 }
197                 return $filesetObj;
198         }
199
200         public function setStorage($sender, $param) {
201                 if(!$this->IsPostBack) {
202                         $storagesList = array();
203                         $storages = $this->getModule('api')->get(array('storages'))->output;
204                         foreach($storages as $storage) {
205                                 $storagesList[$storage->storageid] = $storage->name;
206                         }
207                         $this->GroupBackupStorage->dataSource = $storagesList;
208                         $this->GroupBackupStorage->dataBind();
209                 }
210         }
211
212         public function setPool($sender, $param) {
213                 if(!$this->IsPostBack) {
214                         $poolsList = array();
215                         $pools = $this->getModule('api')->get(array('pools'))->output;
216                         foreach($pools as $pool) {
217                                 $poolsList[$pool->poolid] = $pool->name;
218                         }
219                         $this->GroupBackupPool->dataSource = $poolsList;
220                         $this->GroupBackupPool->dataBind();
221                 }
222         }
223
224         public function setBackupClient($sender, $param) {
225                 $this->ClientToRestore->SelectedValue = $param->SelectedValue;
226         } 
227
228         public function setBackupSelection($sender, $param) {
229                 $this->GroupBackupToRestoreField->Display = ($sender->ID == $this->GroupBackupSelection->ID) ? 'Dynamic' : 'None';
230                 $this->BackupToRestoreField->Display = ($sender->ID == $this->OnlySelectedBackupSelection->ID) ? 'Dynamic' : 'None';
231                 $this->setBrowserFiles(array());
232                 $this->setFileVersions(array());
233                 $this->setFilesToRestore(array());
234                 $this->markFileToRestore(null, null);
235                 $_SESSION['restore_path'] = array();
236         }
237
238         /*public function setGroupBackup($sender, $param) {
239                 foreach($this->jobs as $job) {
240                         if($job->name == $sender->SelectedValue) {
241                                 $this->GroupBackupFileSet->SelectedValue = $job->filesetid;
242                         }
243                 }
244         }*/
245
246         public function resetFileBrowser($sender, $param) {
247                 $this->markFileToRestore(null, null);
248                 $this->setBrowserPath($this->browserRootDir['name']);
249         }
250
251         private function prepareBrowserFiles($files) {
252                 $this->setBrowserFiles($files);
253                 $this->DataGridFiles->dataSource = $files;
254                 @$this->DataGridFiles->dataBind();
255         }
256
257         private function prepareVersionsToRestore() {
258                 $this->VersionsDataGrid->dataSource = $_SESSION['files_versions'];
259                 $this->VersionsDataGrid->dataBind();
260         }
261
262         private function prepareFilesToRestore() {
263                 $this->SelectedVersionsDataGrid->dataSource = $_SESSION['restore'];
264                 $this->SelectedVersionsDataGrid->dataBind();
265         }
266
267         private function setBrowserPath($path) {
268                 if(!empty($path)) {
269                         if($path == $this->browserUpDir['name']) {
270                                 array_pop($_SESSION['restore_path']);
271                         } elseif($path == $this->browserRootDir['name']) {
272                                 $_SESSION['restore_path'] = array();
273                         } else {
274                                 array_push($_SESSION['restore_path'], $path);
275                         }
276                 }
277                 $this->setBrowserLocalizator();
278                 $this->prepareBrowserContent();
279         }
280
281         private function getBrowserPath($stringFormat = false) {
282                 return ($stringFormat === true) ? implode($_SESSION['restore_path']) : $_SESSION['restore_path'];
283         }
284
285         private function setBrowserLocalizator() {
286                 $localization = $this->getBrowserPath(true);
287                 $this->PathField->HeaderText = mb_strlen($localization) > 56 ? '...' . mb_substr($localization, -56) : $localization;
288         }
289
290         private function prepareBrowserContent() {
291                 $jobids = $this->getElementaryBackup();
292         
293                 // generating Bvfs may takes a moment
294                 $this->generateBvfsCacheByJobids($jobids);
295                 $bvfsDirsList = $this->getModule('api')->get(array('bvfs', 'lsdirs', $jobids, '?path=' .  urlencode($this->getBrowserPath(true)) . ''));
296                 $bvfsDirs = is_object($bvfsDirsList) ? $bvfsDirsList->output : array();
297                 $dirs = $this->getModule('misc')->parseBvfsList($bvfsDirs);
298                 $bvfsFilesList = $this->getModule('api')->get(array('bvfs', 'lsfiles', $jobids, '?path=' .  urlencode($this->getBrowserPath(true)) . ''));
299                 $bvfsFiles = is_object($bvfsFilesList) ? $bvfsFilesList->output : array();
300                 $files = $this->getModule('misc')->parseBvfsList($bvfsFiles);
301                 $elements = array_merge($dirs, $files);
302                 if(count($this->getBrowserPath()) > 0) {
303                         array_unshift($elements, $this->browserRootDir);
304                 }
305                 $this->prepareBrowserFiles($elements);
306         }
307
308         private function getElementaryBackup() {
309                 $jobids = null;
310                 if($this->OnlySelectedBackupSelection->Checked === true) {
311                         $jobs = $this->getModule('api')->get(array('bvfs', 'getjobids', $this->BackupToRestore->SelectedValue));
312                         $ids = is_object($jobs) ? $jobs->output : array();
313                         foreach($ids as $jobid) {
314                                 if(preg_match('/^([\d\,]+)$/', $jobid, $match) == 1) {
315                                         $jobids = $match[1];
316                                         break;
317                                 }
318                         }
319                 } else {
320                         $jobsRecent = $this->getModule('api')->get(array('jobs', 'recent', urlencode($this->GroupBackupToRestore->SelectedValue), $this->BackupClientName->SelectedValue));
321                         if(isset($jobsRecent->output) && count($jobsRecent->output) > 0) {
322                                 $ids = $jobsRecent->output;
323                                 $jobids = implode(',', $ids);
324                         }
325                 }
326
327                 $completeJobids = (!is_null($jobids)) ? $jobids : $this->BackupToRestore->SelectedValue;
328                 return $completeJobids;
329         }
330
331         private function generateBvfsCacheByJobids($jobids) {
332                 $this->getModule('api')->set(array('bvfs', 'update', $jobids), array());
333         }
334
335         private function setFileVersions($versions) {
336                 $_SESSION['files_versions'] = $versions;
337         }
338
339         private function getFileVersions($fileid) {
340                 $versions = array();
341                 foreach($_SESSION['files_versions'] as $file) {
342                         if(array_key_exists('fileid', $file) && $file['fileid'] == $fileid) {
343                                 $versions = $file;
344                                 break;
345                         }
346                 }
347                 return $versions;
348         }
349
350         private function setBrowserFiles($files) {
351                 $_SESSION['files_browser'] = $files;
352         }
353
354         private function getBrowserFile($fileid) {
355                 $element = array();
356                 foreach($_SESSION['files_browser'] as $file) {
357                         if(array_key_exists('fileid', $file) && $file['fileid'] == $fileid) {
358                                 $element = $file;
359                                 break;
360                         }
361                 }
362                 return $element;
363         }
364
365         private function markFileToRestore($fileid, $file) {
366                 if($fileid === null) {
367                         $_SESSION['restore'] = array();
368                 } elseif($file['name'] != $this->browserRootDir['name'] && $file['name'] != $this->browserUpDir['name']) {
369                         $_SESSION['restore'][$fileid] = $file;
370                 }
371         }
372
373         private function unmarkFileToRestore($fileid) {
374                 if(array_key_exists($fileid, $_SESSION['restore'])) {
375                         unset($_SESSION['restore'][$fileid]);
376                 }
377         }
378
379         public function getFilesToRestore() {
380                 return $_SESSION['restore'];
381         }
382
383         public function setFilesToRestore($files) {
384                 $_SESSION['restore'] = $files;
385         }
386
387         public function getRestoreElements($asObject = false) {
388                 $fileids = array();
389                 $dirids = array();
390                 foreach($this->getFilesToRestore() as $fileid => $properties) {
391                         if($properties['type'] == 'dir') {
392                                 $dirids[] = $properties['pathid'];
393                         } elseif($properties['type'] == 'file') {
394                                 $fileids[] = $fileid;
395                         }
396                 }
397                 $ret = array('fileid' => $fileids, 'dirid' => $dirids);
398                 if($asObject === true) {
399                         $ret = (object)$ret;
400                 }
401                 return $ret;
402         }
403
404         public function wizardCompleted() {
405                 $jobids = $this->getElementaryBackup();
406                 $path = self::BVFS_PATH_PREFIX . str_replace(',', '', $jobids);
407                 $restoreElements = $this->getRestoreElements();
408                 $cmdProps = array('jobids' => $jobids, 'path' => $path);
409                 if(count($restoreElements['fileid']) > 0) {
410                         $cmdProps['fileid'] = implode(',', $restoreElements['fileid']);
411                 }
412                 if(count($restoreElements['dirid']) > 0) {
413                         $cmdProps['dirid'] = implode(',', $restoreElements['dirid']);
414                 }
415
416                 $this->getModule('api')->create(array('bvfs', 'restore'), $cmdProps);
417                 $restoreProps = array();
418                 $restoreProps['rpath'] = $path;
419                 $restoreProps['clientid'] = intval($this->RestoreClient->SelectedValue);
420                 $restoreProps['fileset'] = $this->GroupBackupFileSet->SelectedValue;
421                 $restoreProps['priority'] = intval($this->RestoreJobPriority->Text);
422                 $restoreProps['where'] =  $this->RestorePath->Text;
423                 $restoreProps['replace'] = $this->ReplaceFiles->SelectedValue;
424                 
425                 $ret = $this->getModule('api')->create(array('jobs', 'restore'), $restoreProps);
426                 $this->goToDefaultPage(array('open' => 'Job'));
427         }
428 }
429 ?>