[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/search/engine/ -> PhabricatorSearchEngineMySQL.php (source)

   1  <?php
   2  
   3  final class PhabricatorSearchEngineMySQL extends PhabricatorSearchEngine {
   4  
   5    public function reindexAbstractDocument(
   6      PhabricatorSearchAbstractDocument $doc) {
   7  
   8      $phid = $doc->getPHID();
   9      if (!$phid) {
  10        throw new Exception('Document has no PHID!');
  11      }
  12  
  13      $store = new PhabricatorSearchDocument();
  14      $store->setPHID($doc->getPHID());
  15      $store->setDocumentType($doc->getDocumentType());
  16      $store->setDocumentTitle($doc->getDocumentTitle());
  17      $store->setDocumentCreated($doc->getDocumentCreated());
  18      $store->setDocumentModified($doc->getDocumentModified());
  19      $store->replace();
  20  
  21      $conn_w = $store->establishConnection('w');
  22  
  23      $field_dao = new PhabricatorSearchDocumentField();
  24      queryfx(
  25        $conn_w,
  26        'DELETE FROM %T WHERE phid = %s',
  27        $field_dao->getTableName(),
  28        $phid);
  29      foreach ($doc->getFieldData() as $field) {
  30        list($ftype, $corpus, $aux_phid) = $field;
  31        queryfx(
  32          $conn_w,
  33          'INSERT INTO %T (phid, phidType, field, auxPHID, corpus) '.
  34          ' VALUES (%s, %s, %s, %ns, %s)',
  35          $field_dao->getTableName(),
  36          $phid,
  37          $doc->getDocumentType(),
  38          $ftype,
  39          $aux_phid,
  40          $corpus);
  41      }
  42  
  43  
  44      $sql = array();
  45      foreach ($doc->getRelationshipData() as $relationship) {
  46        list($rtype, $to_phid, $to_type, $time) = $relationship;
  47        $sql[] = qsprintf(
  48          $conn_w,
  49          '(%s, %s, %s, %s, %d)',
  50          $phid,
  51          $to_phid,
  52          $rtype,
  53          $to_type,
  54          $time);
  55      }
  56  
  57      $rship_dao = new PhabricatorSearchDocumentRelationship();
  58      queryfx(
  59        $conn_w,
  60        'DELETE FROM %T WHERE phid = %s',
  61        $rship_dao->getTableName(),
  62        $phid);
  63      if ($sql) {
  64        queryfx(
  65          $conn_w,
  66          'INSERT INTO %T'.
  67          ' (phid, relatedPHID, relation, relatedType, relatedTime) '.
  68          ' VALUES %Q',
  69          $rship_dao->getTableName(),
  70          implode(', ', $sql));
  71      }
  72  
  73    }
  74  
  75    /**
  76     * Rebuild the PhabricatorSearchAbstractDocument that was used to index
  77     * an object out of the index itself. This is primarily useful for debugging,
  78     * as it allows you to inspect the search index representation of a
  79     * document.
  80     *
  81     * @param  phid PHID of a document which exists in the search index.
  82     * @return null|PhabricatorSearchAbstractDocument Abstract document object
  83     *           which corresponds to the original abstract document used to
  84     *           build the document index.
  85     */
  86    public function reconstructDocument($phid) {
  87      $dao_doc = new PhabricatorSearchDocument();
  88      $dao_field = new PhabricatorSearchDocumentField();
  89      $dao_relationship = new PhabricatorSearchDocumentRelationship();
  90  
  91      $t_doc = $dao_doc->getTableName();
  92      $t_field = $dao_field->getTableName();
  93      $t_relationship = $dao_relationship->getTableName();
  94  
  95      $doc = queryfx_one(
  96        $dao_doc->establishConnection('r'),
  97        'SELECT * FROM %T WHERE phid = %s',
  98        $t_doc,
  99        $phid);
 100  
 101      if (!$doc) {
 102        return null;
 103      }
 104  
 105      $fields = queryfx_all(
 106        $dao_field->establishConnection('r'),
 107        'SELECT * FROM %T WHERE phid = %s',
 108        $t_field,
 109        $phid);
 110  
 111      $relationships = queryfx_all(
 112        $dao_relationship->establishConnection('r'),
 113        'SELECT * FROM %T WHERE phid = %s',
 114        $t_relationship,
 115        $phid);
 116  
 117      $adoc = id(new PhabricatorSearchAbstractDocument())
 118        ->setPHID($phid)
 119        ->setDocumentType($doc['documentType'])
 120        ->setDocumentTitle($doc['documentTitle'])
 121        ->setDocumentCreated($doc['documentCreated'])
 122        ->setDocumentModified($doc['documentModified']);
 123  
 124      foreach ($fields as $field) {
 125        $adoc->addField(
 126          $field['field'],
 127          $field['corpus'],
 128          $field['auxPHID']);
 129      }
 130  
 131      foreach ($relationships as $relationship) {
 132        $adoc->addRelationship(
 133          $relationship['relation'],
 134          $relationship['relatedPHID'],
 135          $relationship['relatedType'],
 136          $relationship['relatedTime']);
 137      }
 138  
 139      return $adoc;
 140    }
 141  
 142    public function executeSearch(PhabricatorSavedQuery $query) {
 143      $where = array();
 144      $join  = array();
 145      $order = 'ORDER BY documentCreated DESC';
 146  
 147      $dao_doc = new PhabricatorSearchDocument();
 148      $dao_field = new PhabricatorSearchDocumentField();
 149  
 150      $t_doc   = $dao_doc->getTableName();
 151      $t_field = $dao_field->getTableName();
 152  
 153      $conn_r = $dao_doc->establishConnection('r');
 154  
 155      $q = $query->getParameter('query');
 156  
 157      if (strlen($q)) {
 158       $join[] = qsprintf(
 159          $conn_r,
 160          '%T field ON field.phid = document.phid',
 161          $t_field);
 162        $where[] = qsprintf(
 163          $conn_r,
 164          'MATCH(corpus) AGAINST (%s IN BOOLEAN MODE)',
 165          $q);
 166  
 167        // When searching for a string, promote user listings above other
 168        // listings.
 169        $order = qsprintf(
 170          $conn_r,
 171          'ORDER BY
 172            IF(documentType = %s, 0, 1) ASC,
 173            MAX(MATCH(corpus) AGAINST (%s)) DESC',
 174          'USER',
 175          $q);
 176  
 177        $field = $query->getParameter('field');
 178        if ($field) {
 179          $where[] = qsprintf(
 180            $conn_r,
 181            'field.field = %s',
 182            $field);
 183        }
 184      }
 185  
 186      $exclude = $query->getParameter('exclude');
 187      if ($exclude) {
 188        $where[] = qsprintf($conn_r, 'document.phid != %s', $exclude);
 189      }
 190  
 191      $types = $query->getParameter('types');
 192      if ($types) {
 193        if (strlen($q)) {
 194          $where[] = qsprintf(
 195            $conn_r,
 196            'field.phidType IN (%Ls)',
 197            $types);
 198        }
 199        $where[] = qsprintf(
 200          $conn_r,
 201          'document.documentType IN (%Ls)',
 202          $types);
 203      }
 204  
 205      $join[] = $this->joinRelationship(
 206        $conn_r,
 207        $query,
 208        'authorPHIDs',
 209        PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR);
 210  
 211      $statuses = $query->getParameter('statuses', array());
 212      $statuses = array_fuse($statuses);
 213      $open_rel = PhabricatorSearchRelationship::RELATIONSHIP_OPEN;
 214      $closed_rel = PhabricatorSearchRelationship::RELATIONSHIP_CLOSED;
 215      $include_open = !empty($statuses[$open_rel]);
 216      $include_closed = !empty($statuses[$closed_rel]);
 217  
 218      if ($include_open && !$include_closed) {
 219        $join[] = $this->joinRelationship(
 220          $conn_r,
 221          $query,
 222          'statuses',
 223          $open_rel,
 224          true);
 225      } else if ($include_closed && !$include_open) {
 226        $join[] = $this->joinRelationship(
 227          $conn_r,
 228          $query,
 229          'statuses',
 230          $closed_rel,
 231          true);
 232      }
 233  
 234      if ($query->getParameter('withUnowned')) {
 235        $join[] = $this->joinRelationship(
 236          $conn_r,
 237          $query,
 238          'withUnowned',
 239          PhabricatorSearchRelationship::RELATIONSHIP_UNOWNED,
 240          true);
 241      } else {
 242        $join[] = $this->joinRelationship(
 243          $conn_r,
 244          $query,
 245          'ownerPHIDs',
 246          PhabricatorSearchRelationship::RELATIONSHIP_OWNER);
 247      }
 248  
 249      $join[] = $this->joinRelationship(
 250        $conn_r,
 251        $query,
 252        'subscriberPHIDs',
 253        PhabricatorSearchRelationship::RELATIONSHIP_SUBSCRIBER);
 254  
 255      $join[] = $this->joinRelationship(
 256        $conn_r,
 257        $query,
 258        'projectPHIDs',
 259        PhabricatorSearchRelationship::RELATIONSHIP_PROJECT);
 260  
 261      $join[] = $this->joinRelationship(
 262        $conn_r,
 263        $query,
 264        'repository',
 265        PhabricatorSearchRelationship::RELATIONSHIP_REPOSITORY);
 266  
 267      $join = array_filter($join);
 268  
 269      foreach ($join as $key => $clause) {
 270        $join[$key] = ' JOIN '.$clause;
 271      }
 272      $join = implode(' ', $join);
 273  
 274      if ($where) {
 275        $where = 'WHERE '.implode(' AND ', $where);
 276      } else {
 277        $where = '';
 278      }
 279  
 280      $offset = (int)$query->getParameter('offset', 0);
 281      $limit  = (int)$query->getParameter('limit', 25);
 282  
 283      $hits = queryfx_all(
 284        $conn_r,
 285        'SELECT
 286          document.phid
 287          FROM %T document
 288            %Q
 289            %Q
 290          GROUP BY document.phid
 291            %Q
 292          LIMIT %d, %d',
 293        $t_doc,
 294        $join,
 295        $where,
 296        $order,
 297        $offset,
 298        $limit);
 299  
 300      return ipull($hits, 'phid');
 301    }
 302  
 303    protected function joinRelationship(
 304      AphrontDatabaseConnection $conn,
 305      PhabricatorSavedQuery $query,
 306      $field,
 307      $type,
 308      $is_existence = false) {
 309  
 310      $sql = qsprintf(
 311        $conn,
 312        '%T AS %C ON %C.phid = document.phid AND %C.relation = %s',
 313        id(new PhabricatorSearchDocumentRelationship())->getTableName(),
 314        $field,
 315        $field,
 316        $field,
 317        $type);
 318  
 319      if (!$is_existence) {
 320        $phids = $query->getParameter($field, array());
 321        if (!$phids) {
 322          return null;
 323        }
 324        $sql .= qsprintf(
 325          $conn,
 326          ' AND %C.relatedPHID in (%Ls)',
 327          $field,
 328          $phids);
 329      }
 330  
 331      return $sql;
 332    }
 333  
 334  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1