<commit_before><?php

final class PhabricatorFileQuery
  extends PhabricatorCursorPagedPolicyAwareQuery {

  private $ids;
  private $phids;
  private $authorPHIDs;
  private $explicitUploads;
  private $transforms;
  private $dateCreatedAfter;
  private $dateCreatedBefore;
  private $contentHashes;
  private $minLength;
  private $maxLength;
  private $names;
  private $isPartial;

  public function withIDs(array $ids) {
    $this->ids = $ids;
    return $this;
  }

  public function withPHIDs(array $phids) {
    $this->phids = $phids;
    return $this;
  }

  public function withAuthorPHIDs(array $phids) {
    $this->authorPHIDs = $phids;
    return $this;
  }

  public function withDateCreatedBefore($date_created_before) {
    $this->dateCreatedBefore = $date_created_before;
    return $this;
  }

  public function withDateCreatedAfter($date_created_after) {
    $this->dateCreatedAfter = $date_created_after;
    return $this;
  }

  public function withContentHashes(array $content_hashes) {
    $this->contentHashes = $content_hashes;
    return $this;
  }

  /**
   * Select files which are transformations of some other file. For example,
   * you can use this query to find previously generated thumbnails of an image
   * file.
   *
   * As a parameter, provide a list of transformation specifications. Each
   * specification is a dictionary with the keys `originalPHID` and `transform`.
   * The `originalPHID` is the PHID of the original file (the file which was
   * transformed) and the `transform` is the name of the transform to query
   * for. If you pass `true` as the `transform`, all transformations of the
   * file will be selected.
   *
   * For example:
   *
   *   array(
   *     array(
   *       'originalPHID' => 'PHID-FILE-aaaa',
   *       'transform'    => 'sepia',
   *     ),
   *     array(
   *       'originalPHID' => 'PHID-FILE-bbbb',
   *       'transform'    => true,
   *     ),
   *   )
   *
   * This selects the `"sepia"` transformation of the file with PHID
   * `PHID-FILE-aaaa` and all transformations of the file with PHID
   * `PHID-FILE-bbbb`.
   *
   * @param list<dict>  List of transform specifications, described above.
   * @return this
   */
  public function withTransforms(array $specs) {
    foreach ($specs as $spec) {
      if (!is_array($spec) ||
          empty($spec['originalPHID']) ||
          empty($spec['transform'])) {
        throw new Exception(
          pht(
            "Transform specification must be a dictionary with keys ".
            "'%s' and '%s'!",
            'originalPHID',
            'transform'));
      }
    }

    $this->transforms = $specs;
    return $this;
  }

  public function withLengthBetween($min, $max) {
    $this->minLength = $min;
    $this->maxLength = $max;
    return $this;
  }

  public function withNames(array $names) {
    $this->names = $names;
    return $this;
  }

  public function withIsPartial($partial) {
    $this->isPartial = $partial;
    return $this;
  }

  public function showOnlyExplicitUploads($explicit_uploads) {
    $this->explicitUploads = $explicit_uploads;
    return $this;
  }

  public function newResultObject() {
    return new PhabricatorFile();
  }

  protected function loadPage() {
    $files = $this->loadStandardPage(new PhabricatorFile());

    if (!$files) {
      return $files;
    }

    // We need to load attached objects to perform policy checks for files.
    // First, load the edges.

    $edge_type = PhabricatorFileHasObjectEdgeType::EDGECONST;
    $file_phids = mpull($files, 'getPHID');
    $edges = id(new PhabricatorEdgeQuery())
      ->withSourcePHIDs($file_phids)
      ->withEdgeTypes(array($edge_type))
      ->execute();

    $object_phids = array();
    foreach ($files as $file) {
      $phids = array_keys($edges[$file->getPHID()][$edge_type]);
      $file->attachObjectPHIDs($phids);
      foreach ($phids as $phid) {
        $object_phids[$phid] = true;
      }
    }

    // If this file is a transform of another file, load that file too. If you
    // can see the original file, you can see the thumbnail.

    // TODO: It might be nice to put this directly on PhabricatorFile and remove
    // the PhabricatorTransformedFile table, which would be a little simpler.

    $xforms = id(new PhabricatorTransformedFile())->loadAllWhere(
      'transformedPHID IN (%Ls)',
      $file_phids);
    $xform_phids = mpull($xforms, 'getOriginalPHID', 'getTransformedPHID');
    foreach ($xform_phids as $derived_phid => $original_phid) {
      $object_phids[$original_phid] = true;
    }
<commit_msg>Don't load attached files for profile images<commit_after><?php

final class PhabricatorFileQuery
  extends PhabricatorCursorPagedPolicyAwareQuery {

  private $ids;
  private $phids;
  private $authorPHIDs;
  private $explicitUploads;
  private $transforms;
  private $dateCreatedAfter;
  private $dateCreatedBefore;
  private $contentHashes;
  private $minLength;
  private $maxLength;
  private $names;
  private $isPartial;

  public function withIDs(array $ids) {
    $this->ids = $ids;
    return $this;
  }

  public function withPHIDs(array $phids) {
    $this->phids = $phids;
    return $this;
  }

  public function withAuthorPHIDs(array $phids) {
    $this->authorPHIDs = $phids;
    return $this;
  }

  public function withDateCreatedBefore($date_created_before) {
    $this->dateCreatedBefore = $date_created_before;
    return $this;
  }

  public function withDateCreatedAfter($date_created_after) {
    $this->dateCreatedAfter = $date_created_after;
    return $this;
  }

  public function withContentHashes(array $content_hashes) {
    $this->contentHashes = $content_hashes;
    return $this;
  }

  /**
   * Select files which are transformations of some other file. For example,
   * you can use this query to find previously generated thumbnails of an image
   * file.
   *
   * As a parameter, provide a list of transformation specifications. Each
   * specification is a dictionary with the keys `originalPHID` and `transform`.
   * The `originalPHID` is the PHID of the original file (the file which was
   * transformed) and the `transform` is the name of the transform to query
   * for. If you pass `true` as the `transform`, all transformations of the
   * file will be selected.
   *
   * For example:
   *
   *   array(
   *     array(
   *       'originalPHID' => 'PHID-FILE-aaaa',
   *       'transform'    => 'sepia',
   *     ),
   *     array(
   *       'originalPHID' => 'PHID-FILE-bbbb',
   *       'transform'    => true,
   *     ),
   *   )
   *
   * This selects the `"sepia"` transformation of the file with PHID
   * `PHID-FILE-aaaa` and all transformations of the file with PHID
   * `PHID-FILE-bbbb`.
   *
   * @param list<dict>  List of transform specifications, described above.
   * @return this
   */
  public function withTransforms(array $specs) {
    foreach ($specs as $spec) {
      if (!is_array($spec) ||
          empty($spec['originalPHID']) ||
          empty($spec['transform'])) {
        throw new Exception(
          pht(
            "Transform specification must be a dictionary with keys ".
            "'%s' and '%s'!",
            'originalPHID',
            'transform'));
      }
    }

    $this->transforms = $specs;
    return $this;
  }

  public function withLengthBetween($min, $max) {
    $this->minLength = $min;
    $this->maxLength = $max;
    return $this;
  }

  public function withNames(array $names) {
    $this->names = $names;
    return $this;
  }

  public function withIsPartial($partial) {
    $this->isPartial = $partial;
    return $this;
  }

  public function showOnlyExplicitUploads($explicit_uploads) {
    $this->explicitUploads = $explicit_uploads;
    return $this;
  }

  public function newResultObject() {
    return new PhabricatorFile();
  }

  protected function loadPage() {
    $files = $this->loadStandardPage(new PhabricatorFile());

    if (!$files) {
      return $files;
    }

    // We need to load attached objects to perform policy checks for files.
    // First, load the edges.

    $edge_type = PhabricatorFileHasObjectEdgeType::EDGECONST;
    $file_phids = mpull($files, 'getPHID');
    $edges = id(new PhabricatorEdgeQuery())
      ->withSourcePHIDs($file_phids)
      ->withEdgeTypes(array($edge_type))
      ->execute();

    $object_phids = array();
    foreach ($files as $file) {
      $phids = array_keys($edges[$file->getPHID()][$edge_type]);
      $file->attachObjectPHIDs($phids);

      if ($file->getIsProfileImage()) {
        // If this is a profile image, don't bother loading related files.
        // It will always be visible, and we can get into trouble if we try
        // to load objects and end up stuck in a cycle. See T8478.
        continue;
      }

      foreach ($phids as $phid) {
        $object_phids[$phid] = true;
      }
    }

    // If this file is a transform of another file, load that file too. If you
    // can see the original file, you can see the thumbnail.

    // TODO: It might be nice to put this directly on PhabricatorFile and remove
    // the PhabricatorTransformedFile table, which would be a little simpler.

    $xforms = id(new PhabricatorTransformedFile())->loadAllWhere(
      'transformedPHID IN (%Ls)',
      $file_phids);
    $xform_phids = mpull($xforms, 'getOriginalPHID', 'getTransformedPHID');
    foreach ($xform_phids as $derived_phid => $original_phid) {
      $object_phids[$original_phid] = true;
    }

{'fraction_non_alphanumeric': 0.11422845691382766, 'fraction_numerical': 0.00042189642442780296, 'mean_word_length': 2.9246688741721854, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 54, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6811535', 'n_tokens_mistral': 2989, 'n_tokens_neox': 2930, 'n_words': 832}