Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F546258
ManiphestTaskDetailController.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
26 KB
Referenced Files
None
Subscribers
None
ManiphestTaskDetailController.php
View Options
<?php
final
class
ManiphestTaskDetailController
extends
ManiphestController
{
public
function
shouldAllowPublic
()
{
return
true
;
}
public
function
handleRequest
(
AphrontRequest
$request
)
{
$viewer
=
$this
->
getViewer
();
$id
=
$request
->
getURIData
(
'id'
);
$task
=
id
(
new
ManiphestTaskQuery
())
->
setViewer
(
$viewer
)
->
withIDs
(
array
(
$id
))
->
needSubscriberPHIDs
(
true
)
->
executeOne
();
if
(!
$task
)
{
return
new
Aphront404Response
();
}
$field_list
=
PhabricatorCustomField
::
getObjectFields
(
$task
,
PhabricatorCustomField
::
ROLE_VIEW
);
$field_list
->
setViewer
(
$viewer
)
->
readFieldsFromStorage
(
$task
);
$edit_engine
=
id
(
new
ManiphestEditEngine
())
->
setViewer
(
$viewer
)
->
setTargetObject
(
$task
);
$edge_types
=
array
(
ManiphestTaskHasCommitEdgeType
::
EDGECONST
,
ManiphestTaskHasRevisionEdgeType
::
EDGECONST
,
ManiphestTaskHasMockEdgeType
::
EDGECONST
,
PhabricatorObjectMentionedByObjectEdgeType
::
EDGECONST
,
PhabricatorObjectMentionsObjectEdgeType
::
EDGECONST
,
ManiphestTaskHasDuplicateTaskEdgeType
::
EDGECONST
,
);
$phid
=
$task
->
getPHID
();
$query
=
id
(
new
PhabricatorEdgeQuery
())
->
withSourcePHIDs
(
array
(
$phid
))
->
withEdgeTypes
(
$edge_types
);
$edges
=
idx
(
$query
->
execute
(),
$phid
);
$phids
=
array_fill_keys
(
$query
->
getDestinationPHIDs
(),
true
);
if
(
$task
->
getOwnerPHID
())
{
$phids
[
$task
->
getOwnerPHID
()]
=
true
;
}
$phids
[
$task
->
getAuthorPHID
()]
=
true
;
$phids
=
array_keys
(
$phids
);
$handles
=
$viewer
->
loadHandles
(
$phids
);
$timeline
=
$this
->
buildTransactionTimeline
(
$task
,
new
ManiphestTransactionQuery
());
$monogram
=
$task
->
getMonogram
();
$crumbs
=
$this
->
buildApplicationCrumbs
()
->
addTextCrumb
(
$monogram
)
->
setBorder
(
true
);
$header
=
$this
->
buildHeaderView
(
$task
);
$details
=
$this
->
buildPropertyView
(
$task
,
$field_list
,
$edges
,
$handles
);
$description
=
$this
->
buildDescriptionView
(
$task
);
$curtain
=
$this
->
buildCurtain
(
$task
,
$edit_engine
);
$title
=
pht
(
'%s %s'
,
$monogram
,
$task
->
getTitle
());
$comment_view
=
$edit_engine
->
buildEditEngineCommentView
(
$task
);
$timeline
->
setQuoteRef
(
$monogram
);
$comment_view
->
setTransactionTimeline
(
$timeline
);
$related_tabs
=
array
();
$graph_menu
=
null
;
$graph_limit
=
200
;
$graph_error_message
=
null
;
$task_graph
=
id
(
new
ManiphestTaskGraph
())
->
setViewer
(
$viewer
)
->
setSeedPHID
(
$task
->
getPHID
())
->
setLimit
(
$graph_limit
)
->
loadGraph
();
if
(!
$task_graph
->
isEmpty
())
{
$parent_type
=
ManiphestTaskDependedOnByTaskEdgeType
::
EDGECONST
;
$subtask_type
=
ManiphestTaskDependsOnTaskEdgeType
::
EDGECONST
;
$parent_map
=
$task_graph
->
getEdges
(
$parent_type
);
$subtask_map
=
$task_graph
->
getEdges
(
$subtask_type
);
$parent_list
=
idx
(
$parent_map
,
$task
->
getPHID
(),
array
());
$subtask_list
=
idx
(
$subtask_map
,
$task
->
getPHID
(),
array
());
$has_parents
=
(
bool
)
$parent_list
;
$has_subtasks
=
(
bool
)
$subtask_list
;
// First, get a count of direct parent tasks and subtasks. If there
// are too many of these, we just don't draw anything. You can use
// the search button to browse tasks with the search UI instead.
$direct_count
=
count
(
$parent_list
)
+
count
(
$subtask_list
);
$graph_table
=
null
;
if
(
$direct_count
>
$graph_limit
)
{
$graph_error_message
=
pht
(
'This task is directly connected to more than %s other tasks. '
.
'Use %s to browse parents or subtasks, or %s to show more of the '
.
'graph.'
,
new
PhutilNumber
(
$graph_limit
),
phutil_tag
(
'strong'
,
array
(),
pht
(
'Search...'
)),
phutil_tag
(
'strong'
,
array
(),
pht
(
'View Standalone Graph'
)));
}
else
{
// If there aren't too many direct tasks, but there are too many total
// tasks, we'll only render directly connected tasks.
if
(
$task_graph
->
isOverLimit
())
{
$task_graph
->
setRenderOnlyAdjacentNodes
(
true
);
$graph_error_message
=
pht
(
'This task is connected to more than %s other tasks. '
.
'Only direct parents and subtasks are shown here. Use '
.
'%s to show more of the graph.'
,
new
PhutilNumber
(
$graph_limit
),
phutil_tag
(
'strong'
,
array
(),
pht
(
'View Standalone Graph'
)));
}
try
{
$graph_table
=
$task_graph
->
newGraphTable
();
}
catch
(
Throwable
$ex
)
{
phlog
(
$ex
);
$graph_error_message
=
pht
(
'There was an unexpected error displaying the task graph. '
.
'Use %s to browse parents or subtasks, or %s to show the graph.'
,
phutil_tag
(
'strong'
,
array
(),
pht
(
'Search...'
)),
phutil_tag
(
'strong'
,
array
(),
pht
(
'View Standalone Graph'
)));
}
}
if
(
$graph_error_message
)
{
$overflow_view
=
$this
->
newTaskGraphOverflowView
(
$task
,
$graph_error_message
,
true
);
$graph_table
=
array
(
$overflow_view
,
$graph_table
,
);
}
$graph_menu
=
$this
->
newTaskGraphDropdownMenu
(
$task
,
$has_parents
,
$has_subtasks
,
true
);
$related_tabs
[]
=
id
(
new
PHUITabView
())
->
setName
(
pht
(
'Task Graph'
))
->
setKey
(
'graph'
)
->
appendChild
(
$graph_table
);
}
$related_tabs
[]
=
$this
->
newMocksTab
(
$task
,
$query
);
$related_tabs
[]
=
$this
->
newMentionsTab
(
$task
,
$query
);
$related_tabs
[]
=
$this
->
newDuplicatesTab
(
$task
,
$query
);
$tab_view
=
null
;
$related_tabs
=
array_filter
(
$related_tabs
);
if
(
$related_tabs
)
{
$tab_group
=
new
PHUITabGroupView
();
foreach
(
$related_tabs
as
$tab
)
{
$tab_group
->
addTab
(
$tab
);
}
$related_header
=
id
(
new
PHUIHeaderView
())
->
setHeader
(
pht
(
'Related Objects'
));
if
(
$graph_menu
)
{
$related_header
->
addActionLink
(
$graph_menu
);
}
$tab_view
=
id
(
new
PHUIObjectBoxView
())
->
setHeader
(
$related_header
)
->
setBackground
(
PHUIObjectBoxView
::
BLUE_PROPERTY
)
->
addTabGroup
(
$tab_group
);
}
$changes_view
=
$this
->
newChangesView
(
$task
,
$edges
);
$view
=
id
(
new
PHUITwoColumnView
())
->
setHeader
(
$header
)
->
setCurtain
(
$curtain
)
->
setMainColumn
(
array
(
$changes_view
,
$tab_view
,
$timeline
,
$comment_view
,
))
->
addPropertySection
(
pht
(
'Description'
),
$description
)
->
addPropertySection
(
pht
(
'Details'
),
$details
);
$page
=
$this
->
newPage
()
->
setTitle
(
$title
)
->
setCrumbs
(
$crumbs
)
->
setPageObjectPHIDs
(
array
(
$task
->
getPHID
(),
))
->
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
)
{
$view
=
id
(
new
PHUIHeaderView
())
->
setHeader
(
$task
->
getTitle
())
->
setUser
(
$this
->
getRequest
()->
getUser
())
->
setPolicyObject
(
$task
);
$priority_name
=
ManiphestTaskPriority
::
getTaskPriorityName
(
$task
->
getPriority
());
$priority_color
=
ManiphestTaskPriority
::
getTaskPriorityColor
(
$task
->
getPriority
());
$status
=
$task
->
getStatus
();
$status_name
=
ManiphestTaskStatus
::
renderFullDescription
(
$status
,
$priority_name
);
$view
->
addProperty
(
PHUIHeaderView
::
PROPERTY_STATUS
,
$status_name
);
$view
->
setHeaderIcon
(
ManiphestTaskStatus
::
getStatusIcon
(
$task
->
getStatus
()).
' '
.
$priority_color
);
if
(
ManiphestTaskPoints
::
getIsEnabled
())
{
$points
=
$task
->
getPoints
();
if
(
$points
!==
null
)
{
$points_name
=
pht
(
'%s %s'
,
$task
->
getPoints
(),
ManiphestTaskPoints
::
getPointsLabel
());
$tag
=
id
(
new
PHUITagView
())
->
setName
(
$points_name
)
->
setColor
(
PHUITagView
::
COLOR_BLUE
)
->
setType
(
PHUITagView
::
TYPE_SHADE
);
$view
->
addTag
(
$tag
);
}
}
$subtype
=
$task
->
newSubtypeObject
();
if
(
$subtype
&&
$subtype
->
hasTagView
())
{
$subtype_tag
=
$subtype
->
newTagView
();
$view
->
addTag
(
$subtype_tag
);
}
return
$view
;
}
private
function
buildCurtain
(
ManiphestTask
$task
,
PhabricatorEditEngine
$edit_engine
)
{
$viewer
=
$this
->
getViewer
();
$id
=
$task
->
getID
();
$phid
=
$task
->
getPHID
();
$can_edit
=
PhabricatorPolicyFilter
::
hasCapability
(
$viewer
,
$task
,
PhabricatorPolicyCapability
::
CAN_EDIT
);
$can_interact
=
PhabricatorPolicyFilter
::
canInteract
(
$viewer
,
$task
);
// We expect a policy dialog if you can't edit the task, and expect a
// lock override dialog if you can't interact with it.
$workflow_edit
=
(!
$can_edit
||
!
$can_interact
);
$curtain
=
$this
->
newCurtainView
(
$task
);
$curtain
->
addAction
(
id
(
new
PhabricatorActionView
())
->
setName
(
pht
(
'Edit Task'
))
->
setIcon
(
'fa-pencil'
)
->
setHref
(
$this
->
getApplicationURI
(
"/task/edit/{$id}/"
))
->
setDisabled
(!
$can_edit
)
->
setWorkflow
(
$workflow_edit
));
$subtype_map
=
$task
->
newEditEngineSubtypeMap
();
$subtask_options
=
$subtype_map
->
getCreateFormsForSubtype
(
$edit_engine
,
$task
);
// If no forms are available, we want to show the user an error.
// If one form is available, we take them user directly to the form.
// If two or more forms are available, we give the user a choice.
// The "subtask" controller handles the first case (no forms) and the
// third case (more than one form). In the case of one form, we link
// directly to the form.
$subtask_uri
=
"/task/subtask/{$id}/"
;
$subtask_workflow
=
true
;
if
(
count
(
$subtask_options
)
==
1
)
{
$subtask_form
=
head
(
$subtask_options
);
$form_key
=
$subtask_form
->
getIdentifier
();
$subtask_uri
=
id
(
new
PhutilURI
(
"/task/edit/form/{$form_key}/"
))
->
replaceQueryParam
(
'parent'
,
$id
)
->
replaceQueryParam
(
'template'
,
$id
)
->
replaceQueryParam
(
'status'
,
ManiphestTaskStatus
::
getDefaultStatus
());
$subtask_workflow
=
false
;
}
$subtask_uri
=
$this
->
getApplicationURI
(
$subtask_uri
);
$subtask_item
=
id
(
new
PhabricatorActionView
())
->
setName
(
pht
(
'Create Subtask'
))
->
setHref
(
$subtask_uri
)
->
setIcon
(
'fa-level-down'
)
->
setDisabled
(!
$subtask_options
)
->
setWorkflow
(
$subtask_workflow
);
$relationship_list
=
PhabricatorObjectRelationshipList
::
newForObject
(
$viewer
,
$task
);
$submenu_actions
=
array
(
$subtask_item
,
ManiphestTaskHasParentRelationship
::
RELATIONSHIPKEY
,
ManiphestTaskHasSubtaskRelationship
::
RELATIONSHIPKEY
,
ManiphestTaskMergeInRelationship
::
RELATIONSHIPKEY
,
ManiphestTaskCloseAsDuplicateRelationship
::
RELATIONSHIPKEY
,
);
$task_submenu
=
$relationship_list
->
newActionSubmenu
(
$submenu_actions
)
->
setName
(
pht
(
'Edit Related Tasks...'
))
->
setIcon
(
'fa-anchor'
);
$curtain
->
addAction
(
$task_submenu
);
$relationship_submenu
=
$relationship_list
->
newActionMenu
();
if
(
$relationship_submenu
)
{
$curtain
->
addAction
(
$relationship_submenu
);
}
$viewer_phid
=
$viewer
->
getPHID
();
$owner_phid
=
$task
->
getOwnerPHID
();
$author_phid
=
$task
->
getAuthorPHID
();
$handles
=
$viewer
->
loadHandles
(
array
(
$owner_phid
,
$author_phid
));
$assigned_refs
=
id
(
new
PHUICurtainObjectRefListView
())
->
setViewer
(
$viewer
)
->
setEmptyMessage
(
pht
(
'None'
));
if
(
$owner_phid
)
{
$assigned_ref
=
$assigned_refs
->
newObjectRefView
()
->
setHandle
(
$handles
[
$owner_phid
])
->
setHighlighted
(
$owner_phid
===
$viewer_phid
);
}
$curtain
->
newPanel
()
->
setHeaderText
(
pht
(
'Assigned To'
))
->
appendChild
(
$assigned_refs
);
$author_refs
=
id
(
new
PHUICurtainObjectRefListView
())
->
setViewer
(
$viewer
);
$author_ref
=
$author_refs
->
newObjectRefView
()
->
setHandle
(
$handles
[
$author_phid
])
->
setEpoch
(
$task
->
getDateCreated
())
->
setHighlighted
(
$author_phid
===
$viewer_phid
);
$curtain
->
newPanel
()
->
setHeaderText
(
pht
(
'Authored By'
))
->
appendChild
(
$author_refs
);
return
$curtain
;
}
private
function
buildPropertyView
(
ManiphestTask
$task
,
PhabricatorCustomFieldList
$field_list
,
array
$edges
,
$handles
)
{
$viewer
=
$this
->
getRequest
()->
getUser
();
$view
=
id
(
new
PHUIPropertyListView
())
->
setUser
(
$viewer
);
$source
=
$task
->
getOriginalEmailSource
();
if
(
$source
)
{
$subject
=
'[T'
.
$task
->
getID
().
'] '
.
$task
->
getTitle
();
$view
->
addProperty
(
pht
(
'From Email'
),
phutil_tag
(
'a'
,
array
(
'href'
=>
'mailto:'
.
$source
.
'?subject='
.
$subject
,
),
$source
));
}
$field_list
->
appendFieldsToPropertyList
(
$task
,
$viewer
,
$view
);
if
(
$view
->
hasAnyProperties
())
{
return
$view
;
}
return
null
;
}
private
function
buildDescriptionView
(
ManiphestTask
$task
)
{
$viewer
=
$this
->
getViewer
();
$section
=
null
;
$description
=
$task
->
getDescription
();
if
(
strlen
(
$description
))
{
$section
=
new
PHUIPropertyListView
();
$section
->
addTextContent
(
phutil_tag
(
'div'
,
array
(
'class'
=>
'phabricator-remarkup'
,
),
id
(
new
PHUIRemarkupView
(
$viewer
,
$description
))
->
setContextObject
(
$task
)));
}
return
$section
;
}
private
function
newMocksTab
(
ManiphestTask
$task
,
PhabricatorEdgeQuery
$edge_query
)
{
$mock_type
=
ManiphestTaskHasMockEdgeType
::
EDGECONST
;
$mock_phids
=
$edge_query
->
getDestinationPHIDs
(
array
(),
array
(
$mock_type
));
if
(!
$mock_phids
)
{
return
null
;
}
$viewer
=
$this
->
getViewer
();
$handles
=
$viewer
->
loadHandles
(
$mock_phids
);
// TODO: It would be nice to render this as pinboard-style thumbnails,
// similar to "{M123}", instead of a list of links.
$view
=
id
(
new
PHUIPropertyListView
())
->
addProperty
(
pht
(
'Mocks'
),
$handles
->
renderList
());
return
id
(
new
PHUITabView
())
->
setName
(
pht
(
'Mocks'
))
->
setKey
(
'mocks'
)
->
appendChild
(
$view
);
}
private
function
newMentionsTab
(
ManiphestTask
$task
,
PhabricatorEdgeQuery
$edge_query
)
{
$in_type
=
PhabricatorObjectMentionedByObjectEdgeType
::
EDGECONST
;
$out_type
=
PhabricatorObjectMentionsObjectEdgeType
::
EDGECONST
;
$in_phids
=
$edge_query
->
getDestinationPHIDs
(
array
(),
array
(
$in_type
));
$out_phids
=
$edge_query
->
getDestinationPHIDs
(
array
(),
array
(
$out_type
));
// Filter out any mentioned users from the list. These are not generally
// very interesting to show in a relationship summary since they usually
// end up as subscribers anyway.
$user_type
=
PhabricatorPeopleUserPHIDType
::
TYPECONST
;
foreach
(
$out_phids
as
$key
=>
$out_phid
)
{
if
(
phid_get_type
(
$out_phid
)
==
$user_type
)
{
unset
(
$out_phids
[
$key
]);
}
}
if
(!
$in_phids
&&
!
$out_phids
)
{
return
null
;
}
$viewer
=
$this
->
getViewer
();
$in_handles
=
$viewer
->
loadHandles
(
$in_phids
);
$out_handles
=
$viewer
->
loadHandles
(
$out_phids
);
$in_handles
=
$this
->
getCompleteHandles
(
$in_handles
);
$out_handles
=
$this
->
getCompleteHandles
(
$out_handles
);
if
(!
count
(
$in_handles
)
&&
!
count
(
$out_handles
))
{
return
null
;
}
$view
=
new
PHUIPropertyListView
();
if
(
count
(
$in_handles
))
{
$view
->
addProperty
(
pht
(
'Mentioned In'
),
$in_handles
->
renderList
());
}
if
(
count
(
$out_handles
))
{
$view
->
addProperty
(
pht
(
'Mentioned Here'
),
$out_handles
->
renderList
());
}
return
id
(
new
PHUITabView
())
->
setName
(
pht
(
'Mentions'
))
->
setKey
(
'mentions'
)
->
appendChild
(
$view
);
}
private
function
newDuplicatesTab
(
ManiphestTask
$task
,
PhabricatorEdgeQuery
$edge_query
)
{
$in_type
=
ManiphestTaskHasDuplicateTaskEdgeType
::
EDGECONST
;
$in_phids
=
$edge_query
->
getDestinationPHIDs
(
array
(),
array
(
$in_type
));
$viewer
=
$this
->
getViewer
();
$in_handles
=
$viewer
->
loadHandles
(
$in_phids
);
$in_handles
=
$this
->
getCompleteHandles
(
$in_handles
);
$view
=
new
PHUIPropertyListView
();
if
(!
count
(
$in_handles
))
{
return
null
;
}
$view
->
addProperty
(
pht
(
'Duplicates Merged Here'
),
$in_handles
->
renderList
());
return
id
(
new
PHUITabView
())
->
setName
(
pht
(
'Duplicates'
))
->
setKey
(
'duplicates'
)
->
appendChild
(
$view
);
}
private
function
getCompleteHandles
(
PhabricatorHandleList
$handles
)
{
$phids
=
array
();
foreach
(
$handles
as
$phid
=>
$handle
)
{
if
(!
$handle
->
isComplete
())
{
continue
;
}
$phids
[]
=
$phid
;
}
return
$handles
->
newSublist
(
$phids
);
}
private
function
newChangesView
(
ManiphestTask
$task
,
array
$edges
)
{
$viewer
=
$this
->
getViewer
();
$revision_type
=
ManiphestTaskHasRevisionEdgeType
::
EDGECONST
;
$commit_type
=
ManiphestTaskHasCommitEdgeType
::
EDGECONST
;
$revision_phids
=
idx
(
$edges
,
$revision_type
,
array
());
$revision_phids
=
array_keys
(
$revision_phids
);
$revision_phids
=
array_fuse
(
$revision_phids
);
$commit_phids
=
idx
(
$edges
,
$commit_type
,
array
());
$commit_phids
=
array_keys
(
$commit_phids
);
$commit_phids
=
array_fuse
(
$commit_phids
);
if
(!
$revision_phids
&&
!
$commit_phids
)
{
return
null
;
}
if
(
$commit_phids
)
{
$link_type
=
DiffusionCommitHasRevisionEdgeType
::
EDGECONST
;
$link_query
=
id
(
new
PhabricatorEdgeQuery
())
->
withSourcePHIDs
(
$commit_phids
)
->
withEdgeTypes
(
array
(
$link_type
));
$link_query
->
execute
();
$commits
=
id
(
new
DiffusionCommitQuery
())
->
setViewer
(
$viewer
)
->
withPHIDs
(
$commit_phids
)
->
execute
();
$commits
=
mpull
(
$commits
,
null
,
'getPHID'
);
}
else
{
$commits
=
array
();
}
if
(
$revision_phids
)
{
$revisions
=
id
(
new
DifferentialRevisionQuery
())
->
setViewer
(
$viewer
)
->
withPHIDs
(
$revision_phids
)
->
execute
();
$revisions
=
mpull
(
$revisions
,
null
,
'getPHID'
);
}
else
{
$revisions
=
array
();
}
$handle_phids
=
array
();
$any_linked
=
false
;
$any_status
=
false
;
$idx
=
0
;
$objects
=
array
();
foreach
(
$commit_phids
as
$commit_phid
)
{
$handle_phids
[]
=
$commit_phid
;
$link_phids
=
$link_query
->
getDestinationPHIDs
(
array
(
$commit_phid
));
foreach
(
$link_phids
as
$link_phid
)
{
$handle_phids
[]
=
$link_phid
;
unset
(
$revision_phids
[
$link_phid
]);
$any_linked
=
true
;
}
$commit
=
idx
(
$commits
,
$commit_phid
);
if
(
$commit
)
{
$repository_phid
=
$commit
->
getRepository
()->
getPHID
();
$handle_phids
[]
=
$repository_phid
;
}
else
{
$repository_phid
=
null
;
}
$status_view
=
null
;
if
(
$commit
)
{
$status
=
$commit
->
getAuditStatusObject
();
if
(!
$status
->
isNoAudit
())
{
$status_view
=
id
(
new
PHUITagView
())
->
setType
(
PHUITagView
::
TYPE_SHADE
)
->
setIcon
(
$status
->
getIcon
())
->
setColor
(
$status
->
getColor
())
->
setName
(
$status
->
getName
());
}
}
$object_link
=
null
;
if
(
$commit
)
{
$commit_monogram
=
$commit
->
getDisplayName
();
$commit_monogram
=
phutil_tag
(
'span'
,
array
(
'class'
=>
'object-name'
,
),
$commit_monogram
);
$commit_link
=
javelin_tag
(
'a'
,
array
(
'href'
=>
$commit
->
getURI
(),
'sigil'
=>
'hovercard'
,
'meta'
=>
array
(
'hovercardSpec'
=>
array
(
'objectPHID'
=>
$commit
->
getPHID
(),
),
),
),
$commit
->
getSummary
());
$object_link
=
array
(
$commit_monogram
,
' '
,
$commit_link
,
);
}
$objects
[]
=
array
(
'objectPHID'
=>
$commit_phid
,
'objectLink'
=>
$object_link
,
'repositoryPHID'
=>
$repository_phid
,
'revisionPHIDs'
=>
$link_phids
,
'status'
=>
$status_view
,
'order'
=>
id
(
new
PhutilSortVector
())
->
addInt
(
$repository_phid
?
1
:
0
)
->
addString
((
string
)
$repository_phid
)
->
addInt
(
1
)
->
addInt
(
$idx
++),
);
}
foreach
(
$revision_phids
as
$revision_phid
)
{
$handle_phids
[]
=
$revision_phid
;
$revision
=
idx
(
$revisions
,
$revision_phid
);
if
(
$revision
)
{
$repository_phid
=
$revision
->
getRepositoryPHID
();
$handle_phids
[]
=
$repository_phid
;
}
else
{
$repository_phid
=
null
;
}
if
(
$revision
)
{
$icon
=
$revision
->
getStatusIcon
();
$color
=
$revision
->
getStatusIconColor
();
$name
=
$revision
->
getStatusDisplayName
();
$status_view
=
id
(
new
PHUITagView
())
->
setType
(
PHUITagView
::
TYPE_SHADE
)
->
setIcon
(
$icon
)
->
setColor
(
$color
)
->
setName
(
$name
);
}
else
{
$status_view
=
null
;
}
$object_link
=
null
;
if
(
$revision
)
{
$revision_monogram
=
$revision
->
getMonogram
();
$revision_monogram
=
phutil_tag
(
'span'
,
array
(
'class'
=>
'object-name'
,
),
$revision_monogram
);
$revision_link
=
javelin_tag
(
'a'
,
array
(
'href'
=>
$revision
->
getURI
(),
'sigil'
=>
'hovercard'
,
'meta'
=>
array
(
'hovercardSpec'
=>
array
(
'objectPHID'
=>
$revision
->
getPHID
(),
),
),
),
$revision
->
getTitle
());
$object_link
=
array
(
$revision_monogram
,
' '
,
$revision_link
,
);
}
$objects
[]
=
array
(
'objectPHID'
=>
$revision_phid
,
'objectLink'
=>
$object_link
,
'repositoryPHID'
=>
$repository_phid
,
'revisionPHIDs'
=>
array
(),
'status'
=>
$status_view
,
'order'
=>
id
(
new
PhutilSortVector
())
->
addInt
(
$repository_phid
?
1
:
0
)
->
addString
((
string
)
$repository_phid
)
->
addInt
(
0
)
->
addInt
(
$idx
++),
);
}
$handles
=
$viewer
->
loadHandles
(
$handle_phids
);
$order
=
ipull
(
$objects
,
'order'
);
$order
=
msortv
(
$order
,
'getSelf'
);
$objects
=
array_select_keys
(
$objects
,
array_keys
(
$order
));
$last_repository
=
false
;
$rows
=
array
();
$rowd
=
array
();
foreach
(
$objects
as
$object
)
{
$repository_phid
=
$object
[
'repositoryPHID'
];
if
(
$repository_phid
!==
$last_repository
)
{
$repository_link
=
null
;
if
(
$repository_phid
)
{
$repository_handle
=
$handles
[
$repository_phid
];
$rows
[]
=
array
(
$repository_handle
->
renderLink
(),
);
$rowd
[]
=
true
;
}
$last_repository
=
$repository_phid
;
}
$object_phid
=
$object
[
'objectPHID'
];
$handle
=
$handles
[
$object_phid
];
$object_link
=
$object
[
'objectLink'
];
if
(
$object_link
===
null
)
{
$object_link
=
$handle
->
renderLink
();
}
$object_icon
=
id
(
new
PHUIIconView
())
->
setIcon
(
$handle
->
getIcon
());
$status_view
=
$object
[
'status'
];
if
(
$status_view
)
{
$any_status
=
true
;
}
$revision_tags
=
array
();
foreach
(
$object
[
'revisionPHIDs'
]
as
$link_phid
)
{
$revision_handle
=
$handles
[
$link_phid
];
$revision_name
=
$revision_handle
->
getName
();
$revision_tags
[]
=
$revision_handle
->
renderHovercardLink
(
$revision_name
);
}
$revision_tags
=
phutil_implode_html
(
phutil_tag
(
'br'
),
$revision_tags
);
$rowd
[]
=
false
;
$rows
[]
=
array
(
$object_icon
,
$status_view
,
$revision_tags
,
$object_link
,
);
}
$changes_table
=
id
(
new
AphrontTableView
(
$rows
))
->
setNoDataString
(
pht
(
'This task has no related commits or revisions.'
))
->
setRowDividers
(
$rowd
)
->
setColumnClasses
(
array
(
'indent center'
,
null
,
null
,
'wide pri object-link'
,
))
->
setColumnVisibility
(
array
(
true
,
$any_status
,
$any_linked
,
true
,
))
->
setDeviceVisibility
(
array
(
false
,
$any_status
,
false
,
true
,
));
$changes_header
=
id
(
new
PHUIHeaderView
())
->
setHeader
(
pht
(
'Revisions and Commits'
));
$changes_view
=
id
(
new
PHUIObjectBoxView
())
->
setHeader
(
$changes_header
)
->
setBackground
(
PHUIObjectBoxView
::
BLUE_PROPERTY
)
->
setTable
(
$changes_table
);
return
$changes_view
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Mon, May 12, 1:10 PM (1 d, 23 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
121062
Default Alt Text
ManiphestTaskDetailController.php (26 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment