Seb35 has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/236417

Change subject: Phabricator extension to add links on Bugzilla "bug NNN" syntax
......................................................................

Phabricator extension to add links on Bugzilla "bug NNN" syntax

DO NOT MERGE - SUPER HACKY - see inside

Added a custom inline rule, which converts "bug NNN" to links to
the corresponding task in Phabricator (with a shift of 2000 for Wikimedia).

The non-hacky part do work in contexts where there is only one parsing engines
(e.g. when previewing a comment) but is mandatory when there are many
parsing engines (e.g. displaying a complete page).

Bug: T687
Change-Id: I0a78ab0418df4219d9413de965854d97936233de
---
A PhabricatorBugzillaRemarkupRule.php
1 file changed, 168 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/phabricator/extensions 
refs/changes/17/236417/1

diff --git a/PhabricatorBugzillaRemarkupRule.php 
b/PhabricatorBugzillaRemarkupRule.php
new file mode 100644
index 0000000..afbcb87
--- /dev/null
+++ b/PhabricatorBugzillaRemarkupRule.php
@@ -0,0 +1,168 @@
+<?php
+
+// A Phabricator extension to convert syntax "bug NNN" (from Bugzilla) to task 
links
+// Licence: WTFPL 2.0
+// Author: Seb35
+
+final class PhabricatorBugzillaRemarkupRule extends 
PhabricatorRemarkupCustomInlineRule {
+
+  // HACKY HACKY HACKY
+  //
+  // Without this, you can observe an exception in 
$this->getEngine()->storeText()
+  // when you have the text "bug 1" in the main description in Maniphest
+  //
+  // It happens PhabricatorRemarkupCustomInlineRule instances got another
+  // PhutilRemarkupEngine instance because two instances seems to be created
+  // (for main description and comments in Maniphest) and, contrary to other
+  // PhutilRemarkupRule instances, the engine for this rule could be 
overwritten
+  // by another engine (e.g. the comment engines used to parse main 
description).
+  // Since the engines are not correctly mapped to their use, all engines are
+  // saved here and it is later used the "correct" engine, i.e. the one which
+  // doesn’t trigger an Error, corresponding to an attempt to execute
+  // "$this->storage->store()" in PhutilRemarkupEngine::storeText() where
+  // the "storage" property is not set (only set on the active engine).
+  //
+  // Note that functions have to be used here since the property $this->engine
+  // is private
+  //
+  // Not sure if it is a Phabricator upstream bug or if I misuse Remarkup
+  // custom rules (anyhow it is not documented)
+
+  private $engines = array();
+  
+  public function setEngine(PhutilRemarkupEngine $engine) {
+    PhutilRemarkupRule::setEngine($engine);
+    $this->engines[] =& $engine;
+    return $this;
+  }
+
+  // END HACKY - but some remainings in markupBugzilla()
+
+
+  public function getPriority() {
+    return 450;
+  }
+
+  public function apply($text) {
+    if ($this->getEngine()->isTextMode()) {
+      return $text;
+    }
+    
+    $text = preg_replace_callback(
+      '@[Bb]ug #?([1-9]\d*)@m',
+      array($this, 'markupBugzilla'),
+      $text);
+
+    return $text;
+  }
+
+  protected function markupBugzilla(array $matches) {
+    if (!$this->isFlatText($matches[0])) {
+      return $matches[0];
+    }
+
+    // Get context
+    $mail_mode = $this->getEngine()->isHTMLMailMode();
+    $status_closed = PhabricatorObjectHandle::STATUS_CLOSED;
+
+    // Parameters and results
+    $text = $matches[0];
+    $id = $matches[1]+2000; // there is a shift of 2000 between Bugzilla and 
Phabricator for Wikimedia
+    $attr = array();
+    $href = '';
+
+    // Get URL and metadata
+    $objects = $this->loadObjects(array($id));
+    $handle = $this->loadHandles($objects)[1];
+    if( !is_null($handle) ) {
+        $href = $this->getObjectHref($objects[1], $handle, $id);
+        $attr = array(
+          'phid'    => $handle->getPHID(),
+          'closed'  => ($handle->getStatus() == $status_closed),
+        );
+    }
+
+    // Depending on the context, add more or less information about the task
+    if( !$href ) return $text;
+    $link = $text;
+    if ($mail_mode) {
+      $link = phutil_tag(
+        'a',
+        array(
+          'href' => $href
+        ),
+        $text);
+    }
+    else {
+      $link = $this->renderHovertag($text, $href, $attr);
+    }
+
+    // HACKY HACKY HACKY - see above
+    $origEngine = $this->getEngine();
+    foreach( $this->engines as $engine ) {
+        PhutilRemarkupRule::setEngine($engine);
+        try {
+            $token = $this->getEngine()->storeText($link);
+        }
+        catch(Error $e) {
+            continue;
+        }
+    }
+    PhutilRemarkupRule::setEngine($origEngine);
+    // END HACKY
+
+    return $token;
+  }
+
+  // Copied from PhabricatorObjectRemarkupRule
+  protected function loadObjects(array $ids) {
+    $viewer = $this->getEngine()->getConfig('viewer');
+
+    return id(new ManiphestTaskQuery())
+      ->setViewer($viewer)
+      ->withIDs($ids)
+      ->execute();
+  }
+
+  // Copied from PhabricatorObjectRemarkupRule
+  protected function loadHandles(array $objects) {
+    $phids = mpull($objects, 'getPHID');
+
+    $viewer = $this->getEngine()->getConfig('viewer');
+    $handles = $viewer->loadHandles($phids);
+    $handles = iterator_to_array($handles);
+
+    $result = array();
+    foreach ($objects as $id => $object) {
+      $result[$id] = $handles[$object->getPHID()];
+    }
+    return $result;
+  }
+
+  // Copied from PhabricatorObjectRemarkupRule
+  protected function getObjectHref(
+    $object,
+    PhabricatorObjectHandle $handle,
+    $id) {
+
+    $uri = $handle->getURI();
+
+    if ($this->getEngine()->getConfig('uri.full')) {
+      $uri = PhabricatorEnv::getURI($uri);
+    }
+
+    return $uri;
+  }
+
+  // Copied from PhabricatorObjectRemarkupRule
+  protected function renderHovertag($name, $href, array $attr = array()) {
+    return id(new PHUITagView())
+      ->setName($name)
+      ->setHref($href)
+      ->setType(PHUITagView::TYPE_OBJECT)
+      ->setPHID(idx($attr, 'phid'))
+      ->setClosed(idx($attr, 'closed'))
+      ->render();
+  }
+}
+

-- 
To view, visit https://gerrit.wikimedia.org/r/236417
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0a78ab0418df4219d9413de965854d97936233de
Gerrit-PatchSet: 1
Gerrit-Project: phabricator/extensions
Gerrit-Branch: master
Gerrit-Owner: Seb35 <seb35wikipe...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to