Correct Aphlict websocket URI construction after PHP8 compatibility changes
[phabricator.git] / src / applications / search / index / PhabricatorIndexEngine.php
blob2517bf994fe0465bb8714ec4e2804adf5c7188fb
1 <?php
3 final class PhabricatorIndexEngine extends Phobject {
5 private $object;
6 private $extensions;
7 private $versions;
8 private $parameters;
10 public function setParameters(array $parameters) {
11 $this->parameters = $parameters;
12 return $this;
15 public function getParameters() {
16 return $this->parameters;
19 public function setObject($object) {
20 $this->object = $object;
21 return $this;
24 public function getObject() {
25 return $this->object;
28 public function shouldIndexObject() {
29 $extensions = $this->newExtensions();
31 $parameters = $this->getParameters();
32 foreach ($extensions as $extension) {
33 $extension->setParameters($parameters);
36 $object = $this->getObject();
37 $versions = array();
38 foreach ($extensions as $key => $extension) {
39 $version = $extension->getIndexVersion($object);
40 if ($version !== null) {
41 $versions[$key] = (string)$version;
45 if (idx($parameters, 'force')) {
46 $current_versions = array();
47 } else {
48 $keys = array_keys($versions);
49 $current_versions = $this->loadIndexVersions($keys);
52 foreach ($versions as $key => $version) {
53 $current_version = idx($current_versions, $key);
55 if ($current_version === null) {
56 continue;
59 // If nothing has changed since we built the current index, we do not
60 // need to rebuild the index.
61 if ($current_version === $version) {
62 unset($extensions[$key]);
66 $this->extensions = $extensions;
67 $this->versions = $versions;
69 // We should index the object only if there is any work to be done.
70 return (bool)$this->extensions;
73 public function indexObject() {
74 $extensions = $this->extensions;
75 $object = $this->getObject();
77 foreach ($extensions as $key => $extension) {
78 $extension->indexObject($this, $object);
81 $this->saveIndexVersions($this->versions);
83 return $this;
86 private function newExtensions() {
87 $object = $this->getObject();
89 $extensions = PhabricatorIndexEngineExtension::getAllExtensions();
90 foreach ($extensions as $key => $extension) {
91 if (!$extension->shouldIndexObject($object)) {
92 unset($extensions[$key]);
96 return $extensions;
99 private function loadIndexVersions(array $extension_keys) {
100 if (!$extension_keys) {
101 return array();
104 $object = $this->getObject();
105 $object_phid = $object->getPHID();
107 $table = new PhabricatorSearchIndexVersion();
108 $conn_r = $table->establishConnection('w');
110 $rows = queryfx_all(
111 $conn_r,
112 'SELECT version, extensionKey
113 FROM %R
114 WHERE objectPHID = %s AND extensionKey IN (%Ls)',
115 $table,
116 $object_phid,
117 $extension_keys);
119 return ipull($rows, 'version', 'extensionKey');
122 private function saveIndexVersions(array $versions) {
123 if (!$versions) {
124 return;
127 $object = $this->getObject();
128 $object_phid = $object->getPHID();
130 $table = new PhabricatorSearchIndexVersion();
131 $conn_w = $table->establishConnection('w');
133 $now = PhabricatorTime::getNow();
135 // See T13587. For now, this is just a marker to make it easy to reindex
136 // documents if some version of the indexing code is later discovered to
137 // be questionable.
138 $index_version = '2021-02-16-A';
140 $sql = array();
141 foreach ($versions as $key => $version) {
142 $sql[] = qsprintf(
143 $conn_w,
144 '(%s, %s, %s, %s, %d)',
145 $object_phid,
146 $key,
147 $version,
148 $index_version,
149 $now);
152 queryfx(
153 $conn_w,
154 'INSERT INTO %R (objectPHID, extensionKey, version,
155 indexVersion, indexEpoch)
156 VALUES %LQ
157 ON DUPLICATE KEY UPDATE
158 version = VALUES(version),
159 indexVersion = VALUES(indexVersion),
160 indexEpoch = VALUES(indexEpoch)',
161 $table,
162 $sql);