silverstripe-blog/src/Forms/GridField/GridFieldAddByDBField.php

241 lines
6.6 KiB
PHP

<?php
namespace SilverStripe\Blog\Forms\GridField;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridField_ActionProvider;
use SilverStripe\Forms\GridField\GridField_FormAction;
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
use SilverStripe\Forms\TextField;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Security;
use SilverStripe\View\ArrayData;
use SilverStripe\View\Requirements;
use UnexpectedValueException;
class GridFieldAddByDBField implements GridField_ActionProvider, GridField_HTMLProvider
{
use Injectable;
/**
* HTML Fragment to render the field.
*
* @var string
*/
protected $targetFragment;
/**
* Default field to create the DataObject by should be Title.
*
* @var string
*/
protected $dataObjectField = 'Title';
/**
* Name for the buttons displayed in the CMS
*
* @var string
*/
protected $buttonName;
/**
* Creates a text field and add button which allows the user to directly create a new
* DataObject by just entering the title.
*
* @param string $targetFragment
* @param string $dataObjectField
*/
public function __construct($targetFragment = 'before', $dataObjectField = 'Title')
{
$this->targetFragment = $targetFragment;
$this->dataObjectField = (string) $dataObjectField;
}
/**
* Provide actions to this component.
*
* @param GridField $gridField
*
* @return array
*/
public function getActions($gridField)
{
return [
'add',
];
}
/**
* Handles the add action for the given DataObject.
*
* @param $gridField GridField
* @param $actionName string
* @param $arguments mixed
* @param $data array
*
* @return null|HTTPResponse
*
* @throws UnexpectedValueException
*/
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
{
if ($actionName == 'add') {
$dbField = $this->getDataObjectField();
$objClass = $gridField->getModelClass();
/**
* @var DataObject $obj
*/
$obj = $objClass::create();
if ($obj->hasField($dbField)) {
$obj->setCastedField($dbField, $data['gridfieldaddbydbfield'][$obj->ClassName][$dbField]);
if ($obj->canCreate()) {
$id = $gridField->getList()->add($obj);
if (!$id) {
$gridField->setCustomValidationMessage(
_t(
__CLASS__ . '.AddFail',
'Unable to save {class} to the database.',
'Unable to add the DataObject.',
[
'class' => get_class($obj),
]
)
);
}
} else {
return Security::permissionFailure(
Controller::curr(),
_t(
__CLASS__ . '.PermissionFail',
'You don\'t have permission to create a {class}.',
'Unable to add the DataObject.',
[
'class' => get_class($obj)
]
)
);
}
} else {
throw new UnexpectedValueException(
sprintf(
'Invalid field (%s) on %s.',
$dbField,
$obj->ClassName
)
);
}
}
return null;
}
/**
* Returns the database field for which we'll add the new data object.
*
* @return string
*/
public function getDataObjectField()
{
return $this->dataObjectField;
}
/**
* Set the button name
*
* @param $name string
* @return $this
*/
public function setButtonName($name)
{
$this->buttonName = $name;
return $this;
}
/**
* Set the database field.
*
* @param $field string
*/
public function setDataObjectField($field)
{
$this->dataObjectField = (string) $field;
}
/**
* Renders the TextField and add button to the GridField.
*
* @param $gridField GridField
*
* @return string[]
*/
public function getHTMLFragments($gridField)
{
Requirements::javascript('silverstripe/blog:client/dist/js/main.bundle.js');
/**
* @var DataList $dataList
*/
$dataList = $gridField->getList();
$dataClass = $dataList->dataClass();
$obj = singleton($dataClass);
if (!$obj->canCreate()) {
return [];
}
$dbField = $this->getDataObjectField();
$textField = TextField::create(
sprintf(
"gridfieldaddbydbfield[%s][%s]",
$obj->ClassName,
Convert::raw2htmlatt($dbField)
)
)
->setAttribute('placeholder', $obj->fieldLabel($dbField))
->addExtraClass('no-change-track');
if (!$this->buttonName) {
// provide a default button name, can be changed by calling {@link setButtonName()} on this component
$objectName = $obj->i18n_singular_name();
$this->buttonName = _t(__CLASS__ . '.ButtonName', '{name}', ['name' => $objectName]);
}
$addAction = GridField_FormAction::create(
$gridField,
'add',
_t(
__CLASS__ . '.Add',
'Add {name}',
'Add button text',
['name' => $this->buttonName]
),
'add',
'add'
);
$addAction->setAttribute('data-icon', 'add');
$addAction->addExtraClass('btn btn-primary');
$forTemplate = ArrayData::create([]);
$forTemplate->Fields = ArrayList::create();
$forTemplate->Fields->push($textField);
$forTemplate->Fields->push($addAction);
return [$this->targetFragment => $forTemplate->renderWith(self::class)];
}
}