If the GridField has a filterable datalist, return an array of actions

@param GridField $gridField
@return void
332609
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
    {
        if (!$this->checkDataType($gridField->getList())) {
            return;
        }

        $state = $gridField->State->GridFieldFilterHeader;
        $state->Columns = null;
        if ($actionName === 'filter') {
            if (isset($data['filter'][$gridField->getName()])) {
                foreach ($data['filter'][$gridField->getName()] as $key => $filter) {
                    $state->Columns->$key = $filter;
                }
            }
        }
    }
839675
public function getManipulatedData(GridField $gridField, SS_List $dataList)
    {
        $state = $gridField->State->MockDataGenerator;
        $count = (string) $state->Count;
        if (!$count) {
            return $dataList;
        }
        $generator = new MockDataBuilder($gridField->getModelClass());
        $ids = $generator
            ->setCount($count)
            ->setIncludeRelations($state->IncludeRelations)
            ->setDownloadImages($state->DownloadImages === true)
            ->generate();

        foreach ($ids as $id) {
            $dataList->add($id);
        }

        return $dataList;
    }
1323826
public function listView(CrudConfigurator $crudConfigurator, array $gridFields, $allowBulkDelete, $formatNumber)
    {
        $crud = $crudConfigurator->getCrud();
        /** @var ListActionHandler $viewHandler */
        $viewHandler = $this->actionHandlers[ListActionHandler::class];
        $viewHandler->setModelClass($crud->getModelClass());
        $viewHandler->setView($this->view);
        $viewHandler->setRequest($this->request);
        $viewHandler->setGridFields($gridFields);
        $viewHandler->setActionList($crudConfigurator->getGridAction());
        $viewHandler->isAllowCrate($crud->isAllowCreate());
        $viewHandler->isAllowBulkDelete($allowBulkDelete);
        $viewHandler->isFormatNumber($formatNumber);
        $viewHandler->setListHandler($crud->getListHandler());

        return $this->getResponse($viewHandler->getView($this->driver));
    }
99215
public function handleImporter($gridField, $request = null)
    {
        $controller = $gridField->getForm()->getController();
        $handler    = new GridFieldImporter_Request($gridField, $this, $controller);

        return $handler->handleRequest($request, DataModel::inst());
    }
