Skip to content

Instantly share code, notes, and snippets.

@tractorcow
Created May 12, 2020 00:25
Show Gist options
  • Save tractorcow/1019030afd0fd0c3e9be0b11d0b2c5fc to your computer and use it in GitHub Desktop.
Save tractorcow/1019030afd0fd0c3e9be0b11d0b2c5fc to your computer and use it in GitHub Desktop.
<?php
namespace App\Forms;
use InvalidArgumentException;
use LogicException;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Forms\CheckboxField;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridField_ColumnProvider;
use SilverStripe\Forms\GridField\GridField_DataManipulator;
use SilverStripe\Forms\GridField\GridField_SaveHandler;
use SilverStripe\Forms\GridField\GridFieldPaginator;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\ORM\Relation;
use SilverStripe\ORM\SS_List;
use SilverStripe\View\HTML;
/**
* Lets you use a gridfield in place of a checkbox set field
*/
class GridFieldMultiSelector implements GridField_SaveHandler, GridField_ColumnProvider, GridField_DataManipulator
{
use Injectable;
/**
* @skipUpgrade
*/
const COLUMN_NAME = 'MultiSelectColumn';
/**
* Optional source list
*
* @var SS_List
*/
protected $source = null;
/**
* @inheritDoc
*/
public function augmentColumns($gridField, &$columns)
{
// Add "enabled in" column
if (in_array(self::COLUMN_NAME, $columns)) {
return;
}
// Add to start
array_unshift($columns, self::COLUMN_NAME);
}
/**
* @inheritDoc
*/
public function getColumnsHandled($gridField)
{
return [self::COLUMN_NAME];
}
/**
* @param GridField $gridField
* @param DataObject $record
* @param string $columnName
* @return string
*/
public function getColumnContent($gridField, $record, $columnName)
{
if ($columnName !== self::COLUMN_NAME) {
return null;
}
// Check if this record is in the base (included) list
$checked = !!$gridField->getList()->find('ID', $record->ID);
// Create checkbox for this locale
$checkbox = CheckboxField::create(
$this->getFieldName($gridField, $record),
false
)
->setValue($checked)
->forTemplate();
return HTML::createTag('label', ['title' => 'Select', 'style' => 'padding: 10px;'], $checkbox);
}
public function getColumnAttributes($gridField, $record, $columnName)
{
return [
'class' => 'col-' . preg_replace('/[^\w]/', '-', $columnName)
];
}
public function getColumnMetadata($gridField, $columnName)
{
return [
'title' => _t(__CLASS__ . '.SELECTED', 'Selected?'),
];
}
public function handleSave(GridField $gridField, DataObjectInterface $record)
{
$value = $gridField->Value();
// Keys for this value will be list of locales to enable
$selectedRecordIDs = isset($value[self::COLUMN_NAME])
? array_keys($value[self::COLUMN_NAME])
: [];
// Set ID list
$gridField->getList()->setByIDList($selectedRecordIDs);
}
protected function getFieldName(GridField $grid, DataObject $record)
{
return sprintf(
'%s[%s][%s]',
$grid->getName(),
self::COLUMN_NAME,
$record->ID
);
}
/**
* @inheritDoc
*/
public function getManipulatedData(GridField $gridField, SS_List $dataList)
{
// Check list type
if (!$dataList instanceof Relation) {
throw new InvalidArgumentException("GridFieldMultiSelector only works with relations");
}
// Safe check (todo: Support this in the future?)
if ($gridField->getConfig()->getComponentByType(GridFieldPaginator::class)) {
throw new LogicException("GridFieldMultiSelector doesn't work with pagination disabled");
}
// In order to act as a multi-selector, we need to get the base (unfiltered) records
// that the relation belongs to
$source = $this->getSource();
if ($source) {
return $source;
}
// Infer source from base datalist
$type = $dataList->dataClass();
return DataObject::get($type);
}
/**
* @return SS_List
*/
public function getSource()
{
return $this->source;
}
/**
* @param SS_List $source
* @return $this
*/
public function setSource(SS_List $source)
{
$this->source = $source;
return $this;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment