1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 06:42:42 +01:00

Add Open Graph protocol meta tags to Maniphest task pages

Summary:
Add OGP <meta> tags to Maniphest task pages when the task is publicly accessible and anonymously accessed. See https://ogp.me/

Based on rP2c72c2b924ffa3f8a49dbec636a2cdca3bae004f reverted in rP49b57eae7df52c189aef1d973823c697fc97fd4b.

Closes T15472

Test Plan:
* Use the default Phorge logo, open a Maniphest task, look at the headers in its HTML.
* Set a custom Phorge logo via `config/edit/ui.logo/`.
* Access a task with "View Policy: All Users" while logged in: No OGP headers included.
* Access a task with "View Policy: Public" while logged in: No OGP headers included.
* Access a task with "View Policy: All Users" while logged out: No OGP headers included; "Access Denied: Restricted Maniphest Task" displayed.
* Access a task with "View Policy: Public" while logged out: OGP headers included.
* Access a task with "View Policy: Public" while logged out with a task description and a task without a task description: OGP headers included.

Reviewers: O1 Blessed Committers, valerio.bozzolan

Reviewed By: O1 Blessed Committers, valerio.bozzolan

Subscribers: avivey, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno

Maniphest Tasks: T15472

Differential Revision: https://we.phorge.it/D25668
This commit is contained in:
Andre Klapper 2024-05-20 22:28:50 +02:00
parent 1cc04fb83c
commit 89778dc9e6
4 changed files with 114 additions and 31 deletions

View file

