1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-19 16:58:48 +02:00

Rought cut of search.

Summary: Botched this pretty badly in git so we'll see how much I broke. :/

Test Plan:

Reviewers:

CC:
This commit is contained in:
epriestley 2011-02-14 15:34:20 -08:00
parent fcc467fe5e
commit 147d2e2e3d
43 changed files with 1183 additions and 30 deletions

31
scripts/__init_env__.php Normal file
View file

@ -0,0 +1,31 @@
<?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.
*/
require_once dirname(dirname(__FILE__)).'/conf/__init_conf__.php';
$env = getenv('PHABRICATOR_ENV');
if (!$env) {
echo "Define PHABRICATOR_ENV before running this script.\n";
exit(1);
}
$conf = phabricator_read_config_file($env);
$conf['phabricator.env'] = $env;
phutil_require_module('phabricator', 'infrastructure/env');
PhabricatorEnv::setEnvConfig($conf);

View file

@ -30,5 +30,3 @@ if (!ini_get('date.timezone')) {
}
phutil_load_library(dirname(__FILE__).'/../src/');
require_once dirname(dirname(__FILE__)).'/conf/__init_conf__.php';

View file

@ -19,18 +19,8 @@
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
require_once $root.'/scripts/__init_env__.php';
$env = getenv('PHABRICATOR_ENV');
if (!$env) {
echo "Define PHABRICATOR_ENV before running scripts.\n";
exit(1);
}
$conf = phabricator_read_config_file($env);
$conf['phabricator.env'] = $env;
phutil_require_module('phabricator', 'infrastructure/env');
PhabricatorEnv::setEnvConfig($conf);
phutil_require_module('phutil', 'symbols');
PhutilSymbolLoader::loadClass('PhabricatorMetaMTADaemon');

View file

@ -0,0 +1,53 @@
#!/usr/bin/env php
<?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.
*/
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
require_once $root.'/scripts/__init_env__.php';
// TODO: Get rid of this script eventually, once this stuff is better-formalized
// in Timeline consumers.
phutil_require_module('phutil', 'symbols');
PhutilSymbolLoader::loadClass('DifferentialRevision');
PhutilSymbolLoader::loadClass('PhabricatorSearchDifferentialIndexer');
PhutilSymbolLoader::loadClass('ManiphestTask');
PhutilSymbolLoader::loadClass('PhabricatorSearchManiphestIndexer');
echo "Loading revisions...\n";
$revs = id(new DifferentialRevision())->loadAll();
$count = count($revs);
echo "Reindexing {$count} revisions";
foreach ($revs as $rev) {
PhabricatorSearchDifferentialIndexer::indexRevision($rev);
echo '.';
}
echo "\n";
echo "Loading tasks...\n";
$tasks = id(new ManiphestTask())->loadAll();
$count = count($tasks);
echo "Reindexing {$count} tasks";
foreach ($tasks as $task) {
PhabricatorSearchManiphestIndexer::indexTask($task);
echo '.';
}
echo "\n";
echo "Done.\n";

View file