565790
public function getHTMLFragments($gridField)
    {
        $list = $gridField->getList();
        if (!$this->checkDataType($list)) {
            return null;
        }
        /** @var Sortable $list */
        $forTemplate = new ArrayData(array());
        $forTemplate->Fields = new ArrayList;

        $state = $gridField->State->GridFieldSortableHeader;
        $columns = $gridField->getColumns();
        $currentColumn = 0;

        $schema = DataObject::getSchema();
        foreach ($columns as $columnField) {
            $currentColumn++;
            $metadata = $gridField->getColumnMetadata($columnField);
            $fieldName = str_replace('.', '-', $columnField);
            $title = $metadata['title'];

            if (isset($this->fieldSorting[$columnField]) && $this->fieldSorting[$columnField]) {
                $columnField = $this->fieldSorting[$columnField];
            }

            $allowSort = ($title && $list->canSortBy($columnField));

            if (!$allowSort && strpos($columnField, '.') !== false) {
                // we have a relation column with dot notation
                // @see DataObject::relField for approximation
                $parts = explode('.', $columnField);
                $tmpItem = singleton($list->dataClass());
                for ($idx = 0; $idx < sizeof($parts); $idx++) {
                    $methodName = $parts[$idx];
                    if ($tmpItem instanceof SS_List) {
                        // It's impossible to sort on a HasManyList/ManyManyList
                        break;
                    } elseif (method_exists($tmpItem, 'hasMethod') && $tmpItem->hasMethod($methodName)) {
                        // The part is a relation name, so get the object/list from it
                        $tmpItem = $tmpItem->$methodName();
                    } elseif ($tmpItem instanceof DataObject
                        && $schema->fieldSpec($tmpItem, $methodName, DataObjectSchema::DB_ONLY)
                    ) {
                        // Else, if we've found a database field at the end of the chain, we can sort on it.
                        // If a method is applied further to this field (E.g. 'Cost.Currency') then don't try to sort.
                        $allowSort = $idx === sizeof($parts) - 1;
                        break;
                    } else {
                        // If neither method nor field, then unable to sort
                        break;
                    }
                }
            }

            if ($allowSort) {
                $dir = 'asc';
                if ($state->SortColumn(null) == $columnField && $state->SortDirection('asc') == 'asc') {
                    $dir = 'desc';
                }

                $field = GridField_FormAction::create(
                    $gridField,
                    'SetOrder' . $fieldName,
                    $title,
                    "sort$dir",
                    array('SortColumn' => $columnField)
                )->addExtraClass('grid-field__sort');

                if ($state->SortColumn(null) == $columnField) {
                    $field->addExtraClass('ss-gridfield-sorted');

                    if ($state->SortDirection('asc') == 'asc') {
                        $field->addExtraClass('ss-gridfield-sorted-asc');
                    } else {
                        $field->addExtraClass('ss-gridfield-sorted-desc');
                    }
                }
            } else {
                if ($currentColumn == count($columns)) {
                    $filter = $gridField->getConfig()->getComponentByType(GridFieldFilterHeader::class);

                    if ($filter && $filter->useLegacyFilterHeader && $filter->canFilterAnyColumns($gridField)) {
                        $field = new LiteralField(
                            $fieldName,
                            sprintf(
                                '<button type="button" name="showFilter" aria-label="%s" title="%s"' .
                                ' class="btn btn-secondary font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>',
                                _t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter"),
                                _t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter")
                            )
                        );
                    } else {
                        $field = new LiteralField($fieldName, '<span class="non-sortable">' . $title . '</span>');
                    }
                } else {
                    $field = new LiteralField($fieldName, '<span class="non-sortable">' . $title . '</span>');
                }
            }
            $forTemplate->Fields->push($field);
        }

        $template = SSViewer::get_templates_by_class($this, '_Row', __CLASS__);
        return array(
            'header' => $forTemplate->renderWith($template),
        );
    }
956385
public function array2xml(string $xmlField = '', ?string $dataField = null): void
    {
        $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><' . $xmlField . '/>');
        $this->createXml($xml, $this->arrayData, $dataField);
        $this->xmlData = $xml->asXML();
    }
426059
public function getManipulatedList()
    {
        $list = $this->getList();

        foreach ($this->getComponents() as $item) {
            if ($item instanceof GridField_DataManipulator) {
                $list = $item->getManipulatedData($this, $list);
            }
        }

        return $list;
    }
617970
protected function getExportColumnsForGridField(GridField $gridField)
    {
        if ($this->exportColumns) {
            return $this->exportColumns;
        }

        /** @var GridFieldDataColumns $dataCols */
        $dataCols = $gridField->getConfig()->getComponentByType(GridFieldDataColumns::class);
        if ($dataCols) {
            return $dataCols->getDisplayFields($gridField);
        }

        return DataObject::singleton($gridField->getModelClass())->summaryFields();
    }
