Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F101560328
ManiphestBatchEditController.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Feb 11, 14:13
Size
8 KB
Mime Type
text/x-php
Expires
Thu, Feb 13, 14:13 (2 d)
Engine
blob
Format
Raw Data
Handle
24166630
Attached To
rPH Phabricator
ManiphestBatchEditController.php
View Options
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @group maniphest
*/
final
class
ManiphestBatchEditController
extends
ManiphestController
{
public
function
processRequest
()
{
$request
=
$this
->
getRequest
();
$user
=
$request
->
getUser
();
$task_ids
=
$request
->
getArr
(
'batch'
);
$tasks
=
id
(
new
ManiphestTask
())->
loadAllWhere
(
'id IN (%Ld)'
,
$task_ids
);
$actions
=
$request
->
getStr
(
'actions'
);
if
(
$actions
)
{
$actions
=
json_decode
(
$actions
,
true
);
}
if
(
$request
->
isFormPost
()
&&
is_array
(
$actions
))
{
foreach
(
$tasks
as
$task
)
{
$xactions
=
$this
->
buildTransactions
(
$actions
,
$task
);
if
(
$xactions
)
{
$editor
=
new
ManiphestTransactionEditor
();
$editor
->
applyTransactions
(
$task
,
$xactions
);
}
}
$task_ids
=
implode
(
','
,
mpull
(
$tasks
,
'getID'
));
return
id
(
new
AphrontRedirectResponse
())
->
setURI
(
'/maniphest/view/custom/?s=oc&tasks='
.
$task_ids
);
}
$panel
=
new
AphrontPanelView
();
$panel
->
setHeader
(
'Maniphest Batch Editor'
);
$handle_phids
=
mpull
(
$tasks
,
'getOwnerPHID'
);
$handles
=
id
(
new
PhabricatorObjectHandleData
(
$handle_phids
))
->
loadHandles
();
$list
=
new
ManiphestTaskListView
();
$list
->
setTasks
(
$tasks
);
$list
->
setUser
(
$user
);
$list
->
setHandles
(
$handles
);
$template
=
new
AphrontTokenizerTemplateView
();
$template
=
$template
->
render
();
require_celerity_resource
(
'maniphest-batch-editor'
);
Javelin
::
initBehavior
(
'maniphest-batch-editor'
,
array
(
'root'
=>
'maniphest-batch-edit-form'
,
'tokenizerTemplate'
=>
$template
,
'sources'
=>
array
(
'project'
=>
array
(
'src'
=>
'/typeahead/common/projects/'
,
'placeholder'
=>
'Type a project name...'
,
),
'owner'
=>
array
(
'src'
=>
'/typeahead/common/searchowner/'
,
'placeholder'
=>
'Type a user name...'
,
'limit'
=>
1
,
),
),
'input'
=>
'batch-form-actions'
,
'priorityMap'
=>
ManiphestTaskPriority
::
getTaskPriorityMap
(),
'statusMap'
=>
ManiphestTaskStatus
::
getTaskStatusMap
(),
));
$form
=
new
AphrontFormView
();
$form
->
setUser
(
$user
);
$form
->
setID
(
'maniphest-batch-edit-form'
);
foreach
(
$tasks
as
$task
)
{
$form
->
appendChild
(
phutil_render_tag
(
'input'
,
array
(
'type'
=>
'hidden'
,
'name'
=>
'batch[]'
,
'value'
=>
$task
->
getID
(),
),
null
));
}
$form
->
appendChild
(
phutil_render_tag
(
'input'
,
array
(
'type'
=>
'hidden'
,
'name'
=>
'actions'
,
'id'
=>
'batch-form-actions'
,
),
null
));
$form
->
appendChild
(
'<p>These tasks will be edited:</p>'
);
$form
->
appendChild
(
$list
);
$form
->
appendChild
(
id
(
new
AphrontFormInsetView
())
->
setTitle
(
'Actions'
)
->
setRightButton
(
javelin_render_tag
(
'a'
,
array
(
'href'
=>
'#'
,
'class'
=>
'button green'
,
'sigil'
=>
'add-action'
,
'mustcapture'
=>
true
,
),
'Add Another Action'
))
->
setContent
(
javelin_render_tag
(
'table'
,
array
(
'sigil'
=>
'maniphest-batch-actions'
,
'class'
=>
'maniphest-batch-actions-table'
,
),
''
)))
->
appendChild
(
id
(
new
AphrontFormSubmitControl
())
->
setValue
(
'Update Tasks'
)
->
addCancelButton
(
'/maniphest/'
,
'Done'
));
$panel
->
appendChild
(
$form
);
return
$this
->
buildStandardPageResponse
(
$panel
,
array
(
'title'
=>
'Batch Editor'
,
));
}
private
function
buildTransactions
(
$actions
,
ManiphestTask
$task
)
{
$value_map
=
array
();
$type_map
=
array
(
'add_comment'
=>
ManiphestTransactionType
::
TYPE_NONE
,
'assign'
=>
ManiphestTransactionType
::
TYPE_OWNER
,
'status'
=>
ManiphestTransactionType
::
TYPE_STATUS
,
'priority'
=>
ManiphestTransactionType
::
TYPE_PRIORITY
,
'add_project'
=>
ManiphestTransactionType
::
TYPE_PROJECTS
,
'remove_project'
=>
ManiphestTransactionType
::
TYPE_PROJECTS
,
);
$xactions
=
array
();
foreach
(
$actions
as
$action
)
{
if
(
empty
(
$type_map
[
$action
[
'action'
]]))
{
throw
new
Exception
(
"Unknown batch edit action '{$action}'!"
);
}
$type
=
$type_map
[
$action
[
'action'
]];
// Figure out the current value, possibly after modifications by other
// batch actions of the same type. For example, if the user chooses to
// "Add Comment" twice, we should add both comments. More notably, if the
// user chooses "Remove Project..." and also "Add Project...", we should
// avoid restoring the removed project in the second transaction.
if
(
array_key_exists
(
$type
,
$value_map
))
{
$current
=
$value_map
[
$type
];
}
else
{
switch
(
$type
)
{
case
ManiphestTransactionType
::
TYPE_NONE
:
$current
=
null
;
break
;
case
ManiphestTransactionType
::
TYPE_OWNER
:
$current
=
$task
->
getOwnerPHID
();
break
;
case
ManiphestTransactionType
::
TYPE_STATUS
:
$current
=
$task
->
getStatus
();
break
;
case
ManiphestTransactionType
::
TYPE_PRIORITY
:
$current
=
$task
->
getPriority
();
break
;
case
ManiphestTransactionType
::
TYPE_PROJECTS
:
$current
=
$task
->
getProjectPHIDs
();
break
;
}
}
// Check if the value is meaningful / provided, and normalize it if
// necessary. This discards, e.g., empty comments and empty owner
// changes.
$value
=
$action
[
'value'
];
switch
(
$type
)
{
case
ManiphestTransactionType
::
TYPE_NONE
:
if
(!
strlen
(
$value
))
{
continue
2
;
}
break
;
case
ManiphestTransactionType
::
TYPE_OWNER
:
if
(
empty
(
$value
))
{
continue
2
;
}
$value
=
head
(
$value
);
if
(
$value
===
ManiphestTaskOwner
::
OWNER_UP_FOR_GRABS
)
{
$value
=
null
;
}
break
;
case
ManiphestTransactionType
::
TYPE_PROJECTS
:
if
(
empty
(
$value
))
{
continue
2
;
}
break
;
}
// If the edit doesn't change anything, go to the next action.
if
(
$value
==
$current
)
{
continue
;
}
// Apply the value change; for most edits this is just replacement, but
// some need to merge the current and edited values (add/remove project).
switch
(
$type
)
{
case
ManiphestTransactionType
::
TYPE_NONE
:
if
(
strlen
(
$current
))
{
$value
=
$current
.
"
\n\n
"
.
$value
;
}
break
;
case
ManiphestTransactionType
::
TYPE_PROJECTS
:
$is_remove
=
(
$action
[
'action'
]
==
'remove_project'
);
$current
=
array_fill_keys
(
$current
,
true
);
$value
=
array_fill_keys
(
$value
,
true
);
$new
=
$current
;
$did_something
=
false
;
if
(
$is_remove
)
{
foreach
(
$value
as
$phid
=>
$ignored
)
{
if
(
isset
(
$new
[
$phid
]))
{
unset
(
$new
[
$phid
]);
$did_something
=
true
;
}
}
}
else
{
foreach
(
$value
as
$phid
=>
$ignored
)
{
if
(
empty
(
$new
[
$phid
]))
{
$new
[
$phid
]
=
true
;
$did_something
=
true
;
}
}
}
if
(!
$did_something
)
{
continue
2
;
}
$value
=
array_keys
(
$new
);
break
;
}
$value_map
[
$type
]
=
$value
;
}
$template
=
new
ManiphestTransaction
();
$template
->
setAuthorPHID
(
$this
->
getRequest
()->
getUser
()->
getPHID
());
// TODO: Set content source to "batch edit".
foreach
(
$value_map
as
$type
=>
$value
)
{
$xaction
=
clone
$template
;
$xaction
->
setTransactionType
(
$type
);
switch
(
$type
)
{
case
ManiphestTransactionType
::
TYPE_NONE
:
$xaction
->
setComments
(
$value
);
break
;
default
:
$xaction
->
setNewValue
(
$value
);
break
;
}
$xactions
[]
=
$xaction
;
}
return
$xactions
;
}
}
Event Timeline
Log In to Comment