mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-22 13:30:55 +01:00
Index "owner" relationship in search correctly for Revisions
Summary: The owners of a revision are only really the reviewers when the revision is in NEEDS_REVIEW. Also build a raw indexed document viewer so you can look at the index of a document from the web interface. Finally, reindex revisions when comments are added, not just when the revision itself is edited. Test Plan: Toggled abandon/reclaim on a revision and verified the relationships indexed properly. Reviewed By: jungejason Reviewers: aran, jungejason, tuomaspelkonen CC: aran, epriestley, jungejason Differential Revision: 470
This commit is contained in:
parent
12772ec35f
commit
3ec76f5f4a
10 changed files with 250 additions and 3 deletions
|
@ -481,6 +481,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/relationship',
|
'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/relationship',
|
||||||
'PhabricatorSearchExecutor' => 'applications/search/execute/base',
|
'PhabricatorSearchExecutor' => 'applications/search/execute/base',
|
||||||
'PhabricatorSearchField' => 'applications/search/constants/field',
|
'PhabricatorSearchField' => 'applications/search/constants/field',
|
||||||
|
'PhabricatorSearchIndexController' => 'applications/search/controller/index',
|
||||||
'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/maniphest',
|
'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/maniphest',
|
||||||
'PhabricatorSearchMySQLExecutor' => 'applications/search/execute/mysql',
|
'PhabricatorSearchMySQLExecutor' => 'applications/search/execute/mysql',
|
||||||
'PhabricatorSearchQuery' => 'applications/search/storage/query',
|
'PhabricatorSearchQuery' => 'applications/search/storage/query',
|
||||||
|
@ -935,6 +936,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSearchDocument' => 'PhabricatorSearchDAO',
|
'PhabricatorSearchDocument' => 'PhabricatorSearchDAO',
|
||||||
'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO',
|
'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO',
|
||||||
'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO',
|
'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO',
|
||||||
|
'PhabricatorSearchIndexController' => 'PhabricatorSearchBaseController',
|
||||||
'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
|
'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
|
||||||
'PhabricatorSearchMySQLExecutor' => 'PhabricatorSearchExecutor',
|
'PhabricatorSearchMySQLExecutor' => 'PhabricatorSearchExecutor',
|
||||||
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
|
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
|
||||||
|
|
|
@ -192,6 +192,7 @@ class AphrontDefaultApplicationConfiguration
|
||||||
=> 'PhabricatorSearchAttachController',
|
=> 'PhabricatorSearchAttachController',
|
||||||
'select/(?P<type>\w+)/$'
|
'select/(?P<type>\w+)/$'
|
||||||
=> 'PhabricatorSearchSelectController',
|
=> 'PhabricatorSearchSelectController',
|
||||||
|
'index/(?P<phid>[^/]+)/$' => 'PhabricatorSearchIndexController',
|
||||||
),
|
),
|
||||||
|
|
||||||
'/project/' => array(
|
'/project/' => array(
|
||||||
|
|
|
@ -332,6 +332,9 @@ class DifferentialCommentEditor {
|
||||||
id(new PhabricatorTimelineEvent('difx', $event_data))
|
id(new PhabricatorTimelineEvent('difx', $event_data))
|
||||||
->recordEvent();
|
->recordEvent();
|
||||||
|
|
||||||
|
// TODO: Move to a daemon?
|
||||||
|
PhabricatorSearchDifferentialIndexer::indexRevision($revision);
|
||||||
|
|
||||||
return $comment;
|
return $comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ phutil_require_module('phabricator', 'applications/differential/storage/comment'
|
||||||
phutil_require_module('phabricator', 'applications/differential/storage/inlinecomment');
|
phutil_require_module('phabricator', 'applications/differential/storage/inlinecomment');
|
||||||
phutil_require_module('phabricator', 'applications/herald/storage/transcript/base');
|
phutil_require_module('phabricator', 'applications/herald/storage/transcript/base');
|
||||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
|
phutil_require_module('phabricator', 'applications/search/index/indexer/differential');
|
||||||
phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/event');
|
phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/event');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'aphront/response/webpage');
|
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||||
phutil_require_module('phabricator', 'applications/base/controller/base');
|
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'infrastructure/env');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PhabricatorSearchIndexController extends PhabricatorSearchBaseController {
|
||||||
|
|
||||||
|
private $phid;
|
||||||
|
|
||||||
|
public function shouldRequireAdmin() {
|
||||||
|
// This basically shows you all the text of any object in the system, so
|
||||||
|
// make it admin-only.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->phid = $data['phid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
|
||||||
|
$executor = new PhabricatorSearchMySQLExecutor();
|
||||||
|
$document = $executor->reconstructDocument($this->phid);
|
||||||
|
if (!$document) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$panels = array();
|
||||||
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel->setHeader('Abstract Document Index');
|
||||||
|
|
||||||
|
$props = array(
|
||||||
|
'PHID' => phutil_escape_html($document->getPHID()),
|
||||||
|
'Title' => phutil_escape_html($document->getDocumentTitle()),
|
||||||
|
'Type' => phutil_escape_html($document->getDocumentType()),
|
||||||
|
);
|
||||||
|
$rows = array();
|
||||||
|
foreach ($props as $name => $value) {
|
||||||
|
$rows[] = array($name, $value);
|
||||||
|
}
|
||||||
|
$table = new AphrontTableView($rows);
|
||||||
|
$table->setColumnClasses(
|
||||||
|
array(
|
||||||
|
'header',
|
||||||
|
'',
|
||||||
|
));
|
||||||
|
$panel->appendChild($table);
|
||||||
|
$panels[] = $panel;
|
||||||
|
|
||||||
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel->setHeader('Document Fields');
|
||||||
|
|
||||||
|
$fields = $document->getFieldData();
|
||||||
|
$rows = array();
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
list($name, $corpus, $aux_phid) = $field;
|
||||||
|
$rows[] = array(
|
||||||
|
phutil_escape_html($name),
|
||||||
|
phutil_escape_html(nonempty($aux_phid, null)),
|
||||||
|
str_replace("\n", '<br />', phutil_escape_html($corpus)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = new AphrontTableView($rows);
|
||||||
|
$table->setHeaders(
|
||||||
|
array(
|
||||||
|
'Field',
|
||||||
|
'Aux PHID',
|
||||||
|
'Corpus',
|
||||||
|
));
|
||||||
|
$table->setColumnClasses(
|
||||||
|
array(
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'wide',
|
||||||
|
));
|
||||||
|
$panel->appendChild($table);
|
||||||
|
$panels[] = $panel;
|
||||||
|
|
||||||
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel->setHeader('Document Relationships');
|
||||||
|
|
||||||
|
$relationships = $document->getRelationshipData();
|
||||||
|
|
||||||
|
$phids = ipull($relationships, 1);
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||||
|
|
||||||
|
$rows = array();
|
||||||
|
foreach ($relationships as $relationship) {
|
||||||
|
list($type, $phid, $rtype, $time) = $relationship;
|
||||||
|
$rows[] = array(
|
||||||
|
phutil_escape_html($type),
|
||||||
|
phutil_escape_html($phid),
|
||||||
|
phutil_escape_html($rtype),
|
||||||
|
$handles[$phid]->renderLink(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$table = new AphrontTableView($rows);
|
||||||
|
$table->setHeaders(
|
||||||
|
array(
|
||||||
|
'Relationship',
|
||||||
|
'Related PHID',
|
||||||
|
'Related Type',
|
||||||
|
'Related Handle',
|
||||||
|
));
|
||||||
|
$table->setColumnClasses(
|
||||||
|
array(
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
'wide',
|
||||||
|
));
|
||||||
|
$panel->appendChild($table);
|
||||||
|
$panels[] = $panel;
|
||||||
|
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
$panels,
|
||||||
|
array(
|
||||||
|
'title' => 'Raw Index',
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
src/applications/search/controller/index/__init__.php
Normal file
20
src/applications/search/controller/index/__init__.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
|
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||||
|
phutil_require_module('phabricator', 'applications/search/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/search/execute/mysql');
|
||||||
|
phutil_require_module('phabricator', 'view/control/table');
|
||||||
|
phutil_require_module('phabricator', 'view/layout/panel');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'markup');
|
||||||
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('PhabricatorSearchIndexController.php');
|
|
@ -18,6 +18,73 @@
|
||||||
|
|
||||||
class PhabricatorSearchMySQLExecutor extends PhabricatorSearchExecutor {
|
class PhabricatorSearchMySQLExecutor extends PhabricatorSearchExecutor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuild the PhabricatorSearchAbstractDocument that was used to index
|
||||||
|
* an object out of the index itself. This is primarily useful for debugging,
|
||||||
|
* as it allows you to inspect the search index representation of a
|
||||||
|
* document.
|
||||||
|
*
|
||||||
|
* @param phid PHID of a document which exists in the search index.
|
||||||
|
* @return null|PhabricatorSearchAbstractDocument Abstract document object
|
||||||
|
* which corresponds to the original abstract document used to
|
||||||
|
* build the document index.
|
||||||
|
*/
|
||||||
|
public function reconstructDocument($phid) {
|
||||||
|
$dao_doc = new PhabricatorSearchDocument();
|
||||||
|
$dao_field = new PhabricatorSearchDocumentField();
|
||||||
|
$dao_relationship = new PhabricatorSearchDocumentRelationship();
|
||||||
|
|
||||||
|
$t_doc = $dao_doc->getTableName();
|
||||||
|
$t_field = $dao_field->getTableName();
|
||||||
|
$t_relationship = $dao_relationship->getTableName();
|
||||||
|
|
||||||
|
$doc = queryfx_one(
|
||||||
|
$dao_doc->establishConnection('r'),
|
||||||
|
'SELECT * FROM %T WHERE phid = %s',
|
||||||
|
$t_doc,
|
||||||
|
$phid);
|
||||||
|
|
||||||
|
if (!$doc) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = queryfx_all(
|
||||||
|
$dao_field->establishConnection('r'),
|
||||||
|
'SELECT * FROM %T WHERE phid = %s',
|
||||||
|
$t_field,
|
||||||
|
$phid);
|
||||||
|
|
||||||
|
$relationships = queryfx_all(
|
||||||
|
$dao_relationship->establishConnection('r'),
|
||||||
|
'SELECT * FROM %T WHERE phid = %s',
|
||||||
|
$t_relationship,
|
||||||
|
$phid);
|
||||||
|
|
||||||
|
$adoc = id(new PhabricatorSearchAbstractDocument())
|
||||||
|
->setPHID($phid)
|
||||||
|
->setDocumentType($doc['documentType'])
|
||||||
|
->setDocumentTitle($doc['documentTitle'])
|
||||||
|
->setDocumentCreated($doc['documentCreated'])
|
||||||
|
->setDocumentModified($doc['documentModified']);
|
||||||
|
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
$adoc->addField(
|
||||||
|
$field['field'],
|
||||||
|
$field['corpus'],
|
||||||
|
$field['auxPHID']);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($relationships as $relationship) {
|
||||||
|
$adoc->addRelationship(
|
||||||
|
$relationship['relation'],
|
||||||
|
$relationship['relatedPHID'],
|
||||||
|
$relationship['relatedType'],
|
||||||
|
$relationship['relatedTime']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $adoc;
|
||||||
|
}
|
||||||
|
|
||||||
public function executeSearch(PhabricatorSearchQuery $query) {
|
public function executeSearch(PhabricatorSearchQuery $query) {
|
||||||
|
|
||||||
$where = array();
|
$where = array();
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'applications/search/constants/relationship');
|
phutil_require_module('phabricator', 'applications/search/constants/relationship');
|
||||||
phutil_require_module('phabricator', 'applications/search/execute/base');
|
phutil_require_module('phabricator', 'applications/search/execute/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/search/index/abstractdocument');
|
||||||
phutil_require_module('phabricator', 'applications/search/storage/document/document');
|
phutil_require_module('phabricator', 'applications/search/storage/document/document');
|
||||||
phutil_require_module('phabricator', 'applications/search/storage/document/field');
|
phutil_require_module('phabricator', 'applications/search/storage/document/field');
|
||||||
phutil_require_module('phabricator', 'applications/search/storage/document/relationship');
|
phutil_require_module('phabricator', 'applications/search/storage/document/relationship');
|
||||||
|
|
|
@ -77,12 +77,22 @@ class PhabricatorSearchDifferentialIndexer
|
||||||
|
|
||||||
$rev->loadRelationships();
|
$rev->loadRelationships();
|
||||||
|
|
||||||
foreach ($rev->getReviewers() as $phid) {
|
// If a revision needs review, the owners are the reviewers. Otherwise, the
|
||||||
|
// owner is the author (e.g., accepted, rejected, committed).
|
||||||
|
if ($rev->getStatus() == DifferentialRevisionStatus::NEEDS_REVIEW) {
|
||||||
|
foreach ($rev->getReviewers() as $phid) {
|
||||||
|
$doc->addRelationship(
|
||||||
|
PhabricatorSearchRelationship::RELATIONSHIP_OWNER,
|
||||||
|
$phid,
|
||||||
|
PhabricatorPHIDConstants::PHID_TYPE_USER,
|
||||||
|
$rev->getDateModified()); // Bogus timestamp.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
$doc->addRelationship(
|
$doc->addRelationship(
|
||||||
PhabricatorSearchRelationship::RELATIONSHIP_OWNER,
|
PhabricatorSearchRelationship::RELATIONSHIP_OWNER,
|
||||||
$phid,
|
$rev->getAuthorPHID(),
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_USER,
|
PhabricatorPHIDConstants::PHID_TYPE_USER,
|
||||||
$rev->getDateModified()); // Bogus timestamp.
|
$rev->getDateCreated());
|
||||||
}
|
}
|
||||||
|
|
||||||
$ccphids = $rev->getCCPHIDs();
|
$ccphids = $rev->getCCPHIDs();
|
||||||
|
|
Loading…
Reference in a new issue