/**
  * Fetch a file or if no FileName set all files found at remote location.
  *
  * @SideEffects:
  *  Writes files to local filesystem
  *
  * If all files then don't overwrite existing files, otherwise if a single file then overwrite it every time.
  *
  * @return int number of files fetched
  */
 public function execute()
 {
     $this->checkPerm();
     $transport = Replicant::transportFactory($this->Protocol, $this->RemoteHost, $this->Proxy, $this->UserName, $this->Password);
     // if we have a FileName then only enqueue that file, otherwise get a list of files from remote host and enqueue all for fetching (existing files won't be refetched in this case).
     if (!$this->FileName) {
         $this->step("Fetching file list from '{$this->Protocol}://{$this->UserName}@{$this->RemoteHost}/{$this->Path}'");
         try {
             $files = $transport->fetchFileList($this->Path);
         } catch (Exception $e) {
             $this->failed("Failed to get file list: " . $e->getMessage());
             return 0;
         }
     } else {
         $fullPath = FileSystemTools::build_path($this->Path, $this->FileName);
         $this->step("Enqueuing file '{$fullPath}'");
         // create the files array as a single entry with path and name
         $files = array(array('Path' => $this->Path, 'FileName' => $this->FileName));
     }
     $numFiles = count($files);
     $numFetched = 0;
     $this->step("Fetching #{$numFiles} files");
     foreach ($files as $fileInfo) {
         // strip off extension here or alpha will reject request
         $fileName = $fileInfo['FileName'];
         $remotePathName = FileSystemTools::build_path(Replicant::config()->get('remote_path'), basename($fileName));
         $localPathName = FileSystemTools::build_path(Replicant::asset_path(), $fileName);
         $overwrite = $this->FileName != '';
         $this->step("Fetching file '{$remotePathName}' with overwrite (" . ($overwrite ? "set" : "not set") . ")");
         try {
             if (false !== $transport->fetchFile($remotePathName, $localPathName, $overwrite)) {
                 $numFetched++;
             }
         } catch (Exception $e) {
             $this->failed("Failed to fetch file '{$remotePathName}': " . $e->getMessage());
             // EARLY EXIT!
             return false;
         }
     }
     $this->success("Fetched #{$numFetched} files of #{$numFiles}");
     return $numFetched;
 }
 /**
  * Save record as normal, then if the record was new invoke the record class (which should be derived from ReplicantAction) to perform the action.
  *
  * If the remote address is provided
  *
  * @param $data
  * @param $form
  * @return HTMLText|SS_HTTPResponse|ViewableData_Customised|void
  */
 public function doSave($data, $form)
 {
     $list = $this->gridField->getList();
     $controller = Controller::curr();
     $new_record = !$this->record->isInDB();
     $ok = false;
     try {
         $this->record->update($data);
         //            $form->saveInto($this->record);
         $this->record->write();
         // now actually run the action. If it is a dump action and the remote host is not localhost then we call dump on the remote host instead.
         if ($this->record->ClassName != 'ReplicantActionDump' || $this->record->RemoteHost == 'localhost') {
             $ok = $this->record->execute();
         } else {
             $transport = Replicant::transportFactory($this->record->Protocol, $this->record->RemoteHost, $this->record->Proxy, $this->record->UserName, $this->record->Password);
             $path = "replicant/dump" . ($this->record->UseGZIP ? "&UseGZIP=1" : "");
             $url = $transport->buildURL($path);
             $this->record->step("Dumping on remote system {$url}");
             try {
                 $result = $transport->fetchPage($path);
             } catch (Exception $e) {
                 $result = $e->getMessage();
             }
             // TODO SW better result checking here
             $ok = false !== strpos($result, 'Success');
             if ($ok) {
                 $this->record->success("Dumped Database on {$url}: {$result}");
             } else {
                 $this->record->failed("Failed calling {$url}: {$result}");
             }
         }
         if ($ok) {
             $link = '"' . $this->record->Title . '"';
             $message = _t('GridFieldDetailForm.Saved', 'Saved {name} {link}', array('name' => $this->record->i18n_singular_name(), 'link' => $link));
             $form->sessionMessage($message, 'good');
         } else {
             $message = _t('Error', 'Failed to {message}: {error}', array('message' => $this->record->i18n_singular_name(), 'error' => $this->record->ResultInfo));
             $form->sessionMessage($message, 'bad');
         }
         $list->add($this->record, null);
     } catch (ValidationException $e) {
         $this->record->failed($e->getResult()->message());
         $form->sessionMessage($e->getResult()->message(), 'bad');
         $responseNegotiator = new PjaxResponseNegotiator(array('CurrentForm' => function () use(&$form) {
             return $form->forTemplate();
         }, 'default' => function () use(&$controller) {
             return $controller->redirectBack();
         }));
         if ($controller->getRequest()->isAjax()) {
             $controller->getRequest()->addHeader('X-Pjax', 'CurrentForm');
         }
         return $responseNegotiator->respond($controller->getRequest());
     } catch (Exception $e) {
         $this->record->failed($e->getMessage());
         $form->sessionMessage($e->getMessage(), 'bad');
         $responseNegotiator = new PjaxResponseNegotiator(array('CurrentForm' => function () use(&$form) {
             return $form->forTemplate();
         }, 'default' => function () use(&$controller) {
             return $controller->redirectBack();
         }));
         if ($controller->getRequest()->isAjax()) {
             $controller->getRequest()->addHeader('X-Pjax', 'CurrentForm');
         }
         return $responseNegotiator->respond($controller->getRequest());
     }
     $noActionURL = $controller->removeAction($data['url']);
     $controller->getRequest()->addHeader('X-Pjax', 'Content');
     return $controller->redirect($noActionURL, 302);
 }