[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/phragment/controller/ -> PhragmentZIPController.php (source)

   1  <?php
   2  
   3  final class PhragmentZIPController extends PhragmentController {
   4  
   5    private $dblob;
   6    private $snapshot;
   7  
   8    private $snapshotCache;
   9  
  10    public function shouldAllowPublic() {
  11      return true;
  12    }
  13  
  14    public function willProcessRequest(array $data) {
  15      $this->dblob = idx($data, 'dblob', '');
  16      $this->snapshot = idx($data, 'snapshot', null);
  17    }
  18  
  19    public function processRequest() {
  20      $request = $this->getRequest();
  21      $viewer = $request->getUser();
  22  
  23      $parents = $this->loadParentFragments($this->dblob);
  24      if ($parents === null) {
  25        return new Aphront404Response();
  26      }
  27      $fragment = idx($parents, count($parents) - 1, null);
  28  
  29      if ($this->snapshot !== null) {
  30        $snapshot = id(new PhragmentSnapshotQuery())
  31          ->setViewer($viewer)
  32          ->withPrimaryFragmentPHIDs(array($fragment->getPHID()))
  33          ->withNames(array($this->snapshot))
  34          ->executeOne();
  35        if ($snapshot === null) {
  36          return new Aphront404Response();
  37        }
  38  
  39        $cache = id(new PhragmentSnapshotChildQuery())
  40          ->setViewer($viewer)
  41          ->needFragmentVersions(true)
  42          ->withSnapshotPHIDs(array($snapshot->getPHID()))
  43          ->execute();
  44        $this->snapshotCache = mpull(
  45          $cache,
  46          'getFragmentVersion',
  47          'getFragmentPHID');
  48      }
  49  
  50      $temp = new TempFile();
  51  
  52      $zip = null;
  53      try {
  54        $zip = new ZipArchive();
  55      } catch (Exception $e) {
  56        $dialog = new AphrontDialogView();
  57        $dialog->setUser($viewer);
  58  
  59        $inst = pht(
  60          'This system does not have the ZIP PHP extension installed. This '.
  61          'is required to download ZIPs from Phragment.');
  62  
  63        $dialog->setTitle(pht('ZIP Extension Not Installed'));
  64        $dialog->appendParagraph($inst);
  65  
  66        $dialog->addCancelButton('/phragment/browse/'.$this->dblob);
  67        return id(new AphrontDialogResponse())->setDialog($dialog);
  68      }
  69  
  70      if (!$zip->open((string)$temp, ZipArchive::CREATE)) {
  71        throw new Exception('Unable to create ZIP archive!');
  72      }
  73  
  74      $mappings = $this->getFragmentMappings($fragment, $fragment->getPath());
  75  
  76      $phids = array();
  77      foreach ($mappings as $path => $file_phid) {
  78        $phids[] = $file_phid;
  79      }
  80  
  81      $files = id(new PhabricatorFileQuery())
  82        ->setViewer($viewer)
  83        ->withPHIDs($phids)
  84        ->execute();
  85      $files = mpull($files, null, 'getPHID');
  86      foreach ($mappings as $path => $file_phid) {
  87        if (!isset($files[$file_phid])) {
  88          // The path is most likely pointing to a deleted fragment, which
  89          // hence no longer has a file associated with it.
  90          unset($mappings[$path]);
  91          continue;
  92        }
  93        $mappings[$path] = $files[$file_phid];
  94      }
  95  
  96      foreach ($mappings as $path => $file) {
  97        if ($file !== null) {
  98          $zip->addFromString($path, $file->loadFileData());
  99        }
 100      }
 101      $zip->close();
 102  
 103      $zip_name = $fragment->getName();
 104      if (substr($zip_name, -4) !== '.zip') {
 105        $zip_name .= '.zip';
 106      }
 107  
 108      $data = Filesystem::readFile((string)$temp);
 109      $file = PhabricatorFile::buildFromFileDataOrHash(
 110        $data,
 111        array(
 112          'name' => $zip_name,
 113          'ttl' => time() + 60 * 60 * 24,
 114        ));
 115  
 116      $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
 117        $file->attachToObject($fragment->getPHID());
 118      unset($unguarded);
 119  
 120      $return = $fragment->getURI();
 121      if ($request->getExists('return')) {
 122        $return = $request->getStr('return');
 123      }
 124  
 125      return id(new AphrontRedirectResponse())
 126        ->setIsExternal(true)
 127        ->setURI($file->getDownloadURI($return));
 128    }
 129  
 130    /**
 131     * Returns a list of mappings like array('some/path.txt' => 'file PHID');
 132     */
 133    private function getFragmentMappings(PhragmentFragment $current, $base_path) {
 134      $mappings = $current->getFragmentMappings(
 135        $this->getRequest()->getUser(),
 136        $base_path);
 137  
 138      $result = array();
 139      foreach ($mappings as $path => $fragment) {
 140        $version = $this->getVersion($fragment);
 141        if ($version !== null) {
 142          $result[$path] = $version->getFilePHID();
 143        }
 144      }
 145      return $result;
 146    }
 147  
 148    private function getVersion($fragment) {
 149      if ($this->snapshot === null) {
 150        return $fragment->getLatestVersion();
 151      } else {
 152        return idx($this->snapshotCache, $fragment->getPHID(), null);
 153      }
 154    }
 155  
 156  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1