├── .nvmrc
├── _config.php
├── lang
├── _manifest_exclude
├── fa_IR.yml
├── sl.yml
├── sv.yml
├── fi_FI.yml
├── pl.yml
├── sk.yml
├── en.yml
├── fi.yml
├── ru.yml
├── hr.yml
├── eo.yml
├── it.yml
├── de.yml
└── nl.yml
├── codecov.yml
├── phpstan.neon.dist
├── .eslintrc.js
├── .stylelintrc.js
├── babel.config.json
├── templates
└── SilverStripe
│ └── Lumberjack
│ └── Forms
│ ├── GridFieldSiteTreeAddNewButton.ss
│ └── GridFieldSiteTreeAddNewButton_holder.ss
├── code-of-conduct.md
├── .tx
└── config
├── .github
├── ISSUE_TEMPLATE
│ ├── 3_blank_issue.md
│ ├── config.yml
│ ├── 2_feature_request.yml
│ └── 1_bug_report.yml
├── workflows
│ ├── ci.yml
│ ├── keepalive.yml
│ ├── merge-up.yml
│ ├── add-prs-to-project.yml
│ ├── tag-patch-release.yml
│ ├── update-js.yml
│ └── dispatch-ci.yml
└── PULL_REQUEST_TEMPLATE.md
├── _config
└── lumberjack.yml
├── client
├── dist
│ ├── js
│ │ └── GridField.js
│ └── styles
│ │ └── lumberjack.css
└── src
│ ├── js
│ └── GridField.js
│ └── styles
│ └── lumberjack.scss
├── phpcs.xml.dist
├── .editorconfig
├── changelog.md
├── phpunit.xml.dist
├── src
├── Forms
│ ├── GridFieldSiteTreeViewButton.php
│ ├── GridFieldSiteTreeEditButton.php
│ ├── GridFieldConfig_Lumberjack.php
│ ├── GridFieldSiteTreeState.php
│ └── GridFieldSiteTreeAddNewButton.php
└── Model
│ └── Lumberjack.php
├── webpack.config.js
├── package.json
├── config.rb
├── composer.json
├── LICENSE
├── behat.yml
└── README.md
/.nvmrc:
--------------------------------------------------------------------------------
1 | 18
2 |
--------------------------------------------------------------------------------
/_config.php:
--------------------------------------------------------------------------------
1 |
2 | $FieldHolder
3 | <% end_loop %>
--------------------------------------------------------------------------------
/templates/SilverStripe/Lumberjack/Forms/GridFieldSiteTreeAddNewButton_holder.ss:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/code-of-conduct.md:
--------------------------------------------------------------------------------
1 | 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).
2 |
--------------------------------------------------------------------------------
/.tx/config:
--------------------------------------------------------------------------------
1 | [main]
2 | host = https://www.transifex.com
3 |
4 | [o:silverstripe:p:silverstripe-lumberjack:r:master]
5 | file_filter = lang/.yml
6 | source_file = lang/en.yml
7 | source_lang = en
8 | type = YML
9 |
10 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/3_blank_issue.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Blank issue
3 | about: Only for use by maintainers
4 | ---
5 |
6 |
--------------------------------------------------------------------------------
/_config/lumberjack.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: lumberjack
3 | ---
4 | SilverStripe\Admin\LeftAndMain:
5 | extra_requirements_css:
6 | - silverstripe/lumberjack:client/dist/styles/lumberjack.css
7 | extra_requirements_javascript:
8 | - silverstripe/lumberjack:client/dist/js/GridField.js
9 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | pull_request:
6 | workflow_dispatch:
7 |
8 | jobs:
9 | ci:
10 | name: CI
11 | # Do not run if this is a pull-request from same repo i.e. not a fork repo
12 | if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
13 | uses: silverstripe/gha-ci/.github/workflows/ci.yml@v2
14 |
--------------------------------------------------------------------------------
/client/dist/js/GridField.js:
--------------------------------------------------------------------------------
1 | !function(){"use strict";var e={669:function(e){e.exports=jQuery}},t={};var r=function r(i){var d=t[i];if(void 0!==d)return d.exports;var n=t[i]={exports:{}};return e[i](n,n.exports,r),n.exports}(669);r.entwine("ss",e=>{e(".ss-gridfield .field .gridfield-dropdown").entwine({onchange(){const e=this.getGridField(),t=e.getState().GridFieldSiteTreeAddNewButton;t.recordType=this.val(),e.setState("GridFieldSiteTreeAddNewButton",t)}})})}();
--------------------------------------------------------------------------------
/phpcs.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 | CodeSniffer ruleset for SilverStripe coding conventions.
4 |
5 | src
6 | tests
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/client/src/js/GridField.js:
--------------------------------------------------------------------------------
1 | /* global jQuery */
2 | (function ($) {
3 | // eslint-disable-next-line no-shadow
4 | $.entwine('ss', ($) => {
5 | $('.ss-gridfield .field .gridfield-dropdown').entwine({
6 |
7 | onchange() {
8 | const gridField = this.getGridField();
9 | const state = gridField.getState().GridFieldSiteTreeAddNewButton;
10 |
11 | state.recordType = this.val();
12 | gridField.setState('GridFieldSiteTreeAddNewButton', state);
13 | }
14 | });
15 | });
16 | }(jQuery));
17 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # For more information about the properties used in this file,
2 | # please see the EditorConfig documentation:
3 | # http://editorconfig.org
4 |
5 | [*]
6 | charset = utf-8
7 | end_of_line = lf
8 | indent_size = 4
9 | indent_style = space
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [{*.yml,*.js,*.scss,package.json,*.feature}]
14 | indent_size = 2
15 | indent_style = space
16 |
17 | # The indent size used in the package.json file cannot be changed:
18 | # https://github.com/npm/npm/pull/3180#issuecomment-16336516
19 |
--------------------------------------------------------------------------------
/client/dist/styles/lumberjack.css:
--------------------------------------------------------------------------------
1 | .cms .ss-gridfield .gridfield-dropdown{margin:3px 8px 0 0;border-bottom:0}.cms .ss-gridfield .gridfield-dropdown .chzn-container,.cms .ss-gridfield .gridfield-dropdown .dropdown{min-width:195px}.cms .ss-gridfield .dropdown-action{font-size:12px;margin-top:.24em}.cms .gridfield-icon i{width:16px;height:16px;display:block;float:left;margin-right:6px}.cms .gridfield-icon.published i{color:#3fa142}.cms .modified{margin-left:5px;color:#7e7470;background-color:#fff0bc;padding:1px 3px;border:1px solid #c9b800;font-size:80%;border-radius:3px;text-transform:uppercase}
2 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | This project adheres to [Semantic Versioning](http://semver.org/).
6 |
7 | ## [1.1.4]
8 |
9 | * Update translations.
10 | * If Translatable is active, set the Locale for new records
11 |
12 | ## [1.1.3]
13 |
14 | * Changelog added
15 | * Update translations
16 | * Update README.md
17 | * fixing composer require statement
18 | * filter hide_ancestor hidden page types from dropdown
19 | * BUG Fix creation of duplicate ParentID field on subtables of SiteTree
20 | * Add 3.2 and php 5.6 tests
21 |
--------------------------------------------------------------------------------
/lang/fa_IR.yml:
--------------------------------------------------------------------------------
1 | fa_IR:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'افزودن {name} جدید'
4 | AddMultipleOptions: 'افزودن جدید'
5 | GridFieldSiteTreeState:
6 | Modified: 'اصلاح شده'
7 | StateTitle: وضیعت
8 | Lumberjack:
9 | TabTitle: 'صفحات زیرین'
10 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
11 | Add: 'افزودن {name} جدید'
12 | AddMultipleOptions: 'افزودن جدید'
13 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
14 | Modified: 'اصلاح شده'
15 | StateTitle: وضیعت
16 | SilverStripe\Lumberjack\Model\Lumberjack:
17 | TabTitle: 'صفحات زیرین'
18 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tests/
6 |
7 |
8 |
9 |
10 |
11 | src/
12 |
13 | tests/
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.github/workflows/keepalive.yml:
--------------------------------------------------------------------------------
1 | name: Keepalive
2 |
3 | on:
4 | # At 3:15 PM UTC, on day 16 of the month
5 | schedule:
6 | - cron: '15 15 16 * *'
7 | workflow_dispatch:
8 |
9 | permissions: {}
10 |
11 | jobs:
12 | keepalive:
13 | name: Keepalive
14 | # Only run cron on the silverstripe account
15 | if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
16 | runs-on: ubuntu-latest
17 | permissions:
18 | actions: write
19 | steps:
20 | - name: Keepalive
21 | uses: silverstripe/gha-keepalive@v1
22 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Security Vulnerability
4 | url: https://docs.silverstripe.org/en/contributing/issues_and_bugs/#reporting-security-issues
5 | about: ⚠️ We do not use GitHub issues to track security vulnerability reports. Click "open" on the right to see how to report security vulnerabilities.
6 | - name: Support Question
7 | url: https://www.silverstripe.org/community/
8 | 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.
9 |
--------------------------------------------------------------------------------
/.github/workflows/merge-up.yml:
--------------------------------------------------------------------------------
1 | name: Merge-up
2 |
3 | on:
4 | # At 6:30 PM UTC, only on Saturday
5 | schedule:
6 | - cron: '30 18 * * 6'
7 | workflow_dispatch:
8 |
9 | permissions: {}
10 |
11 | jobs:
12 | merge-up:
13 | name: Merge-up
14 | # Only run cron on the silverstripe account
15 | if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
16 | runs-on: ubuntu-latest
17 | permissions:
18 | contents: write
19 | actions: write
20 | steps:
21 | - name: Merge-up
22 | uses: silverstripe/gha-merge-up@v2
23 |
--------------------------------------------------------------------------------
/src/Forms/GridFieldSiteTreeViewButton.php:
--------------------------------------------------------------------------------
1 | canView()) {
13 | return null;
14 | }
15 |
16 | $data = ArrayData::create([
17 | 'Link' => $record->CMSEditLink(),
18 | ]);
19 |
20 | return $data->renderWith(GridFieldViewButton::class);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.github/workflows/add-prs-to-project.yml:
--------------------------------------------------------------------------------
1 | name: Add new PRs to github project
2 |
3 | on:
4 | pull_request_target:
5 | types:
6 | - opened
7 | - ready_for_review
8 |
9 | permissions: {}
10 |
11 | jobs:
12 | addprtoproject:
13 | name: Add PR to GitHub Project
14 | # Only run on the silverstripe account
15 | if: github.repository_owner == 'silverstripe'
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Add PR to github project
19 | uses: silverstripe/gha-add-pr-to-project@v1
20 | with:
21 | app_id: ${{ vars.PROJECT_PERMISSIONS_APP_ID }}
22 | private_key: ${{ secrets.PROJECT_PERMISSIONS_APP_PRIVATE_KEY }}
23 |
--------------------------------------------------------------------------------
/lang/sl.yml:
--------------------------------------------------------------------------------
1 | sl:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: "Dodaj '{name}'"
4 | AddMultipleOptions: Dodaj
5 | GridFieldSiteTreeState:
6 | Draft: ' Osnutek pripravljen {date}'
7 | Modified: Spremenjeno
8 | Published: ' Objavljeno {date}'
9 | StateTitle: Status
10 | Lumberjack:
11 | TabTitle: Podstrani
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: "Dodaj '{name}'"
14 | AddMultipleOptions: Dodaj
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Modified: Spremenjeno
17 | StateTitle: Status
18 | SilverStripe\Lumberjack\Model\Lumberjack:
19 | TabTitle: Podstrani
20 |
--------------------------------------------------------------------------------
/lang/sv.yml:
--------------------------------------------------------------------------------
1 | sv:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Lägg till {name}'
4 | AddMultipleOptions: 'Lägg till'
5 | GridFieldSiteTreeState:
6 | Draft: ' Sparat som utkast {date}'
7 | Modified: Ändrad
8 | Published: ' Publicerad {date}'
9 | StateTitle: Status
10 | Lumberjack:
11 | TabTitle: Undersidor
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Lägg till {name}'
14 | AddMultipleOptions: 'Lägg till'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Modified: Ändrad
17 | StateTitle: Status
18 | SilverStripe\Lumberjack\Model\Lumberjack:
19 | TabTitle: Undersidor
20 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const Path = require('path');
2 | const { JavascriptWebpackConfig, CssWebpackConfig } = require('@silverstripe/webpack-config');
3 |
4 | const ENV = process.env.NODE_ENV;
5 | const PATHS = {
6 | ROOT: Path.resolve(),
7 | SRC: Path.resolve('client/src'),
8 | DIST: Path.resolve('client/dist'),
9 | };
10 |
11 | const config = [
12 | // Main JS bundle
13 | new JavascriptWebpackConfig('js', PATHS, 'silverstripe/lumberjack')
14 | .setEntry({
15 | GridField: `${PATHS.SRC}/js/GridField.js`
16 | })
17 | .getConfig(),
18 | // sass to css
19 | new CssWebpackConfig('css', PATHS)
20 | .setEntry({
21 | lumberjack: `${PATHS.SRC}/styles/lumberjack.scss`
22 | })
23 | .getConfig(),
24 | ];
25 |
26 | module.exports = config;
27 |
--------------------------------------------------------------------------------
/lang/fi_FI.yml:
--------------------------------------------------------------------------------
1 | fi_FI:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Lisää uusi {name}'
4 | AddMultipleOptions: 'Lisää uusi'
5 | GridFieldSiteTreeState:
6 | Draft: ' Tallennettiin vedoksena {date}'
7 | Modified: Muokattu
8 | Published: ' Julkaistu {date}'
9 | StateTitle: Tila
10 | Lumberjack:
11 | TabTitle: Alasivut
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Lisää uusi {name}'
14 | AddMultipleOptions: 'Lisää uusi'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Modified: Muokattu
17 | StateTitle: Tila
18 | SilverStripe\Lumberjack\Model\Lumberjack:
19 | TabTitle: Alasivut
20 |
--------------------------------------------------------------------------------
/lang/pl.yml:
--------------------------------------------------------------------------------
1 | pl:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Dodaj nową {name}'
4 | AddMultipleOptions: 'Dodaj nową'
5 | GridFieldSiteTreeState:
6 | Draft: ' Zapisano jaki szkic {date}'
7 | Modified: Zmodyfikowano
8 | Published: ' Opublikowano {date}'
9 | StateTitle: Stan
10 | Lumberjack:
11 | TabTitle: Podstrony
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Dodaj nową {name}'
14 | AddMultipleOptions: 'Dodaj nową'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Modified: Zmodyfikowano
17 | StateTitle: Stan
18 | SilverStripe\Lumberjack\Model\Lumberjack:
19 | TabTitle: Podstrony
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "silverstripe-lumberjack",
3 | "engines": {
4 | "node": ">=18.x"
5 | },
6 | "scripts": {
7 | "build": "yarn && yarn lint && rm -rf client/dist/* && NODE_ENV=production webpack --mode production --bail --progress",
8 | "dev": "NODE_ENV=development webpack --progress",
9 | "watch": "NODE_ENV=development webpack --watch --progress",
10 | "lint": "eslint client/src && stylelint client/src"
11 | },
12 | "dependencies": {},
13 | "devDependencies": {
14 | "@silverstripe/eslint-config": "^1.3.0",
15 | "@silverstripe/webpack-config": "^3",
16 | "webpack": "^5.94.0",
17 | "webpack-cli": "^5.0.0"
18 | },
19 | "resolutions": {
20 | "colors": "1.4.0"
21 | },
22 | "browserslist": [
23 | "defaults"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/lang/sk.yml:
--------------------------------------------------------------------------------
1 | sk:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Pridať {name}'
4 | AddMultipleOptions: Pridať
5 | GridFieldSiteTreeState:
6 | Draft: ' Uložený ako koncept: {date}'
7 | Modified: zmenené
8 | Published: ' Publikovaný: {date}'
9 | StateTitle: Stav
10 | Lumberjack:
11 | TabTitle: Podstránky
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Pridať {name}'
14 | AddMultipleOptions: Pridať
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Uložené ako koncept dňa {date}'
17 | Modified: zmenené
18 | Published: 'Zverejnené dňa {date}'
19 | StateTitle: Stav
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: Podstránky
22 |
--------------------------------------------------------------------------------
/lang/en.yml:
--------------------------------------------------------------------------------
1 | en:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Add new {name}'
4 | AddMultipleOptions: 'Add new'
5 | GridFieldSiteTreeState:
6 | Draft: ' Saved as Draft on {date}'
7 | Modified: Modified
8 | Published: ' Published on {date}'
9 | StateTitle: State
10 | Lumberjack:
11 | TabTitle: 'Child Pages'
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Add new {name}'
14 | AddMultipleOptions: 'Add new'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Saved as Draft on {date}'
17 | Modified: Modified
18 | Published: 'Published on {date}'
19 | StateTitle: State
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: 'Child Pages'
22 |
--------------------------------------------------------------------------------
/lang/fi.yml:
--------------------------------------------------------------------------------
1 | fi:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Lisää uusi {name}'
4 | AddMultipleOptions: 'Lisää uusi'
5 | GridFieldSiteTreeState:
6 | Draft: ' Tallennettu luonnoksena {date}'
7 | Modified: Muokattu
8 | Published: ' Julkaistu {date}'
9 | StateTitle: Tila
10 | Lumberjack:
11 | TabTitle: Alasivut
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Lisää uusi {name}'
14 | AddMultipleOptions: 'Lisää uusi'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Tallennettu luonnoksena {date}'
17 | Modified: Muokattu
18 | Published: 'Julkaistu {date}'
19 | StateTitle: Tila
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: Alasivut
22 |
--------------------------------------------------------------------------------
/lang/ru.yml:
--------------------------------------------------------------------------------
1 | ru:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Добавить {name}'
4 | AddMultipleOptions: Добавить
5 | GridFieldSiteTreeState:
6 | Draft: ' Сохранено как черновик {date}'
7 | Modified: Изменено
8 | Published: ' Опубликовано {date}'
9 | StateTitle: Статус
10 | Lumberjack:
11 | TabTitle: Под-страницы
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Добавить {name}'
14 | AddMultipleOptions: Добавить
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Сохранено как черновик {date}'
17 | Modified: Изменено
18 | Published: 'Опубликовано {date}'
19 | StateTitle: Статус
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: Под-страницы
22 |
--------------------------------------------------------------------------------
/client/src/styles/lumberjack.scss:
--------------------------------------------------------------------------------
1 | .cms {
2 | .ss-gridfield {
3 | .gridfield-dropdown {
4 | margin: 3px 8px 0 0;
5 | border-bottom: 0;
6 |
7 | .chzn-container,
8 | .dropdown {
9 | min-width: 195px;
10 | }
11 | }
12 |
13 | .dropdown-action {
14 | font-size: 12px;
15 | margin-top: 0.24em;
16 | }
17 | }
18 |
19 | .gridfield-icon i {
20 | width: 16px;
21 | height: 16px;
22 | display: block;
23 | float: left;
24 | margin-right: 6px;
25 | }
26 |
27 | .gridfield-icon.published i {
28 | color: #3fa142;
29 | }
30 |
31 | .modified {
32 | margin-left: 5px;
33 | color: #7E7470;
34 | background-color: #fff0bc;
35 | padding: 1px 3px;
36 | border: 1px solid #C9B800;
37 | font-size: 80%;
38 | border-radius: 3px;
39 | text-transform: uppercase;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/.github/workflows/tag-patch-release.yml:
--------------------------------------------------------------------------------
1 | name: Tag patch release
2 |
3 | on:
4 | # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
5 | workflow_dispatch:
6 | inputs:
7 | latest_local_sha:
8 | description: The latest local sha
9 | required: true
10 | type: string
11 |
12 | permissions: {}
13 |
14 | jobs:
15 | tagpatchrelease:
16 | name: Tag patch release
17 | # Only run cron on the silverstripe account
18 | if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
19 | runs-on: ubuntu-latest
20 | permissions:
21 | contents: write
22 | steps:
23 | - name: Tag release
24 | uses: silverstripe/gha-tag-release@v2
25 | with:
26 | latest_local_sha: ${{ inputs.latest_local_sha }}
27 |
--------------------------------------------------------------------------------
/lang/hr.yml:
--------------------------------------------------------------------------------
1 | hr:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Dodaj novi {name}'
4 | AddMultipleOptions: 'Dodaj novi'
5 | GridFieldSiteTreeState:
6 | Draft: ' Spremljeno kao Draft u {date}'
7 | Modified: Promjenjeno
8 | Published: ' Objavljeno u {date}'
9 | StateTitle: Stanje
10 | Lumberjack:
11 | TabTitle: Podstranice
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Dodaj novi {name}'
14 | AddMultipleOptions: 'Dodaj novi'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Spremljeno kao Draft u {date}'
17 | Modified: Promjenjeno
18 | Published: 'Objavljeno u {date}'
19 | StateTitle: Stanje
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: Podstranice
22 |
--------------------------------------------------------------------------------
/lang/eo.yml:
--------------------------------------------------------------------------------
1 | eo:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Enmeti novan {name}'
4 | AddMultipleOptions: 'Enmeti novan'
5 | GridFieldSiteTreeState:
6 | Draft: ' konserviĝis kiel malneto je {date}'
7 | Modified: Ŝanĝita
8 | Published: ' publikiĝis je {date}'
9 | StateTitle: Stato
10 | Lumberjack:
11 | TabTitle: 'Idoj de paĝoj'
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Enmeti novan {name}'
14 | AddMultipleOptions: 'Enmeti novan'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Konservita kiel malneta je {date}'
17 | Modified: Ŝanĝita
18 | Published: 'Publikigita je {date}'
19 | StateTitle: Stato
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: 'Idoj de paĝoj'
22 |
--------------------------------------------------------------------------------
/lang/it.yml:
--------------------------------------------------------------------------------
1 | it:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Aggiungi nuovo {name}'
4 | AddMultipleOptions: 'Aggiungi nuovo'
5 | GridFieldSiteTreeState:
6 | Draft: 'Salvato come Bozza il {date}'
7 | Modified: Modificato
8 | Published: 'Pubblicato il {date}'
9 | StateTitle: Stato
10 | Lumberjack:
11 | TabTitle: 'Pagine Figlio'
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Aggiungi nuovo {name}'
14 | AddMultipleOptions: 'Aggiungi nuovo'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Salvato come Bozza il {date}'
17 | Modified: Modificato
18 | Published: 'Pubblicato il {date}'
19 | StateTitle: Stato
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: 'Pagine Figlio'
22 |
--------------------------------------------------------------------------------
/lang/de.yml:
--------------------------------------------------------------------------------
1 | de:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Neuen {name} hinzufügen'
4 | AddMultipleOptions: 'Neuen hinzufügen'
5 | GridFieldSiteTreeState:
6 | Draft: ' Als Entwurf am {date} gespeichert'
7 | Modified: Geändert
8 | Published: ' Veröffentlicht am {date}'
9 | StateTitle: Status
10 | Lumberjack:
11 | TabTitle: Unterseiten
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Neuen {name} hinzufügen'
14 | AddMultipleOptions: 'Neuen hinzufügen'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Als Entwurf gespeichert am {date}'
17 | Modified: Geändert
18 | Published: 'Veröffentlicht am {date}'
19 | StateTitle: Status
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: Unterseiten
22 |
--------------------------------------------------------------------------------
/lang/nl.yml:
--------------------------------------------------------------------------------
1 | nl:
2 | GridFieldSiteTreeAddNewButton:
3 | Add: 'Voeg nieuwe {name} toe'
4 | AddMultipleOptions: 'Voeg nieuwe toe'
5 | GridFieldSiteTreeState:
6 | Draft: ' Opgeslagen als concept op {date}'
7 | Modified: Aangepast
8 | Published: ' Gepubliceerd op {date}'
9 | StateTitle: Status
10 | Lumberjack:
11 | TabTitle: "Onderliggende pagina's"
12 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeAddNewButton:
13 | Add: 'Voeg nieuwe {name} toe'
14 | AddMultipleOptions: 'Voeg nieuwe toe'
15 | SilverStripe\Lumberjack\Forms\GridFieldSiteTreeState:
16 | Draft: 'Opgeslagen als concept op {date}'
17 | Modified: Aangepast
18 | Published: 'Gepubliceerd op {date}'
19 | StateTitle: Status
20 | SilverStripe\Lumberjack\Model\Lumberjack:
21 | TabTitle: "Onderliggende pagina's"
22 |
--------------------------------------------------------------------------------
/config.rb:
--------------------------------------------------------------------------------
1 | # Require any additional compass plugins here.
2 |
3 | # Set this to the root of your project when deployed:
4 | http_path = "/"
5 | css_dir = "css"
6 | sass_dir = "scss"
7 | images_dir = "images"
8 | javascripts_dir = "javascript"
9 |
10 | # You can select your preferred output style here (can be overridden via the command line):
11 | # output_style = :expanded or :nested or :compact or :compressed
12 |
13 | # To enable relative paths to assets via compass helper functions. Uncomment:
14 | relative_assets = true
15 |
16 | # To disable debugging comments that display the original location of your selectors. Uncomment:
17 | line_comments = true
18 |
19 |
20 | # If you prefer the indented syntax, you might want to regenerate this
21 | # project again passing --syntax sass, or you can uncomment this:
22 | # preferred_syntax = :sass
23 | # and then run:
24 | # sass-convert -R --from scss --to sass scss scss && rm -rf sass && mv scss sass
25 |
--------------------------------------------------------------------------------
/.github/workflows/update-js.yml:
--------------------------------------------------------------------------------
1 | name: Update JS
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | branch_type:
7 | description: 'The branch type to run action on'
8 | required: true
9 | default: 'schedule'
10 | type: choice
11 | options:
12 | - 'schedule'
13 | - 'prev-major-curr-minor'
14 | - 'curr-major-curr-minor'
15 | - 'curr-major-next-minor'
16 | # At 10:50 PM UTC, on day 1 of the month, only in February and August
17 | schedule:
18 | - cron: '50 22 1 2,8 *'
19 |
20 | permissions: {}
21 |
22 | jobs:
23 | update-js:
24 | name: Update JS
25 | # Only run cron on the silverstripe account
26 | if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
27 | runs-on: ubuntu-latest
28 | permissions:
29 | contents: write
30 | pull-requests: write
31 | actions: write
32 | steps:
33 | - name: Update JS
34 | uses: silverstripe/gha-update-js@v1
35 | with:
36 | branch_type: ${{ github.event_name == 'schedule' && 'schedule' || github.event.inputs.branch_type }}
37 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "silverstripe/lumberjack",
3 | "description": "A module to make managing pages in a GridField easy without losing any of the functionality that you're used to in the CMS.",
4 | "type": "silverstripe-vendormodule",
5 | "require": {
6 | "php": "^8.3",
7 | "silverstripe/framework": "^6",
8 | "silverstripe/cms": "^6"
9 | },
10 | "require-dev": {
11 | "phpunit/phpunit": "^11.3",
12 | "squizlabs/php_codesniffer": "^3",
13 | "silverstripe/standards": "^1",
14 | "phpstan/extension-installer": "^1.3",
15 | "silverstripe/frameworktest": "^2"
16 | },
17 | "extra": {
18 | "expose": [
19 | "client/dist"
20 | ]
21 | },
22 | "autoload": {
23 | "psr-4": {
24 | "SilverStripe\\Lumberjack\\": "src/",
25 | "SilverStripe\\Lumberjack\\Tests\\": "tests/php/"
26 | }
27 | },
28 | "license": "BSD-2-Clause",
29 | "minimum-stability": "dev",
30 | "prefer-stable": true,
31 | "authors": [
32 | {
33 | "name": "Michael Strong",
34 | "email": "mstrong@silverstripe.org"
35 | }
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/src/Forms/GridFieldSiteTreeEditButton.php:
--------------------------------------------------------------------------------
1 |
16 | **/
17 | class GridFieldSiteTreeEditButton extends GridFieldEditButton
18 | {
19 | /**
20 | * @param GridField $gridField
21 | * @param DataObject $record
22 | * @param string $columnName
23 | * @return string - the HTML for the column
24 | */
25 | public function getColumnContent($gridField, $record, $columnName)
26 | {
27 | // No permission checks - handled through GridFieldDetailForm
28 | // which can make the form readonly if no edit permissions are available.
29 |
30 | $data = ArrayData::create([
31 | 'Link' => $record->getCMSEditLink(),
32 | 'ExtraClass' => $this->getExtraClass(),
33 | ]);
34 |
35 | return $data->renderWith(GridFieldEditButton::class);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016, Michael Strong
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 |
8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 |
10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11 |
--------------------------------------------------------------------------------
/behat.yml:
--------------------------------------------------------------------------------
1 | default:
2 | suites:
3 | lumberjack:
4 | paths:
5 | - "%paths.modules.lumberjack%/tests/behat/features"
6 | contexts:
7 | - SilverStripe\Framework\Tests\Behaviour\FeatureContext
8 | - SilverStripe\Framework\Tests\Behaviour\CmsFormsContext
9 | - SilverStripe\Framework\Tests\Behaviour\CmsUiContext
10 | - SilverStripe\BehatExtension\Context\BasicContext
11 | - SilverStripe\BehatExtension\Context\LoginContext
12 | -
13 | SilverStripe\BehatExtension\Context\FixtureContext:
14 | - '%paths.modules.lumberjack%/tests/behat/features/files/'
15 | -
16 | SilverStripe\Framework\Tests\Behaviour\ConfigContext:
17 | - '%paths.modules.lumberjack%/tests/behat/features/files/'
18 |
19 | extensions:
20 | SilverStripe\BehatExtension\MinkExtension:
21 | default_session: facebook_web_driver
22 | javascript_session: facebook_web_driver
23 | facebook_web_driver:
24 | browser: chrome
25 | wd_host: "http://127.0.0.1:9515" #chromedriver port
26 | browser_name: chrome
27 |
28 | SilverStripe\BehatExtension\Extension:
29 | screenshot_path: "%paths.base%/artifacts/screenshots"
30 | bootstrap_file: "vendor/silverstripe/framework/tests/behat/serve-bootstrap.php"
31 |
--------------------------------------------------------------------------------
/.github/workflows/dispatch-ci.yml:
--------------------------------------------------------------------------------
1 | name: Dispatch CI
2 |
3 | on:
4 | # At 6:30 PM UTC, only on Monday, Tuesday, and Wednesday
5 | schedule:
6 | - cron: '30 18 * * 1,2,3'
7 | workflow_dispatch:
8 | inputs:
9 | major_type:
10 | description: 'Major branch type'
11 | required: true
12 | type: choice
13 | options:
14 | - 'dynamic'
15 | - 'current'
16 | - 'next'
17 | - 'previous'
18 | default: 'dynamic'
19 | minor_type:
20 | description: 'Minor branch type'
21 | required: true
22 | type: choice
23 | options:
24 | - 'dynamic'
25 | - 'next-minor'
26 | - 'next-patch'
27 | default: 'dynamic'
28 |
29 | permissions: {}
30 |
31 | jobs:
32 | dispatch-ci:
33 | name: Dispatch CI
34 | # Only run cron on the silverstripe account
35 | if: (github.event_name == 'schedule' && github.repository_owner == 'silverstripe') || (github.event_name != 'schedule')
36 | runs-on: ubuntu-latest
37 | permissions:
38 | contents: read
39 | actions: write
40 | steps:
41 | - name: Dispatch CI
42 | uses: silverstripe/gha-dispatch-ci@v1
43 | with:
44 | major_type: ${{ inputs.major_type }}
45 | minor_type: ${{ inputs.minor_type }}
46 |
--------------------------------------------------------------------------------
/src/Forms/GridFieldConfig_Lumberjack.php:
--------------------------------------------------------------------------------
1 |
21 | **/
22 | class GridFieldConfig_Lumberjack extends GridFieldConfig
23 | {
24 | /**
25 | * @param int|null $itemsPerPage
26 | */
27 | public function __construct($itemsPerPage = null)
28 | {
29 | parent::__construct($itemsPerPage);
30 | $this->addComponent(new GridFieldButtonRow('before'));
31 | $this->addComponent(new GridFieldSiteTreeAddNewButton('buttons-before-left'));
32 | $this->addComponent(new GridFieldToolbarHeader());
33 | $this->addComponent(new GridFieldSortableHeader());
34 | $this->addComponent(new GridFieldFilterHeader());
35 | $this->addComponent(new GridFieldDataColumns());
36 | $this->addComponent(new GridFieldSiteTreeEditButton());
37 | $this->addComponent(new GridFieldPageCount('toolbar-header-right'));
38 | $this->addComponent(new GridFieldPaginator($itemsPerPage));
39 | $this->addComponent(new GridFieldSiteTreeState());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/2_feature_request.yml:
--------------------------------------------------------------------------------
1 | name: 🚀 Feature Request
2 | description: Submit a feature request (but only if you're planning on implementing it)
3 | body:
4 | - type: markdown
5 | attributes:
6 | value: |
7 | Please only submit feature requests if you plan on implementing the feature yourself.
8 | 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.
9 | - type: textarea
10 | id: description
11 | attributes:
12 | label: Description
13 | description: A clear and concise description of the new feature, and why it belongs in core
14 | validations:
15 | required: true
16 | - type: textarea
17 | id: more-info
18 | attributes:
19 | label: Additional context or points of discussion
20 | description: |
21 | *Optional: Any additional context, points of discussion, etc that might help validate and refine your idea*
22 | - type: checkboxes
23 | id: validations
24 | attributes:
25 | label: Validations
26 | description: "Before submitting the issue, please confirm the following:"
27 | options:
28 | - label: You intend to implement the feature yourself
29 | required: true
30 | - label: You have read the [contributing guide](https://docs.silverstripe.org/en/contributing/code/)
31 | required: true
32 | - label: You strongly believe this feature should be in core, rather than being its own community module
33 | required: true
34 | - label: You have checked for existing issues or pull requests related to this feature (and didn't find any)
35 | required: true
36 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
6 | ## Description
7 |
11 |
12 | ## Manual testing steps
13 |
17 |
18 | ## Issues
19 |
23 | - #
24 |
25 | ## Pull request checklist
26 |
30 | - [ ] The target branch is correct
31 | - See [picking the right version](https://docs.silverstripe.org/en/contributing/code/#picking-the-right-version)
32 | - [ ] All commits are relevant to the purpose of the PR (e.g. no debug statements, unrelated refactoring, or arbitrary linting)
33 | - 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.
34 | - [ ] The commit messages follow our [commit message guidelines](https://docs.silverstripe.org/en/contributing/code/#commit-messages)
35 | - [ ] The PR follows our [contribution guidelines](https://docs.silverstripe.org/en/contributing/code/)
36 | - [ ] Code changes follow our [coding conventions](https://docs.silverstripe.org/en/contributing/coding_conventions/)
37 | - [ ] This change is covered with tests (or tests aren't necessary for this change)
38 | - [ ] Any relevant User Help/Developer documentation is updated; for impactful changes, information is added to the changelog for the intended release
39 | - [ ] CI is green
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Silverstripe Lumberjack
2 |
3 | [](https://github.com/silverstripe/silverstripe-lumberjack/actions/workflows/ci.yml)
4 | [](https://www.silverstripe.org/software/addons/silverstripe-commercially-supported-module-list/)
5 |
6 | A module to make managing pages in a GridField easy without losing any of the functionality that you're used to in the CMS.
7 |
8 | This is intended to be used in cases where the SiteTree grows beyond a manageable level. eg. blogs, news sections, shops, etc.
9 |
10 | This module was born out of and decoupled from [micmania1/silverstripe-blog](https://github.com/micmania1/silverstripe-blogger).
11 |
12 | ## Installation
13 |
14 | ```sh
15 | composer require silverstripe/lumberjack
16 | ```
17 |
18 | ## Features
19 |
20 | * Easily define which page types to show in the SiteTree and which to manage in a GridField.
21 | * Keep all functionality that comes with the CMS, including versioning and preview.
22 |
23 | ## Usage
24 |
25 | In this example we have a `NewsHolder` page which is the root of our news section, containing `NewsArticle`s and
26 | `NewsPage`s. We want to display `NewsPage` in the site tree but we want to display `NewsArticle`s in a `GridField`.
27 |
28 | ```php
29 |
15 | **/
16 | class GridFieldSiteTreeState implements GridField_ColumnProvider
17 | {
18 | use Injectable;
19 |
20 | public function augmentColumns($gridField, &$columns)
21 | {
22 | // Ensure Actions always appears as the last column.
23 | $key = array_search('Actions', $columns ?? []);
24 | if ($key !== false) {
25 | unset($columns[$key]);
26 | }
27 |
28 | $columns = array_merge($columns, array(
29 | 'State',
30 | 'Actions',
31 | ));
32 | }
33 |
34 | public function getColumnsHandled($gridField)
35 | {
36 | return array('State');
37 | }
38 |
39 | public function getColumnContent($gridField, $record, $columnName)
40 | {
41 | if ($columnName == 'State') {
42 | if ($record->hasMethod('isPublished')) {
43 | $modifiedLabel = '';
44 | if ($record->isModifiedOnDraft()) {
45 | $modifiedLabel = '' . _t(__CLASS__ . '.Modified', 'Modified') . '';
46 | }
47 |
48 | $published = $record->isPublished();
49 | if (!$published) {
50 | return '' . _t(
51 | __CLASS__ . '.Draft',
52 | 'Saved as Draft on {date}',
53 | 'State for when a post is saved.',
54 | array(
55 | 'date' => $record->dbObject('LastEdited')->Nice()
56 | )
57 | );
58 | }
59 | return '' . _t(
60 | __CLASS__ . '.Published',
61 | 'Published on {date}',
62 | 'State for when a post is published.',
63 | array(
64 | 'date' => $record->dbObject('LastEdited')->Nice()
65 | )
66 | ) . $modifiedLabel;
67 | }
68 | }
69 | }
70 |
71 | public function getColumnAttributes($gridField, $record, $columnName)
72 | {
73 | if ($columnName == 'State') {
74 | if ($record->hasMethod('isPublished')) {
75 | $published = $record->isPublished();
76 | if (!$published) {
77 | $class = 'gridfield-icon draft';
78 | } else {
79 | $class = 'gridfield-icon published';
80 | }
81 | return array('class' => $class);
82 | }
83 | }
84 | return array();
85 | }
86 |
87 | public function getColumnMetaData($gridField, $columnName)
88 | {
89 | switch ($columnName) {
90 | case 'State':
91 | return array('title' => _t(__CLASS__ . '.StateTitle', 'State', 'Column title for state'));
92 | default:
93 | break;
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/1_bug_report.yml:
--------------------------------------------------------------------------------
1 | name: 🪳 Bug Report
2 | description: Tell us if something isn't working the way it's supposed to
3 |
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | We strongly encourage you to [submit a pull request](https://docs.silverstripe.org/en/contributing/code/) which fixes the issue.
9 | Bug reports which are accompanied with a pull request are a lot more likely to be resolved quickly.
10 | - type: input
11 | id: affected-versions
12 | attributes:
13 | label: Module version(s) affected
14 | description: |
15 | What version of _this module_ have you reproduced this bug on?
16 | Run `composer info` to see the specific version of each module installed in your project.
17 | If you don't have access to that, check inside the help menu in the bottom left of the CMS.
18 | placeholder: x.y.z
19 | validations:
20 | required: true
21 | - type: textarea
22 | id: description
23 | attributes:
24 | label: Description
25 | description: A clear and concise description of the problem
26 | validations:
27 | required: true
28 | - type: textarea
29 | id: how-to-reproduce
30 | attributes:
31 | label: How to reproduce
32 | description: |
33 | ⚠️ This is the most important part of the report ⚠️
34 | Without a way to easily reproduce your issue, there is little chance we will be able to help you and work on a fix.
35 | - Please, take the time to show us some code and/or configuration that is needed for others to reproduce the problem easily.
36 | - 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.
37 | - If part of the bug includes an error or exception, please provide a full stack trace.
38 | - If any user interaction is required to reproduce the bug, please add an ordered list of steps that are required to reproduce it.
39 | - 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.
40 | placeholder: |
41 |
42 | #### Code sample
43 | ```php
44 |
45 | ```
46 |
47 | #### Reproduction steps
48 | 1.
49 | validations:
50 | required: true
51 | - type: textarea
52 | id: possible-solution
53 | attributes:
54 | label: Possible Solution
55 | description: |
56 | *Optional: only if you have suggestions on a fix/reason for the bug*
57 | 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.
58 | - type: textarea
59 | id: additional-context
60 | attributes:
61 | label: Additional Context
62 | description: "*Optional: any other context about the problem: log messages, screenshots, etc.*"
63 | - type: checkboxes
64 | id: validations
65 | attributes:
66 | label: Validations
67 | description: "Before submitting the issue, please make sure you do the following:"
68 | options:
69 | - label: Check that there isn't already an issue that reports the same bug
70 | required: true
71 | - 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)
72 | required: true
73 |
--------------------------------------------------------------------------------
/src/Forms/GridFieldSiteTreeAddNewButton.php:
--------------------------------------------------------------------------------
1 |
31 | */
32 | class GridFieldSiteTreeAddNewButton extends GridFieldAddNewButton implements GridField_ActionProvider
33 | {
34 | /**
35 | * Determine the list of classnames and titles allowed for a given parent object
36 | *
37 | * @param SiteTree $parent
38 | * @return boolean
39 | */
40 | public function getAllowedChildren(?SiteTree $parent = null)
41 | {
42 | if (!$parent || !$parent->canAddChildren()) {
43 | return array();
44 | }
45 |
46 | $nonHiddenPageTypes = ClassInfo::getValidSubClasses(SiteTree::class);
47 | SiteTree::singleton()->updateAllowedSubClasses($nonHiddenPageTypes);
48 | $allowedChildren = $parent->allowedChildren();
49 | $children = array();
50 | foreach ($allowedChildren as $class) {
51 | if (Config::inst()->get($class, 'show_in_sitetree') === false) {
52 | $instance = Injector::inst()->get($class);
53 | // Note: Second argument to SiteTree::canCreate will support inherited permissions
54 | // post 3.1.12, and will default to the old permission model in 3.1.11 or below
55 | // See http://docs.silverstripe.org/en/changelogs/3.1.11
56 | if (
57 | $instance->canCreate(null, array('Parent' => $parent)) &&
58 | in_array($class, $nonHiddenPageTypes ?? [])
59 | ) {
60 | $children[$class] = $instance->i18n_singular_name();
61 | }
62 | }
63 | }
64 | return $children;
65 | }
66 |
67 | public function getHTMLFragments($gridField)
68 | {
69 | $state = $gridField->State->GridFieldSiteTreeAddNewButton;
70 |
71 | $parent = SiteTree::get()->byId(Controller::curr()->currentRecordID());
72 |
73 | if ($parent) {
74 | $state->currentRecordID = $parent->ID;
75 | }
76 |
77 | $children = $this->getAllowedChildren($parent);
78 | if (empty($children)) {
79 | return array();
80 | } elseif (count($children ?? []) > 1) {
81 | $pageTypes = DropdownField::create('RecordType', 'Page Type', $children, $parent->defaultChild());
82 | $pageTypes
83 | ->setFieldHolderTemplate(__CLASS__ . '_holder')
84 | ->addExtraClass('gridfield-dropdown no-change-track');
85 |
86 | $state->RecordType = $parent->defaultChild();
87 |
88 | if (!$this->buttonName) {
89 | $this->buttonName = _t(
90 | __CLASS__ . '.AddMultipleOptions',
91 | 'Add new',
92 | 'Add button text for multiple options.'
93 | );
94 | }
95 | } else {
96 | $keys = array_keys($children ?? []);
97 | $pageTypes = HiddenField::create('RecordType', 'Page Type', $keys[0]);
98 |
99 | $state->recordType = $keys[0];
100 |
101 | if (!$this->buttonName) {
102 | $this->buttonName = _t(
103 | __CLASS__ . '.Add',
104 | 'Add new {name}',
105 | 'Add button text for a single option.',
106 | ['name' => $children[$keys[0]]]
107 | );
108 | }
109 | }
110 |
111 | $addAction = GridField_FormAction::create($gridField, 'add', $this->buttonName, 'add', 'add');
112 | $addAction
113 | ->setIcon('add')
114 | ->addExtraClass('no-ajax btn btn-primary');
115 |
116 | $forTemplate = ArrayData::create();
117 | $forTemplate->Fields = ArrayList::create();
118 | $forTemplate->Fields->push($pageTypes);
119 | $forTemplate->Fields->push($addAction);
120 |
121 | return [$this->targetFragment => $forTemplate->renderWith(__CLASS__)];
122 | }
123 |
124 | /**
125 | * Provide actions to this component.
126 | *
127 | * @param GridField $gridField
128 | * @return array
129 | **/
130 | public function getActions($gridField)
131 | {
132 | return array('add');
133 | }
134 |
135 | /**
136 | * Handles the add action, but only acts as a wrapper for CMSMain
137 | *
138 | * @param GridField $gridField
139 | * @param string $actionName
140 | * @param mixed $arguments
141 | * @param array $data
142 | *
143 | * @return HTTPResponse|null
144 | */
145 | public function handleAction(GridField $gridField, $actionName, $arguments, $data)
146 | {
147 | if ($actionName == 'add') {
148 | $tmpData = json_decode($data['ChildPages']['GridState'] ?? '', true);
149 | $tmpData = $tmpData['GridFieldSiteTreeAddNewButton'];
150 |
151 | $data = array(
152 | 'ParentID' => $tmpData['currentRecordID'],
153 | 'RecordType' => $tmpData['recordType']
154 | );
155 |
156 | $controller = Injector::inst()->create(CMSMain::class);
157 | $form = $controller->AddForm();
158 |
159 | // pass current request down in case either of these needs it
160 | $request = Controller::curr()->getRequest();
161 | $controller->setRequest($request);
162 | $form->getRequestHandler()->setRequest($request);
163 |
164 | $form->loadDataFrom($data);
165 | return $form->doAdd($data, $form);
166 | }
167 |
168 | return null;
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/src/Model/Lumberjack.php:
--------------------------------------------------------------------------------
1 |
31 | *
32 | * @extends Extension
33 | */
34 | class Lumberjack extends Extension
35 | {
36 | /**
37 | * Loops through subclasses of the owner (intended to be SiteTree) and checks if they've been hidden.
38 | *
39 | * @return array
40 | **/
41 | public function getExcludedSiteTreeClassNames()
42 | {
43 | $classes = array();
44 | $siteTreeClasses = $this->owner->allowedChildren();
45 |
46 | foreach ($siteTreeClasses as $class) {
47 | if (Config::inst()->get($class, 'show_in_sitetree') === false) {
48 | $classes[$class] = $class;
49 | }
50 | }
51 |
52 | $this->owner->extend('updateSiteTreeExcludedClassNames', $classes);
53 |
54 | return $classes;
55 | }
56 |
57 | /**
58 | * This is responsible for adding the child pages tab and gridfield.
59 | *
60 | * @param FieldList $fields
61 | */
62 | protected function updateCMSFields(FieldList $fields)
63 | {
64 | $excluded = $this->owner->getExcludedSiteTreeClassNames();
65 | if (!empty($excluded)) {
66 | $pages = $this->getLumberjackPagesForGridfield($excluded);
67 | $gridField = GridField::create(
68 | 'ChildPages',
69 | $this->getLumberjackTitle(),
70 | $pages,
71 | $this->getLumberjackGridFieldConfig()
72 | );
73 |
74 | // Ensure correct link is used when gridfield is readonly
75 | $readonlyComponents = $gridField->getReadonlyComponents();
76 | $viewButtonIndex = array_search(GridFieldViewButton::class, $readonlyComponents);
77 | if ($viewButtonIndex !== false) {
78 | unset($readonlyComponents[$viewButtonIndex]);
79 | }
80 | $readonlyComponents[] = GridFieldSiteTreeViewButton::class;
81 | $gridField->setReadonlyComponents($readonlyComponents);
82 |
83 | $tab = Tab::create('ChildPages', $this->getLumberjackTitle(), $gridField);
84 | $fields->insertAfter('Main', $tab);
85 | }
86 | }
87 |
88 | /**
89 | * Return children in the stage site.
90 | *
91 | * @param bool $showAll Include all of the elements, even those not shown in the menus. Only applicable when
92 | * extension is applied to {@link SiteTree}.
93 | * @return DataList
94 | */
95 | public function stageChildren($showAll = false)
96 | {
97 | $config = $this->owner->config();
98 | $hideFromHierarchy = $config->get('hide_from_hierarchy');
99 | $hideFromCMSTree = $config->get('hide_from_cms_tree');
100 | $baseClass = $this->owner->baseClass();
101 |
102 | $staged = $baseClass::get()
103 | ->filter('ParentID', (int)$this->owner->ID)
104 | ->exclude('ID', (int)$this->owner->ID);
105 |
106 | if ($hideFromHierarchy) {
107 | $staged = $staged->exclude('ClassName', $hideFromHierarchy);
108 | }
109 |
110 | if ($hideFromCMSTree && $this->owner->showingCMSTree()) {
111 | $staged = $staged->exclude('ClassName', $hideFromCMSTree);
112 | }
113 |
114 | if (!$showAll && DataObject::getSchema()->fieldSpec($this->owner, 'ShowInMenus')) {
115 | $staged = $staged->filter('ShowInMenus', 1);
116 | }
117 |
118 | $this->owner->extend("augmentStageChildren", $staged, $showAll);
119 | $staged = $this->excludeSiteTreeClassNames($staged);
120 | return $staged;
121 | }
122 |
123 | /**
124 | * @param mixed $includeDeleted @deprecated - this parameter is unused and will be removed in a future major release
125 | */
126 | protected function updateGetChildrenForTree(mixed $includeDeleted, SS_List &$children): void
127 | {
128 | $children = $this->excludeSiteTreeClassNames($children);
129 | }
130 |
131 | /**
132 | * Excludes any hidden owner subclasses. Note that the returned DataList will be a different
133 | * instance from the original.
134 | *
135 | * @param SS_List $list
136 | * @return SS_List
137 | */
138 | protected function excludeSiteTreeClassNames($list)
139 | {
140 | $classNames = $this->owner->getExcludedSiteTreeClassNames();
141 | if ($this->shouldFilter() && count($classNames ?? [])) {
142 | // Filter the SiteTree
143 | $list = $list->exclude('ClassName', $classNames);
144 | }
145 | return $list;
146 | }
147 |
148 | /**
149 | * Return children in the live site, if it exists.
150 | *
151 | * @param bool $showAll Include all of the elements, even those not shown in the menus. Only
152 | * applicable when extension is applied to {@link SiteTree}.
153 | * @param bool $onlyDeletedFromStage Only return items that have been deleted from stage
154 | * @return DataList
155 | * @throws Exception
156 | */
157 | public function liveChildren($showAll = false, $onlyDeletedFromStage = false)
158 | {
159 | if (!$this->owner->hasExtension(Versioned::class)) {
160 | throw new Exception('Hierarchy->liveChildren() only works with Versioned extension applied');
161 | }
162 |
163 | $config = $this->owner->config();
164 | $hideFromHierarchy = $config->get('hide_from_hierarchy');
165 | $hideFromCMSTree = $config->get('hide_from_cms_tree');
166 | $baseClass = $this->owner->baseClass();
167 |
168 | $children = $baseClass::get()
169 | ->filter('ParentID', (int)$this->owner->ID)
170 | ->exclude('ID', (int)$this->owner->ID)
171 | ->setDataQueryParam(array(
172 | 'Versioned.mode' => $onlyDeletedFromStage ? 'stage_unique' : 'stage',
173 | 'Versioned.stage' => 'Live'
174 | ));
175 |
176 | if ($hideFromHierarchy) {
177 | $children = $children->exclude('ClassName', $hideFromHierarchy);
178 | }
179 |
180 | if ($hideFromCMSTree && $this->owner->showingCMSTree()) {
181 | $children = $children->exclude('ClassName', $hideFromCMSTree);
182 | }
183 |
184 | if (!$showAll && DataObject::getSchema()->fieldSpec($this->owner, 'ShowInMenus')) {
185 | $children = $children->filter('ShowInMenus', 1);
186 | }
187 | $children = $this->excludeSiteTreeClassNames($children);
188 |
189 | return $children;
190 | }
191 |
192 | /**
193 | * This returns the title for the tab and GridField. This can be overwritten
194 | * in the owner class.
195 | *
196 | * @return string
197 | */
198 | protected function getLumberjackTitle()
199 | {
200 | if (method_exists($this->owner, 'getLumberjackTitle')) {
201 | return $this->owner->getLumberjackTitle();
202 | }
203 |
204 | return _t(__CLASS__ . '.TabTitle', 'Child Pages');
205 | }
206 |
207 | /**
208 | * This returns the gird field config for the lumberjack gridfield.
209 | *
210 | * @return GridFieldConfig_Lumberjack
211 | */
212 | protected function getLumberjackGridFieldConfig()
213 | {
214 | if (method_exists($this->owner, 'getLumberjackGridFieldConfig')) {
215 | return $this->owner->getLumberjackGridFieldConfig();
216 | }
217 |
218 | return GridFieldConfig_Lumberjack::create();
219 | }
220 |
221 | /**
222 | * Checks if we're on a controller where we should filter. ie. Are we loading the SiteTree?
223 | * NB: This only checks the current controller. See https://github.com/silverstripe/silverstripe-lumberjack/pull/60
224 | * for a discussion around this.
225 | *
226 | * @return bool
227 | */
228 | protected function shouldFilter()
229 | {
230 | $controller = Controller::curr();
231 |
232 | // relevant only for CMS
233 | if (!($controller instanceof LeftAndMain)) {
234 | return false;
235 | }
236 |
237 | return in_array($controller->getAction(), [
238 | 'index', 'show', 'treeview', 'listview', 'getsubtree'
239 | ]);
240 | }
241 |
242 | /**
243 | * Returns list of pages for the CMS gridfield
244 | *
245 | * This also allows the owner class to override this method, e.g. to provide custom ordering.
246 | *
247 | * @var array $excluded List of class names excluded from the SiteTree
248 | * @return DataList
249 | */
250 | public function getLumberjackPagesForGridfield($excluded = array())
251 | {
252 | if (method_exists($this->owner, 'getLumberjackPagesForGridfield')) {
253 | return $this->owner->getLumberjackPagesForGridfield($excluded);
254 | }
255 |
256 | return SiteTree::get()->filter([
257 | 'ParentID' => $this->owner->ID,
258 | 'ClassName' => $excluded,
259 | ]);
260 | }
261 | }
262 |
--------------------------------------------------------------------------------