@ -230,6 +230,21 @@ phutil_register_library_map(array(
'PhabricatorRepositoryGitHubNotification' => 'applications/repository/storage/githubnotification',
'PhabricatorRepositoryGitHubPostReceiveController' => 'applications/repository/controller/github-post-receive',
'PhabricatorRepositoryListController' => 'applications/repository/controller/list',
'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument',
'PhabricatorSearchBaseController' => 'applications/search/controller/base',
'PhabricatorSearchController' => 'applications/search/controller/search',
'PhabricatorSearchDAO' => 'applications/search/storage/base',
'PhabricatorSearchDifferentialIndexer' => 'applications/search/index/indexer/differential',
'PhabricatorSearchDocument' => 'applications/search/storage/document/document',
'PhabricatorSearchDocumentField' => 'applications/search/storage/document/field',
'PhabricatorSearchDocumentIndexer' => 'applications/search/index/indexer/base',
'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/relationship',
'PhabricatorSearchExecutor' => 'applications/search/execute/base',
'PhabricatorSearchField' => 'applications/search/constants/field',
'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/maniphest',
'PhabricatorSearchMySQLExecutor' => 'applications/search/execute/mysql',
'PhabricatorSearchQuery' => 'applications/search/storage/query',
'PhabricatorSearchRelationship' => 'applications/search/constants/relationship',
'PhabricatorStandardPageView' => 'view/page/standard',
'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/common',
'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base',
@ -251,6 +266,7 @@ phutil_register_library_map(array(
'phabricator_format_relative_time' => 'view/utils',
'phabricator_format_timestamp' => 'view/utils',
'phabricator_format_units_generic' => 'view/utils',
'phabricator_render_form' => 'infrastructure/javelin/markup',
'qsprintf' => 'storage/qsprintf',
'queryfx' => 'storage/queryfx',
'queryfx_all' => 'storage/queryfx',
@ -437,6 +453,16 @@ phutil_register_library_map(array(
'PhabricatorRepositoryGitHubNotification' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryGitHubPostReceiveController' => 'PhabricatorRepositoryController',
'PhabricatorRepositoryListController' => 'PhabricatorController',
'PhabricatorSearchBaseController' => 'PhabricatorController',
'PhabricatorSearchController' => 'PhabricatorSearchBaseController',
'PhabricatorSearchDAO' => 'PhabricatorLiskDAO',
'PhabricatorSearchDifferentialIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchDocument' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO',
'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO',
'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
'PhabricatorSearchMySQLExecutor' => 'PhabricatorSearchExecutor',
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
'PhabricatorStandardPageView' => 'AphrontPageView',
'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController',
'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController',

View file

@ -155,6 +155,11 @@ class AphrontDefaultApplicationConfiguration
'edit/(?P<id>\d+)/$' => 'PhabricatorRepositoryEditController',
'delete/(?P<id>\d+)/$' => 'PhabricatorRepositoryDeleteController',
),
'/search/' => array(
'$' => 'PhabricatorSearchController',
'(?P<id>\d+)/$' => 'PhabricatorSearchController',
),
);
}

View file

@ -415,6 +415,8 @@ class DifferentialRevisionEditor {
'actor' => $this->getActorPHID(),
);
// TODO: When timelines get implemented, move indexing to them.
PhabricatorSearchDifferentialIndexer::indexRevision($revision);
// TODO
// id(new ToolsTimelineEvent('difx', fb_json_encode($event)))->record();

View file

@ -12,6 +12,7 @@ phutil_require_module('phabricator', 'applications/differential/mail/newdiff');
phutil_require_module('phabricator', 'applications/differential/storage/comment');
phutil_require_module('phabricator', 'applications/differential/storage/revision');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'applications/search/index/indexer/differential');
phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'storage/queryfx');

View file

@ -99,6 +99,9 @@ class ManiphestTransactionEditor {
$email_cc,
$task->getCCPHIDs());
// TODO: Do this offline via timeline
PhabricatorSearchManiphestIndexer::indexTask($task);
$this->sendEmail($task, $transactions, $email_to, $email_cc);
}

View file

@ -11,6 +11,7 @@ phutil_require_module('phabricator', 'applications/maniphest/constants/transacti
phutil_require_module('phabricator', 'applications/maniphest/view/transactiondetail');
phutil_require_module('phabricator', 'applications/metamta/storage/mail');
phutil_require_module('phabricator', 'applications/phid/handle/data');
phutil_require_module('phabricator', 'applications/search/index/indexer/maniphest');
phutil_require_module('phabricator', 'infrastructure/env');
phutil_require_module('phutil', 'utils');

View file

@ -96,6 +96,52 @@ class PhabricatorObjectHandleData {
$handles[$phid] = $handle;
}
break;
case 'DREV':
$class = 'DifferentialRevision';
PhutilSymbolLoader::loadClass($class);
$object = newv($class, array());
$revs = $object->loadAllWhere('phid in (%Ls)', $phids);
$revs = mpull($revs, null, 'getPHID');
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
if (empty($revs[$phid])) {
$handle->setType(self::TYPE_UNKNOWN);
$handle->setName('Unknown Revision');
} else {
$rev = $revs[$phid];
$handle->setType($type);
$handle->setName($rev->getTitle());
$handle->setURI('/D'.$rev->getID());
}
$handles[$phid] = $handle;
}
break;
case 'TASK':
$class = 'ManiphestTask';
PhutilSymbolLoader::loadClass($class);
$object = newv($class, array());
$tasks = $object->loadAllWhere('phid in (%Ls)', $phids);
$tasks = mpull($tasks, null, 'getPHID');
foreach ($phids as $phid) {
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
if (empty($tasks[$phid])) {
$handle->setType(self::TYPE_UNKNOWN);
$handle->setName('Unknown Revision');
} else {
$task = $tasks[$phid];
$handle->setType($type);
$handle->setName($task->getTitle());
$handle->setURI('/T'.$task->getID());
}
$handles[$phid] = $handle;
}
break;
case 'FILE':
$class = 'PhabricatorFile';
PhutilSymbolLoader::loadClass($class);