@ -13,6 +13,45 @@ final class PhabricatorCustomLogoConfigType
return idx($logo, 'wordmarkText'); return idx($logo, 'wordmarkText');
} }
/**
* Return the full URI of the Phorge logo
* @param PhabricatorUser Current viewer
* @return string Full URI of the Phorge logo
*/
public static function getLogoURI(PhabricatorUser $viewer) {
$logo_uri = null;
$custom_header = self::getLogoImagePHID();
if ($custom_header) {
$cache = PhabricatorCaches::getImmutableCache();
$cache_key_logo = 'ui.custom-header.logo-phid.v3.'.$custom_header;
$logo_uri = $cache->getKey($cache_key_logo);
if (!$logo_uri) {
// NOTE: If the file policy has been changed to be restrictive, we'll
// miss here and just show the default logo. The cache will fill later
// when someone who can see the file loads the page. This might be a
// little spooky, see T11982.
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->withPHIDs(array($custom_header))
->execute();
$file = head($files);
if ($file) {
$logo_uri = $file->getViewURI();
$cache->setKey($cache_key_logo, $logo_uri);
}
}
}
if (!$logo_uri) {
$logo_uri =
celerity_get_resource_uri('/rsrc/image/logo/project-logo.png');
}
return $logo_uri;
}
public function validateOption(PhabricatorConfigOption $option, $value) { public function validateOption(PhabricatorConfigOption $option, $value) {
if (!is_array($value)) { if (!is_array($value)) {
throw new Exception( throw new Exception(

View file

@ -203,8 +203,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
->addPropertySection(pht('Description'), $description) ->addPropertySection(pht('Description'), $description)
->addPropertySection(pht('Details'), $details); ->addPropertySection(pht('Details'), $details);
$page = $this->newPage()
return $this->newPage()
->setTitle($title) ->setTitle($title)
->setCrumbs($crumbs) ->setCrumbs($crumbs)
->setPageObjectPHIDs( ->setPageObjectPHIDs(
@ -213,6 +212,74 @@ final class ManiphestTaskDetailController extends ManiphestController {
)) ))
->appendChild($view); ->appendChild($view);
if ($this->getIncludeOpenGraphMetadata($viewer, $task)) {
$page = $this->addOpenGraphProtocolMetadataTags($page, $task);
}
return $page;
}
/**
* Whether the page should include Open Graph metadata tags
* @param PhabricatorUser $viewer Viewer of the object
* @param object $object
* @return bool True if the page should serve Open Graph metadata tags
*/
private function getIncludeOpenGraphMetadata(PhabricatorUser $viewer,
$object) {
// Don't waste time adding OpenGraph metadata for logged-in users
if ($viewer->getIsStandardUser()) {
return false;
}
// Include OpenGraph tags only for public objects
return $object->getViewPolicy() === PhabricatorPolicies::POLICY_PUBLIC;
}
/**
* Get Open Graph Protocol metadata values
* @param ManiphestTask $task
* @return array Map of Open Graph property => value
*/
private function getOpenGraphProtocolMetadataValues($task) {
$viewer = $this->getViewer();
$v = [];
$v['og:site_name'] = PlatformSymbols::getPlatformServerName();
$v['og:type'] = 'object';
$v['og:url'] = PhabricatorEnv::getProductionURI($task->getURI());
$v['og:title'] = $task->getMonogram().' '.$task->getTitle();
$desc = $task->getDescription();
if (phutil_nonempty_string($desc)) {
$v['og:description'] =
PhabricatorMarkupEngine::summarizeSentence($desc);
}
$v['og:image'] =
PhabricatorCustomLogoConfigType::getLogoURI($viewer);
$v['og:image:height'] = 64;
$v['og:image:width'] = 64;
return $v;
}
/**
* Add Open Graph Protocol metadata tags to Maniphest task page
* @param PhabricatorStandardPageView $page
* @param ManiphestTask $task
* @return $page with additional OGP <meta> tags
*/
private function addOpenGraphProtocolMetadataTags($page, $task) {
foreach ($this->getOpenGraphProtocolMetadataValues($task) as $k => $v) {
$page->addHeadItem(phutil_tag(
'meta',
array(
'property' => $k,
'content' => $v,
)));
}
return $page;
} }
private function buildHeaderView(ManiphestTask $task) { private function buildHeaderView(ManiphestTask $task) {

View file

@ -378,7 +378,6 @@ final class PhabricatorStandardPageView extends PhabricatorBarePageView
/** /**
* Insert a HTML element into <head> of the page to render. * Insert a HTML element into <head> of the page to render.
* Used by PhameBlogViewController.
* *
* @param PhutilSafeHTML HTML header to add * @param PhutilSafeHTML HTML header to add
*/ */

View file

@ -293,36 +293,15 @@ final class PhabricatorMainMenuView extends AphrontView {
} }
private function renderPhabricatorLogo() { private function renderPhabricatorLogo() {
$custom_header = PhabricatorCustomLogoConfigType::getLogoImagePHID();
$logo_style = array(); $logo_style = array();
$custom_header = PhabricatorCustomLogoConfigType::getLogoImagePHID();
if ($custom_header) { if ($custom_header) {
$cache = PhabricatorCaches::getImmutableCache(); $viewer = $this->getViewer();
$cache_key_logo = 'ui.custom-header.logo-phid.v3.'.$custom_header; $logo_uri = PhabricatorCustomLogoConfigType::getLogoURI($viewer);
$logo_uri = $cache->getKey($cache_key_logo);
if (!$logo_uri) {
// NOTE: If the file policy has been changed to be restrictive, we'll
// miss here and just show the default logo. The cache will fill later
// when someone who can see the file loads the page. This might be a
// little spooky, see T11982.
$files = id(new PhabricatorFileQuery())
->setViewer($this->getViewer())
->withPHIDs(array($custom_header))
->execute();
$file = head($files);
if ($file) {
$logo_uri = $file->getViewURI();
$cache->setKey($cache_key_logo, $logo_uri);
}
}
if ($logo_uri) {
$logo_style[] = 'background-size: 40px 40px;'; $logo_style[] = 'background-size: 40px 40px;';
$logo_style[] = 'background-position: 0 0;'; $logo_style[] = 'background-position: 0 0;';
$logo_style[] = 'background-image: url('.$logo_uri.')'; $logo_style[] = 'background-image: url('.$logo_uri.')';
} }
}
$logo_node = phutil_tag( $logo_node = phutil_tag(
'span', 'span',
@ -331,7 +310,6 @@ final class PhabricatorMainMenuView extends AphrontView {
'style' => implode(' ', $logo_style), 'style' => implode(' ', $logo_style),
)); ));
$wordmark_text = PhabricatorCustomLogoConfigType::getLogoWordmark(); $wordmark_text = PhabricatorCustomLogoConfigType::getLogoWordmark();
if (!phutil_nonempty_string($wordmark_text)) { if (!phutil_nonempty_string($wordmark_text)) {
$wordmark_text = PlatformSymbols::getPlatformServerName(); $wordmark_text = PlatformSymbols::getPlatformServerName();