2013-07-26 01:59:25 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @group pholio
|
|
|
|
*/
|
|
|
|
final class PholioImageQuery
|
|
|
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
|
|
|
|
|
|
|
private $ids;
|
|
|
|
private $phids;
|
|
|
|
private $mockIDs;
|
|
|
|
private $obsolete;
|
|
|
|
|
|
|
|
private $needInlineComments;
|
|
|
|
private $mockCache = array();
|
|
|
|
|
|
|
|
public function withIDs(array $ids) {
|
|
|
|
$this->ids = $ids;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function withPHIDs(array $phids) {
|
|
|
|
$this->phids = $phids;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function withMockIDs(array $mock_ids) {
|
|
|
|
$this->mockIDs = $mock_ids;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function withObsolete($obsolete) {
|
|
|
|
$this->obsolete = $obsolete;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function needInlineComments($need_inline_comments) {
|
|
|
|
$this->needInlineComments = $need_inline_comments;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setMockCache($mock_cache) {
|
|
|
|
$this->mockCache = $mock_cache;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
public function getMockCache() {
|
|
|
|
return $this->mockCache;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function loadPage() {
|
|
|
|
$table = new PholioImage();
|
|
|
|
$conn_r = $table->establishConnection('r');
|
|
|
|
|
|
|
|
$data = queryfx_all(
|
|
|
|
$conn_r,
|
|
|
|
'SELECT * FROM %T %Q %Q %Q',
|
|
|
|
$table->getTableName(),
|
|
|
|
$this->buildWhereClause($conn_r),
|
|
|
|
$this->buildOrderClause($conn_r),
|
|
|
|
$this->buildLimitClause($conn_r));
|
|
|
|
|
|
|
|
$images = $table->loadAllFromArray($data);
|
|
|
|
|
|
|
|
return $images;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
|
|
|
|
$where = array();
|
|
|
|
|
|
|
|
$where[] = $this->buildPagingClause($conn_r);
|
|
|
|
|
|
|
|
if ($this->ids) {
|
|
|
|
$where[] = qsprintf(
|
|
|
|
$conn_r,
|
|
|
|
'id IN (%Ld)',
|
|
|
|
$this->ids);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->phids) {
|
|
|
|
$where[] = qsprintf(
|
|
|
|
$conn_r,
|
|
|
|
'phid IN (%Ls)',
|
|
|
|
$this->phids);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->mockIDs) {
|
|
|
|
$where[] = qsprintf(
|
|
|
|
$conn_r,
|
|
|
|
'mockID IN (%Ld)',
|
|
|
|
$this->mockIDs);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->obsolete !== null) {
|
|
|
|
$where[] = qsprintf(
|
|
|
|
$conn_r,
|
|
|
|
'isObsolete = %d',
|
|
|
|
$this->obsolete);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->formatWhereClause($where);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function willFilterPage(array $images) {
|
|
|
|
assert_instances_of($images, 'PholioImage');
|
|
|
|
|
Fix some file policy issues and add a "Query Workspace"
Summary:
Ref T603. Several issues here:
1. Currently, `FileQuery` does not actually respect object attachment edges when doing policy checks. Everything else works fine, but this was missing an `array_keys()`.
2. Once that's fixed, we hit a bunch of recursion issues. For example, when loading a User we load the profile picture, and then that loads the User, and that loads the profile picture, etc.
3. Introduce a "Query Workspace", which holds objects we know we've loaded and know we can see but haven't finished filtering and/or attaching data to. This allows subqueries to look up objects instead of querying for them.
- We can probably generalize this a bit to make a few other queries more efficient. Pholio currently has a similar (but less general) "mock cache". However, it's keyed by ID instead of PHID so it's not easy to reuse this right now.
This is a bit complex for the problem being solved, but I think it's the cleanest approach and I believe the primitive will be useful in the future.
Test Plan: Looked at pastes, macros, mocks and projects as a logged-in and logged-out user.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T603
Differential Revision: https://secure.phabricator.com/D7309
2013-10-14 23:36:06 +02:00
|
|
|
if ($this->getMockCache()) {
|
|
|
|
$mocks = $this->getMockCache();
|
|
|
|
} else {
|
|
|
|
$mock_ids = mpull($images, 'getMockID');
|
|
|
|
// DO NOT set needImages to true; recursion results!
|
|
|
|
$mocks = id(new PholioMockQuery())
|
|
|
|
->setViewer($this->getViewer())
|
|
|
|
->withIDs($mock_ids)
|
|
|
|
->execute();
|
|
|
|
$mocks = mpull($mocks, null, 'getID');
|
|
|
|
}
|
|
|
|
foreach ($images as $index => $image) {
|
|
|
|
$mock = idx($mocks, $image->getMockID());
|
|
|
|
if ($mock) {
|
|
|
|
$image->attachMock($mock);
|
|
|
|
} else {
|
|
|
|
// mock is missing or we can't see it
|
|
|
|
unset($images[$index]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $images;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function didFilterPage(array $images) {
|
|
|
|
assert_instances_of($images, 'PholioImage');
|
|
|
|
|
2013-07-26 01:59:25 +02:00
|
|
|
$file_phids = mpull($images, 'getFilePHID');
|
2013-09-30 18:38:13 +02:00
|
|
|
|
|
|
|
$all_files = id(new PhabricatorFileQuery())
|
Fix some file policy issues and add a "Query Workspace"
Summary:
Ref T603. Several issues here:
1. Currently, `FileQuery` does not actually respect object attachment edges when doing policy checks. Everything else works fine, but this was missing an `array_keys()`.
2. Once that's fixed, we hit a bunch of recursion issues. For example, when loading a User we load the profile picture, and then that loads the User, and that loads the profile picture, etc.
3. Introduce a "Query Workspace", which holds objects we know we've loaded and know we can see but haven't finished filtering and/or attaching data to. This allows subqueries to look up objects instead of querying for them.
- We can probably generalize this a bit to make a few other queries more efficient. Pholio currently has a similar (but less general) "mock cache". However, it's keyed by ID instead of PHID so it's not easy to reuse this right now.
This is a bit complex for the problem being solved, but I think it's the cleanest approach and I believe the primitive will be useful in the future.
Test Plan: Looked at pastes, macros, mocks and projects as a logged-in and logged-out user.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T603
Differential Revision: https://secure.phabricator.com/D7309
2013-10-14 23:36:06 +02:00
|
|
|
->setParentQuery($this)
|
2013-09-30 18:38:13 +02:00
|
|
|
->setViewer($this->getViewer())
|
|
|
|
->withPHIDs($file_phids)
|
|
|
|
->execute();
|
|
|
|
$all_files = mpull($all_files, null, 'getPHID');
|
2013-07-26 01:59:25 +02:00
|
|
|
|
|
|
|
if ($this->needInlineComments) {
|
|
|
|
$all_inline_comments = id(new PholioTransactionComment())
|
|
|
|
->loadAllWhere('imageid IN (%Ld)',
|
|
|
|
mpull($images, 'getID'));
|
|
|
|
$all_inline_comments = mgroup($all_inline_comments, 'getImageID');
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($images as $image) {
|
|
|
|
$file = idx($all_files, $image->getFilePHID());
|
|
|
|
if (!$file) {
|
|
|
|
$file = PhabricatorFile::loadBuiltin($this->getViewer(), 'missing.png');
|
|
|
|
}
|
|
|
|
$image->attachFile($file);
|
|
|
|
if ($this->needInlineComments) {
|
|
|
|
$inlines = idx($all_inline_comments, $image->getID(), array());
|
|
|
|
$image->attachInlineComments($inlines);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $images;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|