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