661304
protected function sortToPage(GridField $gridField, $data)
    {
        if (!$paginator = $gridField->getConfig()->getComponentsByType(GridFieldPaginator::class)->First()) {
            user_error('Paginator not detected', E_USER_ERROR);
        }

        if (empty($data['ItemID'])) {
            user_error('No item to sort', E_USER_ERROR);
        }

        if (empty($data['Target'])) {
            user_error('No target page', E_USER_ERROR);
        }

        /** @var Extensible $className */
        $className = $gridField->getModelClass();
        $owner = $gridField->Form->getRecord();

        /** @var DataList $items */
        $items = clone $gridField->getList();

        $many_many = ($items instanceof ManyManyList || $items instanceof ManyManyThroughList);
        $sortColumn = $this->sortColumn;
        $targetItem = $items->byID(intval($data['ItemID']));

        if (!$targetItem) {
            user_error('Target item not found', E_USER_ERROR);
        }

        $currentPage = 1;

        $pageState = $gridField->State->GridFieldPaginator;
        if ($pageState->currentPage && $pageState->currentPage > 1) {
            $currentPage = $pageState->currentPage;
        }

        if ($many_many) {
            $schema=Injector::inst()->get(DataObjectSchema::class);
            $componentDetails=$schema->manyManyComponent(get_class($owner), (!empty($this->custom_relation_name) ? $this->custom_relation_name : $gridField->getName()));
            $parentField=$componentDetails['parentField'];
            $componentField=$componentDetails['childField'];
            $table=$componentDetails['join'];
            
            //For ManyManyThroughLists get the right join table
            if ($items instanceof ManyManyThroughList && class_exists($table)) {
                $table=$schema->tableName($table);
            }
        }

        if ($data['Target'] == 'previouspage') {
            $items = $items->limit($paginator->getItemsPerPage() + 1, ($paginator->getItemsPerPage() * ($currentPage - 1)) - 1);
        } else if ($data['Target'] == 'nextpage') {
            $items = $items->limit($paginator->getItemsPerPage() + 1, $paginator->getItemsPerPage() * ($currentPage - 1));
        } else {
            user_error('Not implemented: ' . $data['Target'], E_USER_ERROR);
        }

        $sortPositions = $items->column($sortColumn);

        //Event to notify the Controller or owner DataObject before list sort
        if ($owner && $owner instanceof DataObject && method_exists($owner, 'onBeforeGridFieldPageSort')) {
            $owner->onBeforeGridFieldPageSort(clone $items);
        } else if (Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onBeforeGridFieldPageSort')) {
            Controller::curr()->onBeforeGridFieldPageSort(clone $items);
        }

        //Find the sort column
        if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) {
            $table = false;
            $classes = ClassInfo::ancestry($className, true);
            foreach ($classes as $class) {
                $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED);
                if (!empty($db) && array_key_exists($sortColumn, $db)) {
                    $table = DataObject::getSchema()->tableName($class);
                    break;
                }
            }

            if ($table === false) {
                user_error('Sort column ' . $this->sortColumn . ' could not be found in ' . $gridField->getModelClass() . '\'s ancestry', E_USER_ERROR);
                exit;
            }
        }

        //Start transaction if supported
        if (DB::get_conn()->supportsTransactions()) {
            DB::get_conn()->transactionStart();
        }

        if ($data['Target'] == 'previouspage') {
            if ($many_many) {
                DB::query('UPDATE "' . $table
                    . '" SET "' . $sortColumn . '" = ' . $sortPositions[0]
                    . ' WHERE "' . $componentField . '" = ' . $targetItem->ID . ' AND "' . $parentField . '" = ' . $owner->ID);
            } else {
                $targetItem->$sortColumn = $sortPositions[0];
                $targetItem->write();

                if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) {
                    DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage
                        . '" SET "' . $sortColumn . '" = ' . $sortPositions[0]
                        . ' WHERE "ID" = ' . $targetItem->ID);
                }
            }

            $i = 1;
            foreach ($items as $obj) {
                if ($obj->ID == $targetItem->ID || $i >= count($sortPositions)) {
                    continue;
                }


                if ($many_many) {
                    DB::query('UPDATE "' . $table
                        . '" SET "' . $sortColumn . '" = ' . $sortPositions[$i]
                        . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID);
                } else {
                    $obj->$sortColumn = $sortPositions[$i];
                    $obj->write();

                    if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) {
                        DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage
                            . '" SET "' . $sortColumn . '" = ' . $sortPositions[$i]
                            . ' WHERE "ID" = ' . $obj->ID);
                    }
                }

                $i++;
            }
        } else {
            if ($many_many) {
                DB::query('UPDATE "' . $table
                    . '" SET "' . $sortColumn . '" = ' . $sortPositions[count($sortPositions) - 1]
                    . ' WHERE "' . $componentField . '" = ' . $targetItem->ID . ' AND "' . $parentField . '" = ' . $owner->ID);
            } else {
                $targetItem->$sortColumn = $sortPositions[count($sortPositions) - 1];
                $targetItem->write();

                if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) {
                    DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage
                        . '" SET "' . $sortColumn . '" = ' . $sortPositions[count($sortPositions) - 1]
                        . ' WHERE "ID" = ' . $targetItem->ID);
                }
            }

            $i = 0;
            foreach ($items as $obj) {
                if ($obj->ID == $targetItem->ID) {
                    continue;
                }


                if ($many_many) {
                    DB::query('UPDATE "' . $table
                        . '" SET "' . $sortColumn . '" = ' . $sortPositions[$i]
                        . ' WHERE "' . $componentField . '" = ' . $obj->ID . ' AND "' . $parentField . '" = ' . $owner->ID);
                } else {
                    $obj->$sortColumn = $sortPositions[$i];
                    $obj->write();

                    if ($this->update_versioned_stage && $this->hasVersionedExtension($className)) {
                        DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage
                            . '" SET "' . $sortColumn . '" = ' . $sortPositions[$i]
                            . ' WHERE "ID" = ' . $obj->ID);
                    }
                }

                $i++;
            }
        }

        //End transaction if supported
        if (DB::get_conn()->supportsTransactions()) {
            DB::get_conn()->transactionEnd();
        }

        //Event to notify the Controller or owner DataObject after list sort
        if ($owner && $owner instanceof DataObject && method_exists($owner, 'onAfterGridFieldPageSort')) {
            $owner->onAfterGridFieldPageSort(clone $items);
        } else if (Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onAfterGridFieldPageSort')) {
            Controller::curr()->onAfterGridFieldPageSort(clone $items);
        }
    }
