@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3/**
4 * @extends PhabricatorCursorPagedPolicyAwareQuery<PhabricatorFlag>
5 */
6final class PhabricatorFlagQuery
7 extends PhabricatorCursorPagedPolicyAwareQuery {
8
9 const GROUP_COLOR = 'color';
10 const GROUP_NONE = 'none';
11
12 private $ids;
13 private $ownerPHIDs;
14 private $types;
15 private $objectPHIDs;
16 private $colors;
17 private $groupBy = self::GROUP_NONE;
18
19 private $needHandles;
20 private $needObjects;
21
22 public function withIDs(array $ids) {
23 $this->ids = $ids;
24 return $this;
25 }
26
27 public function withOwnerPHIDs(array $owner_phids) {
28 $this->ownerPHIDs = $owner_phids;
29 return $this;
30 }
31
32 public function withTypes(array $types) {
33 $this->types = $types;
34 return $this;
35 }
36
37 public function withObjectPHIDs(array $object_phids) {
38 $this->objectPHIDs = $object_phids;
39 return $this;
40 }
41
42 public function withColors(array $colors) {
43 $this->colors = $colors;
44 return $this;
45 }
46
47 /**
48 * NOTE: this is done in PHP and not in MySQL, which means its inappropriate
49 * for large datasets. Pragmatically, this is fine for user flags which are
50 * typically well under 100 flags per user.
51 */
52 public function setGroupBy($group) {
53 $this->groupBy = $group;
54 return $this;
55 }
56
57 public function needHandles($need) {
58 $this->needHandles = $need;
59 return $this;
60 }
61
62 public function needObjects($need) {
63 $this->needObjects = $need;
64 return $this;
65 }
66
67 public static function loadUserFlag(PhabricatorUser $user, $object_phid) {
68 // Specifying the type in the query allows us to use a key.
69 return id(new PhabricatorFlagQuery())
70 ->setViewer($user)
71 ->withOwnerPHIDs(array($user->getPHID()))
72 ->withTypes(array(phid_get_type($object_phid)))
73 ->withObjectPHIDs(array($object_phid))
74 ->executeOne();
75 }
76
77 protected function loadPage() {
78 $table = new PhabricatorFlag();
79 $conn_r = $table->establishConnection('r');
80
81 $data = queryfx_all(
82 $conn_r,
83 'SELECT * FROM %T flag %Q %Q %Q',
84 $table->getTableName(),
85 $this->buildWhereClause($conn_r),
86 $this->buildOrderClause($conn_r),
87 $this->buildLimitClause($conn_r));
88
89 return $table->loadAllFromArray($data);
90 }
91
92 protected function willFilterPage(array $flags) {
93 if ($this->needObjects) {
94 $objects = id(new PhabricatorObjectQuery())
95 ->setViewer($this->getViewer())
96 ->withPHIDs(mpull($flags, 'getObjectPHID'))
97 ->execute();
98 $objects = mpull($objects, null, 'getPHID');
99 foreach ($flags as $key => $flag) {
100 $object = idx($objects, $flag->getObjectPHID());
101 if ($object) {
102 $flags[$key]->attachObject($object);
103 } else {
104 unset($flags[$key]);
105 }
106 }
107 }
108
109 if ($this->needHandles) {
110 $handles = id(new PhabricatorHandleQuery())
111 ->setViewer($this->getViewer())
112 ->withPHIDs(mpull($flags, 'getObjectPHID'))
113 ->execute();
114
115 foreach ($flags as $flag) {
116 $flag->attachHandle($handles[$flag->getObjectPHID()]);
117 }
118 }
119
120 switch ($this->groupBy) {
121 case self::GROUP_COLOR:
122 $flags = msort($flags, 'getColor');
123 break;
124 case self::GROUP_NONE:
125 break;
126 default:
127 throw new Exception(
128 pht('Unknown groupBy parameter: %s', $this->groupBy));
129 }
130
131 return $flags;
132 }
133
134 protected function buildWhereClause(AphrontDatabaseConnection $conn) {
135 $where = array();
136
137 if ($this->ids !== null) {
138 $where[] = qsprintf(
139 $conn,
140 'flag.id IN (%Ld)',
141 $this->ids);
142 }
143
144 if ($this->ownerPHIDs) {
145 $where[] = qsprintf(
146 $conn,
147 'flag.ownerPHID IN (%Ls)',
148 $this->ownerPHIDs);
149 }
150
151 if ($this->types) {
152 $where[] = qsprintf(
153 $conn,
154 'flag.type IN (%Ls)',
155 $this->types);
156 }
157
158 if ($this->objectPHIDs) {
159 $where[] = qsprintf(
160 $conn,
161 'flag.objectPHID IN (%Ls)',
162 $this->objectPHIDs);
163 }
164
165 if ($this->colors) {
166 $where[] = qsprintf(
167 $conn,
168 'flag.color IN (%Ld)',
169 $this->colors);
170 }
171
172 $where[] = $this->buildPagingClause($conn);
173
174 return $this->formatWhereClause($conn, $where);
175 }
176
177 public function getQueryApplicationClass() {
178 return PhabricatorFlagsApplication::class;
179 }
180
181}