[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/phriction/editor/ -> PhrictionTransactionEditor.php (source)

   1  <?php
   2  
   3  final class PhrictionTransactionEditor
   4    extends PhabricatorApplicationTransactionEditor {
   5  
   6    private $description;
   7    private $oldContent;
   8    private $newContent;
   9    private $moveAwayDocument;
  10    private $skipAncestorCheck;
  11    private $contentVersion;
  12    private $processContentVersionError = true;
  13    private $heraldEmailPHIDs = array();
  14  
  15    public function setDescription($description) {
  16      $this->description = $description;
  17      return $this;
  18    }
  19  
  20    private function getDescription() {
  21      return $this->description;
  22    }
  23  
  24    private function setOldContent(PhrictionContent $content) {
  25      $this->oldContent = $content;
  26      return $this;
  27    }
  28  
  29    private function getOldContent() {
  30      return $this->oldContent;
  31    }
  32  
  33    private function setNewContent(PhrictionContent $content) {
  34      $this->newContent = $content;
  35      return $this;
  36    }
  37  
  38    private function getNewContent() {
  39      return $this->newContent;
  40    }
  41  
  42    public function setSkipAncestorCheck($bool) {
  43      $this->skipAncestorCheck = $bool;
  44      return $this;
  45    }
  46  
  47    public function getSkipAncestorCheck() {
  48      return $this->skipAncestorCheck;
  49    }
  50  
  51    public function setContentVersion($version) {
  52      $this->contentVersion = $version;
  53      return $this;
  54    }
  55  
  56    public function getContentVersion() {
  57      return $this->contentVersion;
  58    }
  59  
  60    public function setProcessContentVersionError($process) {
  61      $this->processContentVersionError = $process;
  62      return $this;
  63    }
  64  
  65    public function getProcessContentVersionError() {
  66      return $this->processContentVersionError;
  67    }
  68  
  69    public function getEditorApplicationClass() {
  70      return 'PhabricatorPhrictionApplication';
  71    }
  72  
  73    public function getEditorObjectsDescription() {
  74      return pht('Phriction Documents');
  75    }
  76  
  77    public function getTransactionTypes() {
  78      $types = parent::getTransactionTypes();
  79  
  80      $types[] = PhabricatorTransactions::TYPE_COMMENT;
  81      $types[] = PhrictionTransaction::TYPE_TITLE;
  82      $types[] = PhrictionTransaction::TYPE_CONTENT;
  83      $types[] = PhrictionTransaction::TYPE_DELETE;
  84      $types[] = PhrictionTransaction::TYPE_MOVE_TO;
  85      $types[] = PhrictionTransaction::TYPE_MOVE_AWAY;
  86  
  87      $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
  88      $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
  89  
  90      return $types;
  91    }
  92  
  93    protected function getCustomTransactionOldValue(
  94      PhabricatorLiskDAO $object,
  95      PhabricatorApplicationTransaction $xaction) {
  96  
  97      switch ($xaction->getTransactionType()) {
  98        case PhrictionTransaction::TYPE_TITLE:
  99          if ($this->getIsNewObject()) {
 100            return null;
 101          }
 102          return $this->getOldContent()->getTitle();
 103        case PhrictionTransaction::TYPE_CONTENT:
 104          if ($this->getIsNewObject()) {
 105            return null;
 106          }
 107          return $this->getOldContent()->getContent();
 108        case PhrictionTransaction::TYPE_DELETE:
 109        case PhrictionTransaction::TYPE_MOVE_TO:
 110        case PhrictionTransaction::TYPE_MOVE_AWAY:
 111          return null;
 112      }
 113    }
 114  
 115    protected function getCustomTransactionNewValue(
 116      PhabricatorLiskDAO $object,
 117      PhabricatorApplicationTransaction $xaction) {
 118  
 119      switch ($xaction->getTransactionType()) {
 120        case PhrictionTransaction::TYPE_TITLE:
 121        case PhrictionTransaction::TYPE_CONTENT:
 122        case PhrictionTransaction::TYPE_DELETE:
 123          return $xaction->getNewValue();
 124        case PhrictionTransaction::TYPE_MOVE_TO:
 125          $document = $xaction->getNewValue();
 126          // grab the real object now for the sub-editor to come
 127          $this->moveAwayDocument = $document;
 128          $dict = array(
 129            'id' => $document->getID(),
 130            'phid' => $document->getPHID(),
 131            'content' => $document->getContent()->getContent(),);
 132          return $dict;
 133        case PhrictionTransaction::TYPE_MOVE_AWAY:
 134          $document = $xaction->getNewValue();
 135          $dict = array(
 136            'id' => $document->getID(),
 137            'phid' => $document->getPHID(),
 138            'content' => $document->getContent()->getContent(),);
 139          return $dict;
 140      }
 141    }
 142  
 143    protected function shouldApplyInitialEffects(
 144      PhabricatorLiskDAO $object,
 145      array $xactions) {
 146  
 147      foreach ($xactions as $xaction) {
 148        switch ($xaction->getTransactionType()) {
 149        case PhrictionTransaction::TYPE_TITLE:
 150        case PhrictionTransaction::TYPE_CONTENT:
 151        case PhrictionTransaction::TYPE_DELETE:
 152        case PhrictionTransaction::TYPE_MOVE_TO:
 153        case PhrictionTransaction::TYPE_MOVE_AWAY:
 154          return true;
 155        }
 156      }
 157      return parent::shouldApplyInitialEffects($object, $xactions);
 158    }
 159  
 160    protected function applyInitialEffects(
 161      PhabricatorLiskDAO $object,
 162      array $xactions) {
 163  
 164      $this->setOldContent($object->getContent());
 165      $this->setNewContent($this->buildNewContentTemplate($object));
 166    }
 167  
 168    protected function applyCustomInternalTransaction(
 169      PhabricatorLiskDAO $object,
 170      PhabricatorApplicationTransaction $xaction) {
 171  
 172      switch ($xaction->getTransactionType()) {
 173        case PhrictionTransaction::TYPE_TITLE:
 174        case PhrictionTransaction::TYPE_CONTENT:
 175        case PhrictionTransaction::TYPE_MOVE_TO:
 176          $object->setStatus(PhrictionDocumentStatus::STATUS_EXISTS);
 177          return;
 178        case PhrictionTransaction::TYPE_MOVE_AWAY:
 179          $object->setStatus(PhrictionDocumentStatus::STATUS_MOVED);
 180          return;
 181        case PhrictionTransaction::TYPE_DELETE:
 182          $object->setStatus(PhrictionDocumentStatus::STATUS_DELETED);
 183          return;
 184      }
 185    }
 186  
 187    protected function expandTransaction(
 188      PhabricatorLiskDAO $object,
 189      PhabricatorApplicationTransaction $xaction) {
 190  
 191      $xactions = parent::expandTransaction($object, $xaction);
 192      switch ($xaction->getTransactionType()) {
 193        case PhrictionTransaction::TYPE_CONTENT:
 194          if ($this->getIsNewObject()) {
 195            break;
 196          }
 197          $content = $xaction->getNewValue();
 198          if ($content === '') {
 199            $xactions[] = id(new PhrictionTransaction())
 200              ->setTransactionType(PhrictionTransaction::TYPE_DELETE)
 201              ->setNewValue(true);
 202          }
 203          break;
 204        case PhrictionTransaction::TYPE_MOVE_TO:
 205          $document = $xaction->getNewValue();
 206          $xactions[] = id(new PhrictionTransaction())
 207            ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
 208            ->setNewValue($document->getViewPolicy());
 209          $xactions[] = id(new PhrictionTransaction())
 210            ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
 211            ->setNewValue($document->getEditPolicy());
 212          break;
 213        default:
 214          break;
 215  
 216      }
 217  
 218      return $xactions;
 219    }
 220  
 221    protected function applyCustomExternalTransaction(
 222      PhabricatorLiskDAO $object,
 223      PhabricatorApplicationTransaction $xaction) {
 224  
 225      switch ($xaction->getTransactionType()) {
 226        case PhrictionTransaction::TYPE_TITLE:
 227          $this->getNewContent()->setTitle($xaction->getNewValue());
 228          break;
 229        case PhrictionTransaction::TYPE_CONTENT:
 230          $this->getNewContent()->setContent($xaction->getNewValue());
 231          break;
 232        case PhrictionTransaction::TYPE_DELETE:
 233          $this->getNewContent()->setContent('');
 234          $this->getNewContent()->setChangeType(
 235            PhrictionChangeType::CHANGE_DELETE);
 236          break;
 237        case PhrictionTransaction::TYPE_MOVE_TO:
 238          $dict = $xaction->getNewValue();
 239          $this->getNewContent()->setContent($dict['content']);
 240          $this->getNewContent()->setChangeType(
 241            PhrictionChangeType::CHANGE_MOVE_HERE);
 242          $this->getNewContent()->setChangeRef($dict['id']);
 243          break;
 244        case PhrictionTransaction::TYPE_MOVE_AWAY:
 245          $dict = $xaction->getNewValue();
 246          $this->getNewContent()->setContent('');
 247          $this->getNewContent()->setChangeType(
 248            PhrictionChangeType::CHANGE_MOVE_AWAY);
 249          $this->getNewContent()->setChangeRef($dict['id']);
 250          break;
 251        default:
 252          break;
 253      }
 254    }
 255  
 256    protected function applyFinalEffects(
 257      PhabricatorLiskDAO $object,
 258      array $xactions) {
 259  
 260      $save_content = false;
 261      foreach ($xactions as $xaction) {
 262        switch ($xaction->getTransactionType()) {
 263          case PhrictionTransaction::TYPE_TITLE:
 264          case PhrictionTransaction::TYPE_CONTENT:
 265          case PhrictionTransaction::TYPE_DELETE:
 266          case PhrictionTransaction::TYPE_MOVE_AWAY:
 267          case PhrictionTransaction::TYPE_MOVE_TO:
 268            $save_content = true;
 269            break;
 270          default:
 271            break;
 272        }
 273      }
 274  
 275      if ($save_content) {
 276        $content = $this->getNewContent();
 277        $content->setDocumentID($object->getID());
 278        $content->save();
 279  
 280        $object->setContentID($content->getID());
 281        $object->save();
 282        $object->attachContent($content);
 283      }
 284  
 285      if ($this->getIsNewObject() && !$this->getSkipAncestorCheck()) {
 286        // Stub out empty parent documents if they don't exist
 287        $ancestral_slugs = PhabricatorSlug::getAncestry($object->getSlug());
 288        if ($ancestral_slugs) {
 289          $ancestors = id(new PhrictionDocumentQuery())
 290            ->setViewer(PhabricatorUser::getOmnipotentUser())
 291            ->withSlugs($ancestral_slugs)
 292            ->needContent(true)
 293            ->execute();
 294          $ancestors = mpull($ancestors, null, 'getSlug');
 295          $stub_type = PhrictionChangeType::CHANGE_STUB;
 296          foreach ($ancestral_slugs as $slug) {
 297            $ancestor_doc = idx($ancestors, $slug);
 298            // We check for change type to prevent near-infinite recursion
 299            if (!$ancestor_doc && $content->getChangeType() != $stub_type) {
 300              $ancestor_doc = PhrictionDocument::initializeNewDocument(
 301                $this->getActor(),
 302                $slug);
 303              $stub_xactions = array();
 304              $stub_xactions[] = id(new PhrictionTransaction())
 305                ->setTransactionType(PhrictionTransaction::TYPE_TITLE)
 306                ->setNewValue(PhabricatorSlug::getDefaultTitle($slug))
 307                ->setMetadataValue('stub:create:phid', $object->getPHID());
 308              $stub_xactions[] = id(new PhrictionTransaction())
 309                ->setTransactionType(PhrictionTransaction::TYPE_CONTENT)
 310                ->setNewValue('')
 311                ->setMetadataValue('stub:create:phid', $object->getPHID());
 312              $stub_xactions[] = id(new PhrictionTransaction())
 313                ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
 314                ->setNewValue($object->getViewPolicy());
 315              $stub_xactions[] = id(new PhrictionTransaction())
 316                ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
 317                ->setNewValue($object->getEditPolicy());
 318              $sub_editor = id(new PhrictionTransactionEditor())
 319                ->setActor($this->getActor())
 320                ->setContentSource($this->getContentSource())
 321                ->setContinueOnNoEffect($this->getContinueOnNoEffect())
 322                ->setSkipAncestorCheck(true)
 323                ->setDescription(pht('Empty Parent Document'))
 324                ->applyTransactions($ancestor_doc, $stub_xactions);
 325            }
 326          }
 327        }
 328      }
 329  
 330      if ($this->moveAwayDocument !== null) {
 331        $move_away_xactions = array();
 332        $move_away_xactions[] = id(new PhrictionTransaction())
 333          ->setTransactionType(PhrictionTransaction::TYPE_MOVE_AWAY)
 334          ->setNewValue($object);
 335        $sub_editor = id(new PhrictionTransactionEditor())
 336          ->setActor($this->getActor())
 337          ->setContentSource($this->getContentSource())
 338          ->setContinueOnNoEffect($this->getContinueOnNoEffect())
 339          ->setDescription($this->getDescription())
 340          ->applyTransactions($this->moveAwayDocument, $move_away_xactions);
 341      }
 342  
 343      return $xactions;
 344    }
 345  
 346    protected function shouldSendMail(
 347      PhabricatorLiskDAO $object,
 348      array $xactions) {
 349      return true;
 350    }
 351  
 352    protected function getMailSubjectPrefix() {
 353      return '[Phriction]';
 354    }
 355  
 356    protected function getMailTo(PhabricatorLiskDAO $object) {
 357      return array(
 358        $object->getContent()->getAuthorPHID(),
 359        $this->getActingAsPHID(),
 360      );
 361    }
 362  
 363    protected function getMailCC(PhabricatorLiskDAO $object) {
 364      $phids = array();
 365  
 366      foreach ($this->heraldEmailPHIDs as $phid) {
 367        $phids[] = $phid;
 368      }
 369  
 370      return $phids;
 371    }
 372  
 373    public function getMailTagsMap() {
 374      return array(
 375        PhrictionTransaction::MAILTAG_TITLE =>
 376          pht("A document's title changes."),
 377        PhrictionTransaction::MAILTAG_CONTENT =>
 378          pht("A document's content changes."),
 379        PhrictionTransaction::MAILTAG_DELETE =>
 380          pht('A document is deleted.'),
 381      );
 382    }
 383  
 384    protected function buildReplyHandler(PhabricatorLiskDAO $object) {
 385      return id(new PhrictionReplyHandler())
 386        ->setMailReceiver($object);
 387    }
 388  
 389    protected function buildMailTemplate(PhabricatorLiskDAO $object) {
 390      $id = $object->getID();
 391      $title = $object->getContent()->getTitle();
 392  
 393      return id(new PhabricatorMetaMTAMail())
 394        ->setSubject($title)
 395        ->addHeader('Thread-Topic', $object->getPHID());
 396    }
 397  
 398    protected function buildMailBody(
 399      PhabricatorLiskDAO $object,
 400      array $xactions) {
 401  
 402      $body = parent::buildMailBody($object, $xactions);
 403  
 404      if ($this->getIsNewObject()) {
 405        $body->addTextSection(
 406          pht('DOCUMENT CONTENT'),
 407          $object->getContent()->getContent());
 408      } else {
 409  
 410        foreach ($xactions as $xaction) {
 411          switch ($xaction->getTransactionType()) {
 412            case PhrictionTransaction::TYPE_CONTENT:
 413              $diff_uri = id(new PhutilURI(
 414                '/phriction/diff/'.$object->getID().'/'))
 415                ->alter('l', $this->getOldContent()->getVersion())
 416                ->alter('r', $this->getNewContent()->getVersion());
 417              $body->addLinkSection(
 418                pht('DOCUMENT DIFF'),
 419                PhabricatorEnv::getProductionURI($diff_uri));
 420              break 2;
 421            default:
 422              break;
 423          }
 424        }
 425  
 426      }
 427  
 428      $body->addLinkSection(
 429        pht('DOCUMENT DETAIL'),
 430        PhabricatorEnv::getProductionURI(
 431          PhrictionDocument::getSlugURI($object->getSlug())));
 432  
 433      return $body;
 434    }
 435  
 436    protected function shouldPublishFeedStory(
 437      PhabricatorLiskDAO $object,
 438      array $xactions) {
 439      return $this->shouldSendMail($object, $xactions);
 440    }
 441  
 442    protected function getFeedRelatedPHIDs(
 443      PhabricatorLiskDAO $object,
 444      array $xactions) {
 445  
 446      $phids = parent::getFeedRelatedPHIDs($object, $xactions);
 447  
 448      foreach ($xactions as $xaction) {
 449        switch ($xaction->getTransactionType()) {
 450          case PhrictionTransaction::TYPE_MOVE_TO:
 451            $dict = $xaction->getNewValue();
 452            $phids[] = $dict['phid'];
 453            break;
 454        }
 455      }
 456  
 457      return $phids;
 458    }
 459  
 460    protected function validateTransaction(
 461      PhabricatorLiskDAO $object,
 462      $type,
 463      array $xactions) {
 464  
 465      $errors = parent::validateTransaction($object, $type, $xactions);
 466  
 467      foreach ($xactions as $xaction) {
 468        switch ($type) {
 469          case PhrictionTransaction::TYPE_TITLE:
 470            $title = $object->getContent()->getTitle();
 471            $missing = $this->validateIsEmptyTextField(
 472              $title,
 473              $xactions);
 474  
 475            if ($missing) {
 476              $error = new PhabricatorApplicationTransactionValidationError(
 477                $type,
 478                pht('Required'),
 479                pht('Document title is required.'),
 480                nonempty(last($xactions), null));
 481  
 482              $error->setIsMissingFieldError(true);
 483              $errors[] = $error;
 484            } else if ($this->getProcessContentVersionError()) {
 485              $error = $this->validateContentVersion($object, $type, $xaction);
 486              if ($error) {
 487                $this->setProcessContentVersionError(false);
 488                $errors[] = $error;
 489              }
 490            }
 491            break;
 492  
 493          case PhrictionTransaction::TYPE_CONTENT:
 494            if ($xaction->getMetadataValue('stub:create:phid')) {
 495              continue;
 496            }
 497  
 498            $missing = false;
 499            if ($this->getIsNewObject()) {
 500              $content = $object->getContent()->getContent();
 501              $missing = $this->validateIsEmptyTextField(
 502                $content,
 503                $xactions);
 504            }
 505  
 506            if ($missing) {
 507              $error = new PhabricatorApplicationTransactionValidationError(
 508                $type,
 509                pht('Required'),
 510                pht('Document content is required.'),
 511                nonempty(last($xactions), null));
 512  
 513              $error->setIsMissingFieldError(true);
 514              $errors[] = $error;
 515            } else if ($this->getProcessContentVersionError()) {
 516              $error = $this->validateContentVersion($object, $type, $xaction);
 517              if ($error) {
 518                $this->setProcessContentVersionError(false);
 519                $errors[] = $error;
 520              }
 521            }
 522            break;
 523  
 524          case PhrictionTransaction::TYPE_MOVE_TO:
 525            $source_document = $xaction->getNewValue();
 526            switch ($source_document->getStatus()) {
 527              case PhrictionDocumentStatus::STATUS_DELETED:
 528                $e_text = pht('A deleted document can not be moved.');
 529                break;
 530              case PhrictionDocumentStatus::STATUS_MOVED:
 531                $e_text = pht('A moved document can not be moved again.');
 532                break;
 533              case PhrictionDocumentStatus::STATUS_STUB:
 534                $e_text = pht('A stub document can not be moved.');
 535                break;
 536              default:
 537                $e_text = null;
 538                break;
 539            }
 540  
 541            if ($e_text) {
 542              $error = new PhabricatorApplicationTransactionValidationError(
 543                $type,
 544                pht('Can not move document.'),
 545                $e_text,
 546                $xaction);
 547              $errors[] = $error;
 548            }
 549  
 550            // NOTE: We use the ominpotent user because we can't let users
 551            // overwrite documents even if they can't see them.
 552            $target_document = id(new PhrictionDocumentQuery())
 553              ->setViewer(PhabricatorUser::getOmnipotentUser())
 554              ->withSlugs(array($object->getSlug()))
 555              ->needContent(true)
 556              ->executeOne();
 557  
 558            // Prevent overwrites and no-op moves.
 559            $exists = PhrictionDocumentStatus::STATUS_EXISTS;
 560            if ($target_document) {
 561              if ($target_document->getSlug() == $source_document->getSlug()) {
 562                $message = pht(
 563                  'You can not move a document to its existing location. '.
 564                  'Choose a different location to move the document to.');
 565              } else if ($target_document->getStatus() == $exists) {
 566                $message = pht(
 567                  'You can not move this document there, because it would '.
 568                  'overwrite an existing document which is already at that '.
 569                  'location. Move or delete the existing document first.');
 570              }
 571  
 572              $error = new PhabricatorApplicationTransactionValidationError(
 573                $type,
 574                pht('Invalid'),
 575                $message,
 576                $xaction);
 577              $errors[] = $error;
 578            }
 579            break;
 580  
 581          case PhrictionTransaction::TYPE_DELETE:
 582            switch ($object->getStatus()) {
 583              case PhrictionDocumentStatus::STATUS_DELETED:
 584                $e_text = pht('An already deleted document can not be deleted.');
 585                break;
 586              case PhrictionDocumentStatus::STATUS_MOVED:
 587                $e_text = pht('A moved document can not be deleted.');
 588                break;
 589              case PhrictionDocumentStatus::STATUS_STUB:
 590                $e_text = pht('A stub document can not be deleted.');
 591                break;
 592              default:
 593                break 2;
 594            }
 595  
 596            $error = new PhabricatorApplicationTransactionValidationError(
 597              $type,
 598              pht('Can not delete document.'),
 599              $e_text,
 600              $xaction);
 601            $errors[] = $error;
 602            break;
 603        }
 604      }
 605  
 606      return $errors;
 607    }
 608  
 609    private function validateContentVersion(
 610      PhabricatorLiskDAO $object,
 611      $type,
 612      PhabricatorApplicationTransaction $xaction) {
 613  
 614      $error = null;
 615      if ($this->getContentVersion() &&
 616         ($object->getContent()->getVersion() != $this->getContentVersion())) {
 617        $error = new PhabricatorApplicationTransactionValidationError(
 618          $type,
 619          pht('Edit Conflict'),
 620          pht(
 621            'Another user made changes to this document after you began '.
 622            'editing it. Do you want to overwrite their changes? '.
 623            '(If you choose to overwrite their changes, you should review '.
 624            'the document edit history to see what you overwrote, and '.
 625            'then make another edit to merge the changes if necessary.)'),
 626          $xaction);
 627      }
 628      return $error;
 629    }
 630    protected function requireCapabilities(
 631      PhabricatorLiskDAO $object,
 632      PhabricatorApplicationTransaction $xaction) {
 633  
 634      /*
 635       * New objects have a special case. If a user can't see
 636       *   x/y
 637       * then definitely don't let them make some
 638       *   x/y/z
 639       * We need to load the direct parent to handle this case.
 640       */
 641      if ($this->getIsNewObject()) {
 642        $actor = $this->requireActor();
 643        $parent_doc = null;
 644        $ancestral_slugs = PhabricatorSlug::getAncestry($object->getSlug());
 645        // No ancestral slugs is "/"; the first person gets to play with "/".
 646        if ($ancestral_slugs) {
 647          $parent = end($ancestral_slugs);
 648          $parent_doc = id(new PhrictionDocumentQuery())
 649            ->setViewer($actor)
 650            ->withSlugs(array($parent))
 651            ->executeOne();
 652          // If the $actor can't see the $parent_doc then they can't create
 653          // the child $object; throw a policy exception.
 654          if (!$parent_doc) {
 655            id(new PhabricatorPolicyFilter())
 656              ->setViewer($actor)
 657              ->raisePolicyExceptions(true)
 658              ->rejectObject(
 659                $object,
 660                $object->getEditPolicy(),
 661                PhabricatorPolicyCapability::CAN_EDIT);
 662          }
 663  
 664          // If the $actor can't edit the $parent_doc then they can't create
 665          // the child $object; throw a policy exception.
 666          if (!PhabricatorPolicyFilter::hasCapability(
 667            $actor,
 668            $parent_doc,
 669            PhabricatorPolicyCapability::CAN_EDIT)) {
 670            id(new PhabricatorPolicyFilter())
 671              ->setViewer($actor)
 672              ->raisePolicyExceptions(true)
 673              ->rejectObject(
 674                $object,
 675                $object->getEditPolicy(),
 676                PhabricatorPolicyCapability::CAN_EDIT);
 677          }
 678        }
 679      }
 680      return parent::requireCapabilities($object, $xaction);
 681    }
 682  
 683    protected function supportsSearch() {
 684      return true;
 685    }
 686  
 687    protected function shouldApplyHeraldRules(
 688      PhabricatorLiskDAO $object,
 689      array $xactions) {
 690      return true;
 691    }
 692  
 693    protected function buildHeraldAdapter(
 694      PhabricatorLiskDAO $object,
 695      array $xactions) {
 696  
 697      return id(new PhrictionDocumentHeraldAdapter())
 698        ->setDocument($object);
 699    }
 700  
 701    protected function didApplyHeraldRules(
 702      PhabricatorLiskDAO $object,
 703      HeraldAdapter $adapter,
 704      HeraldTranscript $transcript) {
 705  
 706      $xactions = array();
 707  
 708      $cc_phids = $adapter->getCcPHIDs();
 709      if ($cc_phids) {
 710        $value = array_fuse($cc_phids);
 711        $xactions[] = id(new PhrictionTransaction())
 712          ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
 713          ->setNewValue(array('+' => $value));
 714      }
 715  
 716      $this->heraldEmailPHIDs = $adapter->getEmailPHIDs();
 717  
 718      return $xactions;
 719    }
 720  
 721    private function buildNewContentTemplate(
 722      PhrictionDocument $document) {
 723  
 724      $new_content = id(new PhrictionContent())
 725        ->setSlug($document->getSlug())
 726        ->setAuthorPHID($this->getActor()->getPHID())
 727        ->setChangeType(PhrictionChangeType::CHANGE_EDIT)
 728        ->setTitle($this->getOldContent()->getTitle())
 729        ->setContent($this->getOldContent()->getContent());
 730      if (strlen($this->getDescription())) {
 731        $new_content->setDescription($this->getDescription());
 732      }
 733      $new_content->setVersion($this->getOldContent()->getVersion() + 1);
 734  
 735      return $new_content;
 736    }
 737  
 738  }


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