1216661
public function updateCMSFields(FieldList $fields)
    {
        $global = $fields->dataFieldByName('AvailableGlobally');

        if ($global) {
            $fields->removeByName('AvailableGlobally');
            $fields->addFieldToTab('Root.Settings', $global);
        }

        if ($virtual = $fields->dataFieldByName('VirtualClones')) {
            if ($this->owner->VirtualClones()->Count() > 0) {
                $tab = $fields->findOrMakeTab('Root.VirtualClones');
                $tab->setTitle(_t(__CLASS__ . '.LinkedTo', 'Linked To'));

                if ($ownerPage = $this->owner->getPage()) {
                    $fields->addFieldToTab(
                        'Root.VirtualClones',
                        LiteralField::create(
                            'DisplaysOnPage',
                            sprintf(
                                "<p>"
                                . _t(__CLASS__ . '.OriginalContentFrom', 'The original content element appears on')
                                . " <a href='%s'>%s</a></p>",
                                ($ownerPage->hasMethod('CMSEditLink') && $ownerPage->canEdit()) ? $ownerPage->CMSEditLink() : $ownerPage->Link(),
                                $ownerPage->MenuTitle
                            )
                        ),
                        'VirtualClones'
                    );
                }

                $virtual->setConfig(new GridFieldConfig_Base());
                $virtual
                    ->setTitle(_t(__CLASS__ . '.OtherPages', 'Other pages'))
                    ->getConfig()
                        ->removeComponentsByType(GridFieldAddExistingAutocompleter::class)
                        ->removeComponentsByType(GridFieldAddNewButton::class)
                        ->removeComponentsByType(GridFieldDeleteAction::class)
                        ->removeComponentsByType(GridFieldDetailForm::class)
                        ->addComponent(new ElementalGridFieldDeleteAction());

                $virtual->getConfig()
                    ->getComponentByType(GridFieldDataColumns::class)
                    ->setDisplayFields([
                        'getPage.Title' => _t(__CLASS__ . '.GridFieldTitle', 'Title'),
                        'ParentCMSEditLink' => _t(__CLASS__ . '.GridFieldUsedOn', 'Used on'),
                    ]);
            } else {
                $fields->removeByName('VirtualClones');
            }
        }
    }
1359188
public function canFilterAnyColumns($gridField)
    {
        $list = $gridField->getList();

        if (!$this->checkDataType($list)) {
            return false;
        }

        $columns = $gridField->getColumns();
        foreach ($columns as $columnField) {
            $metadata = $gridField->getColumnMetadata($columnField);
            $title = $metadata['title'];

            if ($title && $list->canFilterBy($columnField)) {
                return true;
            }
        }

        return false;
    }
127603
public function listField()
    {
        $this->actionListField();
        $this->setTitleListField();
        $this->setBreadcrumbListField();
        $this->setFilterListField();
        $this->setPagerListField();

        $this->setData('fields', $this->getListField());
        $this->setData('widget_types', $this->field->getWidgetTypes());

        $this->outputListField();
    }
