* Bacula(R) - The Network Backup Solution
* Baculum - Bacula web interface
*
- * Copyright (C) 2013-2016 Kern Sibbald
+ * Copyright (C) 2013-2017 Kern Sibbald
*
* The main author of Baculum is Marcin Haba.
* The original author of Bacula is Kern Sibbald, with contributions
Prado::using('Application.Web.Class.BaculumWebPage');
Prado::using('System.Exceptions.TException');
Prado::using('System.Web.UI.WebControls.TWizard');
-Prado::using('System.Web.UI.ActiveControls.TActiveDropDownList');
-Prado::using('System.Web.UI.ActiveControls.TActivePanel');
+Prado::using('System.Web.UI.WebControls.TDataGrid');
Prado::using('System.Web.UI.ActiveControls.TActiveLinkButton');
Prado::using('System.Web.UI.ActiveControls.TActiveImageButton');
Prado::using('System.Web.UI.ActiveControls.TDropContainer');
Prado::using('System.Web.UI.ActiveControls.TDraggable');
-Prado::using('System.Web.UI.ActiveControls.TActiveRadioButton');
Prado::using('System.Web.UI.ActiveControls.TActiveDataGrid');
Prado::using('System.Web.UI.ActiveControls.TCallback');
+Prado::using('System.Web.UI.ActiveControls.TActiveTextBox');
class RestoreWizard extends BaculumWebPage
{
- private $jobLevelsToRestore = array('F' => 'Full', 'I' => 'Incremental', 'D'=> 'Differential');
- private $jobs = null;
- private $filesets = null;
- private $storages = null;
- private $clients = null;
- private $browserRootDir = array('name' => '.', 'type' => 'dir');
- private $browserUpDir = array('name' => '..', 'type' => 'dir');
-
- public $excludedElementsFromAdd = array('.', '..');
-
+ /**
+ * Job levels allowed to restore.
+ */
+
+ private $joblevel = array('F', 'I', 'D');
+ /**
+ * Job statuses allowed to restore.
+ */
+ private $jobstatus = array('T', 'W', 'A', 'E', 'e', 'f');
+
+ /**
+ * File browser special directories.
+ */
+ private $browser_root_dir = array('name' => '.', 'type' => 'dir', 'fileid' => null);
+ private $browser_up_dir = array('name' => '..', 'type' => 'dir');
+
+ /**
+ * Used to provide in template selected by user single jobid to restore.
+ */
+ public $restore_single_jobid;
+
+ /**
+ * Stores file relocation option. Used in template.
+ */
+ public $file_relocation_opt;
+
+ /**
+ * FIle browser elements for which 'Add' button is unavailable.
+ */
+ public $excluded_elements_from_add = array('.', '..');
+
+ /**
+ * Prefix for Bvfs path.
+ */
const BVFS_PATH_PREFIX = 'b2';
- public function onPreInit($param) {
- parent::onPreInit($param);
- $this->Application->getModule('web_users')->loginUser();
- }
-
public function onInit($param) {
parent::onInit($param);
if(!$this->IsPostBack && !$this->IsCallBack) {
- $this->setBrowserFiles(array());
- $this->setFileVersions(array());
- $this->setFilesToRestore(array());
- $this->markFileToRestore(null, null);
- $_SESSION['restore_path'] = array();
+ $this->resetWizard();
+ $this->loadBackupClients();
}
}
- public function onLoad($param) {
- parent::onLoad($param);
- if($this->RestoreWizard->ActiveStepIndex == 0) {
- $this->jobs = $this->getModule('api')->get(array('jobs'))->output;
- $this->filesets = $this->getModule('api')->get(array('filesets'))->output;
+ /**
+ * Wizard next button callback actions.
+ *
+ * @param TWizard $sender sender object
+ * @param TWizardNavigationEventParameter $param sender parameters
+ * @return none
+ */
+ public function wizardNext($sender, $param) {
+ if ($param->CurrentStepIndex === 0) {
+ $this->loadBackupsForClient();
+ $this->loadGroupBackupToRestore();
+ $this->loadGroupFileSetToRestore();
+ $this->loadRestoreClients();
+ if (isset($_SESSION['restore_single_jobid'])) {
+ $this->restore_single_jobid = $_SESSION['restore_single_jobid'];
}
- $this->clients = $this->getModule('api')->get(array('clients'))->output;
-
- if(!$this->IsCallBack && (($this->RestoreWizard->ActiveStepIndex == 1 && $this->getPage()->BackupToRestore->ItemCount > 0) || $this->RestoreWizard->ActiveStepIndex == 3)) {
- $this->setFileVersions(array());
- $this->setBrowserPath('');
- $this->prepareFilesToRestore();
- $this->prepareVersionsToRestore();
+ } elseif ($param->CurrentStepIndex === 1) {
+ if ($this->Request->contains('backup_to_restore')) {
+ $_SESSION['restore_single_jobid'] = $this->Request['backup_to_restore'];
}
- }
-
- public function addFileToRestore($sender, $param) {
- $fileid = null;
- if (isset($param->callbackParameter)) {
- list(, , , $sourceElementID, , ) = explode('_', $sender->ClientID, 6);
- $fileid = $param->callbackParameter;
- } else {
- $control = $param->getDroppedControl();
- $item = $control->getNamingContainer();
- list(, , , $sourceElementID, , ) = explode('_', $param->getDragElementID(), 6); // I know that it is ugly.
- }
- if($sourceElementID == $this->VersionsDataGrid->ID) {
- if (is_null($fileid)) {
- $fileid = $this->VersionsDataGrid->getDataKeys()->itemAt($item->getItemIndex());
+ $this->setFileVersions();
+ $this->loadSelectedFiles();
+ $this->loadFileVersions();
+ $this->goToPath();
+ } elseif ($param->CurrentStepIndex === 2) {
+ $this->loadRequiredVolumes();
+ } elseif ($param->CurrentStepIndex === 3) {
+ if (isset($_SESSION['file_relocation'])) {
+ $this->file_relocation_opt = $_SESSION['file_relocation'];
}
- $fileProperties = $this->getFileVersions($fileid);
- } else {
- if (is_null($fileid)) {
- $fileid = $this->DataGridFiles->getDataKeys()->itemAt($item->getItemIndex());
+ } elseif ($param->CurrentStepIndex === 4) {
+ if ($this->Request->contains('file_relocation')) {
+ $_SESSION['file_relocation'] = $this->Request['file_relocation'];
}
- $fileProperties = $this->getBrowserFile($fileid);
+ $this->file_relocation_opt = $_SESSION['file_relocation'];
}
- if($fileProperties['name'] != $this->browserRootDir['name'] && $fileProperties['name'] != $this->browserUpDir['name']) {
- $this->markFileToRestore($fileid, $fileProperties);
- $this->prepareFilesToRestore();
- }
- }
-
- public function removeSelectedFile($sender, $param) {
- $fileid = $param->CallbackParameter;
- $this->unmarkFileToRestore($fileid);
- $this->prepareFilesToRestore();
}
- public function getVersions($sender, $param) {
- list($filename, $pathid, $filenameid, $jobid) = explode('|', $param->CallbackParameter, 4);
- if($filenameid == 0) {
- $this->setBrowserPath($filename);
- return;
- }
- $clientname = null;
- foreach($this->clients as $client) {
- if($client->clientid == $this->BackupClientName->SelectedValue) {
- $clientname = $client->name;
- break;
- }
+ /**
+ * Wizard prev button callback actions.
+ *
+ * @param TWizard $sender sender object
+ * @param TWizardNavigationEventParameter $param sender parameters
+ * @return none
+ */
+ public function wizardPrev($sender, $param) {
+ if ($param->CurrentStepIndex === 2) {
+ $this->restore_single_jobid = $_SESSION['restore_single_jobid'];
+ $this->loadBackupsForClient();
+ } elseif ($param->CurrentStepIndex === 3) {
+ $this->setFileVersions();
+ $this->loadSelectedFiles();
+ $this->loadFileVersions();
+ $this->goToPath();
+ } elseif ($param->CurrentStepIndex === 5) {
+ $this->file_relocation_opt = $_SESSION['file_relocation'];
}
- $versions = $this->getModule('api')->get(array('bvfs', 'versions', $clientname, $jobid, $pathid, $filenameid))->output;
- $fileVersions = $this->getModule('misc')->parseFileVersions($filename, $versions);
- $this->setFileVersions($fileVersions);
- $this->VersionsDataGrid->dataSource = $fileVersions;
- $this->VersionsDataGrid->dataBind();
- $this->prepareFilesToRestore();
}
- public function refreshSelectedFiles($sender, $param) {
- $this->prepareFilesToRestore();
- $this->SelectedVersionsDropper->render($param->NewWriter);
+ /**
+ * Cancel wizard.
+ *
+ * @return none
+ */
+ public function wizardStop($sender, $param) {
+ $this->resetWizard();
+ $this->goToDefaultPage();
}
- public function NextStep($sender, $param) {
- }
-
- public function PreviousStep($sender, $param) {
+ /**
+ * Load backup clients list (step 1).
+ *
+ * @param TActiveDropDownList $sender sender object
+ * @param TCommandParameter $param parameters object
+ * @return none
+ */
+ public function loadBackupClients() {
+ $client_list = array();
+ $clients = $this->getModule('api')->get(array('clients'))->output;
+ for ($i = 0; $i < count($clients); $i++) {
+ $client_list[$clients[$i]->name] = $clients[$i]->name;
+ }
+ asort($client_list);
+ $this->BackupClientName->dataSource = $client_list;
+ $this->BackupClientName->dataBind();
+ }
+
+ /**
+ * Load restore client list.
+ *
+ * @return none
+ */
+ public function loadRestoreClients() {
+ $client_list = array();
+ $clients = $this->getModule('api')->get(array('clients'))->output;
+ for ($i = 0; $i < count($clients); $i++) {
+ $client_list[$clients[$i]->name] = $clients[$i]->name;
+ }
+ $this->RestoreClient->SelectedValue = $this->BackupClientName->SelectedValue;
+ $this->RestoreClient->dataSource = $client_list;
+ $this->RestoreClient->dataBind();
+ }
+
+ /**
+ * Load backups for selected client (Step 2).
+ *
+ * @return none
+ */
+ public function loadBackupsForClient() {
+ $clientid = $this->getBackupClientId();
+ $jobs_for_client = $this->getModule('api')->get(array('clients', 'jobs', $clientid))->output;
+ $jobs = $this->getModule('misc')->objectToArray($jobs_for_client);
+ $this->BackupsToRestore->DataSource = array_filter($jobs, array($this, 'isBackupJobToRestore'));
+ $this->BackupsToRestore->dataBind();
+ }
+
+ /**
+ * Check if job can be used in restore.
+ *
+ * @param array $job job properties
+ * @return true if job should be listed to restore, otherwise false
+ */
+ private function isBackupJobToRestore($job) {
+ return ($job['type'] === 'B' && in_array($job['level'], $this->joblevel) && in_array($job['jobstatus'], $this->jobstatus));
+ }
+
+ public function loadBackupSelection($sender, $param) {
+ $this->GroupBackupToRestoreField->Display = ($sender->ID == $this->GroupBackupSelection->ID) ? 'Dynamic' : 'None';
+ $this->BackupToRestoreField->Display = ($sender->ID == $this->OnlySelectedBackupSelection->ID) ? 'Dynamic' : 'None';
+ $this->setBrowserFiles();
+ $this->setFileVersions();
+ $this->setFilesToRestore();
+ $this->markFileToRestore(null, null);
+ $_SESSION['restore_path'] = array();
}
- public function wizardStop($sender, $param) {
- $this->goToDefaultPage();
- }
- public function setJobs($sender, $param) {
- $jobsList = $jobsGroupList = $fileSetsList = array();
- if(is_array($this->jobs)) {
- foreach($this->jobs as $job) {
- if(array_key_exists($job->level, $this->jobLevelsToRestore) && $job->type == 'B' && $job->jobstatus == 'T' && $job->clientid == $this->BackupClientName->SelectedValue) {
- $jobsList[$job->jobid] = sprintf('[%s] %s, %s, %s', $job->jobid, $job->name, $this->jobLevelsToRestore[$job->level], $job->endtime);
- $jobsGroupList[$job->name] = $job->name;
- //$fileSetsList[$job->filesetid] = $this->getFileSet($job->filesetid)->fileset;
- }
+ /**
+ * Get selected backup client identifier.
+ *
+ * @return mixed client identifier or null if no clientid found
+ */
+ public function getBackupClientId() {
+ $clientid = null;
+ $clients = $this->getModule('api')->get(array('clients'))->output;
+ for ($i = 0; $i < count($clients); $i++) {
+ if ($clients[$i]->name === $this->BackupClientName->SelectedValue) {
+ $clientid = $clients[$i]->clientid;
+ break;
}
}
-
- foreach($this->filesets as $director => $filesets) {
- $fileSetsList = array_merge($filesets, $fileSetsList);
+ return $clientid;
+ }
+
+ /**
+ * Load backup jobs to restore for group most recent backups feature.
+ *
+ * @return none
+ */
+ public function loadGroupBackupToRestore() {
+ $jobs = $this->getModule('api')->get(array('jobs'))->output;
+ $jobs = $this->getModule('misc')->objectToArray($jobs);
+ $clientid = $this->getBackupClientId();
+ $job_group_list = array();
+ for ($i = 0; $i < count($jobs); $i++) {
+ $job = $this->getModule('misc')->objectToArray($jobs[$i]);
+ if ($this->isBackupJobToRestore($jobs[$i]) && $jobs[$i]['clientid'] === $clientid) {
+ $job_group_list[$jobs[$i]['name']] = $jobs[$i]['name'];
+ }
}
- $this->BackupToRestore->dataSource = $jobsList;
- $this->BackupToRestore->dataBind();
- $this->GroupBackupToRestore->dataSource = $jobsGroupList;
+ $this->GroupBackupToRestore->dataSource = $job_group_list;
$this->GroupBackupToRestore->dataBind();
- $this->GroupBackupFileSet->dataSource = array_combine($fileSetsList, $fileSetsList);
- $this->GroupBackupFileSet->dataBind();
- $this->setRestoreClients($sender, $param);
}
- public function setBackupClients($sender, $param) {
- if(!$this->IsPostBack) {
- $clientsList = array();
- foreach($this->clients as $client) {
- $clientsList[$client->clientid] = $client->name;
- }
- $this->BackupClientName->dataSource = $clientsList;
- $this->BackupClientName->dataBind();
+ /**
+ * Load filesets to restore for group most recent backups feature.
+ *
+ * @return none
+ */
+ public function loadGroupFileSetToRestore() {
+ $filesets = $this->getModule('api')->get(array('filesets', 'info'))->output;
+ $fileset_list = array();
+ for ($i = 0; $i < count($filesets); $i++) {
+ $fileset_list[$filesets[$i]->filesetid] = $filesets[$i]->fileset . ' (' . $filesets[$i]->createtime . ')';
}
+ asort($fileset_list);
+
+ $this->GroupBackupFileSet->dataSource = $fileset_list;
+ $this->GroupBackupFileSet->dataBind();
}
- public function setRestoreClients($sender, $param) {
- if(!$this->IsPostBack || $sender->ID == $this->BackupClientName->ID) {
- $clientsList = array();
- foreach($this->clients as $client) {
- $clientsList[$client->clientid] = $client->name;
+ /**
+ * Prepare left file browser content.
+ *
+ * @return none
+ */
+ private function prepareBrowserContent() {
+ $jobids = $this->getElementaryBackup();
+ $elements = array();
+ if (!empty($jobids)) {
+ // generating Bvfs may take a moment
+ $this->generateBvfsCache($jobids);
+
+ // get directories list
+ $bvfs_dirs = $this->getModule('api')->set(
+ array('bvfs', 'lsdirs'),
+ array('jobids' => $jobids, 'path' => implode($_SESSION['restore_path']))
+ );
+ $dirs = $this->getModule('misc')->parseBvfsList($bvfs_dirs->output);
+
+ // get files list
+ $bvfs_files = $this->getModule('api')->set(
+ array('bvfs', 'lsfiles'),
+ array('jobids' => $jobids, 'path' => implode($_SESSION['restore_path']))
+ );
+ $files = $this->getModule('misc')->parseBvfsList($bvfs_files->output);
+
+ $elements = array_merge($dirs, $files);
+ if(count($_SESSION['restore_path']) > 0) {
+ array_unshift($elements, $this->browser_root_dir);
}
- $this->RestoreClient->SelectedValue = $this->BackupClientName->SelectedValue;
- $this->RestoreClient->dataSource = $clientsList;
- $this->RestoreClient->dataBind();
}
+ $this->loadBrowserFiles($elements);
}
- public function getFileSet($filesetId) {
- $filesetObj = null;
- foreach($this->filesets as $fileset) {
- if($fileset->filesetid == $filesetId) {
- $filesetObj = $fileset;
+ /*
+ * Get single elementary backup job identifiers.
+ *
+ * @return string comma separated job identifiers
+ */
+ private function getElementaryBackup() {
+ $jobids = '';
+ if($this->OnlySelectedBackupSelection->Checked && isset($_SESSION['restore_single_jobid'])) {
+ $jobs = $this->getModule('api')->get(
+ array('bvfs', 'getjobids', $_SESSION['restore_single_jobid'])
+ );
+ $ids = is_object($jobs) ? $jobs->output : array();
+ foreach ($ids as $jobid) {
+ if(preg_match('/^([\d\,]+)$/', $jobid, $match) == 1) {
+ $jobids = $match[1];
+ break;
+ }
+ }
+ } else {
+ $params = array(
+ 'jobs',
+ 'recent',
+ $this->GroupBackupToRestore->SelectedValue,
+ 'client',
+ $this->BackupClientName->SelectedValue,
+ 'filesetid',
+ $this->GroupBackupFileSet->SelectedValue
+ );
+ $jobs_recent = $this->getModule('api')->get($params);
+ if (count($jobs_recent->output) > 0) {
+ $ids = $jobs_recent->output;
+ $jobids = implode(',', $ids);
+ }
+ }
+ return $jobids;
+ }
+
+ /**
+ * Load path callback method.
+ * Used for manually typed paths in path field.
+ *
+ * @param TActiveLinkButton $sender sender object
+ * @param TEventParameter $param events parameter
+ * @return none
+ */
+ public function loadPath($sender, $param) {
+ $path = explode('/', $this->PathField->Text);
+ $path_len = count($path);
+ for ($i = 0; $i < count($path); $i++) {
+ if ($i == ($path_len - 1) && empty($path[$i])) {
+ // last path dir is slash so not add slash to last element
break;
}
+ $path[$i] .= '/';
}
- return $filesetObj;
- }
-
- public function setStorage($sender, $param) {
- if(!$this->IsPostBack) {
- $storagesList = array();
- $storages = $this->getModule('api')->get(array('storages'))->output;
- foreach($storages as $storage) {
- $storagesList[$storage->storageid] = $storage->name;
+ $this->goToPath($path, true);
+ }
+
+ /**
+ * Go to specific path in the file browser.
+ * There is possible to pass both single directory 'somedir'
+ * or whole path '/etc/somedir'.
+ *
+ * @param string $path path to go
+ * @param bool $full_path determines if $path param is full path or relative path (singel directory)
+ * @return none
+ */
+ private function goToPath($path = '', $full_path = false) {
+ if(!empty($path) && !$full_path) {
+ if($path == $this->browser_up_dir['name']) {
+ array_pop($_SESSION['restore_path']);
+ } elseif($path == $this->browser_root_dir['name']) {
+ $_SESSION['restore_path'] = array();
+ } else {
+ array_push($_SESSION['restore_path'], $path);
}
- $this->GroupBackupStorage->dataSource = $storagesList;
- $this->GroupBackupStorage->dataBind();
}
+ if ($full_path && is_array($path)) {
+ $_SESSION['restore_path'] = $path;
+ }
+ $this->setBrowserPath();
+ $this->prepareBrowserContent();
}
- public function setPool($sender, $param) {
- if(!$this->IsPostBack) {
- $poolsList = array();
- $pools = $this->getModule('api')->get(array('pools'))->output;
- foreach($pools as $pool) {
- $poolsList[$pool->poolid] = $pool->name;
+ /**
+ * Add/mark file to restore.
+ * Used as callback to drag&drop browser elements.
+ *
+ * @param object $sender sender object
+ * @param object $param param object
+ * @return none
+ */
+ public function addFileToRestore($sender, $param) {
+ $fileid = null;
+ $source_element_id = null;
+ $file_prop = array();
+ if (isset($param->CallbackParameter)) {
+ $id_parts = explode('_', $sender->ClientID, 6);
+ $source_element_id = $id_parts[3];
+ $fileid = $param->CallbackParameter;
+ } else {
+ $control = $param->getDroppedControl();
+ $item = $control->getNamingContainer();
+ $id_parts = explode('_', $param->getDragElementID(), 6);
+ $source_element_id = $id_parts[3];
+ }
+ if($source_element_id == $this->VersionsDataGrid->ID) {
+ if (is_null($fileid)) {
+ $fileid = $this->VersionsDataGrid->getDataKeys()->itemAt($item->getItemIndex());
+ }
+ $file_prop = $this->getFileVersions($fileid);
+ } else {
+ if (is_null($fileid)) {
+ $fileid = $this->DataGridFiles->getDataKeys()->itemAt($item->getItemIndex());
}
- $this->GroupBackupPool->dataSource = $poolsList;
- $this->GroupBackupPool->dataBind();
+ $file_prop = $this->getBrowserFile($fileid);
+ }
+ if($file_prop['name'] != $this->browser_root_dir['name'] && $file_prop['name'] != $this->browser_up_dir['name']) {
+ $this->markFileToRestore($fileid, $file_prop);
+ $this->loadSelectedFiles();
}
}
- public function setBackupClient($sender, $param) {
- $this->ClientToRestore->SelectedValue = $param->SelectedValue;
- }
-
- public function setBackupSelection($sender, $param) {
- $this->GroupBackupToRestoreField->Display = ($sender->ID == $this->GroupBackupSelection->ID) ? 'Dynamic' : 'None';
- $this->BackupToRestoreField->Display = ($sender->ID == $this->OnlySelectedBackupSelection->ID) ? 'Dynamic' : 'None';
- $this->setBrowserFiles(array());
- $this->setFileVersions(array());
- $this->setFilesToRestore(array());
- $this->markFileToRestore(null, null);
- $_SESSION['restore_path'] = array();
+ /**
+ * Remove file from files marked to restre.
+ *
+ * @param TActiveImageButton $sender remove button object
+ * @param TEventParameter $param param object
+ * @return none
+ */
+ public function removeSelectedFile($sender, $param) {
+ $fileid = $param->CallbackParameter;
+ $this->unmarkFileToRestore($fileid);
+ $this->loadSelectedFiles();
}
- /*public function setGroupBackup($sender, $param) {
- foreach($this->jobs as $job) {
- if($job->name == $sender->SelectedValue) {
- $this->GroupBackupFileSet->SelectedValue = $job->filesetid;
- }
+ /**
+ * Get file backed up versions.
+ * Called as callback on file element click.
+ *
+ * @param TCallback $sender sender object
+ * @param object $param param object
+ * @return none
+ */
+ public function getVersions($sender, $param) {
+ list($filename, $pathid, $filenameid, $jobid) = explode('|', $param->CallbackParameter, 4);
+ if($filenameid == 0) {
+ $this->goToPath($filename);
+ return;
}
- }*/
+ $clientname = $this->BackupClientName->SelectedValue;
+ $versions = $this->getModule('api')->get(array('bvfs', 'versions', $clientname, $jobid, $pathid, $filenameid))->output;
+ $file_versions = $this->getModule('misc')->parseFileVersions($filename, $versions);
+ $this->setFileVersions($file_versions);
+ $this->VersionsDataGrid->dataSource = $file_versions;
+ $this->VersionsDataGrid->dataBind();
+ $this->loadSelectedFiles();
+ }
- public function resetFileBrowser($sender, $param) {
- $this->markFileToRestore(null, null);
- $this->setBrowserPath($this->browserRootDir['name']);
+ /**
+ * Refresh/re-render selected files list.
+ *
+ * @param TDropContainer $sender sender object
+ * @param TEventParameter $param param object
+ * @return none
+ */
+ public function refreshSelectedFiles($sender, $param) {
+ $this->loadSelectedFiles();
+ $this->SelectedVersionsDropper->render($param->NewWriter);
}
- private function prepareBrowserFiles($files) {
+ /*
+ * Load file browser files to list.
+ *
+ * @param array $files files to list.
+ * @return none
+ */
+ private function loadBrowserFiles($files) {
$this->setBrowserFiles($files);
$this->DataGridFiles->dataSource = $files;
- @$this->DataGridFiles->dataBind();
+ $this->DataGridFiles->dataBind();
}
- private function prepareVersionsToRestore() {
+ /**
+ * Load file versions area.
+ *
+ * @return none;
+ */
+ private function loadFileVersions() {
$this->VersionsDataGrid->dataSource = $_SESSION['files_versions'];
$this->VersionsDataGrid->dataBind();
}
- private function prepareFilesToRestore() {
+ /**
+ * Load selected files in drop area.
+ *
+ * @return none
+ */
+ private function loadSelectedFiles() {
$this->SelectedVersionsDataGrid->dataSource = $_SESSION['restore'];
$this->SelectedVersionsDataGrid->dataBind();
}
- private function setBrowserPath($path) {
- if(!empty($path)) {
- if($path == $this->browserUpDir['name']) {
- array_pop($_SESSION['restore_path']);
- } elseif($path == $this->browserRootDir['name']) {
- $_SESSION['restore_path'] = array();
- } else {
- array_push($_SESSION['restore_path'], $path);
- }
- }
- $this->setBrowserLocalizator();
- $this->prepareBrowserContent();
- }
-
- private function getBrowserPath($stringFormat = false) {
- return ($stringFormat === true) ? implode($_SESSION['restore_path']) : $_SESSION['restore_path'];
- }
-
- private function setBrowserLocalizator() {
- $localization = $this->getBrowserPath(true);
- $this->PathField->HeaderText = mb_strlen($localization) > 56 ? '...' . mb_substr($localization, -56) : $localization;
- }
-
- private function prepareBrowserContent() {
- $jobids = $this->getElementaryBackup();
-
- // generating Bvfs may takes a moment
- $this->generateBvfsCacheByJobids($jobids);
- $bvfsDirsList = $this->getModule('api')->set(array('bvfs', 'lsdirs'), array('jobids' => $jobids, 'path' => $this->getBrowserPath(true)));
- $bvfsDirs = is_object($bvfsDirsList) ? $bvfsDirsList->output : array();
- $dirs = $this->getModule('misc')->parseBvfsList($bvfsDirs);
- $bvfsFilesList = $this->getModule('api')->set(array('bvfs', 'lsfiles'), array('jobids' => $jobids, 'path' => $this->getBrowserPath(true)));
- $bvfsFiles = is_object($bvfsFilesList) ? $bvfsFilesList->output : array();
- $files = $this->getModule('misc')->parseBvfsList($bvfsFiles);
- $elements = array_merge($dirs, $files);
- if(count($this->getBrowserPath()) > 0) {
- array_unshift($elements, $this->browserRootDir);
- }
- $this->prepareBrowserFiles($elements);
- }
-
- private function getElementaryBackup() {
- $jobids = null;
- if($this->OnlySelectedBackupSelection->Checked === true) {
- $jobs = $this->getModule('api')->get(array('bvfs', 'getjobids', $this->BackupToRestore->SelectedValue));
- $ids = is_object($jobs) ? $jobs->output : array();
- foreach($ids as $jobid) {
- if(preg_match('/^([\d\,]+)$/', $jobid, $match) == 1) {
- $jobids = $match[1];
- break;
- }
- }
- } else {
- $jobsRecent = $this->getModule('api')->get(array('jobs', 'recent', $this->GroupBackupToRestore->SelectedValue, $this->BackupClientName->SelectedValue));
- if(isset($jobsRecent->output) && count($jobsRecent->output) > 0) {
- $ids = $jobsRecent->output;
- $jobids = implode(',', $ids);
- }
- }
-
- $completeJobids = (!is_null($jobids)) ? $jobids : $this->BackupToRestore->SelectedValue;
- return $completeJobids;
- }
-
- private function generateBvfsCacheByJobids($jobids) {
- $this->getModule('api')->set(array('bvfs', 'update'), array('jobids' => $jobids));
- }
-
- private function setFileVersions($versions) {
+ /**
+ * Set file browser path field.
+ *
+ * @return none
+ */
+ private function setBrowserPath() {
+ $this->PathField->Text = implode($_SESSION['restore_path']);
+ }
+
+ /**
+ * Generate Bvfs cache by job identifiers.
+ *
+ * @param string $jobids comma separated job identifiers
+ * @return none
+ */
+ private function generateBvfsCache($jobids) {
+ $this->getModule('api')->set(
+ array('bvfs', 'update'),
+ array('jobids' => $jobids)
+ );
+ }
+
+ /**
+ * Set versions for selected file.
+ *
+ * @param array $versions file versions data
+ * @return none
+ */
+ private function setFileVersions($versions = array()) {
$_SESSION['files_versions'] = $versions;
}
+ /**
+ * Get file versions for specified fileid.
+ *
+ * @param integer $fileid file identifier
+ * @return none
+ */
private function getFileVersions($fileid) {
$versions = array();
foreach($_SESSION['files_versions'] as $file) {
return $versions;
}
- private function setBrowserFiles($files) {
+ /**
+ * Set browser files.
+ *
+ * @param array $files file list
+ * @return none
+ */
+ private function setBrowserFiles($files = array()) {
$_SESSION['files_browser'] = $files;
}
+ /**
+ * Get browser file by fileid.
+ *
+ * @param integer $fileid file identifier
+ * @return none
+ */
private function getBrowserFile($fileid) {
$element = array();
foreach($_SESSION['files_browser'] as $file) {
return $element;
}
+ /**
+ * Mark file to restore.
+ *
+ * @param integer $fileid file identifier
+ * @param array $file file properties to mark
+ * @return none
+ */
private function markFileToRestore($fileid, $file) {
if($fileid === null) {
$_SESSION['restore'] = array();
- } elseif($file['name'] != $this->browserRootDir['name'] && $file['name'] != $this->browserUpDir['name']) {
+ } elseif($file['name'] != $this->browser_root_dir['name'] && $file['name'] != $this->browser_up_dir['name']) {
$_SESSION['restore'][$fileid] = $file;
}
}
+ /**
+ * Unmark file to restore.
+ *
+ * @param integer $fileid file identifier
+ * @return none
+ */
private function unmarkFileToRestore($fileid) {
if(array_key_exists($fileid, $_SESSION['restore'])) {
unset($_SESSION['restore'][$fileid]);
}
}
+ /**
+ * Get files to restore.
+ *
+ * @return array list with files to restore
+ */
public function getFilesToRestore() {
return $_SESSION['restore'];
}
- public function setFilesToRestore($files) {
+ /**
+ * Set files to restore
+ *
+ * @param array $files files to restore
+ * @return none
+ */
+ public function setFilesToRestore($files = array()) {
$_SESSION['restore'] = $files;
}
- public function getRestoreElements($asObject = false) {
+ /**
+ * Get all restore elements (fileids and dirids).
+ *
+ * @param bool $as_object return result as object
+ * @return array list fileids and dirids
+ */
+ public function getRestoreElements($as_object = false) {
$fileids = array();
$dirids = array();
- foreach($this->getFilesToRestore() as $fileid => $properties) {
- if($properties['type'] == 'dir') {
+ $findexes = array();
+ foreach ($this->getFilesToRestore() as $fileid => $properties) {
+ if ($properties['type'] == 'dir') {
$dirids[] = $properties['pathid'];
- } elseif($properties['type'] == 'file') {
+ } elseif ($properties['type'] == 'file') {
$fileids[] = $fileid;
+ if ($properties['lstat']['linkfi'] !== 0) {
+ $findexes[] = $properties['jobid'] . ',' . $properties['lstat']['linkfi'];
+ }
}
}
- $ret = array('fileid' => $fileids, 'dirid' => $dirids);
- if($asObject === true) {
+ $ret = array('fileid' => $fileids, 'dirid' => $dirids, 'findex' => $findexes);
+ if($as_object === true) {
$ret = (object)$ret;
}
return $ret;
}
+ /**
+ * Wizard finish method.
+ *
+ * @return none
+ */
public function wizardCompleted() {
$jobids = $this->getElementaryBackup();
- $path = self::BVFS_PATH_PREFIX . str_replace(',', '', $jobids);
- $restoreElements = $this->getRestoreElements();
- $cmdProps = array('jobids' => $jobids, 'path' => $path);
- if(count($restoreElements['fileid']) > 0) {
- $cmdProps['fileid'] = implode(',', $restoreElements['fileid']);
+ $path = self::BVFS_PATH_PREFIX . getmypid();
+ $restore_elements = $this->getRestoreElements();
+ $cmd_props = array('jobids' => $jobids, 'path' => $path);
+ $is_element = false;
+ if(count($restore_elements['fileid']) > 0) {
+ $cmd_props['fileid'] = implode(',', $restore_elements['fileid']);
+ $is_element = true;
+ }
+ if(count($restore_elements['dirid']) > 0) {
+ $cmd_props['dirid'] = implode(',', $restore_elements['dirid']);
+ $is_element = true;
}
- if(count($restoreElements['dirid']) > 0) {
- $cmdProps['dirid'] = implode(',', $restoreElements['dirid']);
+ if (count($restore_elements['findex']) > 0) {
+ $cmd_props['findex'] = implode(',', $restore_elements['findex']);
+ $is_element = true;
}
- $this->getModule('api')->create(array('bvfs', 'restore'), $cmdProps);
- $restoreProps = array();
- $restoreProps['rpath'] = $path;
- $restoreProps['clientid'] = intval($this->RestoreClient->SelectedValue);
- $restoreProps['fileset'] = $this->GroupBackupFileSet->SelectedValue;
- $restoreProps['priority'] = intval($this->RestoreJobPriority->Text);
- $restoreProps['where'] = $this->RestorePath->Text;
- $restoreProps['replace'] = $this->ReplaceFiles->SelectedValue;
-
- $ret = $this->getModule('api')->create(array('jobs', 'restore'), $restoreProps);
- $jobid = $this->getModule('misc')->findJobIdStartedJob($ret->output);
- $urlParams = array('open' => 'Job');
+ $jobid = null;
+ if ($is_element) {
+ $this->getModule('api')->create(array('bvfs', 'restore'), $cmd_props);
+ $restore_props = array();
+ $restore_props['rpath'] = $path;
+ $restore_props['client'] = $this->RestoreClient->SelectedValue;
+ $restore_props['priority'] = intval($this->RestoreJobPriority->Text);
+ if ($_SESSION['file_relocation'] == 2) {
+ if (!empty($this->RestoreStripPrefix->Text)) {
+ $restore_props['strip_prefix'] = $this->RestoreStripPrefix->Text;
+ }
+ if (!empty($this->RestoreAddPrefix->Text)) {
+ $restore_props['add_prefix'] = $this->RestoreAddPrefix->Text;
+ }
+ if (!empty($this->RestoreAddSuffix->Text)) {
+ $restore_props['add_suffix'] = $this->RestoreAddSuffix->Text;
+ }
+ } elseif ($_SESSION['file_relocation'] == 3) {
+ if (!empty($this->RestoreRegexWhere->Text)) {
+ $restore_props['regex_where'] = $this->RestoreRegexWhere->Text;
+ }
+ }
+ if (!array_key_exists('add_prefix', $restore_props)) {
+ $restore_props['where'] = $this->RestorePath->Text;
+ }
+ $restore_props['replace'] = $this->ReplaceFiles->SelectedValue;
+ $restore_props['restorejob'] = $this->RestoreJob->SelectedValue;
+
+ $ret = $this->getModule('api')->create(array('jobs', 'restore'), $restore_props);
+ $jobid = $this->getModule('misc')->findJobIdStartedJob($ret->output);
+ }
+ $url_params = array('open' => 'Job');
if (is_numeric($jobid)) {
- $urlParams['id'] = $jobid;
+ $url_params['id'] = $jobid;
}
- $this->goToDefaultPage($urlParams);
+ $this->goToDefaultPage($url_params);
+ }
+
+ /**
+ * Load restore jobs on the list.
+ *
+ * @return none
+ */
+ private function loadRestoreJobs() {
+ $restore_job_tasks = $this->getModule('api')->get(array('jobs', 'tasks', 'type', 'R'))->output;
+ $jobs = array();
+ foreach ($restore_job_tasks as $director => $restore_jobs) {
+ $jobs = array_merge($jobs, $restore_jobs);
+ }
+ $this->RestoreJob->DataSource = array_combine($jobs, $jobs);
+ $this->RestoreJob->dataBind();
+ }
+
+ private function loadRequiredVolumes() {
+ $volumes = array();
+ foreach ($this->getFilesToRestore() as $fileid => $props) {
+ // it can be expensive for many restore paths
+ $result = $this->getModule('api')->get(array('volumes', 'required', $props['jobid'], $fileid));
+ if ($result->error === 0) {
+ for ($i = 0; $i < count($result->output); $i++) {
+ $volumes[$result->output[$i]->volume] = array(
+ 'volume' => $result->output[$i]->volume,
+ 'inchanger' => $result->output[$i]->inchanger
+ );
+ }
+ }
+ }
+ $this->RestoreVolumes->DataSource = array_values($volumes);
+ $this->RestoreVolumes->dataBind();
+ }
+
+ /**
+ * Reset wizard.
+ * All fields are back to initial form.
+ *
+ * @return none
+ */
+ private function resetWizard() {
+ $this->setBrowserFiles();
+ $this->setFileVersions();
+ $this->setFilesToRestore();
+ $this->markFileToRestore(null, null);
+ $this->loadRestoreJobs();
+ $_SESSION['restore_path'] = array();
+ $_SESSION['restore_single_jobid'] = null;
+ unset($_SESSION['file_relocation']);
}
}
?>