View file

@ -0,0 +1,25 @@
<?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.
*/
final class PhabricatorSearchField {
const FIELD_TITLE = 'titl';
const FIELD_BODY = 'body';
const FIELD_TEST_PLAN = 'tpln';
}

View file

@ -0,0 +1,10 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_source('PhabricatorSearchField.php');

View file

@ -0,0 +1,26 @@
<?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.
*/
final class PhabricatorSearchRelationship {
const RELATIONSHIP_AUTHOR = 'auth';
const RELATIONSHIP_REVIEWER = 'revw';
const RELATIONSHIP_SUBSCRIBER = 'subs';
const RELATIONSHIP_COMMENTER = 'comm';
}

View file

@ -0,0 +1,10 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_source('PhabricatorSearchRelationship.php');

View file

@ -0,0 +1,34 @@
<?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.
*/
abstract class PhabricatorSearchBaseController extends PhabricatorController {
public function buildStandardPageResponse($view, array $data) {
$page = $this->buildStandardPageView();
$page->setApplicationName('Search');
$page->setBaseURI('/search/');
$page->setTitle(idx($data, 'title'));
$page->setGlyph("(?)");
$page->appendChild($view);
$response = new AphrontWebpageResponse();
return $response->setContent($page->render());
}
}

View file

@ -0,0 +1,15 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/webpage');
phutil_require_module('phabricator', 'applications/base/controller/base');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorSearchBaseController.php');

View file

@ -0,0 +1,95 @@
<?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 PhabricatorSearchController extends PhabricatorSearchBaseController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
if ($this->id) {
$query = id(new PhabricatorSearchQuery())->load($this->id);
if (!$query) {
return new Aphront404Response();
}
} else {
$query = new PhabricatorSearchQuery();
if ($request->isFormPost()) {
$query->setQuery($request->getStr('query'));
$query->save();
return id(new AphrontRedirectResponse())
->setURI('/search/'.$query->getID().'/');
}
}
$search_form = new AphrontFormView();
$search_form
->setUser($user)
->setAction('/search/')
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Search')
->setName('query')
->setValue($query->getQuery()))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue('Search'));
$search_panel = new AphrontPanelView();
$search_panel->setHeader('Search Phabricator');
$search_panel->appendChild($search_form);
if ($query->getID()) {
$executor = new PhabricatorSearchMySQLExecutor();
$results = $executor->executeSearch($query);
$results = ipull($results, 'phid');
$handles = id(new PhabricatorObjectHandleData($results))
->loadHandles();
$results = array();
foreach ($handles as $handle) {
$results[] = '<h1>'.$handle->renderLink().'</h1>';
}
$results =
'<div style="padding: 1em 2em 2em;">'.
implode("\n", $results).
'</div>';
} else {
$results = null;
}
$results = print_r($results, true);
return $this->buildStandardPageResponse(
array(
$search_panel,
$results,
),
array(
'title' => 'Results: what',
));
}
}

View file

@ -0,0 +1,22 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'aphront/response/404');
phutil_require_module('phabricator', 'aphront/response/redirect');
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', 'applications/search/storage/query');
phutil_require_module('phabricator', 'view/form/base');
phutil_require_module('phabricator', 'view/form/control/submit');
phutil_require_module('phabricator', 'view/layout/panel');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorSearchController.php');

View file

@ -0,0 +1,22 @@
<?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.
*/
abstract class PhabricatorSearchExecutor {
}

View file

@ -0,0 +1,10 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_source('PhabricatorSearchExecutor.php');

View file

