2018-03-14 21:21:54 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Colymba\BulkTools;
|
|
|
|
|
|
|
|
use SilverStripe\Control\HTTPResponse;
|
|
|
|
use SilverStripe\Core\Convert;
|
2018-08-16 14:37:19 +02:00
|
|
|
use SilverStripe\Forms\GridField\GridField;
|
2018-03-14 21:21:54 +01:00
|
|
|
use SilverStripe\ORM\ArrayList;
|
2018-08-16 14:37:19 +02:00
|
|
|
use SilverStripe\ORM\DataObject;
|
2018-03-14 21:21:54 +01:00
|
|
|
use SilverStripe\ORM\SS_List;
|
|
|
|
use SilverStripe\View\HTML;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Custom HTTPResponse for all bulk tools to use
|
|
|
|
* for a unified response format and facilitate forn-end handling
|
|
|
|
*
|
|
|
|
* Add custom methods and tool to create a common json output format:
|
|
|
|
* {
|
|
|
|
* isDestructive: false,
|
|
|
|
* isError: false,
|
|
|
|
* isWarning: false,
|
|
|
|
* message: "General response error or not message for the cms user",
|
|
|
|
* successClasses: ['list', 'of-new', 'classes', 'to-add', 'bt-done'],
|
|
|
|
* failedClasses: ['list', 'of-new', 'classes', 'to-add', 'bt-done']
|
|
|
|
* records: {
|
|
|
|
* success: [{
|
|
|
|
* id: 1,
|
|
|
|
* class: 'ObjectClass',
|
|
|
|
* row: 'tr .ss-gridfield-item html markup for this record'
|
|
|
|
* }],
|
|
|
|
* failed: [{
|
|
|
|
* id: 2,
|
|
|
|
* class: 'AnotherClass',
|
|
|
|
* message: 'Erro message for that object.'
|
|
|
|
* }]
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* @author colymba
|
|
|
|
*/
|
|
|
|
class HTTPBulkToolsResponse extends HTTPResponse
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* We always return JSON
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $headers = array(
|
|
|
|
"content-type" => "application/json; charset=utf-8",
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Does the bulk action removes rows?
|
|
|
|
*
|
|
|
|
* @var boolean
|
|
|
|
*/
|
|
|
|
protected $removesRows;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Bulk action result message
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
protected $message = '';
|
|
|
|
|
|
|
|
/**
|
2018-08-16 14:37:19 +02:00
|
|
|
* GridField instance.
|
2018-03-14 21:21:54 +01:00
|
|
|
*
|
|
|
|
* @var GridField
|
|
|
|
*/
|
|
|
|
protected $gridField;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List of DataObject that has been modified successfully by the bulk action
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $successRecords = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List of css classes to add to gridfield row modified successfully
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $successClasses = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List of DataObject IDs that failed to be modified by the bulk action
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $failedRecords = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* List of css classes to add to gridfield row with errors
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $failedClasses = [];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a new bulk tools HTTP response
|
|
|
|
*
|
|
|
|
* @param boolean $removesRows Does the action removes rows?
|
2018-08-16 14:37:19 +02:00
|
|
|
* @param GridField $gridfield gridfield instance that holds the records list
|
2018-03-14 21:21:54 +01:00
|
|
|
* @param int $statusCode The numeric status code - 200, 404, etc
|
|
|
|
* @param string $statusDescription The text to be given alongside the status code.
|
|
|
|
* See {@link setStatusCode()} for more information.
|
|
|
|
*/
|
|
|
|
public function __construct($removesRows, $gridfield, $statusCode = null)
|
|
|
|
{
|
|
|
|
$this->removesRows = $removesRows;
|
2018-08-16 14:37:19 +02:00
|
|
|
$this->gridField = $gridfield;
|
2018-03-14 21:21:54 +01:00
|
|
|
|
2018-03-14 21:44:41 +01:00
|
|
|
parent::__construct(null, $statusCode);
|
2018-03-14 21:21:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-08-16 14:37:19 +02:00
|
|
|
* Overridden here so content-type cannot be changed
|
2018-03-14 21:21:54 +01:00
|
|
|
* Add a HTTP header to the response, replacing any header of the same name.
|
|
|
|
*
|
|
|
|
* @param string $header Example: "content-type"
|
|
|
|
* @param string $value Example: "text/xml"
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function addHeader($header, $value)
|
|
|
|
{
|
|
|
|
if($header === "content-type") {
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
return parent::addHeader($header, $value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Overriden here so content-type cannot be changed
|
|
|
|
* Remove an existing HTTP header by its name,
|
|
|
|
* e.g. "Content-Type".
|
|
|
|
*
|
|
|
|
* @param string $header
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function removeHeader($header)
|
|
|
|
{
|
|
|
|
if($header === "content-type") {
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
return parent::removeHeader($header);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-08-16 14:37:19 +02:00
|
|
|
* Overridden here so the response body cannot be set manually
|
|
|
|
*
|
|
|
|
* @param string $body
|
2018-03-14 21:21:54 +01:00
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setBody($body)
|
|
|
|
{
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Makes sure body is created before being returned
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getBody()
|
|
|
|
{
|
|
|
|
$this->createBody();
|
|
|
|
return $this->body;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the general response message
|
2018-08-16 14:37:19 +02:00
|
|
|
*
|
|
|
|
* @param string $message
|
2018-03-14 21:21:54 +01:00
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function setMessage($message)
|
|
|
|
{
|
|
|
|
$this->message = $message;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a record to the successfully modified list
|
|
|
|
* @param DataObject $record the newly modified dataObject
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function addSuccessRecord($record)
|
|
|
|
{
|
|
|
|
$this->successRecords[] = $record;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a list of records to the successfully modified list
|
|
|
|
* @param SS_List $records newly modified dataObjects list
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function addSuccessRecords(SS_List $records)
|
|
|
|
{
|
|
|
|
array_push($this->successRecords, $records->toArray());
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an ID to the successfully modified list
|
2018-08-16 14:37:19 +02:00
|
|
|
* @param int $id the newly modified ID
|
2018-03-14 21:21:54 +01:00
|
|
|
* @param string $className object class name (default to gridfield getModelClass())
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
/*public function addSuccessID($id, $className = null)
|
|
|
|
{
|
|
|
|
if (!$className) {
|
2018-08-16 14:37:19 +02:00
|
|
|
$className = $this->>gridField->getModelClass();
|
2018-03-14 21:21:54 +01:00
|
|
|
}
|
|
|
|
//we use all caps ID since DO have their ID ion all caps, so createBody finds it...
|
|
|
|
$this->successRecords[] = (object) ['ID' => (int) $id, 'ClassName' => $className];
|
|
|
|
return $this;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add an array of ID to the successfully modified list
|
|
|
|
* @param array $ids of the newly modified objects
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
/*public function addSuccessIDs($ids, $className = null)
|
|
|
|
{
|
|
|
|
//we use all caps ID since DO have their ID ion all caps, so createBody finds it...
|
|
|
|
foreach ($ids as $id) {
|
|
|
|
$this->successRecords[] = (object) ['ID' => (int) $id];
|
|
|
|
}
|
|
|
|
return $this;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
/**
|
2018-08-16 14:37:19 +02:00
|
|
|
* Return the list of successful records
|
2018-03-14 21:21:54 +01:00
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getSuccessRecords()
|
|
|
|
{
|
|
|
|
return $this->successRecords;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a record to the failed to modified list with its error message
|
|
|
|
* @param DataObject $record the failed dataObject
|
|
|
|
* @param string $message error message
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function addFailedRecord($record, $message)
|
|
|
|
{
|
|
|
|
$this->failedRecords[] = array('id' => $record->ID, 'class' => $record->ClassName, 'message' => $message);
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a list of records to the failed to modified list with a common error message
|
|
|
|
* @param SS_List $records the failed dataObject list
|
|
|
|
* @param string $message error message
|
|
|
|
* @return $this
|
|
|
|
*/
|
|
|
|
public function addFailedRecords(SS_List $records, $message)
|
|
|
|
{
|
|
|
|
foreach ($records as $record) {
|
|
|
|
$this->failedRecords[] = array('id' => $record->ID, 'class' => $record->ClassName, 'message' => $message);
|
|
|
|
}
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the list of failed records
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getFailedRecords()
|
|
|
|
{
|
|
|
|
return $this->failedRecords;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a gridfield table row for a given record
|
|
|
|
* @param DataObject $record the record to create the row for
|
|
|
|
* @return string the html TR tag
|
|
|
|
*/
|
|
|
|
protected function getRecordGridfieldRow($record)
|
|
|
|
{
|
2018-08-16 14:37:19 +02:00
|
|
|
$this->gridField->setList(new ArrayList(array($record)));
|
2018-03-14 21:21:54 +01:00
|
|
|
$rowContent = '';
|
|
|
|
|
2018-08-16 14:37:19 +02:00
|
|
|
foreach ($this->gridField->getColumns() as $column) {
|
|
|
|
$colContent = $this->gridField->getColumnContent($record, $column);
|
2018-03-14 21:21:54 +01:00
|
|
|
// Null means this columns should be skipped altogether.
|
|
|
|
if ($colContent === null) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-08-16 14:37:19 +02:00
|
|
|
$colAttributes = $this->gridField->getColumnAttributes($record, $column);
|
2018-03-14 21:21:54 +01:00
|
|
|
$rowContent .= HTML::createTag(
|
|
|
|
'td',
|
|
|
|
$colAttributes,
|
|
|
|
$colContent
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$rowAttributes = array(
|
|
|
|
'class' => 'ss-gridfield-item ' . implode(' ', $this->successClasses),
|
|
|
|
'data-id' => $record->ID,
|
|
|
|
'data-class' => $record->ClassName,
|
|
|
|
);
|
|
|
|
$row = HTML::createTag(
|
|
|
|
'tr',
|
|
|
|
$rowAttributes,
|
|
|
|
$rowContent
|
|
|
|
);
|
|
|
|
return $row;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates the response JSON body
|
|
|
|
*/
|
|
|
|
public function createBody()
|
|
|
|
{
|
|
|
|
$body = array(
|
|
|
|
'isDestructive' => $this->removesRows,
|
|
|
|
'isError' => $this->isError(),
|
|
|
|
'isWarning' => false,
|
|
|
|
'message' => $this->message,
|
|
|
|
'successClasses' => $this->successClasses,
|
|
|
|
'failedClasses' => $this->failedClasses
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!$this->isError()) {
|
|
|
|
$body['records'] = array(
|
|
|
|
'success' => array(),
|
|
|
|
'failed' => array()
|
|
|
|
);
|
|
|
|
|
|
|
|
foreach ($this->successRecords as $record) {
|
|
|
|
$data = array('id' => $record->ID, 'class' => $record->ClassName);
|
|
|
|
if (!$this->removesRows) {
|
|
|
|
$data['row'] = $this->getRecordGridfieldRow($record);
|
|
|
|
}
|
|
|
|
$body['records']['success'][] = $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
$body['records']['failed'] = $this->failedRecords;
|
|
|
|
}
|
|
|
|
|
2020-09-02 14:01:46 +02:00
|
|
|
if (isset($body['records']['success']) && count($body['records']['success']) === 0) {
|
2018-03-14 21:21:54 +01:00
|
|
|
$body['isWarning'] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->body = Convert::raw2json($body);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make sure the body has been created before output
|
|
|
|
* Output body of this response to the browser
|
|
|
|
*/
|
|
|
|
protected function outputBody()
|
|
|
|
{
|
|
|
|
$this->createBody();
|
|
|
|
parent::outputBody();
|
|
|
|
}
|
2021-06-02 00:21:48 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This empty function exists only for semver
|
|
|
|
*/
|
|
|
|
public function shutdown()
|
|
|
|
{
|
|
|
|
// noop
|
|
|
|
}
|
2018-03-14 21:21:54 +01:00
|
|
|
}
|