1370509
protected function getGridPagerState(GridField $gridField)
    {
        $state = $gridField->State->GridFieldPaginator;

        // Force the state to the initial page if none is set
        $state->currentPage(1);
        $state->itemsPerPage($this->getItemsPerPage());

        return $state;
    }
1038431
public function augmentColumns($gridField, &$columns)
    {
        if (Config::inst()->get(__CLASS__, 'prepend_column')) {
		    array_unshift($columns, self::CHECKBOX_COLUMN);
        } else {
		    $columns[] = self::CHECKBOX_COLUMN;
        }
    }
493988
public function getArchiveAction($gridField, $record)
    {
        /* @var DataObject|Versioned $record */
        if (!$record->hasMethod('canArchive') || !$record->canArchive()) {
            return null;
        }

        $title = _t(__CLASS__ . '.Archive', "Archive");

        $field = GridField_FormAction::create(
            $gridField,
            'ArchiveRecord' . $record->ID,
            false,
            "archiverecord",
            ['RecordID' => $record->ID]
        )
            ->addExtraClass('action--archive btn--icon-md font-icon-box btn--no-text grid-field__icon-action action-menu--handled')
            ->setAttribute('classNames', 'action--archive font-icon-box')
            ->setDescription($title)
            ->setAttribute('aria-label', $title);

        return $field;
    }
