@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
3final class PhortuneProductQuery
4 extends PhabricatorCursorPagedPolicyAwareQuery {
5
6 private $ids;
7 private $phids;
8 private $refMap;
9
10 public function withIDs(array $ids) {
11 $this->ids = $ids;
12 return $this;
13 }
14
15 public function withPHIDs(array $phids) {
16 $this->phids = $phids;
17 return $this;
18 }
19
20 public function withClassAndRef($class, $ref) {
21 $this->refMap = array($class => array($ref));
22 return $this;
23 }
24
25 protected function loadPage() {
26 $table = new PhortuneProduct();
27 $conn = $table->establishConnection('r');
28
29 $rows = queryfx_all(
30 $conn,
31 'SELECT * FROM %T %Q %Q %Q',
32 $table->getTableName(),
33 $this->buildWhereClause($conn),
34 $this->buildOrderClause($conn),
35 $this->buildLimitClause($conn));
36
37 $page = $table->loadAllFromArray($rows);
38
39 // NOTE: We're loading product implementations here, but also creating any
40 // products which do not yet exist.
41
42 $class_map = mgroup($page, 'getProductClass');
43 if ($this->refMap) {
44 $class_map += array_fill_keys(array_keys($this->refMap), array());
45 }
46
47 foreach ($class_map as $class => $products) {
48 $refs = mpull($products, null, 'getProductRef');
49 if (isset($this->refMap[$class])) {
50 $refs += array_fill_keys($this->refMap[$class], null);
51 }
52
53 $implementations = newv($class, array())->loadImplementationsForRefs(
54 $this->getViewer(),
55 array_keys($refs));
56 $implementations = mpull($implementations, null, 'getRef');
57
58 foreach ($implementations as $ref => $implementation) {
59 $product = idx($refs, $ref);
60 if ($product === null) {
61 // If this product does not exist yet, create it and add it to the
62 // result page.
63 $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
64 $product = PhortuneProduct::initializeNewProduct()
65 ->setProductClass($class)
66 ->setProductRef($ref)
67 ->save();
68 unset($unguarded);
69
70 $page[] = $product;
71 }
72
73 $product->attachImplementation($implementation);
74 }
75 }
76
77 return $page;
78 }
79
80 protected function buildWhereClause(AphrontDatabaseConnection $conn) {
81 $where = array();
82
83 if ($this->ids !== null) {
84 $where[] = qsprintf(
85 $conn,
86 'id IN (%Ld)',
87 $this->ids);
88 }
89
90 if ($this->phids !== null) {
91 $where[] = qsprintf(
92 $conn,
93 'phid IN (%Ls)',
94 $this->phids);
95 }
96
97 if ($this->refMap !== null) {
98 $sql = array();
99 foreach ($this->refMap as $class => $refs) {
100 foreach ($refs as $ref) {
101 $sql[] = qsprintf(
102 $conn,
103 '(productClassKey = %s AND productRefKey = %s)',
104 PhabricatorHash::digestForIndex($class),
105 PhabricatorHash::digestForIndex($ref));
106 }
107 }
108 $where[] = qsprintf($conn, '%LO', $sql);
109 }
110
111 $where[] = $this->buildPagingClause($conn);
112
113 return $this->formatWhereClause($conn, $where);
114 }
115
116 public function getQueryApplicationClass() {
117 return PhabricatorPhortuneApplication::class;
118 }
119
120}