[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/files/query/ -> PhabricatorFileQuery.php (source)

   1  <?php
   2  
   3  final class PhabricatorFileQuery
   4    extends PhabricatorCursorPagedPolicyAwareQuery {
   5  
   6    private $ids;
   7    private $phids;
   8    private $authorPHIDs;
   9    private $explicitUploads;
  10    private $transforms;
  11    private $dateCreatedAfter;
  12    private $dateCreatedBefore;
  13    private $contentHashes;
  14  
  15    public function withIDs(array $ids) {
  16      $this->ids = $ids;
  17      return $this;
  18    }
  19  
  20    public function withPHIDs(array $phids) {
  21      $this->phids = $phids;
  22      return $this;
  23    }
  24  
  25    public function withAuthorPHIDs(array $phids) {
  26      $this->authorPHIDs = $phids;
  27      return $this;
  28    }
  29  
  30    public function withDateCreatedBefore($date_created_before) {
  31      $this->dateCreatedBefore = $date_created_before;
  32      return $this;
  33    }
  34  
  35    public function withDateCreatedAfter($date_created_after) {
  36      $this->dateCreatedAfter = $date_created_after;
  37      return $this;
  38    }
  39  
  40    public function withContentHashes(array $content_hashes) {
  41      $this->contentHashes = $content_hashes;
  42      return $this;
  43    }
  44  
  45    /**
  46     * Select files which are transformations of some other file. For example,
  47     * you can use this query to find previously generated thumbnails of an image
  48     * file.
  49     *
  50     * As a parameter, provide a list of transformation specifications. Each
  51     * specification is a dictionary with the keys `originalPHID` and `transform`.
  52     * The `originalPHID` is the PHID of the original file (the file which was
  53     * transformed) and the `transform` is the name of the transform to query
  54     * for. If you pass `true` as the `transform`, all transformations of the
  55     * file will be selected.
  56     *
  57     * For example:
  58     *
  59     *   array(
  60     *     array(
  61     *       'originalPHID' => 'PHID-FILE-aaaa',
  62     *       'transform'    => 'sepia',
  63     *     ),
  64     *     array(
  65     *       'originalPHID' => 'PHID-FILE-bbbb',
  66     *       'transform'    => true,
  67     *     ),
  68     *   )
  69     *
  70     * This selects the `"sepia"` transformation of the file with PHID
  71     * `PHID-FILE-aaaa` and all transformations of the file with PHID
  72     * `PHID-FILE-bbbb`.
  73     *
  74     * @param list<dict>  List of transform specifications, described above.
  75     * @return this
  76     */
  77    public function withTransforms(array $specs) {
  78      foreach ($specs as $spec) {
  79        if (!is_array($spec) ||
  80            empty($spec['originalPHID']) ||
  81            empty($spec['transform'])) {
  82          throw new Exception(
  83            "Transform specification must be a dictionary with keys ".
  84            "'originalPHID' and 'transform'!");
  85        }
  86      }
  87  
  88      $this->transforms = $specs;
  89      return $this;
  90    }
  91  
  92    public function showOnlyExplicitUploads($explicit_uploads) {
  93      $this->explicitUploads = $explicit_uploads;
  94      return $this;
  95    }
  96  
  97    protected function loadPage() {
  98      $table = new PhabricatorFile();
  99      $conn_r = $table->establishConnection('r');
 100  
 101      $data = queryfx_all(
 102        $conn_r,
 103        'SELECT f.* FROM %T f %Q %Q %Q %Q',
 104        $table->getTableName(),
 105        $this->buildJoinClause($conn_r),
 106        $this->buildWhereClause($conn_r),
 107        $this->buildOrderClause($conn_r),
 108        $this->buildLimitClause($conn_r));
 109  
 110      $files = $table->loadAllFromArray($data);
 111  
 112      if (!$files) {
 113        return $files;
 114      }
 115  
 116      // We need to load attached objects to perform policy checks for files.
 117      // First, load the edges.
 118  
 119      $edge_type = PhabricatorEdgeConfig::TYPE_FILE_HAS_OBJECT;
 120      $file_phids = mpull($files, 'getPHID');
 121      $edges = id(new PhabricatorEdgeQuery())
 122        ->withSourcePHIDs($file_phids)
 123        ->withEdgeTypes(array($edge_type))
 124        ->execute();
 125  
 126      $object_phids = array();
 127      foreach ($files as $file) {
 128        $phids = array_keys($edges[$file->getPHID()][$edge_type]);
 129        $file->attachObjectPHIDs($phids);
 130        foreach ($phids as $phid) {
 131          $object_phids[$phid] = true;
 132        }
 133      }
 134  
 135      // If this file is a transform of another file, load that file too. If you
 136      // can see the original file, you can see the thumbnail.
 137  
 138      // TODO: It might be nice to put this directly on PhabricatorFile and remove
 139      // the PhabricatorTransformedFile table, which would be a little simpler.
 140  
 141      $xforms = id(new PhabricatorTransformedFile())->loadAllWhere(
 142        'transformedPHID IN (%Ls)',
 143        $file_phids);
 144      $xform_phids = mpull($xforms, 'getOriginalPHID', 'getTransformedPHID');
 145      foreach ($xform_phids as $derived_phid => $original_phid) {
 146        $object_phids[$original_phid] = true;
 147      }
 148  
 149      $object_phids = array_keys($object_phids);
 150  
 151      // Now, load the objects.
 152  
 153      $objects = array();
 154      if ($object_phids) {
 155        // NOTE: We're explicitly turning policy exceptions off, since the rule
 156        // here is "you can see the file if you can see ANY associated object".
 157        // Without this explicit flag, we'll incorrectly throw unless you can
 158        // see ALL associated objects.
 159  
 160        $objects = id(new PhabricatorObjectQuery())
 161          ->setParentQuery($this)
 162          ->setViewer($this->getViewer())
 163          ->withPHIDs($object_phids)
 164          ->setRaisePolicyExceptions(false)
 165          ->execute();
 166        $objects = mpull($objects, null, 'getPHID');
 167      }
 168  
 169      foreach ($files as $file) {
 170        $file_objects = array_select_keys($objects, $file->getObjectPHIDs());
 171        $file->attachObjects($file_objects);
 172      }
 173  
 174      foreach ($files as $key => $file) {
 175        $original_phid = idx($xform_phids, $file->getPHID());
 176        if ($original_phid == PhabricatorPHIDConstants::PHID_VOID) {
 177          // This is a special case for builtin files, which are handled
 178          // oddly.
 179          $original = null;
 180        } else if ($original_phid) {
 181          $original = idx($objects, $original_phid);
 182          if (!$original) {
 183            // If the viewer can't see the original file, also prevent them from
 184            // seeing the transformed file.
 185            $this->didRejectResult($file);
 186            unset($files[$key]);
 187            continue;
 188          }
 189        } else {
 190          $original = null;
 191        }
 192        $file->attachOriginalFile($original);
 193      }
 194  
 195      return $files;
 196    }
 197  
 198    private function buildJoinClause(AphrontDatabaseConnection $conn_r) {
 199      $joins = array();
 200  
 201      if ($this->transforms) {
 202        $joins[] = qsprintf(
 203          $conn_r,
 204          'JOIN %T t ON t.transformedPHID = f.phid',
 205          id(new PhabricatorTransformedFile())->getTableName());
 206      }
 207  
 208      return implode(' ', $joins);
 209    }
 210  
 211    private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
 212      $where = array();
 213  
 214      $where[] = $this->buildPagingClause($conn_r);
 215  
 216      if ($this->ids) {
 217        $where[] = qsprintf(
 218          $conn_r,
 219          'f.id IN (%Ld)',
 220          $this->ids);
 221      }
 222  
 223      if ($this->phids) {
 224        $where[] = qsprintf(
 225          $conn_r,
 226          'f.phid IN (%Ls)',
 227          $this->phids);
 228      }
 229  
 230      if ($this->authorPHIDs) {
 231        $where[] = qsprintf(
 232          $conn_r,
 233          'f.authorPHID IN (%Ls)',
 234          $this->authorPHIDs);
 235      }
 236  
 237      if ($this->explicitUploads) {
 238        $where[] = qsprintf(
 239          $conn_r,
 240          'f.isExplicitUpload = true');
 241      }
 242  
 243      if ($this->transforms) {
 244        $clauses = array();
 245        foreach ($this->transforms as $transform) {
 246          if ($transform['transform'] === true) {
 247            $clauses[] = qsprintf(
 248              $conn_r,
 249              '(t.originalPHID = %s)',
 250              $transform['originalPHID']);
 251          } else {
 252            $clauses[] = qsprintf(
 253              $conn_r,
 254              '(t.originalPHID = %s AND t.transform = %s)',
 255              $transform['originalPHID'],
 256              $transform['transform']);
 257          }
 258        }
 259        $where[] = qsprintf($conn_r, '(%Q)', implode(') OR (', $clauses));
 260      }
 261  
 262      if ($this->dateCreatedAfter) {
 263        $where[] = qsprintf(
 264          $conn_r,
 265          'f.dateCreated >= %d',
 266          $this->dateCreatedAfter);
 267      }
 268  
 269      if ($this->dateCreatedBefore) {
 270        $where[] = qsprintf(
 271          $conn_r,
 272          'f.dateCreated <= %d',
 273          $this->dateCreatedBefore);
 274      }
 275  
 276      if ($this->contentHashes) {
 277        $where[] = qsprintf(
 278          $conn_r,
 279          'f.contentHash IN (%Ls)',
 280          $this->contentHashes);
 281      }
 282  
 283      return $this->formatWhereClause($where);
 284    }
 285  
 286    protected function getPagingColumn() {
 287      return 'f.id';
 288    }
 289  
 290    public function getQueryApplicationClass() {
 291      return 'PhabricatorFilesApplication';
 292    }
 293  
 294  }


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