734970
protected function saveGridRowSort(GridField $gridField, $data)
    {
        $dataList = $gridField->getList();

        if ($dataList instanceof UnsavedRelationList) {
            user_error('Cannot sort an UnsavedRelationList', E_USER_ERROR);
            return;
        }

        if (!singleton($gridField->getModelClass())->canEdit()) {
            throw new ValidationException(_t('GridFieldSortableRows.EditPermissionsFailure', "No edit permissions"), 0);
        }

        if (empty($data['ItemIDs'])) {
            user_error('No items to sort', E_USER_ERROR);
        }

        $className = $gridField->getModelClass();
        $owner = $gridField->Form->getRecord();
        $items = clone $gridField->getList();
        $many_many = ($items instanceof ManyManyList || $items instanceof ManyManyThroughList);
        $sortColumn = $this->sortColumn;
        $pageOffset = 0;

        if ($paginator = $gridField->getConfig()->getComponentsByType(GridFieldPaginator::class)->First()) {
            $pageState = $gridField->State->GridFieldPaginator;

            if ($pageState->currentPage && is_int($pageState->currentPage) && $pageState->currentPage > 1) {
                $pageOffset = $paginator->getItemsPerPage() * ($pageState->currentPage - 1);
            }
        }


        if ($many_many) {
            $schema=Injector::inst()->get(DataObjectSchema::class);
            $componentDetails=$schema->manyManyComponent(get_class($owner), (!empty($this->custom_relation_name) ? $this->custom_relation_name : $gridField->getName()));
            $parentField=$componentDetails['parentField'];
            $componentField=$componentDetails['childField'];
            $table=$componentDetails['join'];
            
            //For ManyManyThroughLists get the right join table
            if ($items instanceof ManyManyThroughList && class_exists($table)) {
                $table=$schema->tableName($table);
            }
        } else {
            //Find table containing the sort column
            $table = false;
            $class = $gridField->getModelClass();
            $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED);
            if (!empty($db) && array_key_exists($sortColumn, $db)) {
                $table = DataObject::getSchema()->tableName($class);
            } else {
                $classes = ClassInfo::ancestry($class, true);
                foreach ($classes as $class) {
                    $db = Config::inst()->get($class, "db", CONFIG::UNINHERITED);
                    if (!empty($db) && array_key_exists($sortColumn, $db)) {
                        $table = DataObject::getSchema()->tableName($class);
                        break;
                    }
                }
            }

            if ($table === false) {
                user_error('Sort column ' . $this->sortColumn . ' could not be found in ' . $gridField->getModelClass() . '\'s ancestry', E_USER_ERROR);
                exit;
            }

            $baseDataClass = DataObject::getSchema()->baseDataClass($gridField->getModelClass());
            $baseDataTable = DataObject::getSchema()->tableName($baseDataClass);
        }


        //Event to notify the Controller or owner DataObject before list sort
        if ($owner && $owner instanceof DataObject && method_exists($owner, 'onBeforeGridFieldRowSort')) {
            $owner->onBeforeGridFieldRowSort(clone $items);
        } else if (Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onBeforeGridFieldRowSort')) {
            Controller::curr()->onBeforeGridFieldRowSort(clone $items);
        }

        //Start transaction if supported
        if (DB::get_conn()->supportsTransactions()) {
            DB::get_conn()->transactionStart();
        }

        //Perform sorting
        $ids = explode(',', $data['ItemIDs']);
        $modelClass = $gridField->getModelClass();
        $hasVersioned = $this->hasVersionedExtension($modelClass);
        for ($sort = 0; $sort < count($ids); $sort++) {
            $id = intval($ids[$sort]);
            if ($many_many) {
                DB::query('UPDATE "' . $table
                    . '" SET "' . $sortColumn . '" = ' . (($sort + 1) + $pageOffset)
                    . ' WHERE "' . $componentField . '" = ' . $id . ' AND "' . $parentField . '" = ' . $owner->ID);
            } else {
                if($hasVersioned) {
                    // For versioned objects, modify them with the ORM so that the *_versions table is updated
                    $obj = $modelClass::get()->byID(intval($id));
                    if (!empty($obj) && $obj !== false && $obj->exists()) {
                        $obj->$sortColumn = (($sort + 1) + $pageOffset);
                        $obj->write();
                    }
                }else {
                    DB::query('UPDATE "' . $table
                        . '" SET "' . $sortColumn . '" = ' . (($sort + 1) + $pageOffset)
                        . ' WHERE "ID" = ' . $id);

                    DB::query('UPDATE "' . $baseDataTable
                        . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\''
                        . ' WHERE "ID" = ' . $id);
                }

                if ($this->update_versioned_stage && $hasVersioned) {
                    DB::query('UPDATE "' . $table . '_' . $this->update_versioned_stage
                        . '" SET "' . $sortColumn . '" = ' . (($sort + 1) + $pageOffset)
                        . ' WHERE "ID" = ' . $id);

                    if ($this->hasVersionedExtension($baseDataClass)) {
                        DB::query('UPDATE "' . $baseDataTable . '_' . $this->update_versioned_stage
                            . '" SET "LastEdited" = \'' . date('Y-m-d H:i:s') . '\''
                            . ' WHERE "ID" = ' . $id);
                    }
                }
            }
        }


        //End transaction if supported
        if (DB::get_conn()->supportsTransactions()) {
            DB::get_conn()->transactionEnd();
        }


        //Event to notify the Controller or owner DataObject after list sort
        if ($owner && $owner instanceof DataObject && method_exists($owner, 'onAfterGridFieldRowSort')) {
            $owner->onAfterGridFieldRowSort(clone $items);
        } else if (Controller::has_curr() && Controller::curr() instanceof ModelAdmin && method_exists(Controller::curr(), 'onAfterGridFieldRowSort')) {
            Controller::curr()->onAfterGridFieldRowSort(clone $items);
        }
    }
1342705
protected function getGridPagerState(GridField $gridField = null)
    {
        if (!$this->gridFieldState) {
            $state = $this->getGridField()->State->GridFieldConfigurablePaginator;

            // SS 3.1 compatibility (missing __call)
            if (is_object($state->firstShown)) {
                $state->firstShown = 1;
            }
            if (is_object($state->pageSize)) {
                $state->pageSize = $this->getItemsPerPage();
            }

            // Handle free input in the page number field
            $parentState = $this->getGridField()->State->GridFieldPaginator;
            if (is_object($parentState->currentPage)) {
                $parentState->currentPage = 0;
            }

            if ($parentState->currentPage >= 1) {
                $state->firstShown = ($parentState->currentPage - 1) * $this->getItemsPerPage() + 1;
                $parentState->currentPage = null;
            }

            $this->gridFieldState = $state;
        }

        return $this->gridFieldState;
    }