mirror of
https://github.com/symbiote/silverstripe-gridfieldextensions.git
synced 2024-09-30 05:09:09 +02:00
Compare commits
No commits in common. "3" and "3.1.2" have entirely different histories.
1
.github/ISSUE_TEMPLATE.md
vendored
1
.github/ISSUE_TEMPLATE.md
vendored
@ -1 +0,0 @@
|
||||
<!-- Blank templates are for use by maintainers only! If you aren't a maintainer, please go back and pick one of the issue templates. -->
|
72
.github/ISSUE_TEMPLATE/1_bug_report.yml
vendored
72
.github/ISSUE_TEMPLATE/1_bug_report.yml
vendored
@ -1,72 +0,0 @@
|
||||
name: 🪳 Bug Report
|
||||
description: Tell us if something isn't working the way it's supposed to
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
We strongly encourage you to [submit a pull request](https://docs.silverstripe.org/en/contributing/code/) which fixes the issue.
|
||||
Bug reports which are accompanied with a pull request are a lot more likely to be resolved quickly.
|
||||
- type: input
|
||||
id: affected-versions
|
||||
attributes:
|
||||
label: Module version(s) affected
|
||||
description: |
|
||||
What version of _this module_ have you reproduced this bug on?
|
||||
Run `composer info` to see the specific version of each module installed in your project.
|
||||
If you don't have access to that, check inside the help menu in the bottom left of the CMS.
|
||||
placeholder: x.y.z
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of the problem
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: how-to-reproduce
|
||||
attributes:
|
||||
label: How to reproduce
|
||||
description: |
|
||||
⚠️ This is the most important part of the report ⚠️
|
||||
Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix.
|
||||
- Please, take the time to show us some code and/or configuration that is needed for others to reproduce the problem easily.
|
||||
- If the bug is too complex to reproduce with some short code samples, please reproduce it in a public repository and provide a link to the repository along with steps for setting up and reproducing the bug using that repository.
|
||||
- If part of the bug includes an error or exception, please provide a full stack trace.
|
||||
- If any user interaction is required to reproduce the bug, please add an ordered list of steps that are required to reproduce it.
|
||||
- Be as clear as you can, but don't miss any steps out. Simply saying "create a page" is less useful than guiding us through the steps you're taking to create a page, for example.
|
||||
placeholder: |
|
||||
|
||||
#### Code sample
|
||||
```php
|
||||
|
||||
```
|
||||
|
||||
#### Reproduction steps
|
||||
1.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: possible-solution
|
||||
attributes:
|
||||
label: Possible Solution
|
||||
description: |
|
||||
*Optional: only if you have suggestions on a fix/reason for the bug*
|
||||
Please consider [submitting a pull request](https://docs.silverstripe.org/en/contributing/code/) with your solution! It helps get faster feedback and greatly increases the chance of the bug being fixed.
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: "*Optional: any other context about the problem: log messages, screenshots, etc.*"
|
||||
- type: checkboxes
|
||||
id: validations
|
||||
attributes:
|
||||
label: Validations
|
||||
description: "Before submitting the issue, please make sure you do the following:"
|
||||
options:
|
||||
- label: Check that there isn't already an issue that reports the same bug
|
||||
required: true
|
||||
- label: Double check that your reproduction steps work in a fresh installation of [`silverstripe/installer`](https://github.com/silverstripe/silverstripe-installer) (with any code examples you've provided)
|
||||
required: true
|
35
.github/ISSUE_TEMPLATE/2_feature_request.yml
vendored
35
.github/ISSUE_TEMPLATE/2_feature_request.yml
vendored
@ -1,35 +0,0 @@
|
||||
name: 🚀 Feature Request
|
||||
description: Submit a feature request (but only if you're planning on implementing it)
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please only submit feature requests if you plan on implementing the feature yourself.
|
||||
See the [contributing code documentation](https://docs.silverstripe.org/en/contributing/code/#make-or-find-a-github-issue) for more guidelines about submitting feature requests.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of the new feature, and why it belongs in core
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: more-info
|
||||
attributes:
|
||||
label: Additional context or points of discussion
|
||||
description: |
|
||||
*Optional: Any additional context, points of discussion, etc that might help validate and refine your idea*
|
||||
- type: checkboxes
|
||||
id: validations
|
||||
attributes:
|
||||
label: Validations
|
||||
description: "Before submitting the issue, please confirm the following:"
|
||||
options:
|
||||
- label: You intend to implement the feature yourself
|
||||
required: true
|
||||
- label: You have read the [contributing guide](https://docs.silverstripe.org/en/contributing/code/)
|
||||
required: true
|
||||
- label: You strongly believe this feature should be in core, rather than being its own community module
|
||||
required: true
|
||||
- label: You have checked for existing issues or pull requests related to this feature (and didn't find any)
|
||||
required: true
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
8
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,8 +0,0 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Security Vulnerability
|
||||
url: https://docs.silverstripe.org/en/contributing/issues_and_bugs/#reporting-security-issues
|
||||
about: ⚠️ We do not use GitHub issues to track security vulnerability reports. Click "open" on the right to see how to report security vulnerabilities.
|
||||
- name: Support Question
|
||||
url: https://www.silverstripe.org/community/
|
||||
about: We use GitHub issues only to discuss bugs and new features. For support questions, please use one of the support options available in our community channels.
|
39
.github/PULL_REQUEST_TEMPLATE.md
vendored
39
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,39 +0,0 @@
|
||||
<!--
|
||||
Thanks for contributing, you're awesome! ⭐
|
||||
|
||||
Please read https://docs.silverstripe.org/en/contributing/code/ if you haven't contributed to this project recently.
|
||||
-->
|
||||
## Description
|
||||
<!--
|
||||
Please describe expected and observed behaviour, and what you're fixing.
|
||||
For visual fixes, please include tested browsers and screenshots.
|
||||
-->
|
||||
|
||||
## Manual testing steps
|
||||
<!--
|
||||
Include any manual testing steps here which a reviewer can perform to validate your pull request works correctly.
|
||||
Note that this DOES NOT replace unit or end-to-end tests.
|
||||
-->
|
||||
|
||||
## Issues
|
||||
<!--
|
||||
List all issues here that this pull request fixes/resolves.
|
||||
If there is no issue already, create a new one! You must link your pull request to at least one issue.
|
||||
-->
|
||||
- #
|
||||
|
||||
## Pull request checklist
|
||||
<!--
|
||||
PLEASE check each of these to ensure you have done everything you need to do!
|
||||
If there's something in this list you need help with, please ask so that we can assist you.
|
||||
-->
|
||||
- [ ] The target branch is correct
|
||||
- See [picking the right version](https://docs.silverstripe.org/en/contributing/code/#picking-the-right-version)
|
||||
- [ ] All commits are relevant to the purpose of the PR (e.g. no debug statements, unrelated refactoring, or arbitrary linting)
|
||||
- Small amounts of additional linting are usually okay, but if it makes it hard to concentrate on the relevant changes, ask for the unrelated changes to be reverted, and submitted as a separate PR.
|
||||
- [ ] The commit messages follow our [commit message guidelines](https://docs.silverstripe.org/en/contributing/code/#commit-messages)
|
||||
- [ ] The PR follows our [contribution guidelines](https://docs.silverstripe.org/en/contributing/code/)
|
||||
- [ ] Code changes follow our [coding conventions](https://docs.silverstripe.org/en/contributing/coding_conventions/)
|
||||
- [ ] This change is covered with tests (or tests aren't necessary for this change)
|
||||
- [ ] Any relevant User Help/Developer documentation is updated; for impactful changes, information is added to the changelog for the intended release
|
||||
- [ ] CI is green
|
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
@ -1,11 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
name: CI
|
||||
uses: silverstripe/gha-ci/.github/workflows/ci.yml@v1
|
21
.github/workflows/dispatch-ci.yml
vendored
21
.github/workflows/dispatch-ci.yml
vendored
@ -1,21 +0,0 @@
|
||||
name: Dispatch CI
|
||||
|
||||
on:
|
||||
# At 8:40 PM UTC, only on Sunday and Monday
|
||||
schedule:
|
||||
- cron: '40 20 * * 0,1'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
dispatch-ci:
|
||||
name: Dispatch CI
|
||||
# Only run cron on the symbiote account
|
||||
if: (github.event_name == 'schedule' && github.repository_owner == 'symbiote') || (github.event_name != 'schedule')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
steps:
|
||||
- name: Dispatch CI
|
||||
uses: silverstripe/gha-dispatch-ci@v1
|
17
.github/workflows/keepalive.yml
vendored
17
.github/workflows/keepalive.yml
vendored
@ -1,17 +0,0 @@
|
||||
name: Keepalive
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# The 7th of every month at 12:50pm UTC
|
||||
schedule:
|
||||
- cron: '50 12 7 * *'
|
||||
|
||||
jobs:
|
||||
keepalive:
|
||||
name: Keepalive
|
||||
# Only run cron on the symbiote account
|
||||
if: (github.event_name == 'schedule' && github.repository_owner == 'symbiote') || (github.event_name != 'schedule')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Keepalive
|
||||
uses: silverstripe/gha-keepalive@v1
|
22
.github/workflows/merge-up.yml
vendored
22
.github/workflows/merge-up.yml
vendored
@ -1,22 +0,0 @@
|
||||
name: Merge-up
|
||||
|
||||
on:
|
||||
# At 8:40 PM UTC, only on Thursday
|
||||
schedule:
|
||||
- cron: '40 20 * * 4'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
merge-up:
|
||||
name: Merge-up
|
||||
# Only run cron on the symbiote account
|
||||
if: (github.event_name == 'schedule' && github.repository_owner == 'symbiote') || (github.event_name != 'schedule')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
actions: write
|
||||
steps:
|
||||
- name: Merge-up
|
||||
uses: silverstripe/gha-merge-up@v1
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,5 +0,0 @@
|
||||
vendor/
|
||||
resources/
|
||||
composer.lock
|
||||
|
||||
assets/
|
33
.travis.yml
Normal file
33
.travis.yml
Normal file
@ -0,0 +1,33 @@
|
||||
language: php
|
||||
|
||||
env:
|
||||
global:
|
||||
- COMPOSER_ROOT_VERSION="4.0.x-dev"
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 5.6
|
||||
env: DB=MYSQL PHPCS_TEST=1 PHPUNIT_TEST=1
|
||||
- php: 7.0
|
||||
env: DB=PGSQL PHPUNIT_TEST=1
|
||||
- php: 7.1
|
||||
env: DB=MYSQL PHPUNIT_COVERAGE_TEST=1
|
||||
- php: 7.2
|
||||
env: DB=MYSQL PHPUNIT_TEST=1
|
||||
|
||||
before_script:
|
||||
- phpenv rehash
|
||||
- phpenv config-rm xdebug.ini
|
||||
|
||||
- composer validate
|
||||
- composer require silverstripe/recipe-core 1.0.x-dev --no-update
|
||||
- if [[ $DB == PGSQL ]]; then composer require silverstripe/postgresql:2.0.x-dev --no-update; fi
|
||||
- composer install --prefer-dist --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile
|
||||
|
||||
script:
|
||||
- if [[ $PHPUNIT_TEST ]]; then vendor/bin/phpunit tests/; fi
|
||||
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then phpdbg -qrr vendor/bin/phpunit --coverage-clover=coverage.xml; fi
|
||||
- if [[ $PHPCS_TEST ]]; then vendor/bin/phpcs src/ tests/ *.php; fi
|
||||
|
||||
after_success:
|
||||
- if [[ $PHPUNIT_COVERAGE_TEST ]]; then bash <(curl -s https://codecov.io/bash) -f coverage.xml; fi
|
15
.tx/config
15
.tx/config
@ -1,15 +0,0 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[o:silverstripe:p:silverstripe-gridfieldextensions:r:master]
|
||||
file_filter = lang/<lang>.yml
|
||||
source_file = lang/en.yml
|
||||
source_lang = en
|
||||
type = YML
|
||||
|
||||
[o:silverstripe:p:silverstripe-gridfieldextensions:r:master-js]
|
||||
file_filter = client/lang/src/<lang>.json
|
||||
source_file = client/lang/src/en.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
17
README.md
17
README.md
@ -1,7 +1,10 @@
|
||||
# Silverstripe Grid Field Extensions Module
|
||||
# SilverStripe Grid Field Extensions Module
|
||||
|
||||
[![CI](https://github.com/symbiote/silverstripe-gridfieldextensions/actions/workflows/ci.yml/badge.svg)](https://github.com/symbiote/silverstripe-gridfieldextensions/actions/workflows/ci.yml)
|
||||
[![Silverstripe supported module](https://img.shields.io/badge/silverstripe-supported-0071C4.svg)](https://www.silverstripe.org/software/addons/silverstripe-commercially-supported-module-list/)
|
||||
[![Build Status](https://travis-ci.org/symbiote/silverstripe-gridfieldextensions.svg?branch=master)](https://travis-ci.org/symbiote/silverstripe-gridfieldextensions)
|
||||
[![Latest Stable Version](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/version.svg)](https://github.com/symbiote/silverstripe-gridfieldextensions/releases)
|
||||
[![Latest Unstable Version](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/v/unstable.svg)](https://packagist.org/packages/symbiote/silverstripe-gridfieldextensions)
|
||||
[![Total Downloads](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/downloads.svg)](https://packagist.org/packages/symbiote/silverstripe-gridfieldextensions)
|
||||
[![License](https://poser.pugx.org/symbiote/silverstripe-gridfieldextensions/license.svg)](https://github.com/symbiote/silverstripe-gridfieldextensions/blob/master/LICENSE.md)
|
||||
|
||||
This module provides a number of useful grid field components:
|
||||
|
||||
@ -19,13 +22,9 @@ This module provides a number of useful grid field components:
|
||||
* `GridFieldTitleHeader` - a simple header which displays column titles.
|
||||
* `GridFieldConfigurablePaginator` - a paginator for GridField that allows customisable page sizes.
|
||||
|
||||
This branch will aim for compatibility with Silverstripe 4.x.
|
||||
This branch will aim for compatibility with SilverStripe 4.x.
|
||||
|
||||
## Installation
|
||||
```bash
|
||||
composer require symbiote/silverstripe-gridfieldextensions:^3
|
||||
```
|
||||
For SilverStripe 3.x, please see the [compatible branch](https://github.com/symbiote/silverstripe-gridfieldextensions/tree/2).
|
||||
|
||||
For Silverstripe 3.x, please see the [compatible branch](https://github.com/symbiote/silverstripe-gridfieldextensions/tree/2).
|
||||
|
||||
See [docs/en/index.md](docs/en/index.md) for documentation and examples.
|
||||
|
@ -2,8 +2,4 @@
|
||||
name: gridfieldextensions
|
||||
---
|
||||
GridFieldAddNewMultiClass:
|
||||
showEmptyString: true
|
||||
|
||||
SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest:
|
||||
extensions:
|
||||
- Symbiote\GridFieldExtensions\Extensions\GridFieldDetailFormItemRequestExtension
|
||||
showEmptyString: true
|
@ -1,14 +0,0 @@
|
||||
// This file was generated by silverstripe/tx-translator from client/lang/src/en.json.
|
||||
// See https://github.com/silverstripe/silverstripe-tx-translator for details
|
||||
if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') {
|
||||
if (typeof(console) !== 'undefined') { // eslint-disable-line no-console
|
||||
console.error('Class ss.i18n not defined'); // eslint-disable-line no-console
|
||||
}
|
||||
} else {
|
||||
ss.i18n.addDictionary('en', {
|
||||
"GridFieldExtensions.ADD_CLASS": "Add: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Are you sure you want to delete this?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Open search and filter",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Save & publish"
|
||||
});
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This file was generated by silverstripe/tx-translator from client/lang/src/eo.json.
|
||||
// See https://github.com/silverstripe/silverstripe-tx-translator for details
|
||||
if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') {
|
||||
if (typeof(console) !== 'undefined') { // eslint-disable-line no-console
|
||||
console.error('Class ss.i18n not defined'); // eslint-disable-line no-console
|
||||
}
|
||||
} else {
|
||||
ss.i18n.addDictionary('eo', {
|
||||
"GridFieldExtensions.ADD_CLASS": "Aldoni: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Ĉu vi certas ke vi volas forigi tion?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Malfermi serĉon kaj filtrilon",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Konservi kaj publikigi"
|
||||
});
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This file was generated by silverstripe/tx-translator from client/lang/src/nl_NL.json.
|
||||
// See https://github.com/silverstripe/silverstripe-tx-translator for details
|
||||
if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') {
|
||||
if (typeof(console) !== 'undefined') { // eslint-disable-line no-console
|
||||
console.error('Class ss.i18n not defined'); // eslint-disable-line no-console
|
||||
}
|
||||
} else {
|
||||
ss.i18n.addDictionary('nl_NL', {
|
||||
"GridFieldExtensions.ADD_CLASS": "Toevoegen: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Weet je zeker dat je dit wil verwijderen?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Open zoeken en filteren",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Opslaan & Publiceren"
|
||||
});
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This file was generated by silverstripe/tx-translator from client/lang/src/sk.json.
|
||||
// See https://github.com/silverstripe/silverstripe-tx-translator for details
|
||||
if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') {
|
||||
if (typeof(console) !== 'undefined') { // eslint-disable-line no-console
|
||||
console.error('Class ss.i18n not defined'); // eslint-disable-line no-console
|
||||
}
|
||||
} else {
|
||||
ss.i18n.addDictionary('sk', {
|
||||
"GridFieldExtensions.ADD_CLASS": "Pridať: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Naozaj to chcete odstrániť?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Otvorte vyhľadávanie a filter",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Uložiť a zverejniť"
|
||||
});
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
// This file was generated by silverstripe/tx-translator from client/lang/src/sl.json.
|
||||
// See https://github.com/silverstripe/silverstripe-tx-translator for details
|
||||
if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') {
|
||||
if (typeof(console) !== 'undefined') { // eslint-disable-line no-console
|
||||
console.error('Class ss.i18n not defined'); // eslint-disable-line no-console
|
||||
}
|
||||
} else {
|
||||
ss.i18n.addDictionary('sl', {
|
||||
"GridFieldExtensions.ADD_CLASS": "Dodaj: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Res želite to izbrisati?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Prikaži iskalnik in filtre",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Shrani in objavi"
|
||||
});
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"GridFieldExtensions.ADD_CLASS": "Add: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Are you sure you want to delete this?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Open search and filter",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Save & publish"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"GridFieldExtensions.ADD_CLASS": "Aldoni: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Ĉu vi certas ke vi volas forigi tion?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Malfermi serĉon kaj filtrilon",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Konservi kaj publikigi"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"GridFieldExtensions.ADD_CLASS": "Toevoegen: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Weet je zeker dat je dit wil verwijderen?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Open zoeken en filteren",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Opslaan & Publiceren"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"GridFieldExtensions.ADD_CLASS": "Pridať: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Naozaj to chcete odstrániť?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Otvorte vyhľadávanie a filter",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Uložiť a zverejniť"
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"GridFieldExtensions.ADD_CLASS": "Dodaj: <i>{classname}</i>",
|
||||
"GridFieldExtensions.CONFIRMDEL": "Res želite to izbrisati?",
|
||||
"GridFieldExtensions.OPEN_SEARCH_FILTER": "Prikaži iskalnik in filtre",
|
||||
"GridFieldExtensions.SAVE_PUBLISH": "Shrani in objavi"
|
||||
}
|
@ -1 +0,0 @@
|
||||
When having discussions about this module in issues or pull request please adhere to the [SilverStripe Community Code of Conduct](https://docs.silverstripe.org/en/contributing/code_of_conduct).
|
@ -3,7 +3,7 @@
|
||||
"description": "A collection of useful grid field components",
|
||||
"type": "silverstripe-vendormodule",
|
||||
"homepage": "http://github.com/symbiote/silverstripe-gridfieldextensions",
|
||||
"keywords": ["silverstripe", "gridfield", "sortable", "sort", "sort field"],
|
||||
"keywords": ["silverstripe", "gridfield"],
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
@ -19,24 +19,23 @@
|
||||
"issues": "http://github.com/symbiote/silverstripe-gridfieldextensions/issues"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"silverstripe/vendor-plugin": "^1.0",
|
||||
"silverstripe/framework": "^4.11"
|
||||
"silverstripe/framework": "~4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"phpunit/phpunit": "^5.7",
|
||||
"squizlabs/php_codesniffer": "^3.0",
|
||||
"silverstripe/versioned": "^1"
|
||||
"silverstripe/versioned": "^1@dev"
|
||||
},
|
||||
"extra": {
|
||||
"installer-name": "gridfieldextensions",
|
||||
"screenshots": [
|
||||
"docs/en/_images/editable-rows.png",
|
||||
"docs/en/_images/add-existing-search.png"
|
||||
],
|
||||
"expose": [
|
||||
"css",
|
||||
"javascript",
|
||||
"client/lang"
|
||||
"javascript"
|
||||
]
|
||||
},
|
||||
"replace": {
|
||||
|
@ -42,11 +42,6 @@
|
||||
background: #DFD;
|
||||
}
|
||||
|
||||
.grid-field__table .form-check-input.editable-column-field {
|
||||
margin-top: .9rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/**
|
||||
* GridFieldAddNewMultiClass
|
||||
*/
|
||||
@ -201,25 +196,3 @@
|
||||
.ss-gridfield-configurable-paginator .pagination-page-number input {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.grid-field-inline-new--multi-class-list {
|
||||
display: none;
|
||||
background-color: #008a00;
|
||||
border-radius: 5px;
|
||||
bottom: 3em;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
right: 3em;
|
||||
padding: 10px;
|
||||
position: fixed;
|
||||
|
||||
}
|
||||
.grid-field-inline-new--multi-class-list a {
|
||||
color: #FFF !important;
|
||||
display: block;
|
||||
margin: 5px -10px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
.grid-field-inline-new--multi-class-list__visible {
|
||||
display: block;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ existing records than a basic autocomplete. It uses the search context construct
|
||||
class to provide the search form.
|
||||
|
||||
```php
|
||||
$grid->getConfig()->addComponent(GridFieldAddExistingSearchButton::create());
|
||||
$grid->getConfig()->addComponent(new GridFieldAddExistingSearchButton());
|
||||
```
|
||||
|
||||
Inline Editing
|
||||
@ -19,17 +19,17 @@ This example replaces the default data columns component with an inline editable
|
||||
default add new button with one that adds new records inline.
|
||||
|
||||
```php
|
||||
$grid = GridField::create(
|
||||
$grid = new GridField(
|
||||
'ExampleGrid',
|
||||
'Example Grid',
|
||||
$this->Items(),
|
||||
GridFieldConfig::create()
|
||||
->addComponent(GridFieldButtonRow::create('before'))
|
||||
->addComponent(GridFieldToolbarHeader::create())
|
||||
->addComponent(GridFieldTitleHeader::create())
|
||||
->addComponent(GridFieldEditableColumns::create())
|
||||
->addComponent(GridFieldDeleteAction::create())
|
||||
->addComponent(GridFieldAddNewInlineButton::create())
|
||||
->addComponent(new GridFieldButtonRow('before'))
|
||||
->addComponent(new GridFieldToolbarHeader())
|
||||
->addComponent(new GridFieldTitleHeader())
|
||||
->addComponent(new GridFieldEditableColumns())
|
||||
->addComponent(new GridFieldDeleteAction())
|
||||
->addComponent(new GridFieldAddNewInlineButton())
|
||||
);
|
||||
```
|
||||
|
||||
@ -37,13 +37,13 @@ You can customise the form fields that are used in the grid by calling `setDispl
|
||||
inline editing component. By default field scaffolding will be used.
|
||||
|
||||
```php
|
||||
$grid->getConfig()->getComponentByType(GridFieldEditableColumns::class)->setDisplayFields(array(
|
||||
$grid->getConfig()->getComponentByType('GridFieldEditableColumns')->setDisplayFields(array(
|
||||
'FirstField' => function($record, $column, $grid) {
|
||||
return TextField::create($column);
|
||||
return new TextField($column);
|
||||
},
|
||||
'SecondField' => array(
|
||||
'title' => 'Custom Title',
|
||||
'field' => ReadonlyField::class
|
||||
'field' => 'ReadonlyField'
|
||||
),
|
||||
'ThirdField' => array(
|
||||
'title' => 'Custom Title Two',
|
||||
@ -69,7 +69,7 @@ use SilverStripe\Forms\GridField\GridFieldAddNewButton;
|
||||
|
||||
$grid->getConfig()
|
||||
->removeComponentsByType(GridFieldAddNewButton::class)
|
||||
->addComponent(GridFieldAddNewMultiClass::create());
|
||||
->addComponent(new GridFieldAddNewMultiClass());
|
||||
```
|
||||
|
||||
Orderable Rows
|
||||
@ -82,10 +82,10 @@ the relationship.
|
||||
|
||||
```php
|
||||
// Basic usage, defaults to "Sort" for the sort field.
|
||||
$grid->getConfig()->addComponent(GridFieldOrderableRows::create());
|
||||
$grid->getConfig()->addComponent(new GridFieldOrderableRows());
|
||||
|
||||
// Specifying the sort field.
|
||||
$grid->getConfig()->addComponent(GridFieldOrderableRows::create('SortField'));
|
||||
$grid->getConfig()->addComponent(new GridFieldOrderableRows('SortField'));
|
||||
```
|
||||
|
||||
By default, when you create a new item, it is created with a sort order of "0" - that is, it is added
|
||||
@ -106,17 +106,6 @@ class Item extends DataObject {
|
||||
}
|
||||
```
|
||||
|
||||
### Versioning
|
||||
By default `GridFieldOrderableRows` will handle versioning but won't automatically publish any records. The user will need to go into each record and publish them manually which could get cumbersome for large lists.
|
||||
|
||||
You can configure the list to automatically publish a record if the record is the latest version and is already published. This won't publish any records which have draft changes.
|
||||
|
||||
```php
|
||||
$orderable = GridFieldOrderableRows::create()->setRepublishLiveRecords(true);
|
||||
```
|
||||
|
||||
There are caveats with both approaches so consideration should be made for which approach best suits the requirements.
|
||||
|
||||
**Please NOTE:** There is a limitation when using `GridFieldOrderableRows` on unsaved data objects; namely, that it doesn't work as without data being saved, the list of related objects has no context. Please check `$this->ID` before adding the `GridFieldOrderableRows` component to the grid field config (or even, before adding the gridfield at all).
|
||||
|
||||
Configurable Paginator
|
||||
@ -129,7 +118,7 @@ To use this component you should remove the original paginator component first:
|
||||
```php
|
||||
$gridField->getConfig()
|
||||
->removeComponentsByType('GridFieldPaginator')
|
||||
->addComponent(GridFieldConfigurablePaginator::create());
|
||||
->addComponent(new GridFieldConfigurablePaginator());
|
||||
```
|
||||
|
||||
You can configure the page sizes with the configuration system. Note that merging is the default strategy, so to replace
|
||||
@ -144,7 +133,7 @@ Config::inst()->update('GridFieldConfigurablePaginator', 'default_page_sizes', a
|
||||
You can also override these at call time:
|
||||
|
||||
```php
|
||||
$paginator = GridFieldConfigurablePaginator::create(100, array(100, 200, 500));
|
||||
$paginator = new GridFieldConfigurablePaginator(100, array(100, 200, 500));
|
||||
|
||||
$paginator->setPageSizes(array(200, 500, 1000));
|
||||
$paginator->setItemsPerPage(500);
|
||||
|
@ -208,7 +208,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
$(".grid-field .action.ss-gridfield-delete-inline").entwine({
|
||||
$(".ss-gridfield-delete-inline").entwine({
|
||||
onclick: function() {
|
||||
var msg = ss.i18n._t("GridFieldExtensions.CONFIRMDEL", "Are you sure you want to delete this?");
|
||||
|
||||
@ -237,28 +237,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
$(".action--new__multi-class").entwine({
|
||||
onmatch: function () {
|
||||
const hrefTemplate = this.data('hrefTemplate');
|
||||
const classes = this.data('classes');
|
||||
const liHtml = Object.keys(classes).map(className => {
|
||||
const link = hrefTemplate.replace('{class}', className);
|
||||
const linkText = ss.i18n.inject(
|
||||
ss.i18n._t('GridFieldExtensions.ADD_CLASS', 'Add: <i>{classname}</i>'),
|
||||
{classname: classes[className]}
|
||||
);
|
||||
return `<li><a href="${link}">${linkText}</a></li>`;
|
||||
});
|
||||
|
||||
const listElement = $(`<ul class="grid-field-inline-new--multi-class-list">${liHtml.join('')}</ul>`);
|
||||
listElement.insertBefore(this);
|
||||
|
||||
this.on('click', function () {
|
||||
listElement.toggleClass('grid-field-inline-new--multi-class-list__visible');
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
$(".ss-gridfield-add-new-multi-class select").entwine({
|
||||
onadd: function() {
|
||||
this.update();
|
||||
@ -340,20 +318,13 @@
|
||||
content = '<span class="non-sortable"></span>';
|
||||
self.addClass('show-filter').find('.grid-field__filter-header').show();
|
||||
} else {
|
||||
const contentTitle = ss.i18n._t('GridFieldExtensions.OPEN_SEARCH_FILTER', 'Open search and filter');
|
||||
content = `<button type="button" title="${contentTitle}" name="showFilter" class="btn btn-secondary font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>`;
|
||||
content = '<button type="button" title="Open search and filter" name="showFilter" class="btn btn-secondary font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>';
|
||||
self.removeClass('show-filter').find('.grid-field__filter-header').hide();
|
||||
}
|
||||
|
||||
self.find('.sortable-header th:last').html(content);
|
||||
}
|
||||
|
||||
// update CMS preview
|
||||
var preview = $('.cms-preview');
|
||||
if (preview.length) {
|
||||
preview.entwine('.ss.preview')._initialiseFromContent();
|
||||
}
|
||||
|
||||
form.removeClass('loading');
|
||||
if (successCallback) {
|
||||
successCallback.apply(this, arguments);
|
||||
@ -369,7 +340,7 @@
|
||||
publish.removeClass('font-icon-tick');
|
||||
publish.addClass('btn-primary');
|
||||
publish.addClass('font-icon-rocket');
|
||||
publish.find('.btn__title').html(ss.i18n._t('GridFieldExtensions.SAVE_PUBLISH', 'Save & publish'));
|
||||
publish.find('.btn__title').html('Save & publish');
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
de_DE:
|
||||
GridFieldAddExistingSearchHandler.ss:
|
||||
NOITEMS: 'Kein Ergebnis'
|
||||
RESULTS: Ergebnisse
|
||||
RESULTS: 'Ergebnisse'
|
||||
GridFieldExtensions:
|
||||
ADD: Hinzufügen
|
||||
ADD: 'Hinzufügen'
|
||||
ADDEXISTING: 'Bestehenden Eintrag hinzufügen'
|
||||
SEARCH: Suche
|
||||
SEARCH: 'Suche'
|
||||
SELECTTYPETOCREATE: '(Bitte Typ auswählen)'
|
||||
|
@ -10,7 +10,5 @@ en:
|
||||
RESULTS: Results
|
||||
SEARCH: Search
|
||||
SELECTTYPETOCREATE: '(Select type to create)'
|
||||
Symbiote\GridFieldExtensions\Extensions\GridFieldDetailFormItemRequestExtension:
|
||||
NEW: 'Add new record'
|
||||
Symbiote\GridFieldExtensions\GridFieldConfigurablePaginator:
|
||||
SHOW: Show
|
||||
|
16
lang/eo.yml
16
lang/eo.yml
@ -1,16 +0,0 @@
|
||||
eo:
|
||||
GridFieldExtensions:
|
||||
ADD: Aldoni
|
||||
ADDEXISTING: 'Aldoni ekzistantan'
|
||||
BACK: Antaŭa
|
||||
CURRENT: (aktuala)
|
||||
NOITEMS: 'Mankas elementoj'
|
||||
Next: Sekva
|
||||
PREVIOUS: Antaŭa
|
||||
RESULTS: Rezultoj
|
||||
SEARCH: Serĉi
|
||||
SELECTTYPETOCREATE: '(Elektu tipon kreotan)'
|
||||
Symbiote\GridFieldExtensions\Extensions\GridFieldDetailFormItemRequestExtension:
|
||||
NEW: 'Aldoni novan rikordon'
|
||||
Symbiote\GridFieldExtensions\GridFieldConfigurablePaginator:
|
||||
SHOW: Vidigi
|
@ -1,9 +1,9 @@
|
||||
es_ES:
|
||||
GridFieldAddExistingSearchHandler.ss:
|
||||
NOITEMS: 'No hay items.'
|
||||
RESULTS: Resultados
|
||||
RESULTS: 'Resultados'
|
||||
GridFieldExtensions:
|
||||
ADD: Agregar
|
||||
ADD: 'Agregar'
|
||||
ADDEXISTING: 'Agregar existente'
|
||||
SEARCH: Buscar
|
||||
SEARCH: 'Buscar'
|
||||
SELECTTYPETOCREATE: '(Seleccionar tipo para crear)'
|
||||
|
@ -1,7 +1,7 @@
|
||||
et_EE:
|
||||
GridFieldAddExistingSearchHandler.ss:
|
||||
NOITEMS: 'Kirjed puuduvad.'
|
||||
RESULTS: Tulemused
|
||||
RESULTS: 'Tulemused'
|
||||
GridFieldExtensions:
|
||||
ADD: Lisa
|
||||
ADDEXISTING: 'Lisa olemasolev'
|
||||
|
@ -1,9 +1,9 @@
|
||||
fi_FI:
|
||||
GridFieldAddExistingSearchHandler.ss:
|
||||
NOITEMS: 'Ei kohteita'
|
||||
RESULTS: Tulokset
|
||||
RESULTS: 'Tulokset'
|
||||
GridFieldExtensions:
|
||||
ADD: Lisää
|
||||
ADD: 'Lisää'
|
||||
ADDEXISTING: 'Lisää olemassa oleva'
|
||||
SEARCH: Etsi
|
||||
SEARCH: 'Etsi'
|
||||
SELECTTYPETOCREATE: 'Valitse lisättävä tyyppi'
|
||||
|
@ -1,9 +1,9 @@
|
||||
it_IT:
|
||||
GridFieldAddExistingSearchHandler.ss:
|
||||
NOITEMS: 'Nessun elemento.'
|
||||
RESULTS: Risultati
|
||||
RESULTS: 'Risultati'
|
||||
GridFieldExtensions:
|
||||
ADD: Aggiungi
|
||||
ADD: 'Aggiungi'
|
||||
ADDEXISTING: 'Aggiungi esistente'
|
||||
SEARCH: Cerca
|
||||
SEARCH: 'Cerca'
|
||||
SELECTTYPETOCREATE: '(Seleziona tipo per creare)'
|
||||
|
@ -1,19 +1,9 @@
|
||||
nl_NL:
|
||||
GridFieldAddExistingSearchHandler.ss:
|
||||
NOITEMS: 'Geen resultaten gevonden.'
|
||||
RESULTS: Resultaten
|
||||
RESULTS: 'Resultaten'
|
||||
GridFieldExtensions:
|
||||
ADD: Toevoegen
|
||||
ADD: 'Toevoegen'
|
||||
ADDEXISTING: 'Bestaande toevoegen'
|
||||
BACK: Terug
|
||||
CURRENT: (huidige)
|
||||
NOITEMS: 'Er zijn geen items.'
|
||||
Next: Volgende
|
||||
PREVIOUS: Vorige
|
||||
RESULTS: Resultaten
|
||||
SEARCH: Zoeken
|
||||
SEARCH: 'Zoeken'
|
||||
SELECTTYPETOCREATE: '(Selecteer type om te creeën)'
|
||||
Symbiote\GridFieldExtensions\Extensions\GridFieldDetailFormItemRequestExtension:
|
||||
NEW: 'Nieuw item maken'
|
||||
Symbiote\GridFieldExtensions\GridFieldConfigurablePaginator:
|
||||
SHOW: Toon
|
||||
|
@ -1,9 +1,9 @@
|
||||
ru_RU:
|
||||
GridFieldAddExistingSearchHandler.ss:
|
||||
NOITEMS: 'Нет элементов.'
|
||||
RESULTS: Результаты
|
||||
RESULTS: 'Результаты'
|
||||
GridFieldExtensions:
|
||||
ADD: Добавить
|
||||
ADD: 'Добавить'
|
||||
ADDEXISTING: 'Добавить существующий'
|
||||
SEARCH: Поиск
|
||||
SEARCH: 'Поиск'
|
||||
SELECTTYPETOCREATE: '(Выберите тип для создания)'
|
||||
|
16
lang/sk.yml
16
lang/sk.yml
@ -1,19 +1,9 @@
|
||||
sk:
|
||||
GridFieldAddExistingSearchHandler.ss:
|
||||
NOITEMS: 'Nie sú tu žiadne položky.'
|
||||
RESULTS: Výsledky
|
||||
RESULTS: 'Výsledky'
|
||||
GridFieldExtensions:
|
||||
ADD: Pridať
|
||||
ADDEXISTING: 'Pridať existujúci'
|
||||
BACK: Späť
|
||||
CURRENT: (aktuálny)
|
||||
NOITEMS: 'Nie sú k dispozícii žiadne položky.'
|
||||
Next: Ďalší
|
||||
PREVIOUS: Predchádzajúci
|
||||
RESULTS: Výsledky
|
||||
ADDEXISTING: Pridať existujúci
|
||||
SEARCH: Hľadať
|
||||
SELECTTYPETOCREATE: '(Vyberte typ na vytvorenie)'
|
||||
Symbiote\GridFieldExtensions\Extensions\GridFieldDetailFormItemRequestExtension:
|
||||
NEW: 'Pridať nový záznam'
|
||||
Symbiote\GridFieldExtensions\GridFieldConfigurablePaginator:
|
||||
SHOW: Zobraziť
|
||||
SELECTTYPETOCREATE: '(Prosím, vyberte typ)'
|
||||
|
16
lang/sl.yml
16
lang/sl.yml
@ -1,16 +0,0 @@
|
||||
sl:
|
||||
GridFieldExtensions:
|
||||
ADD: Dodaj
|
||||
ADDEXISTING: 'Dodaj obstoječe'
|
||||
BACK: Nazaj
|
||||
CURRENT: (trenutno)
|
||||
NOITEMS: 'Ni nobenih elementov.'
|
||||
Next: Naslednja
|
||||
PREVIOUS: Prejšnja
|
||||
RESULTS: Rezultati
|
||||
SEARCH: Iskanje
|
||||
SELECTTYPETOCREATE: '(Izberite tip, ki ga želite ustvariti)'
|
||||
Symbiote\GridFieldExtensions\Extensions\GridFieldDetailFormItemRequestExtension:
|
||||
NEW: 'Dodaj zapis'
|
||||
Symbiote\GridFieldExtensions\GridFieldConfigurablePaginator:
|
||||
SHOW: Prikaži
|
16
lang/sv.yml
16
lang/sv.yml
@ -1,16 +0,0 @@
|
||||
sv:
|
||||
GridFieldExtensions:
|
||||
ADD: 'Lägg till'
|
||||
ADDEXISTING: 'Lägg till existerande'
|
||||
BACK: Tillbaka
|
||||
CURRENT: (befintliga)
|
||||
NOITEMS: 'Hittade ingen data.'
|
||||
Next: Nästa
|
||||
PREVIOUS: Föregående
|
||||
RESULTS: Resultat
|
||||
SEARCH: Sök
|
||||
SELECTTYPETOCREATE: '(Välj för att skapa)'
|
||||
Symbiote\GridFieldExtensions\Extensions\GridFieldDetailFormItemRequestExtension:
|
||||
NEW: 'Lägg till ny rad'
|
||||
Symbiote\GridFieldExtensions\GridFieldConfigurablePaginator:
|
||||
SHOW: Visa
|
@ -2,9 +2,6 @@
|
||||
<ruleset name="SilverStripe">
|
||||
<description>CodeSniffer ruleset for SilverStripe coding conventions.</description>
|
||||
|
||||
<file>src</file>
|
||||
<file>tests</file>
|
||||
|
||||
<rule ref="PSR2" >
|
||||
<!-- Current exclusions -->
|
||||
<exclude name="PSR1.Methods.CamelCapsMethodName" />
|
||||
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit bootstrap="vendor/silverstripe/framework/tests/bootstrap.php" colors="true">
|
||||
<testsuite name="Default">
|
||||
<directory>tests</directory>
|
||||
|
@ -1,83 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Extensions;
|
||||
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Extension;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest as CoreGridFieldDetailForm_ItemRequest;
|
||||
use SilverStripe\Forms\LiteralField;
|
||||
use SilverStripe\View\ArrayData;
|
||||
use SilverStripe\View\HTML;
|
||||
use Symbiote\GridFieldExtensions\GridFieldAddNewMultiClass;
|
||||
use Symbiote\GridFieldExtensions\GridFieldExtensions;
|
||||
|
||||
/**
|
||||
* @property CoreGridFieldDetailForm_ItemRequest $owner
|
||||
*/
|
||||
class GridFieldDetailFormItemRequestExtension extends Extension
|
||||
{
|
||||
/**
|
||||
* @param FieldList $actions
|
||||
*/
|
||||
public function updateFormActions(FieldList &$actions)
|
||||
{
|
||||
$grid = $this->owner->getGridField();
|
||||
$gridFieldConfig = $grid->getConfig();
|
||||
$addMultiClassComponent = $gridFieldConfig->getComponentByType(GridFieldAddNewMultiClass::class);
|
||||
if ($addMultiClassComponent) {
|
||||
$newRecordField = static::get_new_record_field_from_actions($actions);
|
||||
if ($newRecordField) {
|
||||
$newRecordField->getContainerFieldList()->removeByName('new-record');
|
||||
$newRecordField->getContainerFieldList()->push(
|
||||
LiteralField::create('new-record', $this->getHTMLFragment($addMultiClassComponent))
|
||||
);
|
||||
GridFieldExtensions::include_requirements();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private function getHTMLFragment(GridFieldAddNewMultiClass $component)
|
||||
{
|
||||
$grid = $this->owner->getGridField();
|
||||
|
||||
$classes = $component->getClasses($grid);
|
||||
|
||||
if (!count($classes ?? [])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return HTML::createTag('a', [
|
||||
'data-href-template' => Controller::join_links($grid->Link(), 'add-multi-class', '{class}'),
|
||||
'title' => _t(__CLASS__ . '.NEW', 'Add new record'),
|
||||
'aria-label' => _t(__CLASS__ . '.NEW', 'Add new record'),
|
||||
'class' => implode(' ', array(
|
||||
'btn',
|
||||
'btn-primary',
|
||||
'font-icon-plus-thin',
|
||||
'btn--circular',
|
||||
'action--new',
|
||||
'discard-confirmation',
|
||||
'action--new__multi-class',
|
||||
)),
|
||||
'data-classes' => json_encode($classes),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FieldList $actions
|
||||
* @return LiteralField OR NULL
|
||||
*/
|
||||
private static function get_new_record_field_from_actions(FieldList &$actions)
|
||||
{
|
||||
$rightGroup = $actions->fieldByName('RightGroup');
|
||||
if (!$rightGroup) {
|
||||
return null;
|
||||
}
|
||||
return $rightGroup->getChildren()->fieldByName('new-record');
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace Symbiote\GridFieldExtensions;
|
||||
|
||||
use SilverStripe\Forms\GridField\AbstractGridFieldComponent;
|
||||
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
|
||||
use SilverStripe\Forms\GridField\GridField_URLHandler;
|
||||
use SilverStripe\ORM\SS_List;
|
||||
@ -12,9 +11,7 @@ use SilverStripe\View\ArrayData;
|
||||
* A modal search dialog which uses search context to search for and add
|
||||
* existing records to a grid field.
|
||||
*/
|
||||
class GridFieldAddExistingSearchButton extends AbstractGridFieldComponent implements
|
||||
GridField_HTMLProvider,
|
||||
GridField_URLHandler
|
||||
class GridFieldAddExistingSearchButton implements GridField_HTMLProvider, GridField_URLHandler
|
||||
{
|
||||
|
||||
private static $allowed_actions = array(
|
||||
@ -114,6 +111,6 @@ class GridFieldAddExistingSearchButton extends AbstractGridFieldComponent implem
|
||||
|
||||
public function handleSearch($grid, $request)
|
||||
{
|
||||
return GridFieldAddExistingSearchHandler::create($grid, $this);
|
||||
return new GridFieldAddExistingSearchHandler($grid, $this);
|
||||
}
|
||||
}
|
||||
|
@ -94,9 +94,9 @@ class GridFieldAddExistingSearchHandler extends RequestHandler
|
||||
|
||||
public function doSearch($data, $form)
|
||||
{
|
||||
$list = $this->context->getQuery($data, false, null, $this->getSearchList());
|
||||
$list = $this->context->getQuery($data, false, false, $this->getSearchList());
|
||||
$list = $list->subtract($this->grid->getList());
|
||||
$list = PaginatedList::create($list, $this->request);
|
||||
$list = new PaginatedList($list, $this->request);
|
||||
|
||||
$data = $this->customise(array(
|
||||
'SearchForm' => $form,
|
||||
@ -109,7 +109,7 @@ class GridFieldAddExistingSearchHandler extends RequestHandler
|
||||
{
|
||||
$list = $this->getSearchList();
|
||||
$list = $list->subtract($this->grid->getList());
|
||||
$list = PaginatedList::create($list, $this->request);
|
||||
$list = new PaginatedList($list, $this->request);
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ namespace Symbiote\GridFieldExtensions;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\GridField\AbstractGridFieldComponent;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
|
||||
use SilverStripe\Forms\GridField\GridField_SaveHandler;
|
||||
@ -14,7 +13,6 @@ use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectInterface;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\ORM\ManyManyList;
|
||||
use SilverStripe\ORM\ManyManyThroughList;
|
||||
use SilverStripe\View\ArrayData;
|
||||
use SilverStripe\View\Requirements;
|
||||
use Exception;
|
||||
@ -22,9 +20,7 @@ use Exception;
|
||||
/**
|
||||
* Builds on the {@link GridFieldEditableColumns} component to allow creating new records.
|
||||
*/
|
||||
class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
GridField_HTMLProvider,
|
||||
GridField_SaveHandler
|
||||
class GridFieldAddNewInlineButton implements GridField_HTMLProvider, GridField_SaveHandler
|
||||
{
|
||||
/**
|
||||
* @skipUpgrade
|
||||
@ -105,7 +101,7 @@ class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
Requirements::javascript('symbiote/silverstripe-gridfieldextensions:javascript/tmpl.js');
|
||||
GridFieldExtensions::include_requirements();
|
||||
|
||||
$data = ArrayData::create(array(
|
||||
$data = new ArrayData(array(
|
||||
'Title' => $this->getTitle(),
|
||||
));
|
||||
|
||||
@ -117,8 +113,8 @@ class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
|
||||
private function getRowTemplate(GridField $grid, GridFieldEditableColumns $editable)
|
||||
{
|
||||
$columns = ArrayList::create();
|
||||
$handled = array_keys($editable->getDisplayFields($grid) ?? []);
|
||||
$columns = new ArrayList();
|
||||
$handled = array_keys($editable->getDisplayFields($grid));
|
||||
|
||||
if ($grid->getList()) {
|
||||
$record = Injector::inst()->create($grid->getModelClass());
|
||||
@ -129,7 +125,7 @@ class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
$fields = $editable->getFields($grid, $record);
|
||||
|
||||
foreach ($grid->getColumns() as $column) {
|
||||
if (in_array($column, $handled ?? [])) {
|
||||
if (in_array($column, $handled)) {
|
||||
$field = $fields->dataFieldByName($column);
|
||||
$field->setName(sprintf(
|
||||
'%s[%s][{%%=o.num%%}][%s]',
|
||||
@ -138,9 +134,6 @@ class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
$field->getName()
|
||||
));
|
||||
|
||||
if ($record && $record->hasField($column)) {
|
||||
$field->setValue($record->getField($column));
|
||||
}
|
||||
$content = $field->Field();
|
||||
} else {
|
||||
$content = $grid->getColumnContent($record, $column);
|
||||
@ -149,7 +142,7 @@ class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
$content = str_replace(
|
||||
sprintf('[%s][0]', GridFieldEditableColumns::POST_KEY),
|
||||
sprintf('[%s][{%%=o.num%%}]', self::POST_KEY),
|
||||
$content ?? ''
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
@ -164,7 +157,7 @@ class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
$attrs .= sprintf(' %s="%s"', $attr, Convert::raw2att($val));
|
||||
}
|
||||
|
||||
$columns->push(ArrayData::create(array(
|
||||
$columns->push(new ArrayData(array(
|
||||
'Content' => $content,
|
||||
'Attributes' => DBField::create_field('HTMLFragment', $attrs),
|
||||
'IsActions' => $column == 'Actions'
|
||||
@ -196,15 +189,9 @@ class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
foreach ($value[self::POST_KEY] as $fields) {
|
||||
/** @var DataObject $item */
|
||||
$item = $class::create();
|
||||
|
||||
// Add the item before the form is loaded so that the join-object is available
|
||||
if ($list instanceof ManyManyThroughList) {
|
||||
$list->add($item);
|
||||
}
|
||||
|
||||
$extra = array();
|
||||
|
||||
$form = $editable->getForm($grid, $item);
|
||||
$form = $editable->getForm($grid, $record);
|
||||
$form->loadDataFrom($fields, Form::MERGE_CLEAR_MISSING);
|
||||
$form->saveInto($item);
|
||||
|
||||
@ -215,15 +202,11 @@ class GridFieldAddNewInlineButton extends AbstractGridFieldComponent implements
|
||||
}
|
||||
|
||||
if ($list instanceof ManyManyList) {
|
||||
$extra = array_intersect_key($form->getData() ?? [], (array) $list->getExtraFields());
|
||||
$extra = array_intersect_key($form->getData(), (array) $list->getExtraFields());
|
||||
}
|
||||
|
||||
$item->write(false, false, false, true);
|
||||
|
||||
// Add non-through lists after the write. many_many_extraFields are added there too
|
||||
if (!($list instanceof ManyManyThroughList)) {
|
||||
$list->add($item, $extra);
|
||||
}
|
||||
$item->write();
|
||||
$list->add($item, $extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Forms\DropdownField;
|
||||
use SilverStripe\Forms\GridField\AbstractGridFieldComponent;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
|
||||
use SilverStripe\Forms\GridField\GridField_URLHandler;
|
||||
@ -24,9 +23,7 @@ use Exception;
|
||||
* By default the list of classes that are createable is the grid field's model class, and any
|
||||
* subclasses. This can be customised using {@link setClasses()}.
|
||||
*/
|
||||
class GridFieldAddNewMultiClass extends AbstractGridFieldComponent implements
|
||||
GridField_HTMLProvider,
|
||||
GridField_URLHandler
|
||||
class GridFieldAddNewMultiClass implements GridField_HTMLProvider, GridField_URLHandler
|
||||
{
|
||||
/**
|
||||
* @skipUpgrade
|
||||
@ -124,7 +121,7 @@ class GridFieldAddNewMultiClass extends AbstractGridFieldComponent implements
|
||||
$result = array();
|
||||
|
||||
if (is_null($this->classes)) {
|
||||
$classes = array_values(ClassInfo::subclassesFor($grid->getModelClass()) ?? []);
|
||||
$classes = array_values(ClassInfo::subclassesFor($grid->getModelClass()));
|
||||
sort($classes);
|
||||
} else {
|
||||
$classes = $this->classes;
|
||||
@ -135,7 +132,7 @@ class GridFieldAddNewMultiClass extends AbstractGridFieldComponent implements
|
||||
if (!is_string($class)) {
|
||||
$class = $title;
|
||||
}
|
||||
if (!class_exists($class ?? '')) {
|
||||
if (!class_exists($class)) {
|
||||
continue;
|
||||
}
|
||||
$is_abstract = (($reflection = new ReflectionClass($class)) && $reflection->isAbstract());
|
||||
@ -216,7 +213,7 @@ class GridFieldAddNewMultiClass extends AbstractGridFieldComponent implements
|
||||
throw new Exception('The add new multi class component requires the detail form component.');
|
||||
}
|
||||
|
||||
if (!$class || !array_key_exists($class, $classes ?? [])) {
|
||||
if (!$class || !array_key_exists($class, $classes)) {
|
||||
throw new HTTPResponse_Exception(400);
|
||||
}
|
||||
|
||||
@ -241,24 +238,19 @@ class GridFieldAddNewMultiClass extends AbstractGridFieldComponent implements
|
||||
{
|
||||
$classes = $this->getClasses($grid);
|
||||
|
||||
if (!count($classes ?? [])) {
|
||||
if (!count($classes)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
GridFieldExtensions::include_requirements();
|
||||
|
||||
$field = DropdownField::create(
|
||||
sprintf('%s[%s]', __CLASS__, $grid->getName()),
|
||||
'',
|
||||
$classes,
|
||||
$this->defaultClass
|
||||
);
|
||||
$field = new DropdownField(sprintf('%s[%s]', __CLASS__, $grid->getName()), '', $classes, $this->defaultClass);
|
||||
if (Config::inst()->get(__CLASS__, 'showEmptyString')) {
|
||||
$field->setEmptyString(_t('GridFieldExtensions.SELECTTYPETOCREATE', '(Select type to create)'));
|
||||
}
|
||||
$field->addExtraClass('no-change-track');
|
||||
|
||||
$data = ArrayData::create(array(
|
||||
$data = new ArrayData(array(
|
||||
'Title' => $this->getTitle(),
|
||||
'Link' => Controller::join_links($grid->Link(), 'add-multi-class', '{class}'),
|
||||
'ClassField' => $field
|
||||
@ -293,7 +285,7 @@ class GridFieldAddNewMultiClass extends AbstractGridFieldComponent implements
|
||||
*/
|
||||
protected function sanitiseClassName($class)
|
||||
{
|
||||
return str_replace('\\', '-', $class ?? '');
|
||||
return str_replace('\\', '-', $class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -304,6 +296,6 @@ class GridFieldAddNewMultiClass extends AbstractGridFieldComponent implements
|
||||
*/
|
||||
protected function unsanitiseClassName($class)
|
||||
{
|
||||
return str_replace('-', '\\', $class ?? '');
|
||||
return str_replace('-', '\\', $class);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,6 @@ class GridFieldAddNewMultiClassHandler extends GridFieldDetailForm_ItemRequest
|
||||
*/
|
||||
protected function sanitiseClassName($class)
|
||||
{
|
||||
return str_replace('\\', '-', $class ?? '');
|
||||
return str_replace('\\', '-', $class);
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ class GridFieldConfigurablePaginator extends GridFieldPaginator
|
||||
$this->pageSizes = $pageSizes;
|
||||
|
||||
// Reset items per page
|
||||
$this->setItemsPerPage(current($pageSizes ?? []));
|
||||
$this->setItemsPerPage(current($pageSizes));
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -290,34 +290,33 @@ class GridFieldConfigurablePaginator extends GridFieldPaginator
|
||||
'title' => 'First',
|
||||
'args' => array('first-shown' => 1),
|
||||
'extra-class' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-double-left '
|
||||
. 'ss-gridfield-pagination-action ss-gridfield-firstpage',
|
||||
. 'ss-gridfield-firstpage',
|
||||
'disable-previous' => ($this->getCurrentPage() == 1)
|
||||
),
|
||||
'prev' => array(
|
||||
'title' => 'Previous',
|
||||
'args' => array('first-shown' => $arguments['first-shown'] - $this->getItemsPerPage()),
|
||||
'extra-class' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-left '
|
||||
. 'ss-gridfield-pagination-action ss-gridfield-previouspage',
|
||||
. 'ss-gridfield-previouspage',
|
||||
'disable-previous' => ($this->getCurrentPage() == 1)
|
||||
),
|
||||
'next' => array(
|
||||
'title' => 'Next',
|
||||
'args' => array('first-shown' => $arguments['first-shown'] + $this->getItemsPerPage()),
|
||||
'extra-class' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-right '
|
||||
.'ss-gridfield-pagination-action ss-gridfield-nextpage',
|
||||
'extra-class' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-right ss-gridfield-nextpage',
|
||||
'disable-next' => ($this->getCurrentPage() == $arguments['total-pages'])
|
||||
),
|
||||
'last' => array(
|
||||
'title' => 'Last',
|
||||
'args' => array('first-shown' => ($this->getTotalPages() - 1) * $this->getItemsPerPage() + 1),
|
||||
'extra-class' => 'btn btn-secondary btn--hide-text btn-sm font-icon-angle-double-right '
|
||||
. 'ss-gridfield-pagination-action ss-gridfield-lastpage',
|
||||
. 'ss-gridfield-lastpage',
|
||||
'disable-next' => ($this->getCurrentPage() == $arguments['total-pages'])
|
||||
),
|
||||
'pagesize' => array(
|
||||
'title' => 'Page Size',
|
||||
'args' => array('first-shown' => $arguments['first-shown']),
|
||||
'extra-class' => 'ss-gridfield-pagination-action ss-gridfield-pagesize-submit'
|
||||
'extra-class' => 'ss-gridfield-pagesize-submit'
|
||||
),
|
||||
);
|
||||
|
||||
@ -356,7 +355,7 @@ class GridFieldConfigurablePaginator extends GridFieldPaginator
|
||||
return array(
|
||||
'footer' => $forTemplate->renderWith(
|
||||
__CLASS__,
|
||||
array('Colspan' => count($gridField->getColumns() ?? []))
|
||||
array('Colspan' => count($gridField->getColumns()))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -19,12 +19,11 @@ use SilverStripe\Forms\GridField\GridField_URLHandler;
|
||||
use SilverStripe\Forms\HTMLEditor\HTMLEditorField;
|
||||
use SilverStripe\Forms\LiteralField;
|
||||
use SilverStripe\Forms\ReadonlyField;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectInterface;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\ORM\ManyManyList;
|
||||
use SilverStripe\ORM\ManyManyThroughList;
|
||||
|
||||
/**
|
||||
* Allows inline editing of grid field records without having to load a separate
|
||||
@ -57,12 +56,16 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
|
||||
public function getColumnContent($grid, $record, $col)
|
||||
{
|
||||
if (!$record->canEdit()) {
|
||||
return parent::getColumnContent($grid, $record, $col);
|
||||
}
|
||||
|
||||
$fields = $this->getForm($grid, $record)->Fields();
|
||||
|
||||
if (!$this->displayFields) {
|
||||
// If setDisplayFields() not used, utilize $summary_fields
|
||||
// in a way similar to base class
|
||||
$colRelation = explode('.', $col ?? '');
|
||||
$colRelation = explode('.', $col);
|
||||
$value = $grid->getDataFieldValue($record, $colRelation[0]);
|
||||
$field = $fields->fieldByName($colRelation[0]);
|
||||
if (!$field || $field->isReadonly() || $field->isDisabled()) {
|
||||
@ -79,20 +82,15 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
$field = clone $field;
|
||||
} else {
|
||||
$value = $grid->getDataFieldValue($record, $col);
|
||||
$field = $fields->dataFieldByName($col);
|
||||
|
||||
// Fall back to previous logic
|
||||
if (!$field) {
|
||||
$rel = (strpos($col ?? '', '.') === false); // field references a relation value
|
||||
$field = ($rel) ? clone $fields->fieldByName($col) : ReadonlyField::create($col);
|
||||
}
|
||||
$rel = (strpos($col, '.') === false); // field references a relation value
|
||||
$field = ($rel) ? clone $fields->fieldByName($col) : new ReadonlyField($col);
|
||||
|
||||
if (!$field) {
|
||||
throw new Exception("Could not find the field '$col'");
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists($col, $this->fieldCasting ?? [])) {
|
||||
if (array_key_exists($col, $this->fieldCasting)) {
|
||||
$value = $grid->getCastedValue($value, $this->fieldCasting[$col]);
|
||||
}
|
||||
|
||||
@ -101,10 +99,6 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
$field->setName($this->getFieldName($field->getName(), $grid, $record));
|
||||
$field->setValue($value);
|
||||
|
||||
if ($grid->isReadonly() || !$record->canEdit()) {
|
||||
$field = $field->performReadonlyTransformation();
|
||||
}
|
||||
|
||||
if ($field instanceof HtmlEditorField) {
|
||||
return $field->FieldHolder();
|
||||
}
|
||||
@ -131,33 +125,23 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
/** @var GridFieldOrderableRows $sortable */
|
||||
$sortable = $grid->getConfig()->getComponentByType(GridFieldOrderableRows::class);
|
||||
|
||||
// Fetch the items before processing them
|
||||
$ids = array_keys($value[self::POST_KEY]);
|
||||
if (empty($ids)) {
|
||||
return;
|
||||
}
|
||||
$itemsCollection = ArrayList::create($list->filter('ID', $ids)->toArray());
|
||||
|
||||
foreach ($value[self::POST_KEY] as $id => $fields) {
|
||||
if (!is_numeric($id) || !is_array($fields)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the item from the fetched collection of items
|
||||
$item = $itemsCollection->find('ID', $id);
|
||||
$item = $list->byID($id);
|
||||
|
||||
// Skip not found item, or don't have any changed fields, or current user can't edit
|
||||
if (!$item || !$this->isChanged($item, $fields) || !$item->canEdit()) {
|
||||
if (!$item || !$item->canEdit()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extra = array();
|
||||
|
||||
$form = $this->getForm($grid, $item);
|
||||
$form = $this->getForm($grid, $record);
|
||||
$form->loadDataFrom($fields, Form::MERGE_CLEAR_MISSING);
|
||||
$form->saveInto($item);
|
||||
|
||||
|
||||
// Check if we are also sorting these records
|
||||
if ($sortable) {
|
||||
$sortField = $sortable->getSortField();
|
||||
@ -166,11 +150,11 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
}
|
||||
}
|
||||
|
||||
if ($list instanceof ManyManyList || $list instanceof ManyManyThroughList) {
|
||||
$extra = array_intersect_key($form->getData() ?? [], (array) $list->getExtraFields());
|
||||
if ($list instanceof ManyManyList) {
|
||||
$extra = array_intersect_key($form->getData(), (array) $list->getExtraFields());
|
||||
}
|
||||
|
||||
$item->write(false, false, false, true);
|
||||
$item->write();
|
||||
$list->add($item, $extra);
|
||||
}
|
||||
}
|
||||
@ -221,7 +205,7 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
public function getFields(GridField $grid, DataObjectInterface $record)
|
||||
{
|
||||
$cols = $this->getDisplayFields($grid);
|
||||
$fields = FieldList::create();
|
||||
$fields = new FieldList();
|
||||
|
||||
/** @var DataList $list */
|
||||
$list = $grid->getList();
|
||||
@ -251,10 +235,10 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
}
|
||||
}
|
||||
|
||||
if (!$field && ($list instanceof ManyManyList || $list instanceof ManyManyThroughList)) {
|
||||
if (!$field && $list instanceof ManyManyList) {
|
||||
$extra = $list->getExtraFields();
|
||||
|
||||
if ($extra && array_key_exists($col, $extra ?? [])) {
|
||||
if ($extra && array_key_exists($col, $extra)) {
|
||||
$field = Injector::inst()->create($extra[$col], $col)->scaffoldFormField();
|
||||
}
|
||||
}
|
||||
@ -269,16 +253,16 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
// revert to looking good in cases where the field isn't
|
||||
// available or is readonly
|
||||
//
|
||||
$colRelation = explode('.', $col ?? '');
|
||||
$colRelation = explode('.', $col);
|
||||
if ($class && $obj = DataObject::singleton($class)->dbObject($colRelation[0])) {
|
||||
$field = $obj->scaffoldFormField();
|
||||
} else {
|
||||
$field = ReadonlyField::create($colRelation[0]);
|
||||
$field = new ReadonlyField($colRelation[0]);
|
||||
}
|
||||
} elseif ($class && $obj = DataObject::singleton($class)->dbObject($col)) {
|
||||
$field = $obj->scaffoldFormField();
|
||||
} else {
|
||||
$field = ReadonlyField::create($col);
|
||||
$field = new ReadonlyField($col);
|
||||
}
|
||||
}
|
||||
|
||||
@ -311,7 +295,7 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
{
|
||||
$fields = $this->getFields($grid, $record);
|
||||
|
||||
$form = Form::create($grid, null, $fields, FieldList::create());
|
||||
$form = new Form($grid, null, $fields, new FieldList());
|
||||
$form->loadDataFrom($record);
|
||||
|
||||
$form->setFormAction(Controller::join_links(
|
||||
@ -333,18 +317,4 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements
|
||||
$name
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not an object in the grid field has changed data.
|
||||
*/
|
||||
private function isChanged(DataObject $item, array $fields): bool
|
||||
{
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($item->getField($name) !== $value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class GridFieldExternalLink extends GridFieldDataColumns
|
||||
*/
|
||||
public function augmentColumns($gridField, &$columns)
|
||||
{
|
||||
if (!in_array('Actions', $columns ?? [])) {
|
||||
if (!in_array('Actions', $columns)) {
|
||||
$columns[] = 'Actions';
|
||||
}
|
||||
}
|
||||
@ -72,7 +72,7 @@ class GridFieldExternalLink extends GridFieldDataColumns
|
||||
*/
|
||||
public function getColumnContent($gridField, $record, $columnName)
|
||||
{
|
||||
$data = ArrayData::create(array(
|
||||
$data = new ArrayData(array(
|
||||
'Link' => $record->hasMethod('getExternalLink') ? $record->getExternalLink() : $record->ExternalLink,
|
||||
'Text' => $record->hasMethod('getExternalLinkText') ? $record->getExternalLinkText() : 'External Link'
|
||||
));
|
||||
|
@ -2,13 +2,9 @@
|
||||
|
||||
namespace Symbiote\GridFieldExtensions;
|
||||
|
||||
use Exception;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Control\HTTPResponse_Exception;
|
||||
use SilverStripe\Control\RequestHandler;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridField_ColumnProvider;
|
||||
use SilverStripe\Forms\GridField\GridField_DataManipulator;
|
||||
@ -21,13 +17,11 @@ use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectInterface;
|
||||
use SilverStripe\ORM\DataObjectSchema;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||
use SilverStripe\ORM\ManyManyList;
|
||||
use SilverStripe\ORM\ManyManyThroughList;
|
||||
use SilverStripe\ORM\ManyManyThroughQueryManipulator;
|
||||
use SilverStripe\ORM\Map;
|
||||
use SilverStripe\ORM\SS_List;
|
||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
use SilverStripe\View\ViewableData;
|
||||
|
||||
@ -82,15 +76,6 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
*/
|
||||
protected $extraSortFields = null;
|
||||
|
||||
/**
|
||||
* If the items in the list are versioned and this is set to true, then
|
||||
* we will check to see if the version we're sorting is the latest published
|
||||
* version and if so then we will re-publish the item.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $republishLiveRecords = false;
|
||||
|
||||
/**
|
||||
* The number of the column containing the reorder handles
|
||||
*
|
||||
@ -156,40 +141,6 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
return $this->extraSortFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see $republishLiveRecords
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getRepublishLiveRecords()
|
||||
{
|
||||
return $this->republishLiveRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see $republishLiveRecords
|
||||
*
|
||||
* @param boolean $bool
|
||||
* @return GridFieldOrderableRows $this
|
||||
*/
|
||||
public function setRepublishLiveRecords($bool)
|
||||
{
|
||||
$this->republishLiveRecords = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the relationship list is for a type of many_many
|
||||
*
|
||||
* @param SS_List $list
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isManyMany(SS_List $list)
|
||||
{
|
||||
return $list instanceof ManyManyList || $list instanceof ManyManyThroughList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extra sort fields to apply before the sort field.
|
||||
*
|
||||
@ -232,17 +183,10 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
{
|
||||
$field = $this->getSortField();
|
||||
|
||||
// Check extra fields on many many relation types
|
||||
if ($list instanceof ManyManyList) {
|
||||
$extra = $list->getExtraFields();
|
||||
|
||||
if ($extra && array_key_exists($field, $extra ?? [])) {
|
||||
return;
|
||||
}
|
||||
} elseif ($list instanceof ManyManyThroughList) {
|
||||
$manipulator = $this->getManyManyInspector($list);
|
||||
$fieldTable = DataObject::getSchema()->tableForField($manipulator->getJoinClass(), $field);
|
||||
if ($fieldTable) {
|
||||
if ($extra && array_key_exists($field, $extra)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -255,7 +199,7 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Couldn't find the sort field '" . $field . "'");
|
||||
throw new \Exception("Couldn't find the sort field '" . $field . "'");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,22 +211,25 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
public function getSortTable(SS_List $list)
|
||||
{
|
||||
$field = $this->getSortField();
|
||||
|
||||
if ($list instanceof ManyManyList) {
|
||||
$extra = $list->getExtraFields();
|
||||
$table = $list->getJoinTable();
|
||||
if ($extra && array_key_exists($field, $extra ?? [])) {
|
||||
|
||||
if ($extra && array_key_exists($field, $extra)) {
|
||||
return $table;
|
||||
}
|
||||
} elseif ($list instanceof ManyManyThroughList) {
|
||||
return $this->getManyManyInspector($list)->getJoinAlias();
|
||||
}
|
||||
|
||||
$classes = ClassInfo::dataClassesFor($list->dataClass());
|
||||
|
||||
foreach ($classes as $class) {
|
||||
if (singleton($class)->hasDataBaseField($field)) {
|
||||
return DataObject::getSchema()->tableName($class);
|
||||
}
|
||||
}
|
||||
throw new Exception("Couldn't find the sort field '$field'");
|
||||
|
||||
throw new \Exception("Couldn't find the sort field '$field'");
|
||||
}
|
||||
|
||||
public function getURLHandlers($grid)
|
||||
@ -308,8 +255,8 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
|
||||
public function augmentColumns($grid, &$cols)
|
||||
{
|
||||
if (!in_array('Reorder', $cols ?? []) && $grid->getState()->GridFieldOrderableRows->enabled) {
|
||||
array_splice($cols, $this->reorderColumnNumber ?? 0, 0, 'Reorder');
|
||||
if (!in_array('Reorder', $cols) && $grid->getState()->GridFieldOrderableRows->enabled) {
|
||||
array_splice($cols, $this->reorderColumnNumber, 0, 'Reorder');
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,22 +276,7 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
$record->ID,
|
||||
$this->getSortField()
|
||||
);
|
||||
|
||||
// Default: Get the sort field directly from the current record
|
||||
$currentSortValue = $record->getField($this->getSortField());
|
||||
|
||||
$list = $grid->getList();
|
||||
if ($list instanceof ManyManyThroughList) {
|
||||
// In a many many through list we should get the current sort order from the relationship
|
||||
// if it exists, not directly from the record
|
||||
$throughListSorts = $this->getSortValuesFromManyManyThroughList($list, $this->getSortField());
|
||||
|
||||
if (array_key_exists($record->ID, $throughListSorts ?? [])) {
|
||||
$currentSortValue = $throughListSorts[$record->ID];
|
||||
}
|
||||
}
|
||||
|
||||
$sortField = HiddenField::create($sortFieldName, false, $currentSortValue);
|
||||
$sortField = new HiddenField($sortFieldName, false, $record->getField($this->getSortField()));
|
||||
$sortField->addExtraClass('ss-orderable-hidden-sort');
|
||||
$sortField->setForm($grid->getForm());
|
||||
|
||||
@ -392,37 +324,19 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
$sortterm .= $this->getSortTable($list).'.'.$this->getSortField();
|
||||
} else {
|
||||
$sortterm .= '"'.$this->getSortTable($list).'"."'.$this->getSortField().'"';
|
||||
|
||||
if ($list instanceof DataList) {
|
||||
$classname = $list->dataClass();
|
||||
if ($defaultSort = Config::inst()->get($classname, 'default_sort')) {
|
||||
if (is_array($defaultSort)) {
|
||||
$defaultSortArray = [];
|
||||
foreach ($defaultSort as $column => $direction) {
|
||||
$defaultSortArray[] = "\"$column\" $direction";
|
||||
}
|
||||
$defaultSort = implode(', ', $defaultSortArray);
|
||||
}
|
||||
// Append the default sort to the end of the sort string
|
||||
// This may result in redundancy... but it seems to work
|
||||
$sortterm .= ($sortterm ? ', ' : '') . $defaultSort;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $list->sort($sortterm);
|
||||
} else {
|
||||
return $list;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles requests to reorder a set of IDs in a specific order.
|
||||
*
|
||||
* @param GridField $grid
|
||||
* @param HTTPRequest $request
|
||||
* @return string
|
||||
* @throws HTTPResponse_Exception
|
||||
* @param SS_HTTPRequest $request
|
||||
* @return SS_HTTPResponse
|
||||
*/
|
||||
public function handleReorder($grid, $request)
|
||||
{
|
||||
@ -431,10 +345,9 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
}
|
||||
$list = $grid->getList();
|
||||
$modelClass = $grid->getModelClass();
|
||||
$isManyMany = $this->isManyMany($list);
|
||||
if ($isManyMany && !singleton($modelClass)->canView()) {
|
||||
if ($list instanceof ManyManyList && !singleton($modelClass)->canView()) {
|
||||
$this->httpError(403);
|
||||
} elseif (!$isManyMany && !singleton($modelClass)->canEdit()) {
|
||||
} elseif (!($list instanceof ManyManyList) && !singleton($modelClass)->canEdit()) {
|
||||
$this->httpError(403);
|
||||
}
|
||||
|
||||
@ -445,29 +358,21 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
}
|
||||
|
||||
// Get records from the `GridFieldEditableColumns` column
|
||||
$gridFieldName = $grid->getName();
|
||||
if (strpos($gridFieldName ?? '', '.') !== false) {
|
||||
$gridFieldName = str_replace('.', '_', $gridFieldName ?? '');
|
||||
}
|
||||
|
||||
$data = $request->postVar($gridFieldName);
|
||||
$data = $request->postVar($grid->getName());
|
||||
$sortedIDs = $this->getSortedIDs($data);
|
||||
if (!$this->executeReorder($grid, $sortedIDs)) {
|
||||
$this->httpError(400);
|
||||
}
|
||||
|
||||
Controller::curr()->getResponse()->addHeader(
|
||||
'X-Status',
|
||||
rawurlencode(_t(__CLASS__ . '.REORDERED', 'Records reordered.'))
|
||||
);
|
||||
Controller::curr()->getResponse()->addHeader('X-Status', rawurlencode('Records reordered.'));
|
||||
return $grid->FieldHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mapping of sort value to item ID from posted data (gridfield list state), ordered by sort value.
|
||||
* Get mapping of sort value to ID from posted data
|
||||
*
|
||||
* @param array $data Raw posted data
|
||||
* @return array [sortIndex => recordID]
|
||||
* @return array
|
||||
*/
|
||||
protected function getSortedIDs($data)
|
||||
{
|
||||
@ -570,10 +475,10 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
*/
|
||||
protected function executeReorder(GridField $grid, $sortedIDs)
|
||||
{
|
||||
if (!is_array($sortedIDs) || empty($sortedIDs)) {
|
||||
if (!is_array($sortedIDs)) {
|
||||
return false;
|
||||
}
|
||||
$sortField = $this->getSortField();
|
||||
$field = $this->getSortField();
|
||||
|
||||
$sortterm = '';
|
||||
if ($this->extraSortFields) {
|
||||
@ -586,11 +491,11 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
}
|
||||
}
|
||||
$list = $grid->getList();
|
||||
$sortterm .= '"'.$this->getSortTable($list).'"."'.$sortField.'"';
|
||||
$sortterm .= '"'.$this->getSortTable($list).'"."'.$field.'"';
|
||||
$items = $list->filter('ID', $sortedIDs)->sort($sortterm);
|
||||
|
||||
// Ensure that each provided ID corresponded to an actual object.
|
||||
if (count($items ?? []) != count($sortedIDs ?? [])) {
|
||||
if (count($items) != count($sortedIDs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -607,13 +512,11 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
if (isset($record->_SortColumn0)) {
|
||||
$current[$record->ID] = $record->_SortColumn0;
|
||||
} else {
|
||||
$current[$record->ID] = $record->$sortField;
|
||||
$current[$record->ID] = $record->$field;
|
||||
}
|
||||
}
|
||||
} elseif ($items instanceof ManyManyThroughList) {
|
||||
$current = $this->getSortValuesFromManyManyThroughList($list, $sortField);
|
||||
} else {
|
||||
$current = $items->map('ID', $sortField)->toArray();
|
||||
$current = $items->map('ID', $field)->toArray();
|
||||
}
|
||||
|
||||
// Perform the actual re-ordering.
|
||||
@ -621,68 +524,72 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SS_List $list
|
||||
* @param array $values **UNUSED** [listItemID => currentSortValue];
|
||||
* @param array $sortedIDs [newSortValue => listItemID]
|
||||
*/
|
||||
protected function reorderItems($list, array $values, array $sortedIDs)
|
||||
{
|
||||
$this->extend('onBeforeReorderItems', $list, $values, $sortedIDs);
|
||||
|
||||
// setup
|
||||
$sortField = $this->getSortField();
|
||||
// The problem is that $sortedIDs is a list of the _related_ item IDs, which causes trouble
|
||||
// with ManyManyThrough, where we need the ID of the _join_ item in order to set the value.
|
||||
$itemToSortReference = ($list instanceof ManyManyThroughList) ? 'getJoin' : 'Me';
|
||||
$currentSortList = $list->map('ID', $itemToSortReference)->toArray();
|
||||
/** @var SS_List $map */
|
||||
$map = $list->map('ID', $sortField);
|
||||
//fix for versions of SS that return inconsistent types for `map` function
|
||||
if ($map instanceof Map) {
|
||||
$map = $map->toArray();
|
||||
}
|
||||
|
||||
// sanity check.
|
||||
// If not a ManyManyList and using versioning, detect it.
|
||||
$this->validateSortField($list);
|
||||
$class = $list->dataClass();
|
||||
$isVersioned = $class::has_extension(Versioned::class);
|
||||
|
||||
// ManyManyList extra fields aren't easily updated via the ORM, and so they need to be updated through an SQL
|
||||
// Query
|
||||
if ($list instanceof ManyManyList) {
|
||||
// Loop through each item, and update the sort values which do not
|
||||
// match to order the objects.
|
||||
if (!$isVersioned) {
|
||||
$sortTable = $this->getSortTable($list);
|
||||
$now = DBDatetime::now()->Rfc2822();
|
||||
$additionalSQL = '';
|
||||
$baseTable = $sortTable;
|
||||
if (class_exists($sortTable)) {
|
||||
$baseTable = singleton($sortTable)->baseTable();
|
||||
}
|
||||
$isBaseTable = ($baseTable == $sortTable);
|
||||
if (!$list instanceof ManyManyList && $isBaseTable) {
|
||||
$additionalSQL = ", \"LastEdited\" = '$now'";
|
||||
}
|
||||
|
||||
// Loop through each item, and update the sort values which do not match to order the objects.
|
||||
foreach ($sortedIDs as $newSortValue => $targetRecordID) {
|
||||
if ($currentSortList[$targetRecordID]->$sortField != $newSortValue) {
|
||||
foreach ($sortedIDs as $sortValue => $id) {
|
||||
if ($map[$id] != $sortValue) {
|
||||
DB::query(sprintf(
|
||||
'UPDATE "%s" SET "%s" = %d WHERE %s',
|
||||
'UPDATE "%s" SET "%s" = %d%s WHERE %s',
|
||||
$sortTable,
|
||||
$sortField,
|
||||
$newSortValue,
|
||||
$this->getSortTableClauseForIds($list, $targetRecordID)
|
||||
$sortValue,
|
||||
$additionalSQL,
|
||||
$this->getSortTableClauseForIds($list, $id)
|
||||
));
|
||||
|
||||
if (!$isBaseTable) {
|
||||
DB::query(sprintf(
|
||||
'UPDATE "%s" SET "LastEdited" = \'%s\' WHERE %s',
|
||||
$baseTable,
|
||||
$now,
|
||||
$this->getSortTableClauseForIds($list, $id)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For versioned objects, modify them with the ORM so that the
|
||||
// *_Versions table is updated. This ensures re-ordering works
|
||||
// *_versions table is updated. This ensures re-ordering works
|
||||
// similar to the SiteTree where you change the position, and then
|
||||
// you go into the record and publish it.
|
||||
foreach ($sortedIDs as $newSortValue => $targetRecordID) {
|
||||
// either the list data class (has_many, (belongs_)many_many)
|
||||
// or the intermediary join class (many_many through)
|
||||
$record = $currentSortList[$targetRecordID];
|
||||
|
||||
if ($record->$sortField != $newSortValue) {
|
||||
$record->$sortField = $newSortValue;
|
||||
|
||||
// We need to do this before writing otherwith isLiveVersion() will always be false
|
||||
$shouldRepublish = $this->getRepublishLiveRecords() && $record->isLiveVersion();
|
||||
|
||||
// Write our staged record and publish if required
|
||||
foreach ($sortedIDs as $sortValue => $id) {
|
||||
if ($map[$id] != $sortValue) {
|
||||
$record = $class::get()->byID($id);
|
||||
$record->$sortField = $sortValue;
|
||||
$record->write();
|
||||
if ($shouldRepublish) {
|
||||
$record->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->extend('onAfterReorderItems', $list, $values, $sortedIDs);
|
||||
$this->extend('onAfterReorderItems', $list);
|
||||
}
|
||||
|
||||
protected function populateSortValues(DataList $list)
|
||||
@ -693,8 +600,10 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
$clause = sprintf('"%s"."%s" = 0', $table, $this->getSortField());
|
||||
$now = DBDatetime::now()->Rfc2822();
|
||||
$additionalSQL = '';
|
||||
$baseTable = DataObject::getSchema()->baseDataTable($list->dataClass());
|
||||
|
||||
$baseTable = $table;
|
||||
if (class_exists($table)) {
|
||||
$baseTable = singleton($table)->baseTable();
|
||||
}
|
||||
$isBaseTable = ($baseTable == $table);
|
||||
if (!$list instanceof ManyManyList && $isBaseTable) {
|
||||
$additionalSQL = ", \"LastEdited\" = '$now'";
|
||||
@ -713,7 +622,7 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
$this->getSortTableClauseForIds($list, $id)
|
||||
));
|
||||
|
||||
if (!$isBaseTable && !$this->isManyMany($list)) {
|
||||
if (!$isBaseTable) {
|
||||
DB::query(sprintf(
|
||||
'UPDATE "%s" SET "LastEdited" = \'%s\' WHERE %s',
|
||||
$baseTable,
|
||||
@ -724,36 +633,21 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forms a WHERE clause for the table the sort column is defined on.
|
||||
* e.g. ID = 5
|
||||
* e.g. ID IN(5, 8, 10)
|
||||
* e.g. SortOrder = 5 AND RelatedThing.ID = 3
|
||||
* e.g. SortOrder IN(5, 8, 10) AND RelatedThing.ID = 3
|
||||
*
|
||||
* @param DataList $list
|
||||
* @param int|string|array $ids a single number, or array of numbers
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getSortTableClauseForIds(DataList $list, $ids)
|
||||
{
|
||||
if (is_array($ids)) {
|
||||
$value = 'IN (' . implode(', ', array_map('intval', $ids ?? [])) . ')';
|
||||
$value = 'IN (' . implode(', ', array_map('intval', $ids)) . ')';
|
||||
} else {
|
||||
$value = '= ' . (int) $ids;
|
||||
}
|
||||
|
||||
if ($this->isManyMany($list)) {
|
||||
$introspector = $this->getManyManyInspector($list);
|
||||
$extra = $list instanceof ManyManyList ?
|
||||
$introspector->getExtraFields() :
|
||||
DataObjectSchema::create()->fieldSpecs($introspector->getJoinClass(), DataObjectSchema::DB_ONLY);
|
||||
$key = $introspector->getLocalKey();
|
||||
$foreignKey = $this->getManyManyInspectorForeignKey($introspector);
|
||||
if ($list instanceof ManyManyList) {
|
||||
$extra = $list->getExtraFields();
|
||||
$key = $list->getLocalKey();
|
||||
$foreignKey = $list->getForeignKey();
|
||||
$foreignID = (int) $list->getForeignID();
|
||||
|
||||
if ($extra && array_key_exists($this->getSortField(), $extra ?? [])) {
|
||||
if ($extra && array_key_exists($this->getSortField(), $extra)) {
|
||||
return sprintf(
|
||||
'"%s" %s AND "%s" = %d',
|
||||
$key,
|
||||
@ -766,71 +660,4 @@ class GridFieldOrderableRows extends RequestHandler implements
|
||||
|
||||
return "\"ID\" $value";
|
||||
}
|
||||
|
||||
/**
|
||||
* A ManyManyList defines functions such as getLocalKey, however on ManyManyThroughList
|
||||
* these functions are moved to ManyManyThroughQueryManipulator, but otherwise retain
|
||||
* the same signature.
|
||||
*
|
||||
* @param ManyManyList|ManyManyThroughList $list
|
||||
*
|
||||
* @return ManyManyList|ManyManyThroughQueryManipulator
|
||||
*/
|
||||
protected function getManyManyInspector($list)
|
||||
{
|
||||
$inspector = $list;
|
||||
if ($list instanceof ManyManyThroughList) {
|
||||
foreach ($list->dataQuery()->getDataQueryManipulators() as $manipulator) {
|
||||
if ($manipulator instanceof ManyManyThroughQueryManipulator) {
|
||||
$inspector = $manipulator;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $inspector;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Depending on the list inspector and the list itself (ManyMany vs ManyManyThrough), the method to obtain
|
||||
* the foreign key may be different.
|
||||
*
|
||||
* @param $inspector
|
||||
* @return string
|
||||
*/
|
||||
private function getManyManyInspectorForeignKey($inspector)
|
||||
{
|
||||
if (($inspector instanceof ManyManyThroughQueryManipulator) && (method_exists($inspector, 'getForeignIDKey'))) {
|
||||
// This method has been introduced in framework 4.1
|
||||
return $inspector->getForeignIDKey();
|
||||
}
|
||||
|
||||
return $inspector->getForeignKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get sort orders from a many many through list relationship record, rather than the current
|
||||
* record itself.
|
||||
*
|
||||
* @param ManyManyList|ManyManyThroughList $list
|
||||
* @return int[] Sort orders for the
|
||||
*/
|
||||
protected function getSortValuesFromManyManyThroughList($list, $sortField)
|
||||
{
|
||||
$manipulator = $this->getManyManyInspector($list);
|
||||
|
||||
// Find the foreign key name, ID and class to look up
|
||||
$joinClass = $manipulator->getJoinClass();
|
||||
$fromRelationName = $this->getManyManyInspectorForeignKey($manipulator);
|
||||
$toRelationName = $manipulator->getLocalKey();
|
||||
|
||||
// Create a list of the MMTL relations
|
||||
$sortlist = DataList::create($joinClass)->filter([
|
||||
$toRelationName => $list->column('ID'),
|
||||
// first() is safe as there are earlier checks to ensure our list to sort is valid
|
||||
$fromRelationName => $list->first()->getJoin()->$fromRelationName,
|
||||
]);
|
||||
|
||||
return $sortlist->map($toRelationName, $sortField)->toArray();
|
||||
}
|
||||
}
|
||||
|
@ -83,11 +83,11 @@ abstract class GridFieldRequestHandler extends RequestHandler
|
||||
*/
|
||||
public function Form()
|
||||
{
|
||||
$form = Form::create(
|
||||
$form = new Form(
|
||||
$this,
|
||||
'SilverStripe\\Forms\\Form',
|
||||
FieldList::create($root = TabSet::create('Root', Tab::create('Main'))),
|
||||
FieldList::create()
|
||||
new FieldList($root = new TabSet('Root', new Tab('Main'))),
|
||||
new FieldList()
|
||||
);
|
||||
|
||||
if ($this->getTopLevelController() instanceof LeftAndMain) {
|
||||
@ -136,7 +136,7 @@ abstract class GridFieldRequestHandler extends RequestHandler
|
||||
if ($controller->hasMethod('Breadcrumbs')) {
|
||||
return $controller->Breadcrumbs();
|
||||
} else {
|
||||
return ArrayList::create();
|
||||
return new ArrayList();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace Symbiote\GridFieldExtensions;
|
||||
|
||||
use SilverStripe\Forms\GridField\AbstractGridFieldComponent;
|
||||
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\View\ArrayData;
|
||||
@ -10,17 +9,17 @@ use SilverStripe\View\ArrayData;
|
||||
/**
|
||||
* A simple header which displays column titles.
|
||||
*/
|
||||
class GridFieldTitleHeader extends AbstractGridFieldComponent implements GridField_HTMLProvider
|
||||
class GridFieldTitleHeader implements GridField_HTMLProvider
|
||||
{
|
||||
|
||||
public function getHTMLFragments($grid)
|
||||
{
|
||||
$cols = ArrayList::create();
|
||||
$cols = new ArrayList();
|
||||
|
||||
foreach ($grid->getColumns() as $name) {
|
||||
$meta = $grid->getColumnMetadata($name);
|
||||
|
||||
$cols->push(ArrayData::create(array(
|
||||
$cols->push(new ArrayData(array(
|
||||
'Name' => $name,
|
||||
'Title' => $meta['title']
|
||||
)));
|
||||
|
@ -1,3 +1,3 @@
|
||||
<button href="$Link" class="ss-gridfield-add-new-inline btn btn-primary font-icon-plus-circled">
|
||||
<button href="$Link" class="ss-gridfield-add-new-inline btn btn-primary" data-icon="add">
|
||||
$Title
|
||||
</button>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<td class="grid-field__paginator bottom-all" colspan="$Colspan">
|
||||
<span class="pagination-page-size">
|
||||
<%t Symbiote\\GridFieldExtensions\\GridFieldConfigurablePaginator.SHOW 'Show' is 'Verb. Example: Show 1 of 2' %>
|
||||
<select name="$PageSizesName" class="pagination-page-size-select no-change-track" data-skip-autofocus="true">
|
||||
<select name="$PageSizesName" class="pagination-page-size-select" data-skip-autofocus="true">
|
||||
<% loop $PageSizes %>
|
||||
<option <% if $Selected %>selected="selected"<% end_if %>>$Size</option>
|
||||
<% end_loop %>
|
||||
@ -14,7 +14,7 @@
|
||||
$FirstPage $PreviousPage
|
||||
<span class="pagination-page-number">
|
||||
<%t SilverStripe\\Forms\\GridField\\GridFieldPaginator.Page 'Page' %>
|
||||
<input class="text no-change-track" value="$CurrentPageNum" data-skip-autofocus="true" />
|
||||
<input class="text" value="$CurrentPageNum" data-skip-autofocus="true" />
|
||||
<%t SilverStripe\\Forms\\GridField\\GridFieldPaginator.OF 'of' is 'Example: View 1 of 2' %>
|
||||
$NumPages
|
||||
</span>
|
||||
|
@ -16,7 +16,7 @@ class GridFieldConfigurablePaginatorTest extends SapphireTest
|
||||
*/
|
||||
protected $gridField;
|
||||
|
||||
protected function setUp(): void
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
@ -172,10 +172,12 @@ class GridFieldConfigurablePaginatorTest extends SapphireTest
|
||||
), $paginator->getPageSizesAsList());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
* @expectedExceptionMessage No GridField available yet for this request!
|
||||
*/
|
||||
public function testGetGridFieldThrowsExceptionWhenNotSet()
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('No GridField available yet for this request!');
|
||||
$paginator = new GridFieldConfigurablePaginator;
|
||||
$paginator->getGridField();
|
||||
}
|
||||
@ -203,9 +205,9 @@ class GridFieldConfigurablePaginatorTest extends SapphireTest
|
||||
)
|
||||
);
|
||||
|
||||
$gridField = $this->getMockBuilder(GridField::class)->disableOriginalConstructor()->getMock();
|
||||
$paginator = new GridFieldConfigurablePaginator;
|
||||
$paginator->setGridField($this->gridField);
|
||||
$result = $paginator->getPagerActions($controls, $this->gridField);
|
||||
$result = $paginator->getPagerActions($controls, $gridField);
|
||||
|
||||
$this->assertCount(2, $result);
|
||||
$this->assertArrayHasKey('next', $result);
|
||||
|
@ -1,94 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests;
|
||||
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\TestController;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\StubUnorderable;
|
||||
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
|
||||
use SilverStripe\ORM\FieldType\DBHTMLText;
|
||||
use SilverStripe\Forms\TextField;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
class GridFieldEditableColumnsTest extends SapphireTest
|
||||
{
|
||||
private function getMockGrid()
|
||||
{
|
||||
$controller = new TestController('Test');
|
||||
$form = new Form($controller, 'TestForm', new FieldList(
|
||||
$grid = new GridField('TestGridField')
|
||||
), new FieldList());
|
||||
$grid->setModelClass(StubUnorderable::class);
|
||||
$grid->setList(StubUnorderable::get());
|
||||
return $grid;
|
||||
}
|
||||
|
||||
private function getMockRecord($id, $title)
|
||||
{
|
||||
$record = new StubUnorderable();
|
||||
$record->ID = $id;
|
||||
$record->Title = $title;
|
||||
return $record;
|
||||
}
|
||||
|
||||
public function testProvidesEditableFieldsInColumns()
|
||||
{
|
||||
$grid = $this->getMockGrid();
|
||||
$component = new GridFieldEditableColumns();
|
||||
$record = $this->getMockRecord(100, "foo");
|
||||
|
||||
$this->assertEquals(
|
||||
[ 'Title' ],
|
||||
$component->getColumnsHandled($grid)
|
||||
);
|
||||
|
||||
$record->setCanEdit(true);
|
||||
$column = $component->getColumnContent($grid, $record, 'Title');
|
||||
|
||||
$this->assertInstanceOf(DBHTMLText::class, $column);
|
||||
$this->assertMatchesRegularExpression(
|
||||
'/<input type="text" name="TestGridField\[GridFieldEditableColumns\]\[100\]\[Title\]" value="foo"[^>]*>/',
|
||||
$column->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
public function testProvidesReadonlyColumnsForNoneditableRecords()
|
||||
{
|
||||
$grid = $this->getMockGrid();
|
||||
$component = new GridFieldEditableColumns();
|
||||
$record = $this->getMockRecord(100, "testval");
|
||||
|
||||
$record->setCanEdit(false);
|
||||
$column = $component->getColumnContent($grid, $record, 'Title');
|
||||
|
||||
$this->assertInstanceOf(DBHTMLText::class, $column);
|
||||
$this->assertMatchesRegularExpression(
|
||||
'/<span[^>]*>\s*testval\s*<\/span>/',
|
||||
$column->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
public function testProvidesReadonlyColumnsForReadonlyGrids()
|
||||
{
|
||||
$grid = $this->getMockGrid();
|
||||
$component = new GridFieldEditableColumns();
|
||||
$record = $this->getMockRecord(100, "testval");
|
||||
|
||||
$record->setCanEdit(true);
|
||||
$grid = $grid->performReadonlyTransformation();
|
||||
|
||||
if (!$grid instanceof GridField) {
|
||||
$this->markTestSkipped('silverstripe/framework <4.2.2 doesn\'t support readonly GridFields');
|
||||
}
|
||||
|
||||
$column = $component->getColumnContent($grid, $record, 'Title');
|
||||
|
||||
$this->assertInstanceOf(DBHTMLText::class, $column);
|
||||
$this->assertMatchesRegularExpression(
|
||||
'/<span[^>]*>\s*testval\s*<\/span>/',
|
||||
$column->getValue()
|
||||
);
|
||||
}
|
||||
}
|
@ -6,101 +6,50 @@ use ReflectionMethod;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
||||
use SilverStripe\ORM\DataList;
|
||||
use Symbiote\GridFieldExtensions\GridFieldOrderableRows;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MMapper;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MParent;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\StubOrderableChild;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\StubOrderedVersioned;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\StubParent;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\StubSubclass;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\StubUnorderable;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongs;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongsVersioned;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefiner;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefinerVersioned;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughIntermediary;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\TitleObject;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\TitleSortedObject;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\TitleArraySortedObject;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughIntermediaryVersioned;
|
||||
|
||||
/**
|
||||
* Tests for the {@link GridFieldOrderableRows} component.
|
||||
*/
|
||||
class GridFieldOrderableRowsTest extends SapphireTest
|
||||
{
|
||||
protected static $fixture_file = [
|
||||
'GridFieldOrderableRowsTest.yml',
|
||||
'OrderableRowsThroughTest.yml',
|
||||
// 'OrderablePolymorphicManyToMany.yml' // TODO: introduce this tests in the next minor release
|
||||
];
|
||||
|
||||
protected static $extra_dataobjects = [
|
||||
// PolymorphM2MChild::class,
|
||||
// PolymorphM2MMapper::class,
|
||||
// PolymorphM2MParent::class,
|
||||
protected $usesDatabase = true;
|
||||
|
||||
protected static $fixture_file = 'GridFieldOrderableRowsTest.yml';
|
||||
|
||||
protected static $extra_dataobjects = array(
|
||||
StubParent::class,
|
||||
StubOrdered::class,
|
||||
StubSubclass::class,
|
||||
StubUnorderable::class,
|
||||
StubOrderableChild::class,
|
||||
StubOrderedVersioned::class,
|
||||
StubSubclassOrderedVersioned::class,
|
||||
ThroughDefiner::class,
|
||||
ThroughIntermediary::class,
|
||||
ThroughBelongs::class,
|
||||
TitleObject::class,
|
||||
TitleSortedObject::class,
|
||||
TitleArraySortedObject::class,
|
||||
ThroughDefinerVersioned::class,
|
||||
ThroughIntermediaryVersioned::class,
|
||||
ThroughBelongsVersioned::class,
|
||||
];
|
||||
);
|
||||
|
||||
public function reorderItemsProvider()
|
||||
public function testReorderItems()
|
||||
{
|
||||
return [
|
||||
[StubParent::class . '.parent', 'MyHasMany', 'Sort'],
|
||||
[StubParent::class . '.parent', 'MyHasManySubclass', 'Sort'],
|
||||
[StubParent::class . '.parent-subclass-ordered-versioned', 'MyHasManySubclassOrderedVersioned', 'Sort'],
|
||||
[StubParent::class . '.parent', 'MyManyMany', 'ManyManySort'],
|
||||
[StubParent::class . '.parent', 'MyManyManyVersioned', 'ManyManySort'],
|
||||
[ThroughDefiner::class . '.DefinerOne', 'Belongings', 'Sort'],
|
||||
[ThroughDefinerVersioned::class . '.DefinerOne', 'Belongings', 'Sort'],
|
||||
// [PolymorphM2MParent::class . '.ParentOne', 'Children', 'Sort']
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider reorderItemsProvider
|
||||
*/
|
||||
public function testReorderItems($fixtureID, $relationName, $sortName)
|
||||
{
|
||||
$orderable = new GridFieldOrderableRows($sortName);
|
||||
$orderable = new GridFieldOrderableRows('ManyManySort');
|
||||
$reflection = new ReflectionMethod($orderable, 'executeReorder');
|
||||
$reflection->setAccessible(true);
|
||||
|
||||
$parent = $this->objFromFixture(StubParent::class, 'parent');
|
||||
|
||||
$config = new GridFieldConfig_RelationEditor();
|
||||
$config->addComponent($orderable);
|
||||
|
||||
list($parentClass, $parentInstanceID) = explode('.', $fixtureID ?? '');
|
||||
$parent = $this->objFromFixture($parentClass, $parentInstanceID);
|
||||
|
||||
$grid = new GridField(
|
||||
$relationName,
|
||||
'Testing Many Many',
|
||||
$parent->$relationName()->sort($sortName),
|
||||
'MyManyMany',
|
||||
'My Many Many',
|
||||
$parent->MyManyMany()->sort('ManyManySort'),
|
||||
$config
|
||||
);
|
||||
|
||||
$originalOrder = $parent->$relationName()->sort($sortName)->column('ID');
|
||||
$desiredOrder = [];
|
||||
$originalOrder = $parent->MyManyMany()->sort('ManyManySort')->column('ID');
|
||||
$desiredOrder = array();
|
||||
|
||||
// Make order non-contiguous, and 1-based
|
||||
foreach (array_reverse($originalOrder ?? []) as $index => $id) {
|
||||
foreach (array_reverse($originalOrder) as $index => $id) {
|
||||
$desiredOrder[$index * 2 + 1] = $id;
|
||||
}
|
||||
|
||||
@ -108,111 +57,13 @@ class GridFieldOrderableRowsTest extends SapphireTest
|
||||
|
||||
$reflection->invoke($orderable, $grid, $desiredOrder);
|
||||
|
||||
$newOrder = $parent->$relationName()->sort($sortName)->map($sortName, 'ID')->toArray();
|
||||
|
||||
$this->assertEquals($desiredOrder, $newOrder);
|
||||
}
|
||||
|
||||
public function testManyManyThroughListSortOrdersAreUsedForInitialRender()
|
||||
{
|
||||
/** @var ThroughDefiner $record */
|
||||
$record = $this->objFromFixture(ThroughDefiner::class, 'DefinerOne');
|
||||
|
||||
$orderable = new GridFieldOrderableRows('Sort');
|
||||
$config = new GridFieldConfig_RelationEditor();
|
||||
$config->addComponent($orderable);
|
||||
|
||||
$grid = new GridField(
|
||||
'Belongings',
|
||||
'Testing Many Many',
|
||||
$record->Belongings()->sort('Sort'),
|
||||
$config
|
||||
);
|
||||
|
||||
// Get the first record, which would be the first one to have column contents generated
|
||||
/** @var ThroughIntermediary $expected */
|
||||
$intermediary = $this->objFromFixture(ThroughIntermediary::class, 'One');
|
||||
|
||||
$result = $orderable->getColumnContent($grid, $record, 'irrelevant');
|
||||
|
||||
$this->assertStringContainsString(
|
||||
'Belongings[GridFieldEditableColumns][' . $record->ID . '][Sort]',
|
||||
$result,
|
||||
'The field name is indexed under the record\'s ID'
|
||||
);
|
||||
$this->assertStringContainsString(
|
||||
'value="' . $intermediary->Sort . '"',
|
||||
$result,
|
||||
'The value comes from the MMTL intermediary Sort value'
|
||||
);
|
||||
}
|
||||
|
||||
public function testPolymorphicManyManyListSortOrdersAreUsedForInitialRender()
|
||||
{
|
||||
$this->markTestSkipped('TODO: Introduce this test in the next minor release (3.3)');
|
||||
|
||||
$record = $this->objFromFixture(PolymorphM2MParent::class, 'ParentOne');
|
||||
|
||||
$orderable = new GridFieldOrderableRows('Sort');
|
||||
$config = new GridFieldConfig_RelationEditor();
|
||||
$config->addComponent($orderable);
|
||||
|
||||
$grid = new GridField(
|
||||
'Children',
|
||||
'Testing Polymorphic Many Many',
|
||||
$record->Children()->sort('Sort'),
|
||||
$config
|
||||
);
|
||||
|
||||
// Get the first record, which would be the first one to have column contents generated
|
||||
$intermediary = $this->objFromFixture(PolymorphM2MMapper::class, 'MapP1ToC1');
|
||||
|
||||
$result = $orderable->getColumnContent($grid, $record, 'irrelevant');
|
||||
|
||||
$this->assertStringContainsString(
|
||||
'Children[GridFieldEditableColumns][' . $record->ID . '][Sort]',
|
||||
$result,
|
||||
'The field name is indexed under the record\'s ID'
|
||||
);
|
||||
$this->assertStringContainsString(
|
||||
'value="' . $intermediary->Sort . '"',
|
||||
$result,
|
||||
'The value comes from the MMTL intermediary Sort value'
|
||||
);
|
||||
}
|
||||
|
||||
public function testSortableChildClass()
|
||||
{
|
||||
$orderable = new GridFieldOrderableRows('Sort');
|
||||
$reflection = new ReflectionMethod($orderable, 'executeReorder');
|
||||
$reflection->setAccessible(true);
|
||||
|
||||
$parent = $this->objFromFixture(StubOrdered::class, 'nestedtest');
|
||||
|
||||
$config = new GridFieldConfig_RelationEditor();
|
||||
$config->addComponent($orderable);
|
||||
|
||||
$grid = new GridField(
|
||||
'Children',
|
||||
'Children',
|
||||
$parent->Children(),
|
||||
$config
|
||||
);
|
||||
|
||||
$originalOrder = $parent->Children()->column('ID');
|
||||
$desiredOrder = array_reverse($originalOrder ?? []);
|
||||
|
||||
$this->assertNotEquals($originalOrder, $desiredOrder);
|
||||
|
||||
$reflection->invoke($orderable, $grid, $desiredOrder);
|
||||
|
||||
$newOrder = $parent->Children()->column('ID');
|
||||
$newOrder = $parent->MyManyMany()->sort('ManyManySort')->map('ManyManySort', 'ID')->toArray();
|
||||
|
||||
$this->assertEquals($desiredOrder, $newOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \Symbiote\GridFieldExtensions\GridFieldOrderableRows::getSortTable
|
||||
* @covers GridFieldOrderableRows::getSortTable
|
||||
*/
|
||||
public function testGetSortTable()
|
||||
{
|
||||
@ -240,125 +91,5 @@ class GridFieldOrderableRowsTest extends SapphireTest
|
||||
'StubParent_MyManyMany',
|
||||
$orderable->setSortField('ManyManySort')->getSortTable($parent->MyManyMany())
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
'StubOrderedVersioned',
|
||||
$orderable->setSortField('Sort')->getSortTable($parent->MyHasManySubclassOrderedVersioned())
|
||||
);
|
||||
}
|
||||
|
||||
public function testReorderItemsSubclassVersioned()
|
||||
{
|
||||
$orderable = new GridFieldOrderableRows('Sort');
|
||||
$reflection = new ReflectionMethod($orderable, 'executeReorder');
|
||||
$reflection->setAccessible(true);
|
||||
|
||||
$parent = $this->objFromFixture(StubParent::class, 'parent-subclass-ordered-versioned');
|
||||
|
||||
// make sure all items are published
|
||||
foreach ($parent->MyHasManySubclassOrderedVersioned() as $item) {
|
||||
$item->publishRecursive();
|
||||
}
|
||||
|
||||
// there should be no difference between stages at this point
|
||||
$differenceFound = false;
|
||||
foreach ($parent->MyHasManySubclassOrderedVersioned() as $item) {
|
||||
/** @var StubSubclassOrderedVersioned|Versioned $item */
|
||||
if ($item->stagesDiffer()) {
|
||||
$this->fail('Unexpected difference found on stages');
|
||||
}
|
||||
}
|
||||
|
||||
// reorder items
|
||||
$config = new GridFieldConfig_RelationEditor();
|
||||
$config->addComponent($orderable);
|
||||
|
||||
$grid = new GridField(
|
||||
'TestField',
|
||||
'TestField',
|
||||
$parent->MyHasManySubclassOrderedVersioned()->sort('Sort', 'ASC'),
|
||||
$config
|
||||
);
|
||||
|
||||
$originalOrder = $parent->MyHasManySubclassOrderedVersioned()
|
||||
->sort('Sort', 'ASC')
|
||||
->column('ID');
|
||||
|
||||
$desiredOrder = [];
|
||||
|
||||
// Make order non-contiguous, and 1-based
|
||||
foreach (array_reverse($originalOrder ?? []) as $index => $id) {
|
||||
$desiredOrder[$index * 2 + 1] = $id;
|
||||
}
|
||||
|
||||
$this->assertNotEquals($originalOrder, $desiredOrder);
|
||||
|
||||
$reflection->invoke($orderable, $grid, $desiredOrder);
|
||||
|
||||
$newOrder = $parent->MyHasManySubclassOrderedVersioned()
|
||||
->sort('Sort', 'ASC')
|
||||
->map('Sort', 'ID')
|
||||
->toArray();
|
||||
|
||||
$this->assertEquals($desiredOrder, $newOrder);
|
||||
|
||||
// reorder should have been handled as versioned - there should be a difference between stages now
|
||||
$differenceFound = false;
|
||||
foreach ($parent->MyHasManySubclassOrderedVersioned() as $item) {
|
||||
if ($item->stagesDiffer()) {
|
||||
$differenceFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertTrue($differenceFound);
|
||||
}
|
||||
|
||||
public function testGetManipulatedDataWithoutDefaultSort()
|
||||
{
|
||||
$sortedList = $this->getTitleSortedListForManipuatedData(TitleObject::class, [
|
||||
['Title' => 'C'],
|
||||
['Title' => 'A'],
|
||||
['Title' => 'B'],
|
||||
]);
|
||||
$this->assertSame(['A', 'B', 'C'], $sortedList->column('Title'));
|
||||
}
|
||||
|
||||
public function testGetManipulatedDataWithDefaultSort()
|
||||
{
|
||||
$sortedList = $this->getTitleSortedListForManipuatedData(TitleSortedObject::class, [
|
||||
['Title' => 'Z', 'Iden' => 'C', 'DefaultSort' => 3],
|
||||
['Title' => 'Z', 'Iden' => 'A', 'DefaultSort' => 2],
|
||||
['Title' => 'Z', 'Iden' => 'B', 'DefaultSort' => 1],
|
||||
]);
|
||||
$this->assertSame(['B', 'A', 'C'], $sortedList->column('Iden'));
|
||||
}
|
||||
|
||||
|
||||
public function testGetManipulatedDataWithDefaultSortArray()
|
||||
{
|
||||
$sortedList = $this->getTitleSortedListForManipuatedData(TitleArraySortedObject::class, [
|
||||
['Title' => 'X', 'Iden' => 'C', 'OtherSort' => 3],
|
||||
['Title' => 'Z', 'Iden' => 'A', 'OtherSort' => 2],
|
||||
['Title' => 'Z', 'Iden' => 'B', 'OtherSort' => 1],
|
||||
]);
|
||||
$this->assertSame(['C', 'B', 'A'], $sortedList->column('Iden'));
|
||||
}
|
||||
|
||||
private function getTitleSortedListForManipuatedData(string $dataClass, array $data): DataList
|
||||
{
|
||||
$list = new DataList($dataClass);
|
||||
foreach ($data as $values) {
|
||||
$item = new $dataClass();
|
||||
$item->update($values);
|
||||
$item->write();
|
||||
$list->add($item);
|
||||
}
|
||||
$orderable = new GridFieldOrderableRows('Title');
|
||||
$config = new GridFieldConfig_RelationEditor();
|
||||
$config->addComponent($orderable);
|
||||
$grid = new GridField('MyName', 'MyTitle', $list, $config);
|
||||
$sortedList = $orderable->getManipulatedData($grid, $list);
|
||||
return $sortedList;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,3 @@
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\StubOrderableChild:
|
||||
item1:
|
||||
Sort: 1
|
||||
item2:
|
||||
Sort: 2
|
||||
item3:
|
||||
Sort: 3
|
||||
item4:
|
||||
Sort: 4
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered:
|
||||
item1:
|
||||
Sort: 1
|
||||
@ -21,40 +11,6 @@ Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered:
|
||||
Sort: 5
|
||||
item6:
|
||||
Sort: 6
|
||||
nestedtest:
|
||||
Children:
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrderableChild.item1
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrderableChild.item2
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrderableChild.item3
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrderableChild.item4
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\StubSubclass:
|
||||
item1:
|
||||
Sort: 1
|
||||
item2:
|
||||
Sort: 2
|
||||
item3:
|
||||
Sort: 3
|
||||
item4:
|
||||
Sort: 4
|
||||
item5:
|
||||
Sort: 5
|
||||
item6:
|
||||
Sort: 6
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned:
|
||||
item1:
|
||||
ExtraField: 1
|
||||
Sort: 1
|
||||
item2:
|
||||
ExtraField: 2
|
||||
Sort: 2
|
||||
item3:
|
||||
ExtraField: 3
|
||||
Sort: 3
|
||||
item4:
|
||||
ExtraField: 4
|
||||
Sort: 4
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\StubParent:
|
||||
parent:
|
||||
@ -71,32 +27,3 @@ Symbiote\GridFieldExtensions\Tests\Stub\StubParent:
|
||||
ManyManySort: 108
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered.item6:
|
||||
ManyManySort: 108
|
||||
MyManyManyVersioned:
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned.item1:
|
||||
ManyManySort: 1
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned.item2:
|
||||
ManyManySort: 1
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned.item3:
|
||||
ManyManySort: 108
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned.item4:
|
||||
ManyManySort: 108
|
||||
MyHasMany:
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered.item1
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered.item2
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered.item3
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered.item4
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered.item5
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubOrdered.item6
|
||||
MyHasManySubclass:
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclass.item1
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclass.item2
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclass.item3
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclass.item4
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclass.item5
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclass.item6
|
||||
parent-subclass-ordered-versioned:
|
||||
MyHasManySubclassOrderedVersioned:
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned.item1
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned.item2
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned.item3
|
||||
- =>Symbiote\GridFieldExtensions\Tests\Stub\StubSubclassOrderedVersioned.item4
|
||||
|
@ -1,28 +0,0 @@
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MParent:
|
||||
ParentOne:
|
||||
ParentTwo:
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MChild:
|
||||
ChildOne:
|
||||
ChildTwo:
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MMapper:
|
||||
MapP1ToC1:
|
||||
Parent: '=>Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MParent.ParentOne'
|
||||
Child: '=>Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MChild.ChildOne'
|
||||
Sort: 1
|
||||
|
||||
MapP1ToC2:
|
||||
Parent: '=>Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MParent.ParentOne'
|
||||
Child: '=>Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MChild.ChildTwo'
|
||||
Sort: 2
|
||||
|
||||
MapP2ToC1:
|
||||
Parent: '=>Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MParent.ParentTwo'
|
||||
Child: '=>Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MChild.ChildOne'
|
||||
Sort: 2
|
||||
|
||||
MapP2ToC2:
|
||||
Parent: '=>Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MParent.ParentTwo'
|
||||
Child: '=>Symbiote\GridFieldExtensions\Tests\Stub\PolymorphM2MChild.ChildTwo'
|
||||
Sort: 1
|
@ -1,61 +0,0 @@
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefiner:
|
||||
DefinerOne:
|
||||
DefinerTwo:
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongs:
|
||||
BelongsOne:
|
||||
BelongsTwo:
|
||||
BelongsThree:
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\ThroughIntermediary:
|
||||
One:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefiner.DefinerOne
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongs.BelongsOne
|
||||
Sort: 3
|
||||
Two:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefiner.DefinerOne
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongs.BelongsTwo
|
||||
Sort: 2
|
||||
Three:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefiner.DefinerOne
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongs.BelongsThree
|
||||
Sort: 1
|
||||
Four:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefiner.DefinerTwo
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongs.BelongsTwo
|
||||
Sort: 1
|
||||
Five:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefiner.DefinerTwo
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongs.BelongsThree
|
||||
Sort: 2
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefinerVersioned:
|
||||
DefinerOne:
|
||||
DefinerTwo:
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongsVersioned:
|
||||
BelongsOne:
|
||||
BelongsTwo:
|
||||
BelongsThree:
|
||||
|
||||
Symbiote\GridFieldExtensions\Tests\Stub\ThroughIntermediaryVersioned:
|
||||
One:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefinerVersioned.DefinerOne
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongsVersioned.BelongsOne
|
||||
Sort: 3
|
||||
Two:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefinerVersioned.DefinerOne
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongsVersioned.BelongsTwo
|
||||
Sort: 2
|
||||
Three:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefinerVersioned.DefinerOne
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongsVersioned.BelongsThree
|
||||
Sort: 1
|
||||
Four:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefinerVersioned.DefinerTwo
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongsVersioned.BelongsTwo
|
||||
Sort: 1
|
||||
Five:
|
||||
Defining: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefinerVersioned.DefinerTwo
|
||||
Belonging: =>Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongsVersioned.BelongsThree
|
||||
Sort: 2
|
@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests;
|
||||
|
||||
use ReflectionMethod;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughDefiner;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughIntermediary;
|
||||
use Symbiote\GridFieldExtensions\Tests\Stub\ThroughBelongs;
|
||||
use Symbiote\GridFieldExtensions\GridFieldOrderableRows;
|
||||
|
||||
class OrderableRowsThroughVersionedTest extends SapphireTest
|
||||
{
|
||||
protected static $fixture_file = 'OrderableRowsThroughTest.yml';
|
||||
|
||||
protected static $extra_dataobjects = [
|
||||
ThroughDefiner::class,
|
||||
ThroughIntermediary::class,
|
||||
ThroughBelongs::class,
|
||||
];
|
||||
|
||||
protected static $required_extensions = [
|
||||
ThroughDefiner::class => [Versioned::class],
|
||||
ThroughIntermediary::class => [Versioned::class],
|
||||
ThroughBelongs::class => [Versioned::class],
|
||||
];
|
||||
|
||||
protected $originalReadingMode;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->orignalReadingMode = Versioned::get_reading_mode();
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Versioned::set_reading_mode($this->originalReadingMode);
|
||||
unset($this->originalReadingMode);
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically the same as GridFieldOrderableRowsTest::testReorderItems
|
||||
* but with some Versioned calls & checks mixed in.
|
||||
*/
|
||||
public function testReorderingSavesAndPublishes()
|
||||
{
|
||||
$parent = $this->objFromFixture(ThroughDefiner::class, 'DefinerOne');
|
||||
$relationName = 'Belongings';
|
||||
$sortName = 'Sort';
|
||||
|
||||
$orderable = new GridFieldOrderableRows($sortName);
|
||||
$reflection = new ReflectionMethod($orderable, 'executeReorder');
|
||||
$reflection->setAccessible(true);
|
||||
|
||||
$config = new GridFieldConfig_RelationEditor();
|
||||
$config->addComponent($orderable);
|
||||
|
||||
// This test data is versioned - ensure we're all published
|
||||
$parent->publishRecursive();
|
||||
// there should be no difference between stages at this point
|
||||
foreach ($parent->$relationName() as $item) {
|
||||
$this->assertFalse(
|
||||
$item->getJoin()->stagesDiffer(),
|
||||
'No records should be different from their published versions'
|
||||
);
|
||||
}
|
||||
|
||||
$grid = new GridField(
|
||||
'Belongings',
|
||||
'Testing Many Many',
|
||||
$parent->$relationName()->sort($sortName),
|
||||
$config
|
||||
);
|
||||
|
||||
$originalOrder = $parent->$relationName()->sort($sortName)->column('ID');
|
||||
// Ring (un)shift by one, e.g. 3,2,1 becomes 1,3,2.
|
||||
// then string key our new order starting at 1
|
||||
$desiredOrder = array_values($originalOrder ?? []);
|
||||
array_unshift($desiredOrder, array_pop($desiredOrder));
|
||||
$desiredOrder = array_combine(
|
||||
range('1', count($desiredOrder ?? [])),
|
||||
$desiredOrder ?? []
|
||||
);
|
||||
$this->assertNotEquals($originalOrder, $desiredOrder);
|
||||
|
||||
// Perform the reorder
|
||||
$reflection->invoke($orderable, $grid, $desiredOrder);
|
||||
|
||||
// Verify draft stage has reordered
|
||||
Versioned::set_stage(Versioned::DRAFT);
|
||||
$newOrder = $parent->$relationName()->sort($sortName)->map($sortName, 'ID')->toArray();
|
||||
$this->assertEquals($desiredOrder, $newOrder);
|
||||
|
||||
// reorder should have been handled as versioned - there should be a difference between stages now
|
||||
// by using a ring style shift every item should have a new sort (thus a new version).
|
||||
$differenceFound = false;
|
||||
foreach ($parent->$relationName() as $item) {
|
||||
if ($item->getJoin()->stagesDiffer()) {
|
||||
$differenceFound = true;
|
||||
}
|
||||
}
|
||||
$this->assertTrue($differenceFound, 'All records should have changes in draft');
|
||||
|
||||
// Verify live stage has NOT reordered
|
||||
Versioned::set_stage(Versioned::LIVE);
|
||||
$sameOrder = $parent->$relationName()->sort($sortName)->column('ID');
|
||||
$this->assertEquals($originalOrder, $sameOrder);
|
||||
|
||||
$parent->publishRecursive();
|
||||
|
||||
foreach ($parent->$relationName() as $item) {
|
||||
$this->assertFalse(
|
||||
$item->getJoin()->stagesDiffer(),
|
||||
'No records should be different from their published versions anymore'
|
||||
);
|
||||
}
|
||||
|
||||
$newLiveOrder = $parent->$relationName()->sort($sortName)->map($sortName, 'ID')->toArray();
|
||||
$this->assertEquals($desiredOrder, $newLiveOrder);
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class PolymorphM2MChild extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'TestOnly_PolymorphM2MChild';
|
||||
|
||||
private static $has_many = [
|
||||
'Parents' => PolymorphM2MMapper::class
|
||||
];
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class PolymorphM2MMapper extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'TestOnly_PolymorphM2MMapper';
|
||||
|
||||
private static $db = [
|
||||
'Sort' => 'Int'
|
||||
];
|
||||
|
||||
private static $has_one = [
|
||||
'Parent' => DataObject::class, // PolymorphM2MParent
|
||||
'Child' => PolymorphM2MChild::class,
|
||||
];
|
||||
|
||||
private static $default_sort = '"Sort" ASC';
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class PolymorphM2MParent extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'TableOnly_PolymorphM2MParent';
|
||||
|
||||
private static $many_many = [
|
||||
'Children' => [
|
||||
'through' => PolymorphM2MMapper::class,
|
||||
'from' => 'Parent',
|
||||
'to' => 'Child',
|
||||
]
|
||||
];
|
||||
}
|
@ -9,7 +9,7 @@ class StubA implements TestOnly
|
||||
public function i18n_singular_name()
|
||||
{
|
||||
$class = get_class($this);
|
||||
return substr($class ?? '', -1);
|
||||
return substr($class, -1);
|
||||
}
|
||||
|
||||
public function canCreate()
|
||||
|
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
class StubOrderableChild extends StubUnorderable
|
||||
{
|
||||
private static $db = [
|
||||
'Sort' => 'Int',
|
||||
];
|
||||
|
||||
private static $has_one = [
|
||||
'Parent' => StubOrdered::class,
|
||||
];
|
||||
|
||||
private static $default_sort = '"Sort" ASC';
|
||||
|
||||
private static $table_name = 'StubOrderableChild';
|
||||
}
|
@ -15,10 +15,6 @@ class StubOrdered extends DataObject implements TestOnly
|
||||
'Parent' => StubParent::class
|
||||
);
|
||||
|
||||
private static $has_many = array(
|
||||
'Children' => StubOrderableChild::class,
|
||||
);
|
||||
|
||||
private static $belongs_many_many =array(
|
||||
'MyManyMany' => StubParent::class,
|
||||
);
|
||||
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
|
||||
/**
|
||||
* Class StubOrderedVersioned
|
||||
* @package Symbiote\GridFieldExtensions\Tests\Stub
|
||||
*/
|
||||
class StubOrderedVersioned extends DataObject implements TestOnly
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $table_name = 'StubOrderedVersioned';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $extensions = [
|
||||
Versioned::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $db = [
|
||||
'Sort' => 'Int',
|
||||
];
|
||||
}
|
@ -7,21 +7,18 @@ use SilverStripe\ORM\DataObject;
|
||||
|
||||
class StubParent extends DataObject implements TestOnly
|
||||
{
|
||||
private static $has_many = [
|
||||
private static $has_many = array(
|
||||
'MyHasMany' => StubOrdered::class,
|
||||
'MyHasManySubclass' => StubSubclass::class,
|
||||
'MyHasManySubclassOrderedVersioned' => StubSubclassOrderedVersioned::class,
|
||||
];
|
||||
'MyHasManySubclass' => StubSubclass::class
|
||||
);
|
||||
|
||||
private static $many_many = [
|
||||
'MyManyMany' => StubOrdered::class,
|
||||
'MyManyManyVersioned' => StubSubclassOrderedVersioned::class,
|
||||
];
|
||||
private static $many_many = array(
|
||||
'MyManyMany' => StubOrdered::class
|
||||
);
|
||||
|
||||
private static $many_many_extraFields = [
|
||||
'MyManyMany' => ['ManyManySort' => 'Int'],
|
||||
'MyManyManyVersioned' => ['ManyManySort' => 'Int'],
|
||||
];
|
||||
private static $many_many_extraFields = array(
|
||||
'MyManyMany' => array('ManyManySort' => 'Int')
|
||||
);
|
||||
|
||||
private static $table_name = 'StubParent';
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
|
||||
/**
|
||||
* Class StubOrderedVersioned
|
||||
* @package Symbiote\GridFieldExtensions\Tests\Stub
|
||||
*/
|
||||
class StubSubclassOrderedVersioned extends StubOrderedVersioned
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $table_name = 'StubSubclassOrderedVersioned';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $db = [
|
||||
'ExtraField' => 'Int',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $has_one = [
|
||||
'Parent' => StubParent::class,
|
||||
];
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class StubUnorderable extends DataObject implements TestOnly
|
||||
{
|
||||
private static $db = [
|
||||
'Title' => 'Varchar',
|
||||
];
|
||||
|
||||
private static $table_name = 'StubUnorderable';
|
||||
|
||||
private $canEdit = false;
|
||||
|
||||
public function setCanEdit($canEdit)
|
||||
{
|
||||
$this->canEdit = $canEdit;
|
||||
}
|
||||
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
return $this->canEdit;
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Control\Controller;
|
||||
|
||||
class TestController extends Controller
|
||||
{
|
||||
private static $url_segment = 'test';
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class ThroughBelongs extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'BelongsThrough';
|
||||
|
||||
private static $belongs_many_many = [
|
||||
'Definers' => ThroughDefiner::class,
|
||||
];
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\ManyManyList;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
|
||||
/**
|
||||
* @method ManyManyList|ThroughDefinerVersioned[] Definers()
|
||||
* @mixin Versioned
|
||||
*/
|
||||
class ThroughBelongsVersioned extends DataObject implements TestOnly
|
||||
{
|
||||
private static string $table_name = 'ThroughBelongsVersioned';
|
||||
|
||||
private static array $belongs_many_many = [
|
||||
'Definers' => ThroughDefinerVersioned::class,
|
||||
];
|
||||
|
||||
private static array $extensions = [
|
||||
Versioned::class,
|
||||
];
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class ThroughDefiner extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'ManyThrough';
|
||||
|
||||
private static $many_many = [
|
||||
'Belongings' => [
|
||||
'through' => ThroughIntermediary::class,
|
||||
'from' => 'Defining',
|
||||
'to' => 'Belonging',
|
||||
]
|
||||
];
|
||||
|
||||
private static $owns = [
|
||||
'Belongings'
|
||||
];
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\ManyManyThroughList;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
|
||||
/**
|
||||
* @method ManyManyThroughList|ThroughIntermediaryVersioned Belongings()
|
||||
* @mixin Versioned
|
||||
*/
|
||||
class ThroughDefinerVersioned extends DataObject implements TestOnly
|
||||
{
|
||||
private static string $table_name = 'ThroughDefinerVersioned';
|
||||
|
||||
private static array $many_many = [
|
||||
'Belongings' => [
|
||||
'through' => ThroughIntermediaryVersioned::class,
|
||||
'from' => 'Defining',
|
||||
'to' => 'Belonging',
|
||||
]
|
||||
];
|
||||
|
||||
private static array $owns = [
|
||||
'Belongings'
|
||||
];
|
||||
|
||||
private static array $extensions = [
|
||||
Versioned::class,
|
||||
];
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class ThroughIntermediary extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'IntermediaryThrough';
|
||||
|
||||
private static $db = [
|
||||
'Sort' => 'Int',
|
||||
];
|
||||
|
||||
private static $has_one = [
|
||||
'Defining' => ThroughDefiner::class,
|
||||
'Belonging' => ThroughBelongs::class,
|
||||
];
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
|
||||
/**
|
||||
* @property int $DefiningID
|
||||
* @property int $BelongingID
|
||||
* @method ThroughDefinerVersioned Defining()
|
||||
* @method ThroughBelongsVersioned Belonging()
|
||||
* @mixin Versioned
|
||||
*/
|
||||
class ThroughIntermediaryVersioned extends DataObject implements TestOnly
|
||||
{
|
||||
private static string $table_name = 'ThroughIntermediaryVersioned';
|
||||
|
||||
private static array $db = [
|
||||
'Sort' => 'Int',
|
||||
];
|
||||
|
||||
private static array $has_one = [
|
||||
'Defining' => ThroughDefinerVersioned::class,
|
||||
'Belonging' => ThroughBelongsVersioned::class,
|
||||
];
|
||||
|
||||
private static array $extensions = [
|
||||
Versioned::class,
|
||||
];
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class TitleArraySortedObject extends DataObject implements TestOnly
|
||||
{
|
||||
private static $db = [
|
||||
'Title' => 'Varchar',
|
||||
'Iden' => 'Varchar',
|
||||
'OtherSort' => 'Int'
|
||||
];
|
||||
|
||||
private static array $default_sort = [
|
||||
'Title' => 'ASC',
|
||||
'OtherSort' => 'ASC',
|
||||
];
|
||||
|
||||
private static $table_name = 'TitleArraySortedObject';
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class TitleObject extends DataObject implements TestOnly
|
||||
{
|
||||
private static $db = [
|
||||
'Title' => 'Varchar',
|
||||
];
|
||||
|
||||
private static $table_name = 'TitleObject';
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions\Tests\Stub;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class TitleSortedObject extends DataObject implements TestOnly
|
||||
{
|
||||
private static $db = [
|
||||
'Title' => 'Varchar',
|
||||
'Iden' => 'Varchar',
|
||||
'DefaultSort' => 'Int'
|
||||
];
|
||||
|
||||
private static $default_sort = '"DefaultSort" ASC';
|
||||
|
||||
private static $table_name = 'TitleSortedObject';
|
||||
}
|
Loading…
Reference in New Issue
Block a user