@ -0,0 +1,137 @@
<?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 PhabricatorSearchMySQLExecutor extends PhabricatorSearchExecutor {
public function executeSearch(PhabricatorSearchQuery $query) {
$where = array();
$join = array();
$order = 'ORDER BY documentCreated DESC';
$dao_doc = new PhabricatorSearchDocument();
$dao_field = new PhabricatorSearchDocumentField();
$t_doc = $dao_doc->getTableName();
$t_field = $dao_field->getTableName();
$conn_r = $dao_doc->establishConnection('r');
$q = $query->getQuery();
if (strlen($q)) {
$join[] = qsprintf(
$conn_r,
"{$t_field} field ON field.phid = document.phid");
$where[] = qsprintf(
$conn_r,
'MATCH(corpus) AGAINST (%s)',
$q);
/*
if ($query->getParameter('order') == AdjutantQuery::ORDER_RELEVANCE) {
$order = qsprintf(
$conn_r,
'ORDER BY MATCH(corpus) AGAINST (%s) DESC',
$q);
}
*/
$field = $query->getParameter('field');
if ($field/* && $field != AdjutantQuery::FIELD_ALL*/) {
$where[] = qsprintf(
$conn_r,
'field.field = %s',
$field);
}
}
if ($query->getParameter('type')) {
$where[] = qsprintf(
$conn_r,
'document.documentType = %s',
$query->getParameter('type'));
}
/*
$join[] = $this->joinRelationship(
$conn_r,
$query,
'author',
AdjutantRelationship::RELATIONSHIP_AUTHOR);
$join[] = $this->joinRelationship(
$conn_r,
$query,
'reviewer',
AdjutantRelationship::RELATIONSHIP_REVIEWER);
$join[] = $this->joinRelationship(
$conn_r,
$query,
'subscriber',
AdjutantRelationship::RELATIONSHIP_SUBSCRIBER);
$join[] = $this->joinRelationship(
$conn_r,
$query,
'repository',
AdjutantRelationship::RELATIONSHIP_REPOSITORY);
*/
$join = array_filter($join);
foreach ($join as $key => $clause) {
$join[$key] = ' JOIN '.$clause;
}
$join = implode(' ', $join);
if ($where) {
$where = 'WHERE '.implode(' AND ', $where);
} else {
$where = '';
}
$hits = queryfx_all(
$conn_r,
'SELECT DISTINCT
document.phid,
document.documentType,
document.documentCreated FROM %T document %Q %Q %Q
LIMIT 50',
$t_doc,
$join,
$where,
$order);
return $hits;
}
protected function joinRelationship($conn, $query, $field, $type) {
$fbids = $query->getParameter($field, array());
if (!$fbids) {
return null;
}
return qsprintf(
$conn,
'relationship AS %C ON %C.fbid = data.fbid AND %C.relation = %s
AND %C.relatedFBID in (%Ld)',
$field,
$field,
$field,
$type,
$field,
$fbids);
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/search/execute/base');
phutil_require_module('phabricator', 'applications/search/storage/document/document');
phutil_require_module('phabricator', 'applications/search/storage/document/field');
phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_source('PhabricatorSearchMySQLExecutor.php');

View file

@ -0,0 +1,92 @@
<?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.
*/
final class PhabricatorSearchAbstractDocument {
private $phid;
private $documentType;
private $documentTitle;
private $documentCreated;
private $documentModified;
private $fields = array();
private $relationships = array();
public function setPHID($phid) {
$this->phid = $phid;
return $this;
}
public function setDocumentType($document_type) {
$this->documentType = $document_type;
return $this;
}
public function setDocumentTitle($title) {
$this->documentTitle = $title;
$this->addField(PhabricatorSearchField::FIELD_TITLE, $title);
return $this;
}
public function addField($field, $corpus, $aux_phid = null) {
$this->fields[] = array($field, $corpus, $aux_phid);
return $this;
}
public function addRelationship($type, $related_phid) {
$this->relationships[] = array($type, $related_phid);
return $this;
}
public function setDocumentCreated($date) {
$this->documentCreated = $date;
return $this;
}
public function setDocumentModified($date) {
$this->documentModified = $date;
return $this;
}
public function getPHID() {
return $this->phid;
}
public function getDocumentType() {
return $this->documentType;
}
public function getDocumentTitle() {
return $this->documentTitle;
}
public function getDocumentCreated() {
return $this->documentCreated;
}
public function getDocumentModified() {
return $this->documentModified;
}
public function getFieldData() {
return $this->fields;
}
public function getRelationshipData() {
return $this->relationships;
}
}

View file

@ -0,0 +1,12 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/search/constants/field');
phutil_require_source('PhabricatorSearchAbstractDocument.php');

View file

@ -0,0 +1,19 @@
<?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.
*/
abstract class PhabricatorSearchDocumentIndexer { }

View file

@ -0,0 +1,10 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_source('PhabricatorSearchDocumentIndexer.php');

View file

@ -0,0 +1,43 @@
<?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 PhabricatorSearchDifferentialIndexer
extends PhabricatorSearchDocumentIndexer {
public static function indexRevision(DifferentialRevision $rev) {
$doc = new PhabricatorSearchAbstractDocument();
$doc->setPHID($rev->getPHID());
$doc->setDocumentType('DREV');
$doc->setDocumentTitle($rev->getTitle());
$doc->setDocumentCreated($rev->getDateCreated());
$doc->setDocumentModified($rev->getDateModified());
$doc->addField(
PhabricatorSearchField::FIELD_BODY,
$rev->getSummary());
$doc->addField(
PhabricatorSearchField::FIELD_TEST_PLAN,
$rev->getTestPlan());
$doc->addRelationship(
PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR,
$rev->getAuthorPHID());
PhabricatorSearchDocument::reindexAbstractDocument($doc);
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/search/constants/field');
phutil_require_module('phabricator', 'applications/search/constants/relationship');
phutil_require_module('phabricator', 'applications/search/index/abstractdocument');
phutil_require_module('phabricator', 'applications/search/index/indexer/base');
phutil_require_module('phabricator', 'applications/search/storage/document/document');
phutil_require_source('PhabricatorSearchDifferentialIndexer.php');

View file

@ -0,0 +1,40 @@
<?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 PhabricatorSearchManiphestIndexer
extends PhabricatorSearchDocumentIndexer {
public static function indexTask(ManiphestTask $task) {
$doc = new PhabricatorSearchAbstractDocument();
$doc->setPHID($task->getPHID());
$doc->setDocumentType('TASK');
$doc->setDocumentTitle($task->getTitle());
$doc->setDocumentCreated($task->getDateCreated());
$doc->setDocumentModified($task->getDateModified());
$doc->addField(
PhabricatorSearchField::FIELD_BODY,
$task->getDescription());
$doc->addRelationship(
PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR,
$task->getAuthorPHID());
PhabricatorSearchDocument::reindexAbstractDocument($doc);
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/search/constants/field');
phutil_require_module('phabricator', 'applications/search/constants/relationship');
phutil_require_module('phabricator', 'applications/search/index/abstractdocument');
phutil_require_module('phabricator', 'applications/search/index/indexer/base');
phutil_require_module('phabricator', 'applications/search/storage/document/document');
phutil_require_source('PhabricatorSearchManiphestIndexer.php');

View file

@ -0,0 +1,25 @@
<?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.
*/
abstract class PhabricatorSearchDAO extends PhabricatorLiskDAO {
public function getApplicationName() {
return 'search';
}
}

View file

@ -0,0 +1,12 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/base/storage/lisk');
phutil_require_source('PhabricatorSearchDAO.php');

View file

@ -0,0 +1,104 @@
<?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 PhabricatorSearchDocument extends PhabricatorSearchDAO {
protected $phid;
protected $documentType;
protected $documentTitle;
protected $documentCreated;
protected $documentModified;
public function getConfiguration() {
return array(
self::CONFIG_TIMESTAMPS => false,
self::CONFIG_IDS => self::IDS_MANUAL,
) + parent::getConfiguration();
}
public function getIDKey() {
return 'phid';
}
public static function reindexAbstractDocument(
PhabricatorSearchAbstractDocument $doc) {
$phid = $doc->getPHID();
if (!$phid) {
throw new Exception("Document has no PHID!");
}
$store = new PhabricatorSearchDocument();
$store->setPHID($doc->getPHID());
$store->setDocumentType($doc->getDocumentType());
$store->setDocumentTitle($doc->getDocumentTitle());
$store->setDocumentCreated($doc->getDocumentCreated());
$store->setDocumentModified($doc->getDocumentModified());
$store->replace();
$conn_w = $store->establishConnection('w');
$field_dao = new PhabricatorSearchDocumentField();
queryfx(
$conn_w,
'DELETE FROM %T WHERE phid = %s',
$field_dao->getTableName(),
$phid);
foreach ($doc->getFieldData() as $field) {
list($ftype, $corpus, $aux_phid) = $field;
queryfx(
$conn_w,
'INSERT INTO %T (phid, field, auxPHId, corpus) '.
' VALUES (%s, %s, %ns, %s)',
$field_dao->getTableName(),
$phid,
$ftype,
$aux_phid,
$corpus);
}
$sql = array();
foreach ($doc->getRelationshipData() as $relationship) {
list($rtype, $toPHID) = $relationship;
$sql[] = qsprintf(
$conn_w,
'(%s, %s, %s)',
$phid,
$toPHID,
$rtype);
}
$rship_dao = new PhabricatorSearchDocumentRelationship();
queryfx(
$conn_w,
'DELETE FROM %T WHERE phid = %s',
$rship_dao->getTableName(),
$phid);
if ($sql) {
queryfx(
$conn_w,
'INSERT INTO %T (phid, relatedPHID, relation) '.
' VALUES %Q',
$rship_dao->getTableName(),
implode(', ', $sql));
}
}
}

View file

@ -0,0 +1,16 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/search/storage/base');
phutil_require_module('phabricator', 'applications/search/storage/document/field');
phutil_require_module('phabricator', 'applications/search/storage/document/relationship');
phutil_require_module('phabricator', 'storage/qsprintf');
phutil_require_module('phabricator', 'storage/queryfx');
phutil_require_source('PhabricatorSearchDocument.php');

View file

@ -0,0 +1,33 @@
<?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 PhabricatorSearchDocumentField extends PhabricatorSearchDAO {
protected $phid;
protected $field;
protected $auxPHID;
protected $corpus;
public function getConfiguration() {
return array(
self::CONFIG_TIMESTAMPS => false,
self::CONFIG_IDS => self::IDS_MANUAL,
) + parent::getConfiguration();
}
}

View file

@ -0,0 +1,12 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/search/storage/base');
phutil_require_source('PhabricatorSearchDocumentField.php');

View file

@ -0,0 +1,32 @@
<?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 PhabricatorSearchDocumentRelationship extends PhabricatorSearchDAO {
protected $phid;
protected $relatedPHID;
protected $relation;
public function getConfiguration() {
return array(
self::CONFIG_TIMESTAMPS => false,
self::CONFIG_IDS => self::IDS_MANUAL,
) + parent::getConfiguration();
}
}

View file

@ -0,0 +1,12 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/search/storage/base');
phutil_require_source('PhabricatorSearchDocumentRelationship.php');

View file

@ -0,0 +1,42 @@
<?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 PhabricatorSearchQuery extends PhabricatorSearchDAO {
protected $authorPHID;
protected $query;
protected $parameters = array();
public function getConfiguration() {
return array(
self::CONFIG_SERIALIZATION => array(
'parameters' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
public function setParameter($parameter, $value) {
$this->parameters[$parameter] = $value;
return $this;
}
public function getParameter($parameter, $default = null) {
return idx($this->parameters, $parameter, $default);
}
}

View file

@ -0,0 +1,14 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/search/storage/base');
phutil_require_module('phutil', 'utils');
phutil_require_source('PhabricatorSearchQuery.php');

View file

@ -46,3 +46,25 @@ function javelin_render_tag(
return phutil_render_tag($tag, $attributes, $content);
}
function phabricator_render_form(PhabricatorUser $user, $attributes, $content) {
return javelin_render_tag(
'form',
$attributes,
phutil_render_tag(
'input',
array(
'type' => 'hidden',
'name' => '__csrf__',
'value' => $user->getCSRFToken(),
)).
phutil_render_tag(
'input',
array(
'type' => 'hidden',
'name' => '__form__',
'value' => true,
)).$content);
}

View file

@ -154,23 +154,15 @@ class PhabricatorStandardPageView extends AphrontPageView {
' &middot; '.
'<a href="/settings/">Settings</a>'.
' &middot; '.
'<form action="/logout/" method="post" style="display: inline;">'.
phutil_render_tag(
'input',
array(
'type' => 'hidden',
'name' => '__csrf__',
'value' => $user->getCSRFToken(),
)).
phutil_render_tag(
'input',
array(
'type' => 'hidden',
'name' => '__form__',
'value' => true,
)).
'<button class="link">Logout</button>'.
'</form>';
phabricator_render_form(
$user,
array(
'action' => '/search/',
'method' => 'post',
'style' => 'display: inline',
),
'<input type="text" name="query" />'.
'<button>Search</button>');
}
}
@ -200,6 +192,17 @@ class PhabricatorStandardPageView extends AphrontPageView {
}
$foot_links[] = $link;
}
// This ends up very early in tab order at the top of the page and there's
// a bunch of junk up there anyway, just shove it down here.
$foot_links[] = phabricator_render_form(
$user,
array(
'action' => '/logout/',
'method' => 'post',
'style' => 'display: inline',
),
'<button class="link">Logout</button>');
$foot_links = implode(' &middot; ', $foot_links);
return