├── .babelrc
├── .github
└── workflows
│ ├── build-2x.yml
│ └── build-3x.yml
├── .gitignore
├── .nvmrc
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── _build
├── assets
│ ├── images
│ │ ├── edit.svg
│ │ ├── eye-slash.svg
│ │ ├── eye.svg
│ │ ├── trash-restore.svg
│ │ └── trash.svg
│ ├── index.js
│ ├── js
│ │ ├── Sidebar
│ │ │ ├── Actions.ts
│ │ │ ├── Utils.ts
│ │ │ └── index.ts
│ │ └── index.ts
│ └── sass
│ │ └── collections.scss
├── gpm.json
├── gpm_resolvers
│ ├── gpm.resolve.bootstrap.php
│ └── gpm.resolve.element_property_set.php
├── gpm_scripts
│ ├── gpm.script.customevents.php
│ ├── gpm.script.defaulttemplate.php
│ ├── gpm.script.fixoldcollections.php
│ ├── gpm.script.fixselections.php
│ ├── gpm.script.fixsystemsettings.php
│ ├── gpm.script.fred_get_service.php
│ ├── gpm.script.fred_link_element_option_set.php
│ ├── gpm.script.migrator.php
│ ├── gpm.script.reload_system_settings.php
│ ├── gpm.script.switchback.php
│ ├── gpm.script.sync_tables.php
│ └── gpm.script.tables.php
├── migrations
│ ├── 200pl.migration.php
│ ├── 340pl.migration.php
│ └── 370pl.migration.php
└── scripts
│ ├── customevents.gpm.php
│ ├── defaulttemplate.gpm.php
│ ├── fixoldcollections.gpm.php
│ ├── fixselections.gpm.php
│ ├── fixsystemsettings.gpm.php
│ └── switchback.gpm.php
├── assets
└── components
│ └── collections
│ ├── css
│ ├── i
│ │ └── collection.png
│ ├── index.html
│ └── mgr.css
│ ├── index.html
│ ├── js
│ ├── index.html
│ └── mgr
│ │ ├── collections.js
│ │ ├── extra
│ │ ├── collections.combo.js
│ │ ├── collections.renderers.js
│ │ ├── griddraganddrop.js
│ │ └── hijackclose.js
│ │ ├── sections
│ │ ├── category
│ │ │ └── update.js
│ │ └── template
│ │ │ ├── home.js
│ │ │ └── template.js
│ │ └── widgets
│ │ ├── category
│ │ ├── collections.grid.resources.js
│ │ ├── collections.grid.selection.js
│ │ ├── collections.panel.category.js
│ │ ├── collections.panel.selection.js
│ │ └── collections.window.js
│ │ └── template
│ │ ├── column.grid.js
│ │ ├── column.window.js
│ │ ├── home.panel.js
│ │ ├── template.grid.js
│ │ ├── template.panel.js
│ │ └── template.window.js
│ └── web
│ ├── ajax.php
│ ├── bars-solid.svg
│ ├── fred_integration.css
│ ├── fred_integration.js
│ └── index.html
├── core
└── components
│ └── collections
│ ├── bootstrap.php
│ ├── controllers
│ ├── create.class.php
│ ├── data.class.php
│ ├── home.class.php
│ ├── selection
│ │ ├── create.class.php
│ │ ├── data.class.php
│ │ └── update.class.php
│ ├── template
│ │ ├── create.class.php
│ │ ├── export.class.php
│ │ └── update.class.php
│ └── update.class.php
│ ├── elements
│ ├── plugins
│ │ └── Collections.php
│ ├── snippets
│ │ └── getSelections.php
│ └── widgets
│ │ └── test.php
│ ├── index.class.php
│ ├── lexicon
│ ├── cs
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── da
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── de
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── en
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── fr
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── it
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── nl
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── pt
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── ru
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ └── sv
│ │ ├── custom.inc.php
│ │ ├── default.inc.php
│ │ ├── fred.inc.php
│ │ ├── selections.inc.php
│ │ └── templates.inc.php
│ ├── schema
│ └── collections.mysql.schema.xml
│ ├── src
│ ├── Collections.php
│ ├── Endpoint
│ │ ├── Ajax.php
│ │ └── Ajax
│ │ │ ├── Endpoint.php
│ │ │ ├── GetAuthors.php
│ │ │ ├── GetCollection.php
│ │ │ ├── GetCollectionView.php
│ │ │ └── GetCollections.php
│ ├── Events
│ │ ├── Event.php
│ │ ├── FredBeforeRender.php
│ │ ├── FredOnBeforeGetResourceTree.php
│ │ ├── OnBeforeDocFormSave.php
│ │ ├── OnBeforeEmptyTrash.php
│ │ ├── OnDocFormPrerender.php
│ │ ├── OnDocFormRender.php
│ │ ├── OnManagerPageBeforeRender.php
│ │ ├── OnManagerPageInit.php
│ │ ├── OnResourceBeforeSort.php
│ │ └── OnResourceDuplicate.php
│ ├── Model
│ │ ├── CollectionContainer.php
│ │ ├── CollectionContainerCreateProcessor.php
│ │ ├── CollectionContainerUpdateProcessor.php
│ │ ├── CollectionResourceTemplate.php
│ │ ├── CollectionSelection.php
│ │ ├── CollectionSetting.php
│ │ ├── CollectionTemplate.php
│ │ ├── CollectionTemplateColumn.php
│ │ ├── SelectionContainer.php
│ │ ├── SelectionContainerCreateProcessor.php
│ │ ├── SelectionContainerUpdateProcessor.php
│ │ ├── metadata.mysql.php
│ │ └── mysql
│ │ │ ├── CollectionContainer.php
│ │ │ ├── CollectionResourceTemplate.php
│ │ │ ├── CollectionSelection.php
│ │ │ ├── CollectionSetting.php
│ │ │ ├── CollectionTemplate.php
│ │ │ ├── CollectionTemplateColumn.php
│ │ │ └── SelectionContainer.php
│ ├── Processors
│ │ ├── Extra
│ │ │ ├── Breadcrumbs.php
│ │ │ ├── FredGetBlueprints.php
│ │ │ ├── GetContentTypes.php
│ │ │ ├── GetDerivates.php
│ │ │ ├── GetResources.php
│ │ │ └── GetTemplates.php
│ │ ├── Resource
│ │ │ ├── ChangeChildParent.php
│ │ │ ├── ChangeParent.php
│ │ │ ├── DDReorder.php
│ │ │ ├── Delete.php
│ │ │ ├── DeleteMultiple.php
│ │ │ ├── GetList.php
│ │ │ ├── Publish.php
│ │ │ ├── PublishMultiple.php
│ │ │ ├── Remove.php
│ │ │ ├── UnDelete.php
│ │ │ ├── UnDeleteMultiple.php
│ │ │ ├── UnPublish.php
│ │ │ ├── UnPublishMultiple.php
│ │ │ └── UpdateFromGrid.php
│ │ ├── Selection
│ │ │ ├── Create.php
│ │ │ ├── DDReorder.php
│ │ │ ├── GetList.php
│ │ │ ├── Remove.php
│ │ │ ├── RemoveMultiple.php
│ │ │ └── UpdateFromGrid.php
│ │ └── Template
│ │ │ ├── Column
│ │ │ ├── Create.php
│ │ │ ├── DDReorder.php
│ │ │ ├── GetList.php
│ │ │ ├── Remove.php
│ │ │ ├── Update.php
│ │ │ └── UpdateFromGrid.php
│ │ │ ├── Create.php
│ │ │ ├── Duplicate.php
│ │ │ ├── Get.php
│ │ │ ├── GetList.php
│ │ │ ├── Import.php
│ │ │ ├── Remove.php
│ │ │ ├── Update.php
│ │ │ └── UpdateFromGrid.php
│ └── Utils.php
│ └── templates
│ └── template
│ ├── home.tpl
│ └── template.tpl
├── crowdin.yml
├── package-lock.json
├── package.json
├── postcss.config.js
├── tsconfig.json
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["babel-plugin-add-module-exports"],
3 | "presets": [
4 | ["@babel/preset-env", { "targets": "> 0.25%, not dead", "corejs": "3.37", "useBuiltIns": "usage"}]
5 | ]
6 | }
--------------------------------------------------------------------------------
/.github/workflows/build-2x.yml:
--------------------------------------------------------------------------------
1 | name: Build Package 2.x
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | jobs:
7 |
8 | deploy:
9 | # The type of runner that the job will run on
10 | runs-on: ubuntu-latest
11 | environment: 2.x
12 |
13 | # Steps represent a sequence of tasks that will be executed as part of the job
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v4
17 |
18 | - name: Get Branch Name
19 | uses: nelonoel/branch-name@v1.0.1
20 |
21 | - run: echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITHUB_ENV
22 |
23 | - name: Build & Deploy GPM Package
24 | uses: appleboy/ssh-action@v1.0.3
25 | env:
26 | BRANCH: ${{ env.BRANCH_NAME }}
27 | with:
28 | command_timeout: 20m
29 | host: ${{ secrets.DEPLOY_HOST }}
30 | key: ${{ secrets.DEPLOY_KEY }}
31 | username: ${{ secrets.DEPLOY_USER }}
32 | envs: BRANCH
33 | script_stop: true
34 | script: |
35 | cd /www/pkgs/collections/
36 | git add .
37 | git stash
38 | git fetch origin
39 | git checkout -f $BRANCH
40 | git pull origin $BRANCH
41 | npm install
42 | npm run build
43 | rm -rf _packages
44 | /www/pkgs/gpm/cli/bin/gpm package:update --pkg collections --updateDB=alter
45 | /www/pkgs/gpm/cli/bin/gpm package:build --pkg collections
--------------------------------------------------------------------------------
/.github/workflows/build-3x.yml:
--------------------------------------------------------------------------------
1 | name: Build Package 3.x
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | jobs:
7 |
8 | deploy:
9 | # The type of runner that the job will run on
10 | runs-on: ubuntu-latest
11 | environment: 3.x
12 |
13 | # Steps represent a sequence of tasks that will be executed as part of the job
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v4
17 |
18 | - name: Get Branch Name
19 | uses: nelonoel/branch-name@v1.0.1
20 |
21 | - run: echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITHUB_ENV
22 |
23 | - name: Build & Deploy GPM Package
24 | uses: appleboy/ssh-action@v1.0.3
25 | env:
26 | BRANCH: ${{ env.BRANCH_NAME }}
27 | with:
28 | command_timeout: 20m
29 | host: ${{ secrets.DEPLOY_HOST }}
30 | key: ${{ secrets.DEPLOY_KEY }}
31 | username: ${{ secrets.DEPLOY_USER }}
32 | envs: BRANCH
33 | script_stop: true
34 | script: |
35 | cd /www/pkgs/collections/
36 | git add .
37 | git stash
38 | git fetch origin
39 | git checkout -f $BRANCH
40 | git pull origin $BRANCH
41 | npm install
42 | npm run build
43 | /www/pkgs/gpm/bin/gpm collections:update --alterDB
44 | /www/pkgs/gpm/bin/gpm collections:build
45 |
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS-generated and dev tool files #
2 | ###################################
3 | .DS_Store
4 | .DS_Store?
5 | ._*
6 | .Spotlight-V100
7 | .Trashes
8 | ehthumbs.db
9 | Thumbs.db
10 | .idea
11 | .settings
12 | nbproject
13 | .project
14 |
15 | # MODX-related files #
16 | ######################
17 | config.core.php
18 |
19 | # Build-related files for distribution #
20 | ########################################
21 | _build/build.config.php
22 | _packages
23 | _build/build.config.php
24 | node_modules
25 | npm-debug.log
26 | .sass-cache
27 | assets/components/collections/web/fred_integration.*
28 | package-lock.json
29 | core/components/collections/model/vendor
30 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 20
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Collections [  ](https://crowdin.com/project/collections)
2 | ===========
3 |
4 | Collections is a MODX Revolution Extra that adds a custom `CollectionContainer` resource class with the following behaviour:
5 |
6 | 1. Any direct child resource will be hidden from the Resource Tree in the Manager, and listed in a grid view (similar to Articles) under a dedicated "Children" tab, for which the label can be customized.
7 | 2. Any children that themselves have children will be shown in the Tree, to be managed normally.
8 |
9 | 
10 |
11 | #### Sub Collections
12 | Just like the MODX Resource Tree itself, Collections supports nesting. You can create a Collection within another Collection. Sub Collection Containers will be displayed in the resource tree and their children will be displayed in the grid view.
13 |
14 | #### Drag n Drop
15 | You can drag n drop Resources into a Collections container and if they don't have children of their own they will be listed in the grid. If they do have children, they'll just remain in the Tree as usual.
16 |
17 | ### Custom Views
18 | As of version 2.x, Collections supports customizable views. Views are configured in Collections Custom Manager Page (CMP):
19 |
20 | 
21 | 
22 |
23 | There are specific settings for Collections Resources vs Selections.
24 |
25 | ### Resources
26 | The official documentation for Collections can be found here: [https://docs.modx.com/extras/revo/collections](https://docs.modx.com/extras/revo/collections)
27 |
--------------------------------------------------------------------------------
/_build/assets/images/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_build/assets/images/eye-slash.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_build/assets/images/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_build/assets/images/trash-restore.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_build/assets/images/trash.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_build/assets/index.js:
--------------------------------------------------------------------------------
1 | var pkg = require('../../package.json');
2 | var libFile = pkg.library['bundle-node'] ? pkg.library['dist-node'] : pkg.library['entry'];
3 | module.exports = require('./lib/' + libFile);
--------------------------------------------------------------------------------
/_build/assets/js/Sidebar/Actions.ts:
--------------------------------------------------------------------------------
1 | export default class Actions {
2 | private config: any;
3 | private fetch: any;
4 | private emitter: any;
5 | constructor(config, fetch, emitter) {
6 | this.config = config;
7 | this.fetch = fetch;
8 | this.emitter = emitter;
9 | }
10 |
11 | getCollections() {
12 | return this.fetch(`${this.config.endpoint}?action=get-collections`).then(response => {
13 | return response.json();
14 | }).then(data => {
15 | return data.data.collections;
16 | });
17 | }
18 |
19 | getAuthors(collection) {
20 | return this.fetch(`${this.config.endpoint}?action=get-authors&collection=${collection}`).then(response => {
21 | return response.json();
22 | }).then(data => {
23 | return data.data;
24 | });
25 | }
26 |
27 | getCollectionView(collection) {
28 | return this.fetch(`${this.config.endpoint}?action=get-collection-view&collection=${collection}`).then(response => {
29 | return response.json();
30 | }).then(data => {
31 | return data.data;
32 | });
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/_build/assets/js/Sidebar/Utils.ts:
--------------------------------------------------------------------------------
1 | export const debounce = (delay, fn) => {
2 | let timerId;
3 |
4 | return function (...args) {
5 | if (timerId) {
6 | clearTimeout(timerId);
7 | }
8 | timerId = setTimeout(() => {
9 | fn(...args);
10 | timerId = null;
11 | }, delay);
12 | };
13 | };
--------------------------------------------------------------------------------
/_build/assets/js/index.ts:
--------------------------------------------------------------------------------
1 | import SidebarPlugin from './Sidebar';
2 |
3 | export default {
4 | SidebarPlugin
5 | };
--------------------------------------------------------------------------------
/_build/assets/sass/collections.scss:
--------------------------------------------------------------------------------
1 | @import "tabulator-tables/dist/css/tabulator_bulma.min.css";
2 |
3 | $white: #FEFEFE;
4 | .fred--modal-body{
5 | .tabulator {
6 | min-height: 300px;
7 | .tabulator-header{
8 | background-color: #f1f1f1;
9 | }
10 | }
11 | fieldset, .fred--collections-filters {
12 | vertical-align: top !important;
13 | margin-bottom: 16px !important;
14 | }
15 | }
16 | .fred--collections-sidebar:before {
17 | mask: url('./bars-solid.svg') center center no-repeat;
18 | }
19 | .fred--btn-wrapper {
20 | position: absolute;
21 | top: 12px;
22 | right: 60px;
23 | }
24 | .fred--btn{
25 | &-collections{
26 | &-newpage{
27 | margin-left: 8px !important;
28 | }
29 | &-icon{
30 | padding: 2px !important;
31 | margin: 0 !important;
32 | text-indent: -9999px !important;
33 | position: relative !important;
34 | background-color: transparent !important;
35 | height: 24px !important;
36 | width: 24px !important;
37 | &:before{
38 | content: "";
39 | position: absolute;
40 | display:inline-block;
41 | top: 2px;
42 | left: 2px;
43 | //padding: 6px 6px;
44 | height: 100%;
45 | width: 100%;
46 | color: #FEFEFE;
47 | background-color: #505050;
48 | background-repeat: no-repeat;
49 | background-position: center;
50 | background-size: 14px;
51 | border-radius: 4px;
52 | }
53 | }
54 | &-edit:before{
55 | //background-image: inline-svg('edit', $white);
56 | background-image: svg-load('edit.svg');
57 | background-position: 6px;
58 | }
59 | &-publish:before{
60 | //background-image: inline-svg('eye', $white);
61 | background-image: svg-load('eye.svg');
62 | }
63 | &-unpublish:before{
64 | //background-image: inline-svg('eye-slash', $white);
65 | background-image: svg-load('eye-slash.svg');
66 | }
67 | &-delete:before{
68 | background-color: #dc3838;
69 | //background-image: inline-svg('trash', $white);
70 | background-image: svg-load('trash.svg');
71 | }
72 | &-undelete:before{
73 | //background-image: inline-svg('trash-restore', $white);
74 | background-image: svg-load('trash-restore.svg');
75 | }
76 | }
77 | }
78 | @media screen and (min-width: 768px){
79 | .fred .fred--modal .fred--collections-filters{
80 | label{
81 | display: inline-block;
82 | width: calc(100% / 3);
83 | padding: 0 8px;
84 | }
85 | }
86 | .fred--collections-createpage {
87 | fieldset{
88 | & > label, & > div:not(.fred--btn-wrapper) {
89 | display: inline-block !important;
90 | width: calc(100% / 3) !important;
91 | padding: 0 8px !important;
92 | }
93 | //& > div{
94 | // position: relative !important;
95 | // top: -5px !important;
96 | //}
97 | & > button{
98 | display: inline-block !important;
99 | width: calc(24% / 2) !important;
100 | }
101 | }
102 | }
103 | }
104 | .fred--collections-createpage,
105 | .fred--collections-filters,
106 | .fred--modal-body .tabulator{
107 | animation: fred--collections-fade .5s;
108 | }
109 |
110 | @keyframes fred--collections-fade {
111 | 0%{opacity:0}
112 | 100%{opacity:1}
113 | }
114 |
--------------------------------------------------------------------------------
/_build/gpm.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Collections",
3 | "lowCaseName": "collections",
4 | "namespace": "Collections",
5 | "description": "Hides resources under this container in tree. Adding grid int o the update resource panel.",
6 | "author": "John Peca",
7 | "version": "4.1.1-pl",
8 | "menus": [
9 | {
10 | "text": "collections.menu.collection_templates",
11 | "description": "collections.menu.collection_templates_desc",
12 | "action": "home"
13 | }
14 | ],
15 | "plugins": [
16 | {
17 | "name": "Collections",
18 | "events": [
19 | "OnManagerPageInit",
20 | "OnBeforeDocFormSave",
21 | "OnResourceBeforeSort",
22 | "OnDocFormPrerender",
23 | "OnBeforeEmptyTrash",
24 | "OnDocFormRender",
25 | "OnManagerPageBeforeRender",
26 | "FredOnBeforeGetResourceTree",
27 | "FredBeforeRender",
28 | "OnResourceDuplicate"
29 | ]
30 | }
31 | ],
32 | "snippets": [
33 | {
34 | "name": "getSelections"
35 | }
36 | ],
37 | "systemSettings": [
38 | {
39 | "key": "mgr_date_format",
40 | "area": "manager",
41 | "value": "M d"
42 | },
43 | {
44 | "key": "mgr_time_format",
45 | "area": "manager",
46 | "value": "g:i a"
47 | },
48 | {
49 | "key": "mgr_datetime_format",
50 | "area": "manager",
51 | "value": "M d, g:i a"
52 | },
53 | {
54 | "key": "user_js",
55 | "area": "manager",
56 | "value": ""
57 | },
58 | {
59 | "key": "user_css",
60 | "area": "manager",
61 | "value": ""
62 | },
63 | {
64 | "key": "mgr_tree_icon_collectioncontainer",
65 | "area": "manager",
66 | "value": "collectioncontainer",
67 | "namespace": "core"
68 | },
69 | {
70 | "key": "mgr_tree_icon_selectioncontainer",
71 | "area": "manager",
72 | "value": "selectioncontainer",
73 | "namespace": "core"
74 | },
75 | {
76 | "key": "renderer_image_path",
77 | "area": "manager",
78 | "value": ""
79 | },
80 | {
81 | "key": "tree_tbar_collection",
82 | "area": "manager",
83 | "type": "combo-boolean",
84 | "value": 0
85 | },
86 | {
87 | "key": "tree_tbar_selection",
88 | "area": "manager",
89 | "type": "combo-boolean",
90 | "value": 0
91 | }
92 | ],
93 | "database": {
94 | "tables": [
95 | "\\Collections\\Model\\CollectionSetting",
96 | "\\Collections\\Model\\CollectionTemplate",
97 | "\\Collections\\Model\\CollectionTemplateColumn",
98 | "\\Collections\\Model\\CollectionResourceTemplate",
99 | "\\Collections\\Model\\CollectionSelection"
100 | ]
101 | },
102 | "build": {
103 | "scriptsBefore": [
104 | "fixoldcollections.gpm.php",
105 | "customevents.gpm.php",
106 | "switchback.gpm.php"
107 | ],
108 | "scriptsAfter": [
109 | "defaulttemplate.gpm.php",
110 | "fixselections.gpm.php",
111 | "fixsystemsettings.gpm.php"
112 | ],
113 | "requires": {
114 | "gpm": ">=3.0.0",
115 | "modx": ">=3.0.0-alpha"
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/_build/gpm_resolvers/gpm.resolve.bootstrap.php:
--------------------------------------------------------------------------------
1 | xpdo;
18 | if ($options[xPDOTransport::PACKAGE_ACTION] !== xPDOTransport::ACTION_INSTALL) return true;
19 |
20 | $bootstrap = $object->getCorePath() . 'bootstrap.php';
21 | if (file_exists($bootstrap)) {
22 | $namespace = $object->toArray();
23 | $namespace['path'] = $object->getCorePath();
24 | $namespace['assets_path'] = $object->getAssetsPath();
25 |
26 | require $object->getCorePath() . 'bootstrap.php';
27 | }
28 |
29 | return true;
30 |
--------------------------------------------------------------------------------
/_build/gpm_resolvers/gpm.resolve.element_property_set.php:
--------------------------------------------------------------------------------
1 | xpdo;
19 | if ($options[xPDOTransport::PACKAGE_ACTION] === xPDOTransport::ACTION_UNINSTALL) return true;
20 |
21 | $propertySetsCache = [];
22 |
23 | $elementClasses = [
24 | 'snippets' => 'MODX\\Revolution\\modSnippet',
25 | 'chunks' => 'MODX\\Revolution\\modChunk',
26 | 'templates' => 'MODX\\Revolution\\modTemplate',
27 | 'plugins' => 'MODX\\Revolution\\modPlugin',
28 | ];
29 |
30 | foreach ($elementClasses as $type => $elementClass) {
31 | if (isset($fileMeta[$type]) && is_array($fileMeta[$type])) {
32 | foreach ($fileMeta[$type] as $elementName => $propertySets) {
33 | $nameColumn = $type === 'templates' ? 'templatename' : 'name';
34 | /** @var \MODX\Revolution\modElement $element */
35 | $element = $modx->getObject($elementClass, [$nameColumn => $elementName]);
36 | if (!$element) continue;
37 |
38 | if (empty($propertySets)) {
39 | $modx->removeCollection(\MODX\Revolution\modElementPropertySet::class, ['element' => $element->id, 'element_class' => $elementClass]);
40 | continue;
41 | }
42 |
43 | if (!is_array($propertySets)) continue;
44 |
45 | foreach ($propertySets as $propertySetName) {
46 | if (!isset($propertySetsCache[$propertySetName])) {
47 | /** @var \MODX\Revolution\modPropertySet $propertySet */
48 | $propertySet = $modx->getObject(\MODX\Revolution\modPropertySet::class, ['name' => $propertySetName]);
49 | if (!$propertySet) continue;
50 |
51 | $propertySetsCache[$propertySetName] = $propertySet->id;
52 | }
53 |
54 | $elementPropertySet = $modx->getObject(\MODX\Revolution\modElementPropertySet::class, ['element' => $element->id, 'element_class' => $elementClass, 'property_set' => $propertySetsCache[$propertySetName]]);
55 | if ($elementPropertySet) continue;
56 |
57 | $elementPropertySet = $modx->newObject(\MODX\Revolution\modElementPropertySet::class);
58 | $elementPropertySet->set('element', $element->id);
59 | $elementPropertySet->set('element_class', $elementClass);
60 | $elementPropertySet->set('property_set', $propertySetsCache[$propertySetName]);
61 | $elementPropertySet->save();
62 | }
63 | }
64 | }
65 | }
66 |
67 | return true;
68 |
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.customevents.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
35 | $this->action = $action;
36 |
37 | $events = [
38 | 'CollectionsOnResourceSort',
39 | ];
40 |
41 | switch ($this->action) {
42 | case \xPDO\Transport\xPDOTransport::ACTION_INSTALL:
43 | case \xPDO\Transport\xPDOTransport::ACTION_UPGRADE:
44 | foreach ($events as $eventName) {
45 | $event = $this->modx->getObject(\MODX\Revolution\modEvent::class, ['name' => $eventName]);
46 | if (!$event) {
47 | $event = $this->modx->newObject(\MODX\Revolution\modEvent::class);
48 | $event->set('name', $eventName);
49 | $event->set('service', 6);
50 | $event->set('groupname', 'Collections');
51 | $event->save();
52 | }
53 | }
54 |
55 | break;
56 | case \xPDO\Transport\xPDOTransport::ACTION_UNINSTALL:
57 | foreach ($events as $eventName) {
58 | $event = $this->modx->getObject(\MODX\Revolution\modEvent::class, ['name' => $eventName]);
59 | if ($event) {
60 | $event->remove();
61 | }
62 | }
63 |
64 | break;
65 | }
66 |
67 | return true;
68 | }
69 | };
70 | })()($transport->xpdo, $options[xPDOTransport::PACKAGE_ACTION]);
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.fixoldcollections.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
39 | $this->action = $action;
40 |
41 | if ($this->action === xPDOTransport::ACTION_UNINSTALL) {
42 | return true;
43 | }
44 |
45 | if (isset($this->modx->packages['collections'])) {
46 | unset($this->modx->packages['collections']);
47 | }
48 |
49 | $this->modx->removeExtensionPackage('collections');
50 |
51 | $this->modx->updateCollection(modResource::class, ['class_key' => 'Collections\\Model\\CollectionContainer'], ['class_key' => 'CollectionContainer']);
52 | $this->modx->updateCollection(modResource::class, ['class_key' => 'Collections\\Model\\SelectionContainer'], ['class_key' => 'SelectionContainer']);
53 |
54 | return true;
55 | }
56 |
57 | };
58 | })()($transport->xpdo, $options[xPDOTransport::PACKAGE_ACTION]);
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.fixselections.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
40 | $this->action = $action;
41 |
42 | if ($this->action !== xPDOTransport::ACTION_UPGRADE) {
43 | return true;
44 | }
45 |
46 | $this->modx->updateCollection(modResource::class, ['hide_children_in_tree' => 1], ['class_key' => SelectionContainer::class]);
47 |
48 | return true;
49 | }
50 |
51 | };
52 | })()($transport->xpdo, $options[xPDOTransport::PACKAGE_ACTION]);
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.fixsystemsettings.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
39 | $this->action = $action;
40 |
41 | if ($this->action !== xPDOTransport::ACTION_UPGRADE) {
42 | return true;
43 | }
44 |
45 | /** @var modSystemSetting $ss */
46 | $ss = $this->modx->getObject(modSystemSetting::class, ['key' => 'renderer_image_path']);
47 | if ($ss) {
48 | $ss->remove();
49 | }
50 |
51 | return true;
52 | }
53 |
54 | };
55 | })()($transport->xpdo, $options[xPDOTransport::PACKAGE_ACTION]);
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.fred_get_service.php:
--------------------------------------------------------------------------------
1 | xpdo;
21 | $fred = $modx->services->get('fred');
22 | }
23 |
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.fred_link_element_option_set.php:
--------------------------------------------------------------------------------
1 | xpdo;
23 |
24 | $map = $object['map'];
25 | if (empty($map)) {
26 | return true;
27 | }
28 |
29 | foreach ($map as $uuid => $optionSetName) {
30 | /** @var FredElement $element */
31 | $element = $modx->getObject(FredElement::class, ['uuid' => $uuid]);
32 | if (!$element) continue;
33 |
34 | $category = $element->getOne('Category');
35 | if (!$category) continue;
36 |
37 | $optionSet = $modx->getObject(FredElementOptionSet::class, ['name' => $optionSetName, 'theme' => $category->get('theme')]);
38 | if (!$optionSet) continue;
39 |
40 | $element->set('option_set', $optionSet->id);
41 | $element->save();
42 | }
43 |
44 |
45 |
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.reload_system_settings.php:
--------------------------------------------------------------------------------
1 | xpdo;
24 |
25 | $modx->reloadConfig();
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.switchback.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
42 | $this->action = $action;
43 |
44 | if ($this->action !== xPDOTransport::ACTION_UNINSTALL) {
45 | return true;
46 | }
47 |
48 | $c = $this->modx->newQuery(modResource::class);
49 | $c->where(['class_key' => CollectionContainer::class]);
50 |
51 | /** @var modResource $collections[] */
52 | $collections = $this->modx->getCollection(modResource::class, $c);
53 | foreach ($collections as $collection) {
54 | $children = $collection->Children;
55 | foreach ($children as $child) {
56 | $child->set('show_in_tree', 1);
57 | $child->save();
58 | }
59 |
60 | $collection->set('class_key', modDocument::class);
61 | $collection->save();
62 | }
63 |
64 | $c = $this->modx->newQuery(modResource::class);
65 | $c->where(['class_key' => SelectionContainer::class]);
66 |
67 | /** @var modResource[] $selections */
68 | $selections = $this->modx->getCollection(modResource::class, $c);
69 | foreach ($selections as $selection) {
70 | $selection->set('hide_children_in_tree', 0);
71 | $selection->set('class_key', modDocument::class);
72 | $selection->save();
73 | }
74 |
75 | return true;
76 | }
77 |
78 | };
79 | })()($transport->xpdo, $options[xPDOTransport::PACKAGE_ACTION]);
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.sync_tables.php:
--------------------------------------------------------------------------------
1 | getTableName($table);
21 | $tableName = str_replace('`', '', $tableName);
22 | $dbname = $modx->getOption('dbname');
23 |
24 | $c = $modx->prepare("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = :dbName AND table_name = :tableName");
25 | $c->bindParam(':dbName', $dbname);
26 | $c->bindParam(':tableName', $tableName);
27 | $c->execute();
28 |
29 | $unusedColumns = $c->fetchAll(PDO::FETCH_COLUMN, 0);
30 | $unusedColumns = array_flip($unusedColumns);
31 |
32 | $meta = $modx->getFieldMeta($table);
33 | $columns = array_keys($meta);
34 |
35 | $m = $modx->getManager();
36 |
37 | foreach ($columns as $column) {
38 | if (isset($unusedColumns[$column])) {
39 | $m->alterField($table, $column);
40 | $modx->log(modX::LOG_LEVEL_INFO, ' -- altered column: ' . $column);
41 | unset($unusedColumns[$column]);
42 | } else {
43 | $m->addField($table, $column);
44 | $modx->log(modX::LOG_LEVEL_INFO, ' -- added column: ' . $column);
45 | }
46 | }
47 |
48 | foreach ($unusedColumns as $column => $v) {
49 | $m->removeField($table, $column);
50 | $modx->log(modX::LOG_LEVEL_INFO, ' -- removed column: ' . $column);
51 | }
52 | }
53 | }
54 |
55 | if (!function_exists('updateTableIndexes')) {
56 | /**
57 | * @param $modx
58 | * @param string $table
59 | */
60 | function updateTableIndexes($modx, $table)
61 | {
62 | $tableName = $modx->getTableName($table);
63 | $tableName = str_replace('`', '', $tableName);
64 | $dbname = $modx->getOption('dbname');
65 |
66 | $c = $modx->prepare("SELECT DISTINCT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema = :dbName AND table_name = :tableName AND INDEX_NAME != 'PRIMARY'");
67 | $c->bindParam(':dbName', $dbname);
68 | $c->bindParam(':tableName', $tableName);
69 | $c->execute();
70 |
71 | $oldIndexes = $c->fetchAll(PDO::FETCH_COLUMN, 0);
72 |
73 | $m = $modx->getManager();
74 |
75 | foreach ($oldIndexes as $oldIndex) {
76 | $m->removeIndex($table, $oldIndex);
77 | $modx->log(modX::LOG_LEVEL_INFO, ' -- removed index: ' . $oldIndex);
78 | }
79 |
80 | $meta = $modx->getIndexMeta($table);
81 | $indexes = array_keys($meta);
82 |
83 | foreach ($indexes as $index) {
84 | if ($index == 'PRIMARY') continue;
85 | $m->addIndex($table, $index);
86 | $modx->log(modX::LOG_LEVEL_INFO, ' -- added index: ' . $index);
87 | }
88 | }
89 | }
90 |
91 | if (!function_exists('alterTable')) {
92 | /**
93 | * @param $modx
94 | * @param string $table
95 | */
96 | function alterTable($modx, $table)
97 | {
98 | $modx->log(modX::LOG_LEVEL_INFO, ' - Updating columns');
99 | updateTableColumns($modx, $table);
100 |
101 | $modx->log(modX::LOG_LEVEL_INFO, ' - Updating indexes');
102 | updateTableIndexes($modx, $table);
103 | }
104 | }
105 |
106 | if ($transport->xpdo) {
107 | switch ($options[xPDOTransport::PACKAGE_ACTION]) {
108 | case xPDOTransport::ACTION_UPGRADE:
109 | $modx =& $transport->xpdo;
110 |
111 | $tables = [
112 | \Collections\Model\CollectionSetting::class,
113 | \Collections\Model\CollectionTemplate::class,
114 | \Collections\Model\CollectionTemplateColumn::class,
115 | \Collections\Model\CollectionResourceTemplate::class,
116 | \Collections\Model\CollectionSelection::class,
117 | ];
118 |
119 | foreach ($tables as $table) {
120 | $modx->log(modX::LOG_LEVEL_INFO, 'Altering table: ' . $table);
121 | alterTable($modx, $table);
122 | }
123 |
124 | break;
125 | }
126 | }
127 | return true;
128 |
--------------------------------------------------------------------------------
/_build/gpm_scripts/gpm.script.tables.php:
--------------------------------------------------------------------------------
1 | xpdo;
18 |
19 | if ($options[xPDOTransport::PACKAGE_ACTION] === xPDOTransport::ACTION_UNINSTALL) return true;
20 |
21 | $manager = $modx->getManager();
22 |
23 | $manager->createObjectContainer(\Collections\Model\CollectionSetting::class);
24 | $manager->createObjectContainer(\Collections\Model\CollectionTemplate::class);
25 | $manager->createObjectContainer(\Collections\Model\CollectionTemplateColumn::class);
26 | $manager->createObjectContainer(\Collections\Model\CollectionResourceTemplate::class);
27 | $manager->createObjectContainer(\Collections\Model\CollectionSelection::class);
28 |
29 | return true;
30 |
--------------------------------------------------------------------------------
/_build/migrations/200pl.migration.php:
--------------------------------------------------------------------------------
1 | currently installed version
7 | const VERSION = '2.0.0-pl';
8 |
9 | /**
10 | * @var \MODX\Revolution\modX
11 | */
12 | private $modx;
13 |
14 | /**
15 | * @param \MODX\Revolution\modX $modx
16 | * @return void
17 | */
18 | public function __invoke(&$modx)
19 | {
20 | $this->modx =& $modx;
21 |
22 | $date = $this->modx->getObject(modSystemSetting::class, ['key' => 'collections.mgr_date_format']);
23 | if (!$date) {
24 | $date = $this->modx->newObject(modSystemSetting::class);
25 | $date->set('key', 'collections.mgr_date_format');
26 | $date->set('namespace', 'collections');
27 | $date->set('xtype', 'textfield');
28 | }
29 |
30 | $date->set('value', 'M d');
31 | $date->save();
32 |
33 | $time = $this->modx->getObject(modSystemSetting::class, ['key' => 'collections.mgr_time_format']);
34 | if (!$time) {
35 | $time = $this->modx->newObject(modSystemSetting::class);
36 | $time->set('key', 'collections.mgr_time_format');
37 | $time->set('namespace', 'collections');
38 | $time->set('xtype', 'textfield');
39 | }
40 |
41 | $time->set('value', 'g:i a');
42 | $time->save();
43 | }
44 | };
45 |
--------------------------------------------------------------------------------
/_build/migrations/340pl.migration.php:
--------------------------------------------------------------------------------
1 | currently installed version
9 | const VERSION = '3.4.0-pl';
10 |
11 | /**
12 | * @var \MODX\Revolution\modX
13 | */
14 | private $modx;
15 |
16 | /**
17 | * @param \MODX\Revolution\modX $modx
18 | * @return void
19 | */
20 | public function __invoke(&$modx)
21 | {
22 | $this->modx =& $modx;
23 |
24 | /** @var modResource[] $collections */
25 | $collections = $this->modx->getIterator(modResource::class, ['class_key' => CollectionContainer::class]);
26 | foreach ($collections as $collection) {
27 | $this->modx->updateCollection(modResource::class, ['show_in_tree' => 0], ['parent' => $collection->id, 'class_key:!=' => CollectionContainer::class]);
28 | }
29 |
30 | /** @var CollectionTemplate[] $views */
31 | $views = $this->modx->getIterator(CollectionTemplate::class);
32 | foreach ($views as $view) {
33 | $buttons = $view->get('buttons');
34 | if (strpos($buttons, 'open') === false) {
35 | $buttons = 'open,' . $buttons;
36 | $view->set('buttons', $buttons);
37 | $view->save();
38 | }
39 | }
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/_build/migrations/370pl.migration.php:
--------------------------------------------------------------------------------
1 | currently installed version
7 | const VERSION = '3.7.0-pl';
8 |
9 | /**
10 | * @var \MODX\Revolution\modX
11 | */
12 | private $modx;
13 |
14 | /**
15 | * @param \MODX\Revolution\modX $modx
16 | * @return void
17 | */
18 | public function __invoke(&$modx)
19 | {
20 | $this->modx =& $modx;
21 |
22 | /** @var CollectionTemplate[] $views */
23 | $views = $this->modx->getIterator(CollectionTemplate::class);
24 | foreach ($views as $view) {
25 | $buttons = $view->get('buttons');
26 | if (strpos($buttons, 'changeparent') === false) {
27 | $buttons = $buttons . ',changeparent';
28 | $view->set('buttons', $buttons);
29 | $view->save();
30 | }
31 | }
32 | }
33 | };
34 |
--------------------------------------------------------------------------------
/_build/scripts/customevents.gpm.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
22 | $this->action = $action;
23 |
24 | $events = [
25 | 'CollectionsOnResourceSort',
26 | ];
27 |
28 | switch ($this->action) {
29 | case \xPDO\Transport\xPDOTransport::ACTION_INSTALL:
30 | case \xPDO\Transport\xPDOTransport::ACTION_UPGRADE:
31 | foreach ($events as $eventName) {
32 | $event = $this->modx->getObject(\MODX\Revolution\modEvent::class, ['name' => $eventName]);
33 | if (!$event) {
34 | $event = $this->modx->newObject(\MODX\Revolution\modEvent::class);
35 | $event->set('name', $eventName);
36 | $event->set('service', 6);
37 | $event->set('groupname', 'Collections');
38 | $event->save();
39 | }
40 | }
41 |
42 | break;
43 | case \xPDO\Transport\xPDOTransport::ACTION_UNINSTALL:
44 | foreach ($events as $eventName) {
45 | $event = $this->modx->getObject(\MODX\Revolution\modEvent::class, ['name' => $eventName]);
46 | if ($event) {
47 | $event->remove();
48 | }
49 | }
50 |
51 | break;
52 | }
53 |
54 | return true;
55 | }
56 | };
57 |
--------------------------------------------------------------------------------
/_build/scripts/fixoldcollections.gpm.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
25 | $this->action = $action;
26 |
27 | if ($this->action === xPDOTransport::ACTION_UNINSTALL) {
28 | return true;
29 | }
30 |
31 | if (isset($this->modx->packages['collections'])) {
32 | unset($this->modx->packages['collections']);
33 | }
34 |
35 | $this->modx->removeExtensionPackage('collections');
36 |
37 | $this->modx->updateCollection(modResource::class, ['class_key' => 'Collections\\Model\\CollectionContainer'], ['class_key' => 'CollectionContainer']);
38 | $this->modx->updateCollection(modResource::class, ['class_key' => 'Collections\\Model\\SelectionContainer'], ['class_key' => 'SelectionContainer']);
39 |
40 | return true;
41 | }
42 |
43 | };
44 |
--------------------------------------------------------------------------------
/_build/scripts/fixselections.gpm.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
26 | $this->action = $action;
27 |
28 | if ($this->action !== xPDOTransport::ACTION_UPGRADE) {
29 | return true;
30 | }
31 |
32 | $this->modx->updateCollection(modResource::class, ['hide_children_in_tree' => 1], ['class_key' => SelectionContainer::class]);
33 |
34 | return true;
35 | }
36 |
37 | };
38 |
--------------------------------------------------------------------------------
/_build/scripts/fixsystemsettings.gpm.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
26 | $this->action = $action;
27 |
28 | if ($this->action !== xPDOTransport::ACTION_UPGRADE) {
29 | return true;
30 | }
31 |
32 | /** @var modSystemSetting $ss */
33 | $ss = $this->modx->getObject(modSystemSetting::class, ['key' => 'renderer_image_path']);
34 | if ($ss) {
35 | $ss->remove();
36 | }
37 |
38 | return true;
39 | }
40 |
41 | };
42 |
--------------------------------------------------------------------------------
/_build/scripts/switchback.gpm.php:
--------------------------------------------------------------------------------
1 | modx =& $modx;
28 | $this->action = $action;
29 |
30 | if ($this->action !== xPDOTransport::ACTION_UNINSTALL) {
31 | return true;
32 | }
33 |
34 | $c = $this->modx->newQuery(modResource::class);
35 | $c->where(['class_key' => CollectionContainer::class]);
36 |
37 | /** @var modResource $collections[] */
38 | $collections = $this->modx->getCollection(modResource::class, $c);
39 | foreach ($collections as $collection) {
40 | $children = $collection->Children;
41 | foreach ($children as $child) {
42 | $child->set('show_in_tree', 1);
43 | $child->save();
44 | }
45 |
46 | $collection->set('class_key', modDocument::class);
47 | $collection->save();
48 | }
49 |
50 | $c = $this->modx->newQuery(modResource::class);
51 | $c->where(['class_key' => SelectionContainer::class]);
52 |
53 | /** @var modResource[] $selections */
54 | $selections = $this->modx->getCollection(modResource::class, $c);
55 | foreach ($selections as $selection) {
56 | $selection->set('hide_children_in_tree', 0);
57 | $selection->set('class_key', modDocument::class);
58 | $selection->save();
59 | }
60 |
61 | return true;
62 | }
63 |
64 | };
65 |
--------------------------------------------------------------------------------
/assets/components/collections/css/i/collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/modxcms/Collections/97de34662aee2488ac38b4f1fc7bef01a2967137/assets/components/collections/css/i/collection.png
--------------------------------------------------------------------------------
/assets/components/collections/css/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/modxcms/Collections/97de34662aee2488ac38b4f1fc7bef01a2967137/assets/components/collections/css/index.html
--------------------------------------------------------------------------------
/assets/components/collections/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/modxcms/Collections/97de34662aee2488ac38b4f1fc7bef01a2967137/assets/components/collections/index.html
--------------------------------------------------------------------------------
/assets/components/collections/js/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/modxcms/Collections/97de34662aee2488ac38b4f1fc7bef01a2967137/assets/components/collections/js/index.html
--------------------------------------------------------------------------------
/assets/components/collections/js/mgr/collections.js:
--------------------------------------------------------------------------------
1 | var Collections = function(config) {
2 | config = config || {};
3 | Collections.superclass.constructor.call(this,config);
4 | };
5 | Ext.extend(Collections,Ext.Component,{
6 | page:{},window:{},grid:{},tree:{},panel:{},combo:{},config: {},renderer: {},
7 | getPageUrl: function(action, parameters) {
8 | // Handles url, passed as first argument
9 | var parts = [];
10 | if (action) {
11 | if (isNaN(parseInt(action)) && (action.substr(0,1) == '?' || (action.substr(0, "index.php?".length) == 'index.php?'))) {
12 | parts.push(action);
13 | } else {
14 | parts.push('?a=' + action);
15 | }
16 | }
17 |
18 | if (parameters) {
19 | parts.push(parameters);
20 | }
21 |
22 | return parts.join('&');
23 | }
24 | });
25 | Ext.reg('collections',Collections);
26 | collections = new Collections();
27 |
--------------------------------------------------------------------------------
/assets/components/collections/js/mgr/extra/hijackclose.js:
--------------------------------------------------------------------------------
1 | Ext.override(MODx.page[Collections_mode + Collections_type], {
2 | collectionsOriginals: {
3 | getButtons: MODx.page[Collections_mode + Collections_type].prototype.getButtons
4 | }
5 | ,getButtons: function(config) {
6 | var buttons = this.collectionsOriginals.getButtons.call(this, config);
7 |
8 | if (MODx.request.selection) {
9 | buttons.unshift({
10 | text: _(Collections_labels.back_to_selection) ? _(Collections_labels.back_to_selection) : Collections_labels.back_to_selection
11 | ,handler: function() {
12 | MODx.loadPage('resource/update', 'id=' + MODx.request.selection);
13 | }
14 | });
15 | } else {
16 | buttons.unshift({
17 | text: _(Collections_labels.back_to_collection) ? _(Collections_labels.back_to_collection) : Collections_labels.back_to_collection
18 | ,handler: function() {
19 | var targetCollection = (Collections_collection_get || MODx.request.collection || config.record.parent);
20 |
21 | var folder = parseInt(MODx.request.folder);
22 | if (folder > 0) {
23 | folder = '&folder=' + folder;
24 | } else {
25 | var parent = parseInt(MODx.request.parent);
26 |
27 | if ((parent > 0) && (targetCollection != parent)) {
28 | folder = '&folder=' + parent;
29 | } else {
30 | folder = '';
31 | }
32 | }
33 |
34 | MODx.loadPage('resource/update', 'id=' + targetCollection + folder);
35 | }
36 | });
37 | }
38 |
39 | return buttons;
40 | }
41 | });
42 |
--------------------------------------------------------------------------------
/assets/components/collections/js/mgr/sections/category/update.js:
--------------------------------------------------------------------------------
1 | collections.page.UpdateCategory = function(config) {
2 | config = config || {record:{}};
3 | config.record = config.record || {};
4 | Ext.applyIf(config,{
5 | panelXType: 'collections-panel-category'
6 | });
7 | config.canDelete = true;
8 | collections.page.UpdateCategory.superclass.constructor.call(this,config);
9 | };
10 | Ext.extend(collections.page.UpdateCategory,MODx.page.UpdateResource,{
11 |
12 | });
13 | Ext.reg('collections-page-category-update',collections.page.UpdateCategory);
14 |
15 | collections.page.UpdateSelection = function(config) {
16 | config = config || {record:{}};
17 | config.record = config.record || {};
18 | Ext.applyIf(config,{
19 | panelXType: 'collections-panel-selection'
20 | });
21 | config.canDelete = true;
22 | collections.page.UpdateSelection.superclass.constructor.call(this,config);
23 | };
24 | Ext.extend(collections.page.UpdateSelection,MODx.page.UpdateResource,{
25 |
26 | });
27 | Ext.reg('collections-page-selection-update',collections.page.UpdateSelection);
28 |
--------------------------------------------------------------------------------
/assets/components/collections/js/mgr/sections/template/home.js:
--------------------------------------------------------------------------------
1 | collections.page.TemplateHome = function(config) {
2 | config = config || {};
3 | Ext.applyIf(config,{
4 | components: [{
5 | xtype: 'collections-panel-template-home'
6 | ,renderTo: 'collections-panel-template-home-div'
7 | }]
8 | });
9 | collections.page.TemplateHome.superclass.constructor.call(this,config);
10 | };
11 | Ext.extend(collections.page.TemplateHome,MODx.Component);
12 | Ext.reg('collections-page-template-home',collections.page.TemplateHome);
--------------------------------------------------------------------------------
/assets/components/collections/js/mgr/sections/template/template.js:
--------------------------------------------------------------------------------
1 | collections.page.Template = function(config) {
2 | config = config || {};
3 |
4 | config.isUpdate = (MODx.request.id) ? true : false;
5 |
6 | Ext.applyIf(config,{
7 | formpanel: 'collections-panel-template'
8 | ,buttons: [{
9 | text: _('save')
10 | ,method: 'remote'
11 | ,process: config.isUpdate ? 'Collections\\Processors\\Template\\Update' : 'Collections\\Processors\\Template\\Create'
12 | ,keys: [{
13 | key: MODx.config.keymap_save || 's'
14 | ,ctrl: true
15 | }]
16 | },{
17 | text: _('cancel')
18 | ,params: {a:'home', namespace:'collections'}
19 | }]
20 | ,components: [{
21 | xtype: 'collections-panel-template'
22 | ,renderTo: 'collections-panel-template-div'
23 | ,isUpdate: config.isUpdate
24 | ,fredInstalled: !!config.fredInstalled
25 | }]
26 | });
27 | collections.page.Template.superclass.constructor.call(this,config);
28 | };
29 | Ext.extend(collections.page.Template,MODx.Component);
30 | Ext.reg('collections-page-template',collections.page.Template);
31 |
--------------------------------------------------------------------------------
/assets/components/collections/js/mgr/widgets/template/home.panel.js:
--------------------------------------------------------------------------------
1 | collections.panel.TemplateHome = function(config) {
2 | config = config || {};
3 | Ext.apply(config,{
4 | border: false
5 | ,baseCls: 'modx-formpanel'
6 | ,cls: 'container'
7 | ,items: [{
8 | html: '
'+_('collections.template.page_title')+'
'
9 | ,border: false
10 | ,cls: 'modx-page-header'
11 | },{
12 | xtype: 'modx-tabs'
13 | ,defaults: { border: false ,autoHeight: true }
14 | ,border: true
15 | ,activeItem: 0
16 | ,hideMode: 'offsets'
17 | ,items: [{
18 | title: _('collections.template.templates')
19 | ,layout: 'form'
20 | ,items: [{
21 | html: ''+_('collections.template.templates_desc')+'
'
22 | ,border: false
23 | ,bodyCssClass: 'panel-desc'
24 | },{
25 | xtype: 'collections-grid-template'
26 | ,preventRender: true
27 | ,cls: 'main-wrapper'
28 | }]
29 | }]
30 | }]
31 | });
32 | collections.panel.TemplateHome.superclass.constructor.call(this,config);
33 | };
34 | Ext.extend(collections.panel.TemplateHome,MODx.Panel);
35 | Ext.reg('collections-panel-template-home',collections.panel.TemplateHome);
--------------------------------------------------------------------------------
/assets/components/collections/web/ajax.php:
--------------------------------------------------------------------------------
1 | startTime= $tStart;
26 |
27 | $modx->initialize('web');
28 |
29 | /** @var Collections\Collections $collections */
30 | $collections = $modx->services->get('collections');
31 |
32 | $ajax = new \Collections\Endpoint\Ajax($collections);
33 | $ajax->run();
34 |
--------------------------------------------------------------------------------
/assets/components/collections/web/bars-solid.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/components/collections/web/index.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/modxcms/Collections/97de34662aee2488ac38b4f1fc7bef01a2967137/assets/components/collections/web/index.html
--------------------------------------------------------------------------------
/core/components/collections/bootstrap.php:
--------------------------------------------------------------------------------
1 | addPackage('Collections\Model', $namespace['path'] . 'src/', null, 'Collections\\');
7 |
8 | $modx->services->add('collections', function($c) use ($modx) {
9 | return new Collections\Collections($modx);
10 | });
11 |
--------------------------------------------------------------------------------
/core/components/collections/controllers/create.class.php:
--------------------------------------------------------------------------------
1 | modx->lexicon('collections.system.new_container');
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/core/components/collections/controllers/data.class.php:
--------------------------------------------------------------------------------
1 | modx->lexicon('collections.template.page_title');
22 | }
23 |
24 | public function process(array $scriptProperties = []) {}
25 |
26 | public function loadCustomCssJs() {
27 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/widgets/template/template.window.js');
28 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/widgets/template/template.grid.js');
29 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/widgets/template/home.panel.js');
30 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/sections/template/home.js');
31 |
32 | $this->addHtml('
33 |
38 | ');
39 | }
40 |
41 | public function getTemplateFile() { return $this->collections->getOption('templatesPath').'template/home.tpl'; }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/core/components/collections/controllers/selection/create.class.php:
--------------------------------------------------------------------------------
1 | modx->lexicon('selections.system.new_container');
20 | }
21 | }
--------------------------------------------------------------------------------
/core/components/collections/controllers/selection/data.class.php:
--------------------------------------------------------------------------------
1 | modx->lexicon('collections.template.page_title');
22 | }
23 |
24 | public function process(array $scriptProperties = []) {}
25 |
26 | public function loadCustomCssJs() {
27 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/extra/collections.combo.js');
28 |
29 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/widgets/template/template.panel.js');
30 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/sections/template/template.js');
31 |
32 | $this->addHtml('
33 |
41 | ');
42 | }
43 |
44 | public function getTemplateFile() { return $this->collections->getOption('templatesPath').'template/template.tpl'; }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/core/components/collections/controllers/template/export.class.php:
--------------------------------------------------------------------------------
1 | modx->lexicon('collections.err.template_ns'));
28 | }
29 |
30 | /** @var CollectionTemplate[] $templates */
31 | $templates = $this->modx->getIterator(CollectionTemplate::class, ['id:IN' => $templateIDs]);
32 |
33 | $fileContent = [];
34 | $fileName = '';
35 |
36 | foreach ($templates as $template) {
37 | $export = $template->toArray();
38 | unset($export['id'], $export['global_template']);
39 | $export['columns'] = [];
40 |
41 | foreach ($template->Columns as $column) {
42 | $exportColumn = $column->toArray();
43 | unset($exportColumn['id'], $exportColumn['template']);
44 | $export['columns'][] = $exportColumn;
45 | }
46 |
47 | $fileContent[] = $export;
48 |
49 | if (empty($fileName)) {
50 | $fileName = 'collection_view_' . strtolower($template->name);
51 | } else {
52 | $fileName = 'collection_views';
53 | }
54 | }
55 |
56 | if (empty($fileContent)) {
57 | die($this->modx->lexicon('collections.err.template_ns'));
58 | }
59 |
60 | session_write_close();
61 | ob_clean();
62 |
63 | header('Pragma: public'); // required
64 | header('Expires: 0'); // no cache
65 | header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
66 | header('Cache-Control: private', false);
67 | header('Content-Description: File Transfer');
68 | header('Content-Type:'); //added to fix ZIP file corruption
69 |
70 | header('Content-Type: "application/force-download"');
71 | header('Content-Disposition: attachment; filename="' . $fileName . '.json"');
72 | header('Content-Transfer-Encoding: binary');
73 | header('Connection: close');
74 |
75 | echo json_encode($fileContent, JSON_PRETTY_PRINT);
76 |
77 | die();
78 |
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/core/components/collections/controllers/template/update.class.php:
--------------------------------------------------------------------------------
1 | modx->lexicon('collections.template.page_title');
22 | }
23 |
24 | public function process(array $scriptProperties = []) {}
25 |
26 | public function loadCustomCssJs() {
27 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/extra/griddraganddrop.js');
28 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/extra/collections.renderers.js');
29 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/extra/collections.combo.js');
30 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/widgets/template/column.window.js');
31 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/widgets/template/column.grid.js');
32 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/widgets/template/template.panel.js');
33 | $this->addLastJavascript($this->collections->getOption('jsUrl').'mgr/sections/template/template.js');
34 |
35 | $this->addHtml('
36 |
44 | ');
45 | }
46 |
47 | public function getTemplateFile() { return $this->collections->getOption('templatesPath').'template/template.tpl'; }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/core/components/collections/elements/plugins/Collections.php:
--------------------------------------------------------------------------------
1 | services->has('collections')) {
15 | return;
16 | }
17 |
18 | /** @var Collections\Collections $collections */
19 | $collections = $modx->services->get('collections');
20 | if (!($collections instanceof Collections\Collections)) return '';
21 |
22 | $className = "\\Collections\\Events\\{$modx->event->name}";
23 | if (class_exists($className)) {
24 | /** @var \Collections\Events\Event $handler */
25 | $handler = new $className($modx, $scriptProperties);
26 | $handler->run();
27 | }
28 |
29 | return;
--------------------------------------------------------------------------------
/core/components/collections/elements/snippets/getSelections.php:
--------------------------------------------------------------------------------
1 | services->get('collections');
35 | if (!($collections instanceof Collections\Collections)) return '';
36 |
37 | $getResourcesSnippet = $modx->getOption('getResourcesSnippet', $scriptProperties, 'getResources');
38 |
39 | $getResourcesExists = $modx->getCount(modSnippet::class, ['name' => $getResourcesSnippet]);
40 | if ($getResourcesExists == 0) return 'getResources not found';
41 |
42 | $sortDir = strtolower($modx->getOption('sortdir', $scriptProperties, 'asc'));
43 | $selections = $modx->getOption('selections', $scriptProperties, '');
44 | $sortBy = $modx->getOption('sortby', $scriptProperties, '');
45 | $excludeToPlaceholder = $modx->getOption('excludeToPlaceholder', $scriptProperties, '');
46 |
47 | $selections = Utils::explodeAndClean($selections);
48 |
49 | if ($sortDir != 'asc') {
50 | $sortDir = 'desc';
51 | }
52 |
53 | $linkedResourcesQuery = $modx->newQuery(CollectionSelection::class);
54 |
55 | if (!empty($selections)) {
56 | $linkedResourcesQuery->where([
57 | 'collection:IN' => $selections
58 | ]);
59 | }
60 |
61 | if ($sortBy == '') {
62 | $linkedResourcesQuery->sortby('menuindex', $sortDir);
63 | }
64 |
65 | $linkedResourcesQuery->select([
66 | 'resource' => 'DISTINCT(resource)',
67 | 'menuindex' => 'menuindex'
68 | ]);
69 |
70 | $linkedResourcesQuery->prepare();
71 |
72 | $linkedResourcesQuery->stmt->execute();
73 |
74 | $linkedResources = $linkedResourcesQuery->stmt->fetchAll(PDO::FETCH_COLUMN, 0);
75 |
76 | if (!empty($excludeToPlaceholder)) {
77 | $excludeResources = [];
78 | foreach($linkedResources as $res) {
79 | $excludeResources[] = '-' . $res;
80 | }
81 | $excludeResources = implode(',', $excludeResources);
82 | $modx->setPlaceholder($excludeToPlaceholder, $excludeResources);
83 | }
84 |
85 | $linkedResources = implode(',', $linkedResources);
86 |
87 | $properties = $scriptProperties;
88 | unset($properties['selections']);
89 |
90 | $properties['parents'] = ($properties['getResourcesSnippet'] == 'pdoResources') ? 0 : -1;
91 |
92 | if (empty($linkedResources)) {
93 | $properties['where'] = '2=1';
94 | } else {
95 | $properties['resources'] = $linkedResources;
96 |
97 | if ($sortBy == '') {
98 | $properties['sortby'] = 'FIELD(modResource.id, ' . $linkedResources . ' )';
99 | $properties['sortdir'] = 'asc';
100 | }
101 | };
102 |
103 | return $modx->runSnippet($getResourcesSnippet, $properties);
104 |
--------------------------------------------------------------------------------
/core/components/collections/elements/widgets/test.php:
--------------------------------------------------------------------------------
1 | Test";
18 | }
19 |
20 |
21 | /**
22 | * @return string
23 | * @throws Exception
24 | */
25 | public function process()
26 | {
27 | return "Test2
";
28 | }
29 | }
30 |
31 | return 'TestWidget';
32 |
--------------------------------------------------------------------------------
/core/components/collections/index.class.php:
--------------------------------------------------------------------------------
1 | collections = $this->modx->services->get('collections');
13 |
14 | $this->addCss($this->collections->config['cssUrl'] . 'mgr.css');
15 | $this->addJavascript($this->collections->config['jsUrl'] . 'mgr/collections.js');
16 |
17 | $this->addHtml('');
22 |
23 | parent::initialize();
24 | }
25 |
26 | public function getLanguageTopics()
27 | {
28 | return ['collections:default'];
29 | }
30 |
31 | public function checkPermissions()
32 | {
33 | return true;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/core/components/collections/lexicon/cs/custom.inc.php:
--------------------------------------------------------------------------------
1 | Tato změna je nevratná.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Odpojit označené';
35 | $_lang['selections.back_to_selection_label'] = 'Zpět na výběr';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Dokument nebo výběr nebyl specifikován.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Tento výběr není možné změnit na dokument, jelikož obsahuje připojené dokumenty.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/cs/templates.inc.php:
--------------------------------------------------------------------------------
1 | Denne handling er permanent og kan ikke omgøres.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Fjern sammenkædningen af flere';
35 | $_lang['selections.back_to_selection_label'] = 'Tilbage til Selection';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Ressource eller Collection blev ikke angivet.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Du kan ikke ændre denne ressource fra Selection fordi den har tilknyttede ressourcer.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/da/templates.inc.php:
--------------------------------------------------------------------------------
1 | Dies kann nicht rückgängig gemacht werden.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Auswahl Verlinkung aufheben';
35 | $_lang['selections.back_to_selection_label'] = 'Zurück zur Selektion';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Ressource oder Kollektion wurde nicht angegeben.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Sie können diese Ressource nicht von einer Selektion umwandeln, da sie verlinkte Ressourcen enthält.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/de/templates.inc.php:
--------------------------------------------------------------------------------
1 | This operation is permanent and can\'t be reverted.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Unlink multiple';
35 | $_lang['selections.back_to_selection_label'] = 'Back to Selection';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Resource or Collection was not specified.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'You can\'t switch this Resource from Selection, because it has linked Resources.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/en/templates.inc.php:
--------------------------------------------------------------------------------
1 | Cette opération est irrémédiable et irréversible.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Délier multiple';
35 | $_lang['selections.back_to_selection_label'] = 'Retour à la sélection';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Ressource ou Collection non spécifiée.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Vous ne pouvez pas basculer cette ressource depuis la Sélection, elle a Ressources liées.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/fr/templates.inc.php:
--------------------------------------------------------------------------------
1 | Questa operazione è permanente e irreversibile.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Scollegamento multiplo';
35 | $_lang['selections.back_to_selection_label'] = 'Torna alla Selezione';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'La risorsa o la Collezione non è stata specificata.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Non puoi spostare questa Risorsa dalla Selezione, perchè contiene Risorse collegate.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/it/templates.inc.php:
--------------------------------------------------------------------------------
1 | Deze handeling is definitief en kan niet worden teruggedraaid.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Ontkoppel meerdere';
35 | $_lang['selections.back_to_selection_label'] = 'Terug naar Selectie';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Document of Collection is niet gespecificeerd.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Je kunt dit document niet omzetten van de selectie, want het heeft gekoppelde documenten.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/nl/templates.inc.php:
--------------------------------------------------------------------------------
1 | Esta operação é permanente e não pode ser revertida.';
33 | $_lang['selections.resource'] = 'Recurso';
34 | $_lang['selections.unlink_multiple'] = 'Desassociar múltiplos';
35 | $_lang['selections.back_to_selection_label'] = 'Voltar à Selecção';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Recurso ou Coleção não especificado.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Não pode modificar este Recurso de Seleção para outro tipo, porque tem Recursos associados.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/pt/templates.inc.php:
--------------------------------------------------------------------------------
1 | Это действие нельзя отменить.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Отвязать несколько';
35 | $_lang['selections.back_to_selection_label'] = 'Вернуться в Подборку';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Ресурс или коллекция не указаны.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Вы не можете переключить этот Ресурс на Подборку, т.к. он имеет связанные Ресурсы.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/ru/templates.inc.php:
--------------------------------------------------------------------------------
1 | Denna åtgärd är permanent och kan inte återställas.';
33 | $_lang['selections.resource'] = 'Resource';
34 | $_lang['selections.unlink_multiple'] = 'Avlänka flera';
35 | $_lang['selections.back_to_selection_label'] = 'Tillbaka till urval';
36 |
37 | // Errors
38 | $_lang['collections.err.selection_res_col_ns'] = 'Resurs eller samling angavs inte.';
39 | $_lang['collections.err.cant_switch_from_selection_linked'] = 'Du kan inte byta denna resurs från urval, eftersom den har länkade resurser.';
--------------------------------------------------------------------------------
/core/components/collections/lexicon/sv/templates.inc.php:
--------------------------------------------------------------------------------
1 | collections =& $collections;
31 | $this->modx =& $collections->modx;
32 |
33 | if ($this->modx->services->has('fred')) {
34 | $this->fred = $this->modx->services->get('fred');
35 | }
36 | }
37 |
38 | public function run()
39 | {
40 | if ($this->fred === null) {
41 | http_response_code(500);
42 | return;
43 | }
44 |
45 | if (!$this->modx->user) {
46 | http_response_code(401);
47 | return;
48 | }
49 |
50 | try {
51 | $payload = $this->fred->getJWTPayload();
52 |
53 | $this->modx->switchContext($payload['context']);
54 |
55 | if (!$this->modx->hasPermission('fred')) {
56 | http_response_code(403);
57 | return;
58 | }
59 |
60 | if ($payload['iss'] !== $this->modx->user->id) {
61 | http_response_code(403);
62 | return;
63 | }
64 | } catch (\Exception $e) {
65 | http_response_code(403);
66 | return;
67 | }
68 |
69 | $action = $this->modx->getOption('action', $_REQUEST, '');
70 | if (empty($action)) return;
71 |
72 | $action = str_replace('/', '', $action);
73 | $action = str_replace('\\', '', $action);
74 | $action = explode('-', $action);
75 | $action = array_map('ucfirst', $action);
76 | $action = implode('', $action);
77 |
78 | $className = "\\Collections\\Endpoint\\Ajax\\{$action}";
79 | if (class_exists($className) !== true) {
80 | http_response_code(404);
81 | return;
82 | }
83 |
84 | /** @var Ajax\Endpoint $ajaxEndpoint */
85 | $ajaxEndpoint = new $className($this->collections, $this->fred, $payload);
86 |
87 | header('Content-Type: application/json; charset=UTF-8');
88 |
89 | echo $ajaxEndpoint->run();
90 |
91 | return;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/core/components/collections/src/Endpoint/Ajax/Endpoint.php:
--------------------------------------------------------------------------------
1 | collections =& $collections;
36 | $this->fred =& $fred;
37 | $this->modx =& $collections->modx;
38 | $this->jwtPayload = $payload;
39 | }
40 |
41 | public function run()
42 | {
43 | if (!$this->modx->user) {
44 | http_response_code(401);
45 | return '';
46 | }
47 |
48 | if (!$this->modx->hasPermission('fred')) {
49 | http_response_code(403);
50 | return '';
51 | }
52 |
53 | /** @var bool|string $checked */
54 | $checked = $this->checkMethod();
55 | if ($checked !== true) {
56 | return $checked;
57 | }
58 |
59 | if ($this->method === 'POST') {
60 | $this->body = json_decode(file_get_contents('php://input'), true);
61 | }
62 |
63 |
64 | return $this->process();
65 | }
66 |
67 | /**
68 | * @return string
69 | */
70 | abstract function process();
71 |
72 | /**
73 | * @param string|array $message
74 | * @param array $fields
75 | * @return string
76 | */
77 | protected function failure($message, $fields = [])
78 | {
79 | http_response_code(400);
80 |
81 | if (!is_array($message)) {
82 | $message = ['message' => $message];
83 | }
84 |
85 | $message['_fields'] = $fields;
86 |
87 | return json_encode($message);
88 | }
89 |
90 | /**
91 | * @param string|array $message
92 | * @return string
93 | */
94 | protected function success($message = '')
95 | {
96 | http_response_code(200);
97 |
98 | if (!is_array($message)) {
99 | $message = ['message' => $message];
100 | }
101 |
102 | return json_encode($message);
103 | }
104 |
105 | /**
106 | * @param array $data
107 | * @param array $meta
108 | * @return string
109 | */
110 | protected function data($data, $meta = [])
111 | {
112 | http_response_code(200);
113 |
114 | $meta['data'] = $data;
115 |
116 | return json_encode($meta);
117 | }
118 |
119 | protected function checkMethod()
120 | {
121 | $this->method = strtoupper($_SERVER['REQUEST_METHOD']);
122 |
123 | if (in_array($this->method, $this->allowedMethod)) return true;
124 |
125 | http_response_code(405);
126 | return '{}';
127 | }
128 |
129 | protected function verifyClaim($name, $value)
130 | {
131 | if (!isset($this->jwtPayload[$name])) return false;
132 |
133 | return $this->jwtPayload[$name] === $value;
134 | }
135 |
136 | protected function getClaim($name)
137 | {
138 | if (!isset($this->jwtPayload[$name])) return false;
139 |
140 | return $this->jwtPayload[$name];
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/core/components/collections/src/Endpoint/Ajax/GetAuthors.php:
--------------------------------------------------------------------------------
1 | failure('No collection was provided');
19 | }
20 |
21 | $templates = $this->fred->getFredTemplates();
22 | if (empty($templates)) {
23 | return $this->failure('No Fred templates');
24 | }
25 |
26 |
27 | $c = $this->modx->newQuery(modResource::class);
28 | $c->where([
29 | 'parent' => $collection,
30 | 'template:IN' => $templates
31 | ]);
32 |
33 | $c->select([
34 | 'createdby' => 'distinct(createdby)'
35 | ]);
36 |
37 | $c->prepare();
38 | $c->stmt->execute();
39 |
40 | $authorIDs = $c->stmt->fetchAll(\PDO::FETCH_COLUMN, 0);
41 | if (empty($authorIDs)) {
42 | return $this->data([]);
43 | }
44 |
45 | $cProfile = $this->modx->newQuery(modUserProfile::class);
46 | $cProfile->where([
47 | 'internalKey:IN' => $authorIDs
48 | ]);
49 | $cProfile->select($this->modx->getSelectColumns(modUserProfile::class, 'modUserProfile', '', ['internalKey', 'fullname']));
50 | $cProfile->sortby('fullname', 'asc');
51 | $cProfile->prepare();
52 | $cProfile->stmt->execute();
53 |
54 | $authors = ['-1' => 'Any'];
55 | while($row = $cProfile->stmt->fetch(\PDO::FETCH_ASSOC)) {
56 | $authors[(string)$row['internalKey']] = $row['fullname'];
57 | }
58 |
59 | return $this->data($authors);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/core/components/collections/src/Endpoint/Ajax/GetCollectionView.php:
--------------------------------------------------------------------------------
1 | failure('No Collection');
15 |
16 | /** @var \modResource $collection */
17 | $collection = $this->modx->getObject(modResource::class, ['id' => $collection]);
18 | if (!$collection) return $this->failure('No Collection');
19 |
20 | $view = $this->collections->getCollectionsView($collection);
21 | $templates = $this->fred->getFredTemplates();
22 | $templates = array_flip($templates);
23 |
24 | $childTemplate = isset($templates[$view->child_template]) ? $view->child_template : 0;
25 | $defaultBlueprint = 0;
26 |
27 | if (($childTemplate > 0) && ($view->fred_default_blueprint > 0)) {
28 | /** @var \FredBlueprint $blueprint */
29 | $blueprint = $this->modx->getObject('Fred\\Model\\FredBlueprint', ['uuid' => $view->fred_default_blueprint]);
30 |
31 | if ($blueprint) {
32 | $category = $blueprint->Category;
33 | if ($category) {
34 | $themedTemplate = $this->modx->getCount('Fred\\Model\\FredThemedTemplate', [
35 | 'theme' => $category->get('theme'),
36 | 'template' => $childTemplate
37 | ]);
38 |
39 | if ($themedTemplate === 1) {
40 | $defaultBlueprint = $blueprint->id;
41 | }
42 | }
43 | }
44 | }
45 |
46 | return $this->data([
47 | 'template' => $childTemplate,
48 | 'blueprint' => $defaultBlueprint,
49 | 'sort' => $view->sort_field,
50 | 'sortDir' => $view->sort_dir,
51 | ]);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/core/components/collections/src/Endpoint/Ajax/GetCollections.php:
--------------------------------------------------------------------------------
1 | getClaim('context');
15 |
16 | $c = $this->modx->newQuery(modResource::class);
17 | $c->where([
18 | 'class_key' => CollectionContainer::class,
19 | 'context_key' => $context
20 | ]);
21 | $c->sortby('pagetitle');
22 |
23 | /** @var \modResource[] $resources */
24 | $resources = $this->modx->getIterator(modResource::class, $c);
25 | $data = [];
26 |
27 | foreach ($resources as $resource) {
28 | $data[] = [
29 | 'id' => $resource->get('id'),
30 | 'pagetitle' => $resource->get('pagetitle'),
31 | 'published' => $resource->get('published'),
32 | 'deleted' => $resource->get('deleted'),
33 | ];
34 | }
35 |
36 | return $this->data(['collections' => $data]);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/core/components/collections/src/Events/Event.php:
--------------------------------------------------------------------------------
1 | scriptProperties =& $scriptProperties;
20 | $this->modx = $modx;
21 | $this->collections = $this->modx->services->get('collections');
22 | }
23 |
24 | abstract public function run();
25 | }
26 |
--------------------------------------------------------------------------------
/core/components/collections/src/Events/FredBeforeRender.php:
--------------------------------------------------------------------------------
1 | modx->services->has('fred')) {
18 | $this->fred = $this->modx->services->get('fred');
19 | } else {
20 | $this->preventRun = true;
21 | }
22 | }
23 |
24 | public function run()
25 | {
26 | if ($this->preventRun) return true;
27 |
28 | $assetsPath = $this->collections->getOption('assets_url', [], $this->modx->getOption('assets_url', null, MODX_ASSETS_URL) . 'components/collections/');
29 |
30 | $assetsPath = rtrim($assetsPath, '/') . '/web/';
31 |
32 | $includes = '
33 |
34 |
35 | ';
36 |
37 | $endpoint = $assetsPath . 'ajax.php';
38 |
39 | $beforeRender = '
40 | this.registerSidebarPlugin("CollectionsSidebar", FredCollections.SidebarPlugin({endpoint:"' . $endpoint . '"}));
41 | ';
42 |
43 | $this->modx->event->_output = [
44 | 'includes' => $includes,
45 | 'beforeRender' => $beforeRender,
46 | 'lexicons' => ['collections:fred'],
47 | ];
48 |
49 | return true;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/core/components/collections/src/Events/FredOnBeforeGetResourceTree.php:
--------------------------------------------------------------------------------
1 | modx->services->has('fred')) {
20 | $this->fred = $this->modx->services->get('fred');
21 | } else {
22 | $this->preventRun = true;
23 | }
24 | }
25 |
26 | public function run()
27 | {
28 | if ($this->preventRun) return true;
29 |
30 | $params = $this->modx->getOption('params', $this->scriptProperties);
31 | if (empty($params)) return false;
32 |
33 | $query = $this->modx->newQuery(modResource::class, [
34 | 'class_key' => CollectionContainer::class
35 | ]);
36 |
37 | $query->select($this->modx->getSelectColumns(modResource::class, 'modResource', '', ['id']));
38 |
39 | $query->prepare();
40 | $query->stmt->execute();
41 |
42 | while ($row = $query->stmt->fetch(\PDO::FETCH_ASSOC)) {
43 | $params->hideChildren[] = $row['id'];
44 | }
45 |
46 | return true;
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/core/components/collections/src/Events/OnBeforeEmptyTrash.php:
--------------------------------------------------------------------------------
1 | scriptProperties['ids'];
14 |
15 | foreach ($ids as $id) {
16 | /** @var \modResource $resource */
17 | $resource = $this->modx->getObject(modResource::class, $id);
18 | if (!$resource) return;
19 |
20 | $this->modx->removeCollection(CollectionSelection::class, ['resource' => $resource->id]);
21 |
22 | /** @var \modResource $parent */
23 | $parent = $resource->Parent;
24 | if (!$parent) return;
25 |
26 | /** @var \modResource $grandParent */
27 | $grandParent = $parent->Parent;
28 | if (!$grandParent) return;
29 |
30 | if (($grandParent->class_key == CollectionContainer::class) && ($parent->class_key != CollectionContainer::class)) {
31 | $parent->set('show_in_tree', 0);
32 | $parent->save();
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/core/components/collections/src/Events/OnDocFormRender.php:
--------------------------------------------------------------------------------
1 | scriptProperties['mode']) || $this->scriptProperties['mode'] !== 'new') {
13 | return;
14 | }
15 |
16 | /** @var modResource $parent */
17 | $parent = $this->scriptProperties['resource']->Parent;
18 |
19 | if (empty($parent) || $parent->class_key != CollectionContainer::class) {
20 | return;
21 | }
22 |
23 | /** @var CollectionTemplate $template */
24 | $template = $this->collections->getCollectionsView($parent);
25 |
26 | $this->setConfig('hidemenu_default', $template->child_hide_from_menu);
27 | $this->setConfig('publish_default', $template->child_published);
28 | $this->setConfig('cache_default', $template->child_cacheable);
29 | $this->setConfig('richtext_default', $template->child_richtext);
30 | $this->setConfig('search_default', $template->child_searchable);
31 | $this->setConfig('default_content_type', $template->child_content_type, 0);
32 |
33 | $this->modx->regClientStartupHTMLBlock('
34 | ');
39 | }
40 |
41 | private function setConfig($name, $value, $default = null)
42 | {
43 | if ($value !== $default) {
44 | $this->modx->_userConfig[$name] = intval($value);
45 | }
46 | }
47 |
48 | private function setJSConfig($name, $value, $default = null)
49 | {
50 | if ($value !== $default) {
51 | return 'if (Ext.getCmp("' . $name . '")) {Ext.getCmp("' . $name . '").setValue(' . intval($value) . ');}';
52 | }
53 |
54 | return '';
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/core/components/collections/src/Events/OnManagerPageBeforeRender.php:
--------------------------------------------------------------------------------
1 | scriptProperties['controller']->addLexiconTopic('collections:default');
10 |
11 | $this->scriptProperties['controller']->addHtml("
12 |
49 | ");
50 |
51 | return true;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/core/components/collections/src/Events/OnManagerPageInit.php:
--------------------------------------------------------------------------------
1 | collections->getOption('assetsUrl') . 'css/mgr.css';
10 | $this->modx->regClientCSS($cssFile);
11 | }
12 | }
--------------------------------------------------------------------------------
/core/components/collections/src/Events/OnResourceBeforeSort.php:
--------------------------------------------------------------------------------
1 | scriptProperties['nodes'];
15 |
16 | foreach ($nodes as $id => $node) {
17 | /** @var modResource $resource */
18 | $resource = $this->modx->getObject(modResource::class, $node['id']);
19 | if (!$resource) continue;
20 |
21 | /** @var modResource $originalParent */
22 | $originalParent = $resource->Parent;
23 |
24 | /** @var modResource $parent */
25 | $parent = $this->modx->getObject(modResource::class, $node['parent']);
26 |
27 | if (($parent && $originalParent && $parent->id == $originalParent->id) || (!$parent && !$originalParent)) {
28 | continue;
29 | }
30 |
31 |
32 | $this->handleParent($parent, $resource, $originalParent);
33 |
34 | // if ($originalParent) {
35 | // $this->handleOriginalParent($originalParent);
36 | // }
37 |
38 | if ($resource->class_key == CollectionContainer::class) {
39 | $resource->set('show_in_tree', 1);
40 | }
41 |
42 | $resource->save();
43 |
44 | }
45 | }
46 |
47 | /**
48 | * @param modResource $parent
49 | * @param modResource $resource
50 | * @param modResource $originalParent
51 | */
52 | protected function handleParent($parent, $resource, $originalParent)
53 | {
54 | if ($parent) {
55 | if ($parent->class_key == CollectionContainer::class) {
56 | $resource->set('show_in_tree', 0);
57 | } else {
58 | if (($originalParent->class_key == CollectionContainer::class) && ($parent->class_key != CollectionContainer::class)) {
59 | $resource->set('show_in_tree', 1);
60 | }
61 | }
62 | } else {
63 | if ($originalParent && ($originalParent->class_key == CollectionContainer::class)) {
64 | $resource->set('show_in_tree', 1);
65 | }
66 | }
67 | }
68 |
69 | /**
70 | * @param modResource $originalParent
71 | */
72 | protected function handleOriginalParent($originalParent)
73 | {
74 | $originalGreatParent = $originalParent->Parent;
75 |
76 | if ($originalGreatParent && ($originalGreatParent->class_key == CollectionContainer::class) && ($originalParent->hasChildren() == 0)) {
77 | $originalParent->set('show_in_tree', 0);
78 | $originalParent->save();
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/core/components/collections/src/Events/OnResourceDuplicate.php:
--------------------------------------------------------------------------------
1 | scriptProperties['newResource'];
14 |
15 | /** @var modResource $oldResource */
16 | $oldResource = $this->scriptProperties['oldResource'];
17 |
18 | if ($oldResource->class_key !== CollectionContainer::class) return;
19 |
20 | /** @var CollectionSetting $oldSettings */
21 | $oldSettings = $this->modx->getObject(CollectionSetting::class, ['collection' => $oldResource->id]);
22 | if ($oldSettings) {
23 | /** @var CollectionSetting $newSettings */
24 | $newSettings = $this->modx->newObject(CollectionSetting::class);
25 | $newSettings->set('collection', $newResource->id);
26 | $newSettings->set('template', $oldSettings->template);
27 | $newSettings->save();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/CollectionContainer.php:
--------------------------------------------------------------------------------
1 | set('class_key', CollectionContainer::class);
24 | }
25 |
26 | public static function getControllerPath(xPDO &$modx)
27 | {
28 | return $modx->getOption('collections.core_path', null, $modx->getOption('core_path') . 'components/collections/') . 'controllers/';
29 | }
30 |
31 | public function getContextMenuText()
32 | {
33 | $this->xpdo->lexicon->load('collections:default');
34 | return [
35 | 'text_create' => $this->xpdo->lexicon('collections.system.text_create'),
36 | 'text_create_here' => $this->xpdo->lexicon('collections.system.text_create_here'),
37 | ];
38 | }
39 |
40 | public function getResourceTypeName()
41 | {
42 | $this->xpdo->lexicon->load('collections:default');
43 | return $this->xpdo->lexicon('collections.system.type_name');
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/CollectionContainerCreateProcessor.php:
--------------------------------------------------------------------------------
1 | getProperty('collections_template');
9 | if ($collectionsTemplate === null) {
10 | return parent::afterSave();
11 | }
12 |
13 | $collectionsTemplate = (int)$collectionsTemplate;
14 |
15 | $config = $this->modx->getObject(CollectionSetting::class, ['collection' => $this->object->id]);
16 |
17 | if (!$config) {
18 | $config = $this->modx->newObject(CollectionSetting::class);
19 | $config->set('collection', $this->object->id);
20 | }
21 |
22 | $config->set('template', $collectionsTemplate);
23 |
24 | $config->save();
25 |
26 | return parent::afterSave();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/CollectionContainerUpdateProcessor.php:
--------------------------------------------------------------------------------
1 | getProperty('collections_template');
19 | if ($collectionsTemplate === null) {
20 | return parent::afterSave();
21 | }
22 |
23 | $collectionsTemplate = (int)$collectionsTemplate;
24 |
25 | $config = $this->modx->getObject(CollectionSetting::class, ['collection' => $this->object->id]);
26 |
27 | if (!$config) {
28 | $config = $this->modx->newObject(CollectionSetting::class);
29 | $config->set('collection', $this->object->id);
30 | }
31 |
32 | $config->set('template', $collectionsTemplate);
33 |
34 | $config->save();
35 |
36 | return parent::afterSave();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/CollectionResourceTemplate.php:
--------------------------------------------------------------------------------
1 | xpdo->removeCollection(CollectionResourceTemplate::class, ['collection_template' => $this->id]);
60 |
61 | if (!empty($templates)) {
62 | foreach ($templates as $idTemplate) {
63 | $newTemplate = $this->xpdo->newObject(CollectionResourceTemplate::class);
64 | $newTemplate->set('collection_template', $this->id);
65 | $newTemplate->set('resource_template', $idTemplate);
66 | $newTemplate->save();
67 | }
68 | }
69 |
70 | return true;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/CollectionTemplateColumn.php:
--------------------------------------------------------------------------------
1 | set('class_key', SelectionContainer::class);
24 | }
25 |
26 | public static function getControllerPath(xPDO &$modx)
27 | {
28 | return $modx->getOption('collections.core_path', null, $modx->getOption('core_path') . 'components/collections/') . 'controllers/selection/';
29 | }
30 |
31 | public function getContextMenuText()
32 | {
33 | $this->xpdo->lexicon->load('collections:default', 'collections:selections');
34 |
35 | return [
36 | 'text_create' => $this->xpdo->lexicon('selections.system.text_create'),
37 | 'text_create_here' => $this->xpdo->lexicon('selections.system.text_create_here'),
38 | ];
39 | }
40 |
41 | public function getResourceTypeName()
42 | {
43 | $this->xpdo->lexicon->load('collections:default', 'collections:selections');
44 | return $this->xpdo->lexicon('selections.system.type_name');
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/SelectionContainerCreateProcessor.php:
--------------------------------------------------------------------------------
1 | '3.0',
4 | 'namespace' => 'Collections\\Model',
5 | 'namespacePrefix' => 'Collections',
6 | 'class_map' =>
7 | array (
8 | 'MODX\\Revolution\\modResource' =>
9 | array (
10 | 0 => 'Collections\\Model\\CollectionContainer',
11 | ),
12 | 'Collections\\Model\\CollectionContainer' =>
13 | array (
14 | 0 => 'Collections\\Model\\SelectionContainer',
15 | ),
16 | 'xPDO\\Om\\xPDOSimpleObject' =>
17 | array (
18 | 0 => 'Collections\\Model\\CollectionSetting',
19 | 1 => 'Collections\\Model\\CollectionTemplate',
20 | 2 => 'Collections\\Model\\CollectionTemplateColumn',
21 | ),
22 | 'xPDO\\Om\\xPDOObject' =>
23 | array (
24 | 0 => 'Collections\\Model\\CollectionResourceTemplate',
25 | 1 => 'Collections\\Model\\CollectionSelection',
26 | ),
27 | ),
28 | );
--------------------------------------------------------------------------------
/core/components/collections/src/Model/mysql/CollectionContainer.php:
--------------------------------------------------------------------------------
1 | 'Collections\\Model\\',
11 | 'version' => '3.0',
12 | 'extends' => 'MODX\\Revolution\\modResource',
13 | 'tableMeta' =>
14 | array (
15 | 'engine' => 'MyISAM',
16 | ),
17 | 'fields' =>
18 | array (
19 | ),
20 | 'fieldMeta' =>
21 | array (
22 | ),
23 | 'composites' =>
24 | array (
25 | 'Setting' =>
26 | array (
27 | 'class' => 'Collections\\Model\\CollectionSetting',
28 | 'local' => 'id',
29 | 'foreign' => 'collection',
30 | 'cardinality' => 'one',
31 | 'owner' => 'local',
32 | ),
33 | ),
34 | );
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/mysql/CollectionResourceTemplate.php:
--------------------------------------------------------------------------------
1 | 'Collections\\Model\\',
11 | 'version' => '3.0',
12 | 'table' => 'collection_resource_template',
13 | 'tableMeta' =>
14 | array (
15 | 'engine' => 'MyISAM',
16 | ),
17 | 'fields' =>
18 | array (
19 | 'collection_template' => NULL,
20 | 'resource_template' => NULL,
21 | ),
22 | 'fieldMeta' =>
23 | array (
24 | 'collection_template' =>
25 | array (
26 | 'dbtype' => 'int',
27 | 'attributes' => 'unsigned',
28 | 'precision' => '10',
29 | 'phptype' => 'integer',
30 | 'null' => false,
31 | 'index' => 'pk',
32 | ),
33 | 'resource_template' =>
34 | array (
35 | 'dbtype' => 'int',
36 | 'attributes' => 'unsigned',
37 | 'precision' => '10',
38 | 'phptype' => 'integer',
39 | 'null' => false,
40 | 'index' => 'pk',
41 | ),
42 | ),
43 | 'indexes' =>
44 | array (
45 | 'PRIMARY' =>
46 | array (
47 | 'alias' => 'PRIMARY',
48 | 'primary' => true,
49 | 'unique' => true,
50 | 'type' => 'BTREE',
51 | 'columns' =>
52 | array (
53 | 'collection_template' =>
54 | array (
55 | 'length' => '',
56 | 'collation' => 'A',
57 | 'null' => false,
58 | ),
59 | 'resource_template' =>
60 | array (
61 | 'length' => '',
62 | 'collation' => 'A',
63 | 'null' => false,
64 | ),
65 | ),
66 | ),
67 | ),
68 | 'aggregates' =>
69 | array (
70 | 'CollectionTemplate' =>
71 | array (
72 | 'class' => 'Collections\\Model\\CollectionTemplate',
73 | 'local' => 'collection_template',
74 | 'foreign' => 'id',
75 | 'cardinality' => 'one',
76 | 'owner' => 'foreign',
77 | ),
78 | 'ResourceTemplate' =>
79 | array (
80 | 'class' => 'MODX\\Revolution\\modTemplate',
81 | 'local' => 'resource_template',
82 | 'foreign' => 'id',
83 | 'cardinality' => 'one',
84 | 'owner' => 'foreign',
85 | ),
86 | ),
87 | );
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/mysql/CollectionSelection.php:
--------------------------------------------------------------------------------
1 | 'Collections\\Model\\',
11 | 'version' => '3.0',
12 | 'table' => 'collection_selections',
13 | 'tableMeta' =>
14 | array (
15 | 'engine' => 'MyISAM',
16 | ),
17 | 'fields' =>
18 | array (
19 | 'collection' => NULL,
20 | 'resource' => NULL,
21 | 'menuindex' => 0,
22 | ),
23 | 'fieldMeta' =>
24 | array (
25 | 'collection' =>
26 | array (
27 | 'dbtype' => 'int',
28 | 'attributes' => 'unsigned',
29 | 'precision' => '10',
30 | 'phptype' => 'integer',
31 | 'null' => false,
32 | 'index' => 'pk',
33 | ),
34 | 'resource' =>
35 | array (
36 | 'dbtype' => 'int',
37 | 'attributes' => 'unsigned',
38 | 'precision' => '10',
39 | 'phptype' => 'integer',
40 | 'null' => false,
41 | 'index' => 'pk',
42 | ),
43 | 'menuindex' =>
44 | array (
45 | 'dbtype' => 'int',
46 | 'attributes' => 'unsigned',
47 | 'precision' => '10',
48 | 'phptype' => 'integer',
49 | 'null' => false,
50 | 'default' => 0,
51 | ),
52 | ),
53 | 'indexes' =>
54 | array (
55 | 'PRIMARY' =>
56 | array (
57 | 'alias' => 'PRIMARY',
58 | 'primary' => true,
59 | 'unique' => true,
60 | 'type' => 'BTREE',
61 | 'columns' =>
62 | array (
63 | 'collection' =>
64 | array (
65 | 'length' => '',
66 | 'collation' => 'A',
67 | 'null' => false,
68 | ),
69 | 'resource' =>
70 | array (
71 | 'length' => '',
72 | 'collation' => 'A',
73 | 'null' => false,
74 | ),
75 | ),
76 | ),
77 | ),
78 | 'aggregates' =>
79 | array (
80 | 'Collection' =>
81 | array (
82 | 'class' => 'Collections\\Model\\CollectionContainer',
83 | 'local' => 'collection',
84 | 'foreign' => 'id',
85 | 'cardinality' => 'one',
86 | 'owner' => 'foreign',
87 | ),
88 | 'CollectionSetting' =>
89 | array (
90 | 'class' => 'Collections\\Model\\CollectionSetting',
91 | 'local' => 'collection',
92 | 'foreign' => 'id',
93 | 'cardinality' => 'one',
94 | 'owner' => 'foreign',
95 | ),
96 | 'Resource' =>
97 | array (
98 | 'class' => 'MODX\\Revolution\\modResource',
99 | 'local' => 'resource',
100 | 'foreign' => 'id',
101 | 'cardinality' => 'one',
102 | 'owner' => 'foreign',
103 | ),
104 | ),
105 | );
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/mysql/CollectionSetting.php:
--------------------------------------------------------------------------------
1 | 'Collections\\Model\\',
11 | 'version' => '3.0',
12 | 'table' => 'collection_settings',
13 | 'extends' => 'xPDO\\Om\\xPDOSimpleObject',
14 | 'tableMeta' =>
15 | array (
16 | 'engine' => 'MyISAM',
17 | ),
18 | 'fields' =>
19 | array (
20 | 'collection' => NULL,
21 | 'template' => 0,
22 | ),
23 | 'fieldMeta' =>
24 | array (
25 | 'collection' =>
26 | array (
27 | 'dbtype' => 'int',
28 | 'attributes' => 'unsigned',
29 | 'precision' => '10',
30 | 'phptype' => 'integer',
31 | 'null' => false,
32 | 'index' => 'unique',
33 | ),
34 | 'template' =>
35 | array (
36 | 'dbtype' => 'int',
37 | 'attributes' => 'unsigned',
38 | 'precision' => '10',
39 | 'phptype' => 'integer',
40 | 'null' => false,
41 | 'default' => 0,
42 | ),
43 | ),
44 | 'aggregates' =>
45 | array (
46 | 'Collection' =>
47 | array (
48 | 'class' => 'Collections\\Model\\CollectionContainer',
49 | 'local' => 'collection',
50 | 'foreign' => 'id',
51 | 'cardinality' => 'one',
52 | 'owner' => 'foreign',
53 | ),
54 | 'Template' =>
55 | array (
56 | 'class' => 'Collections\\Model\\CollectionTemplate',
57 | 'local' => 'template',
58 | 'foreign' => 'id',
59 | 'cardinality' => 'one',
60 | 'owner' => 'local',
61 | ),
62 | ),
63 | );
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/core/components/collections/src/Model/mysql/SelectionContainer.php:
--------------------------------------------------------------------------------
1 | 'Collections\\Model\\',
11 | 'version' => '3.0',
12 | 'extends' => 'Collections\\Model\\CollectionContainer',
13 | 'tableMeta' =>
14 | array (
15 | 'engine' => 'MyISAM',
16 | ),
17 | 'fields' =>
18 | array (
19 | ),
20 | 'fieldMeta' =>
21 | array (
22 | ),
23 | 'composites' =>
24 | array (
25 | 'Selection' =>
26 | array (
27 | 'class' => 'Collections\\Model\\CollectionSelection',
28 | 'local' => 'id',
29 | 'foreign' => 'collection',
30 | 'cardinality' => 'many',
31 | 'owner' => 'local',
32 | ),
33 | ),
34 | );
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Extra/Breadcrumbs.php:
--------------------------------------------------------------------------------
1 | getProperty('folder', 0);
12 | $collection = (int)$this->getProperty('collection', 0);
13 |
14 | if (($folder <= 0) || ($collection <= 0)) {
15 | return $this->failure();
16 | }
17 |
18 | /** @var modResource $resource */
19 | $resource = $this->modx->getObject(modResource::class, $folder);
20 | if (!$resource) {
21 | return $this->failure();
22 | }
23 |
24 | $haveParent = false;
25 | $parents = [
26 | [
27 | 'id' => $resource->id,
28 | 'text' => $resource->pagetitle
29 | ]
30 | ];
31 |
32 | while ($haveParent === false) {
33 | $parent = $resource->Parent;
34 |
35 | if ($parent->id == $collection) {
36 | $haveParent = true;
37 | } else {
38 | $parents[] = [
39 | 'id' => $parent->id,
40 | 'text' => $parent->pagetitle
41 | ];
42 | $resource = $parent;
43 | }
44 |
45 | }
46 |
47 | return $this->outputArray(array_reverse($parents));
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Extra/FredGetBlueprints.php:
--------------------------------------------------------------------------------
1 | modx->services->has('fred')) {
19 | return false;
20 | }
21 |
22 | $this->setDefaultProperties([
23 | 'start' => 0,
24 | 'limit' => 20,
25 | 'query' => '',
26 | ]);
27 |
28 | return parent::initialize();
29 | }
30 |
31 | public function beforeIteration(array $list)
32 | {
33 | $addNone = (int)$this->getProperty('addNone', 0);
34 |
35 | if ($addNone === 1) {
36 | $list[] = [
37 | 'id' => '',
38 | 'name' => $this->modx->lexicon('fred.global.none')
39 | ];
40 | }
41 |
42 | return parent::beforeIteration($list);
43 | }
44 |
45 | public function prepareQueryBeforeCount(xPDOQuery $c)
46 | {
47 | $uuid = $this->getProperty('uuid', '');
48 | if (!empty($uuid)) {
49 | $c->where(['uuid' => $uuid]);
50 | }
51 |
52 | $query = $this->getProperty('query', '');
53 | if (!empty($query)) {
54 | $c->where(['name:LIKE' => "%{$query}%"]);
55 | }
56 |
57 | $c->where([
58 | 'public' => true,
59 | 'Category.public' => true
60 | ]);
61 |
62 | $template = (int)$this->getProperty('template', 0);
63 | if (!empty($template)) {
64 | $c->where([
65 | 'Templates.template' => $template
66 | ]);
67 | }
68 |
69 | return parent::prepareQueryBeforeCount($c);
70 | }
71 |
72 | public function prepareQueryAfterCount(xPDOQuery $c)
73 | {
74 | $c->leftJoin('Fred\\Model\\FredBlueprintCategory', 'Category');
75 | $c->leftJoin('Fred\\Model\\FredTheme', 'Theme', 'Category.theme = Theme.id');
76 | $c->leftJoin('Fred\\Model\\FredThemedTemplate', 'Templates', 'Templates.theme = Theme.id');
77 |
78 | $c->select($this->modx->getSelectColumns('Fred\\Model\\FredBlueprint', 'FredBlueprint', '', ['data'], true));
79 | $c->select($this->modx->getSelectColumns('Fred\\Model\\FredBlueprintCategory', 'Category', 'category_', ['name']));
80 | $c->select($this->modx->getSelectColumns('Fred\\Model\\FredTheme', 'Theme', 'theme_', ['name']));
81 |
82 | return parent::prepareQueryAfterCount($c);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Extra/GetContentTypes.php:
--------------------------------------------------------------------------------
1 | 0, 'name' => $this->modx->lexicon('collections.global.use_default')]);
15 |
16 | return $list;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Extra/GetDerivates.php:
--------------------------------------------------------------------------------
1 | modx->hasPermission('class_map');
12 | }
13 |
14 | public function initialize()
15 | {
16 | $this->setDefaultProperties([
17 | 'class' => '',
18 | 'skip' => 'modXMLRPCResource',
19 | ]);
20 | return true;
21 | }
22 |
23 | public function process()
24 | {
25 | $class = $this->getProperty('class');
26 | if (empty($class)) $this->failure($this->modx->lexicon('class_err_ns'));
27 |
28 | $skip = explode(',', $this->getProperty('skip'));
29 | $descendants = $this->modx->getDescendants($class);
30 |
31 | $list = [];
32 | foreach ($descendants as $descendant) {
33 | if (in_array($descendant, $skip)) continue;
34 |
35 | /** @var modResource $obj */
36 | $obj = $this->modx->newObject($descendant);
37 | if (!$obj) continue;
38 |
39 | if ($class == 'MODX\\Revolution\\modResource' && !$obj->allowListingInClassKeyDropdown) continue;
40 | if ($class == 'MODX\\Revolution\\modResource') {
41 | $name = $obj->getResourceTypeName();
42 | } else {
43 | $name = $descendant;
44 | }
45 |
46 | $list[$descendant] = [
47 | 'id' => $descendant,
48 | 'name' => $name,
49 | ];
50 | }
51 |
52 | return $this->outputArray($list);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Extra/GetTemplates.php:
--------------------------------------------------------------------------------
1 | getProperty('addEmpty', false);
19 |
20 | if ($addEmpty) {
21 | $list[] = [
22 | 'id' => 0,
23 | 'templatename' => $this->modx->lexicon('template_empty'),
24 | ];
25 | }
26 |
27 | return $list;
28 | }
29 |
30 | public function prepareQueryBeforeCount(xPDOQuery $c)
31 | {
32 | $query = $this->getProperty('query');
33 | $template = (int)$this->getProperty('template');
34 |
35 | $where = [];
36 |
37 | if ($template != 0) {
38 | $where[] = "NOT EXISTS (SELECT 1 FROM {$this->modx->getTableName(CollectionResourceTemplate::class)} r WHERE r.resource_template = modTemplate.id AND r.collection_template != " . $template . ")";
39 | }
40 |
41 | if (!empty($query)) {
42 | $valuesqry = $this->getProperty('valuesqry');
43 |
44 | if ($valuesqry == true) {
45 | $where['id:IN'] = Utils::explodeAndClean($query, '|');
46 | } else {
47 | $where['templatename:LIKE'] = '%' . $query . '%';
48 |
49 | }
50 | }
51 |
52 | $c->where($where);
53 |
54 | return $c;
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Resource/ChangeChildParent.php:
--------------------------------------------------------------------------------
1 | getProperty('parent', '');
17 |
18 | if ($parent == '') {
19 | return $this->modx->lexicon('collections.err.parent_ns');
20 | }
21 |
22 | return parent::beforeSet();
23 | }
24 |
25 | public function beforeSave()
26 | {
27 | /** @var modResource $parent */
28 | $parent = $this->modx->getObject(modResource::class, $this->object->parent);
29 | if ($parent && ($parent->class_key == CollectionContainer::class)) {
30 | $this->object->set('show_in_tree', 0);
31 | } else {
32 | $this->object->set('show_in_tree', 1);
33 | }
34 |
35 | return parent::beforeSave();
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Resource/ChangeParent.php:
--------------------------------------------------------------------------------
1 | getProperty('parent', '');
18 |
19 | if ($parent == '') {
20 | return $this->modx->lexicon('collections.err.parent_ns');
21 | } else {
22 | $parent = explode('_', $parent);
23 |
24 | /** @var modContext $ctx */
25 | $ctx = $this->modx->getObject(modContext::class, $parent[0]);
26 | if ($ctx) {
27 | $this->setProperty('context_key', $ctx->key);
28 | $this->setProperty('parent', intval($parent[1]));
29 | } else {
30 | return $this->modx->lexicon('collections.err.common');
31 | }
32 | }
33 |
34 | return parent::beforeSet();
35 | }
36 |
37 | public function beforeSave()
38 | {
39 | /** @var modResource $parent */
40 | $parent = $this->modx->getObject(modResource::class, $this->object->parent);
41 | if ($parent && ($parent->class_key == CollectionContainer::class)) {
42 | $this->object->set('show_in_tree', 0);
43 | } else {
44 | $this->object->set('show_in_tree', 1);
45 | }
46 |
47 | return parent::beforeSave();
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Resource/DDReorder.php:
--------------------------------------------------------------------------------
1 | getProperty('idItem');
15 | $oldIndex = $this->getProperty('oldIndex');
16 | $newIndex = $this->getProperty('newIndex');
17 | $parent = $this->getProperty('parent');
18 |
19 | if (intval($parent) == 0) {
20 | return $this->failure($this->modx->lexicon('collections.err.parent_ns'));
21 | }
22 |
23 | $items = $this->modx->newQuery($this->classKey);
24 | $items->where([
25 | 'id:!=' => $idItem,
26 | 'parent' => $parent,
27 | 'menuindex:>=' => min($oldIndex, $newIndex),
28 | 'menuindex:<=' => max($oldIndex, $newIndex),
29 | ]);
30 |
31 | $items->sortby('menuindex', 'ASC');
32 |
33 | $itemsCollection = $this->modx->getCollection($this->classKey, $items);
34 | $affectedResources = [];
35 |
36 | if (min($oldIndex, $newIndex) == $newIndex) {
37 | foreach ($itemsCollection as $item) {
38 | $itemObject = $this->modx->getObject($this->classKey, $item->get('id'));
39 | $itemObject->set('menuindex', $itemObject->get('menuindex') + 1);
40 | $itemObject->save();
41 |
42 | $affectedResources[] = $itemObject;
43 | }
44 | } else {
45 | foreach ($itemsCollection as $item) {
46 | $itemObject = $this->modx->getObject($this->classKey, $item->get('id'));
47 | $itemObject->set('menuindex', $itemObject->get('menuindex') - 1);
48 | $itemObject->save();
49 |
50 | $affectedResources[] = $itemObject;
51 | }
52 | }
53 |
54 | $itemObject = $this->modx->getObject($this->classKey, $idItem);
55 | $itemObject->set('menuindex', $newIndex);
56 | $itemObject->save();
57 |
58 | $this->modx->invokeEvent('CollectionsOnResourceSort', [
59 | 'resourceId' => $idItem,
60 | 'parentId' => $parent,
61 | 'oldIndex' => $oldIndex,
62 | 'newIndex' => $newIndex,
63 | 'affectedResources' => &$affectedResources,
64 | ]);
65 |
66 | return $this->success('', $itemObject);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Resource/DeleteMultiple.php:
--------------------------------------------------------------------------------
1 | getProperty('ids', null);
14 | if (empty($ids)) {
15 | return $this->failure($this->modx->lexicon('collections.children.err_ns_multiple'));
16 | }
17 | $ids = is_array($ids) ? $ids : explode(',', $ids);
18 |
19 | $lastId = 0;
20 |
21 | foreach ($ids as $id) {
22 | if (empty($id)) continue;
23 | $lastId = $id;
24 | $this->modx->runProcessor('Collections\\Processors\\Resource\\Delete', [
25 | 'id' => $id,
26 | 'skipClearCache' => true,
27 | ]);
28 | }
29 |
30 | /** @var modResource $res */
31 | $res = $this->modx->getObject(modResource::class, $lastId);
32 |
33 | if ($res) {
34 | $this->clearCache($res->context_key);
35 | }
36 |
37 | return $this->success();
38 | }
39 |
40 | public function clearCache($context)
41 | {
42 | $this->modx->cacheManager->refresh([
43 | 'db' => [],
44 | 'auto_publish' => ['contexts' => [$context]],
45 | 'context_settings' => ['contexts' => [$context]],
46 | 'resource' => ['contexts' => [$context]],
47 | ]);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Resource/PublishMultiple.php:
--------------------------------------------------------------------------------
1 | getProperty('ids', null);
14 | if (empty($ids)) {
15 | return $this->failure($this->modx->lexicon('collections.children.err_ns_multiple'));
16 | }
17 | $ids = is_array($ids) ? $ids : explode(',', $ids);
18 |
19 | $lastId = 0;
20 |
21 | foreach ($ids as $id) {
22 | if (empty($id)) continue;
23 | $lastId = $id;
24 | $this->modx->runProcessor('Collections\\Processors\\Resource\\Publish', [
25 | 'id' => $id,
26 | 'skipClearCache' => true,
27 | ]);
28 | }
29 |
30 | /** @var modResource $res */
31 | $res = $this->modx->getObject(modResource::class, $lastId);
32 |
33 | if ($res) {
34 | $this->clearCache($res->context_key);
35 | }
36 |
37 | return $this->success();
38 | }
39 |
40 | public function clearCache($context)
41 | {
42 | $this->modx->cacheManager->refresh([
43 | 'db' => [],
44 | 'auto_publish' => ['contexts' => [$context]],
45 | 'context_settings' => ['contexts' => [$context]],
46 | 'resource' => ['contexts' => [$context]],
47 | ]);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Resource/UnDeleteMultiple.php:
--------------------------------------------------------------------------------
1 | getProperty('ids', null);
14 | if (empty($ids)) {
15 | return $this->failure($this->modx->lexicon('collections.children.err_ns_multiple'));
16 | }
17 | $ids = is_array($ids) ? $ids : explode(',', $ids);
18 |
19 | $lastId = 0;
20 |
21 | foreach ($ids as $id) {
22 | if (empty($id)) continue;
23 | $lastId = $id;
24 | $this->modx->runProcessor('Collections\\Processors\\Resource\\UndDelete', [
25 | 'id' => $id,
26 | 'skipClearCache' => true,
27 | ]);
28 | }
29 |
30 | /** @var modResource $res */
31 | $res = $this->modx->getObject(modResource::class, $lastId);
32 |
33 | if ($res) {
34 | $this->clearCache($res->context_key);
35 | }
36 |
37 | return $this->success();
38 | }
39 |
40 | public function clearCache($context)
41 | {
42 | $this->modx->cacheManager->refresh([
43 | 'db' => [],
44 | 'auto_publish' => ['contexts' => [$context]],
45 | 'context_settings' => ['contexts' => [$context]],
46 | 'resource' => ['contexts' => [$context]],
47 | ]);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Resource/UnPublishMultiple.php:
--------------------------------------------------------------------------------
1 | getProperty('ids', null);
14 | if (empty($ids)) {
15 | return $this->failure($this->modx->lexicon('collections.children.err_ns_multiple'));
16 | }
17 | $ids = is_array($ids) ? $ids : explode(',', $ids);
18 |
19 | $lastId = 0;
20 |
21 | foreach ($ids as $id) {
22 | if (empty($id)) continue;
23 | $lastId = $id;
24 | $this->modx->runProcessor('Collections\\Processors\\Resource\\UnPublish', [
25 | 'id' => $id,
26 | 'skipClearCache' => true,
27 | ]);
28 | }
29 |
30 | /** @var modResource $res */
31 | $res = $this->modx->getObject(modResource::class, $lastId);
32 |
33 | if ($res) {
34 | $this->clearCache($res->context_key);
35 | }
36 |
37 | return $this->success();
38 | }
39 |
40 | public function clearCache($context)
41 | {
42 | $this->modx->cacheManager->refresh([
43 | 'db' => [],
44 | 'auto_publish' => ['contexts' => [$context]],
45 | 'context_settings' => ['contexts' => [$context]],
46 | 'resource' => ['contexts' => [$context]],
47 | ]);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Selection/Create.php:
--------------------------------------------------------------------------------
1 | getProperty('collection');
23 | $resource = $this->getProperty('resource');
24 |
25 | if (empty($collection) || empty($resource)) {
26 | if (empty($collection)) {
27 | $this->addFieldError('collection', $this->modx->lexicon('collections.err.selection_ns_collection'));
28 | }
29 |
30 | if (empty($resource)) {
31 | $this->addFieldError('resource', $this->modx->lexicon('collections.err.selection_ns_resource'));
32 | }
33 | } else {
34 | if ($this->doesAlreadyExist(['collections' => $collection, 'resource' => $resource])) {
35 | $this->addFieldError('resource', $this->modx->lexicon('collections.err.selection_ae_resource'));
36 | }
37 | }
38 |
39 | return parent::beforeSet();
40 | }
41 |
42 | public function beforeSave()
43 | {
44 | $collection = $this->getProperty('collection');
45 | $resource = $this->getProperty('resource');
46 |
47 | $menuindex = $this->modx->newQuery(CollectionSelection::class);
48 | $menuindex->where(['collection' => $collection]);
49 | $menuindex->sortby('menuindex', 'DESC');
50 | $menuindex->limit(1);
51 | $menuindex->select($this->modx->getSelectColumns(CollectionSelection::class, 'CollectionSelection', '', ['menuindex']));
52 |
53 | $menuindex->prepare();
54 | $menuindex->stmt->execute();
55 |
56 | $lastMenuindex = (int)$menuindex->stmt->fetchColumn(0);
57 |
58 | $this->object->set('collection', $collection);
59 | $this->object->set('resource', $resource);
60 | $this->object->set('menuindex', $lastMenuindex + 1);
61 |
62 | return parent::beforeSave();
63 | }
64 |
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Selection/DDReorder.php:
--------------------------------------------------------------------------------
1 | getProperty('idItem');
21 | $oldIndex = $this->getProperty('oldIndex');
22 | $newIndex = $this->getProperty('newIndex');
23 | $parent = $this->getProperty('parent');
24 |
25 | if (intval($parent) == 0) {
26 | return $this->failure($this->modx->lexicon('collections.err.parent_ns'));
27 | }
28 |
29 | $items = $this->modx->newQuery($this->classKey);
30 | $items->where([
31 | 'resource:!=' => $idItem,
32 | 'collection' => $parent,
33 | 'menuindex:>=' => min($oldIndex, $newIndex),
34 | 'menuindex:<=' => max($oldIndex, $newIndex),
35 | ]);
36 |
37 | $items->sortby('menuindex', 'ASC');
38 |
39 | $itemsCollection = $this->modx->getCollection($this->classKey, $items);
40 |
41 | if (min($oldIndex, $newIndex) == $newIndex) {
42 | foreach ($itemsCollection as $item) {
43 | $itemObject = $this->modx->getObject($this->classKey, ['resource' => $item->get('resource'), 'collection' => $parent]);
44 | $itemObject->set('menuindex', $itemObject->get('menuindex') + 1);
45 | $itemObject->save();
46 | }
47 | } else {
48 | foreach ($itemsCollection as $item) {
49 | $itemObject = $this->modx->getObject($this->classKey, ['resource' => $item->get('resource'), 'collection' => $parent]);
50 | $itemObject->set('menuindex', $itemObject->get('menuindex') - 1);
51 | $itemObject->save();
52 | }
53 | }
54 |
55 | $itemObject = $this->modx->getObject($this->classKey, ['resource' => $idItem, 'collection' => $parent]);
56 | $itemObject->set('menuindex', $newIndex);
57 | $itemObject->save();
58 |
59 |
60 | return $this->success('', $itemObject);
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Selection/Remove.php:
--------------------------------------------------------------------------------
1 | getProperty('collection');
22 | $resource = $this->getProperty('resource');
23 |
24 | if (empty($collection) || empty($resource)) {
25 | return $this->modx->lexicon('collections.err.selection_res_col_ns');
26 | }
27 |
28 | $this->object = $this->modx->getObject($this->classKey, ['collection' => $collection, 'resource' => $resource]);
29 | if (empty($this->object)) return $this->modx->lexicon($this->objectType . '_err_nfs', [$this->primaryKeyField => $collection . ',' . $resource]);
30 |
31 | if ($this->checkRemovePermission && $this->object instanceof modAccessibleObject && !$this->object->checkPolicy('remove')) {
32 | return $this->modx->lexicon('access_denied');
33 | }
34 |
35 | return true;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Selection/RemoveMultiple.php:
--------------------------------------------------------------------------------
1 | getProperty('collection');
21 | $resources = $this->getProperty('resources', '');
22 |
23 | $resources = Utils::explodeAndClean($resources);
24 |
25 | if (empty($collection) || empty($resources)) {
26 | return $this->modx->lexicon('collections.err.selection_res_col_ns');
27 | }
28 |
29 | $this->modx->removeCollection($this->classKey, ['resource:IN' => $resources, 'collection' => $collection]);
30 |
31 | return $this->success();
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/Column/DDReorder.php:
--------------------------------------------------------------------------------
1 | getProperty('idItem');
16 | $oldIndex = $this->getProperty('oldIndex');
17 | $newIndex = $this->getProperty('newIndex');
18 | $template = $this->getProperty('template');
19 |
20 | if (intval($template) == 0) {
21 | return $this->failure($this->modx->lexicon('collections.err.template_ns'));
22 | }
23 |
24 | $items = $this->modx->newQuery($this->classKey);
25 | $items->where([
26 | 'id:!=' => $idItem,
27 | 'template' => $template,
28 | 'position:>=' => min($oldIndex, $newIndex),
29 | 'position:<=' => max($oldIndex, $newIndex),
30 | ]);
31 |
32 | $items->sortby('position', 'ASC');
33 |
34 | $itemsColumn = $this->modx->getCollection($this->classKey, $items);
35 |
36 | if (min($oldIndex, $newIndex) == $newIndex) {
37 | foreach ($itemsColumn as $item) {
38 | $itemObject = $this->modx->getObject($this->classKey, $item->get('id'));
39 | $itemObject->set('position', $itemObject->get('position') + 1);
40 | $itemObject->save();
41 | }
42 | } else {
43 | foreach ($itemsColumn as $item) {
44 | $itemObject = $this->modx->getObject($this->classKey, $item->get('id'));
45 | $itemObject->set('position', $itemObject->get('position') - 1);
46 | $itemObject->save();
47 | }
48 | }
49 |
50 | $itemObject = $this->modx->getObject($this->classKey, $idItem);
51 | $itemObject->set('position', $newIndex);
52 | $itemObject->save();
53 |
54 |
55 | return $this->success('', $itemObject);
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/Column/GetList.php:
--------------------------------------------------------------------------------
1 | getProperty('template');
19 |
20 | if (!empty($template)) {
21 | $c->where([
22 | 'template' => $template
23 | ]);
24 | }
25 |
26 | return $c;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/Column/Remove.php:
--------------------------------------------------------------------------------
1 | object->name == 'id') {
17 | return $this->modx->lexicon('collections.err.cant_remove_id_column');
18 | }
19 |
20 | return parent::beforeRemove();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/Column/UpdateFromGrid.php:
--------------------------------------------------------------------------------
1 | getProperty('data');
9 | if (empty($data)) return $this->modx->lexicon('invalid_data');
10 | $data = json_decode($data, true);
11 | if (empty($data)) return $this->modx->lexicon('invalid_data');
12 | $this->setProperties($data);
13 | $this->unsetProperty('data');
14 |
15 | return parent::initialize();
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/Duplicate.php:
--------------------------------------------------------------------------------
1 | getProperty('id', false);
22 | if (empty($id)) return $this->modx->lexicon('collections.err.template_ns');
23 |
24 | $this->oldTemplate = $this->modx->getObject($this->classKey, $id);
25 | if (empty($this->oldTemplate)) return $this->modx->lexicon('collections.err.template_ns');
26 |
27 | return true;
28 | }
29 |
30 | public function process()
31 | {
32 | $canDuplicate = $this->beforeDuplicate();
33 | if ($canDuplicate !== true) {
34 | return $this->failure($canDuplicate);
35 | }
36 |
37 | $oldValues = $this->oldTemplate->toArray();
38 |
39 | /** @var CollectionTemplateColumn[] $oldColumns */
40 | $oldColumns = $this->oldTemplate->Columns;
41 |
42 | $oldValues['name'] = $this->getProperty('name');
43 | $oldValues['description'] = $this->getProperty('description');
44 | $oldValues['global_template'] = false;
45 |
46 | /** @var CollectionTemplate $newTemplate */
47 | $newTemplate = $this->modx->newObject($this->classKey);
48 | $newTemplate->fromArray($oldValues);
49 |
50 | $newColumns = [];
51 |
52 | foreach ($oldColumns as $column) {
53 | $columnArray = $column->toArray();
54 | unset($columnArray['template']);
55 |
56 | /** @var CollectionTemplateColumn $newColumn */
57 | $newColumn = $this->modx->newObject(CollectionTemplateColumn::class);
58 | $newColumn->fromArray($columnArray);
59 |
60 | $newColumns[] = $newColumn;
61 | }
62 |
63 | $newTemplate->addMany($newColumns, 'Columns');
64 |
65 | $newTemplate->save();
66 |
67 | return $this->success('', ['id' => $newTemplate->get('id')]);
68 | }
69 |
70 | public function beforeDuplicate()
71 | {
72 | $name = $this->getProperty('name', '');
73 |
74 | if (empty($name)) {
75 | $this->addFieldError('name', $this->modx->lexicon('collections.err.template_ns_name'));
76 | } else {
77 | if ($this->modx->getCount($this->classKey, ['name' => $name]) > 0) {
78 | $this->addFieldError('name', $this->modx->lexicon('collections.err.template_ae_name'));
79 | }
80 | }
81 |
82 | return !$this->hasErrors();
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/Get.php:
--------------------------------------------------------------------------------
1 | modx->newQuery(CollectionResourceTemplate::class);
17 | $c->where(array(
18 | 'collection_template' => $this->object->id
19 | ));
20 | $c->select($this->modx->getSelectColumns(CollectionResourceTemplate::class, 'CollectionResourceTemplate', '', array('resource_template')));
21 |
22 | $c->prepare();
23 | $c->stmt->execute();
24 | $templates = $c->stmt->fetchAll(\PDO::FETCH_COLUMN, 0);
25 |
26 | $this->object->set('templates[]', $templates);
27 |
28 | return true;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/GetList.php:
--------------------------------------------------------------------------------
1 | getProperty('addEmpty', false);
20 |
21 | if ($addEmpty) {
22 | $list[] = [
23 | 'id' => 0,
24 | 'name' => $this->modx->lexicon('collections.template.empty'),
25 | ];
26 | }
27 | return $list;
28 | }
29 |
30 | public function prepareRow(xPDOObject $object)
31 | {
32 | $template = $object->toArray();
33 |
34 | $c = $this->modx->newQuery(CollectionResourceTemplate::class);
35 | $c->leftJoin(modTemplate::class, 'ResourceTemplate');
36 | $c->where([
37 | 'collection_template' => $template['id']
38 | ]);
39 | $c->select([
40 | 'test' => 'IF(resource_template = 0, \'' . $this->modx->lexicon('template_empty') . '\', ResourceTemplate.templatename)'
41 | ]);
42 | $c->prepare();
43 | $c->stmt->execute();
44 |
45 | $template['default_for_templates'] = $c->stmt->fetchAll(\PDO::FETCH_COLUMN, 0);
46 |
47 | return $template;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/Import.php:
--------------------------------------------------------------------------------
1 | failure();
15 | }
16 |
17 | $templates = file_get_contents($_FILES['file']['tmp_name']);
18 |
19 | $templates = json_decode($templates, true);
20 |
21 | if (!is_array($templates)) {
22 | return $this->failure();
23 | }
24 |
25 | $importTemplates = $this->getProperty('template', null);
26 |
27 | foreach ($templates as $template) {
28 | if (!in_array($template['name'], $importTemplates) || $importTemplates === null) continue;
29 |
30 | $exists = $this->modx->getCount(CollectionTemplate::class, ['name' => $template['name']]);
31 | if ($exists > 0) {
32 | $newName = $template['name'] . ' Imported';
33 | $exists = $this->modx->getCount(CollectionTemplate::class, ['name' => $newName]);
34 |
35 | $i = 0;
36 | $testName = $newName;
37 | while ($exists > 0) {
38 | $testName = $newName . $i;
39 | $exists = $this->modx->getCount(CollectionTemplate::class, ['name' => $testName]);
40 | $i++;
41 | }
42 |
43 | $template['name'] = $testName;
44 | }
45 |
46 | /** @var CollectionTemplate $tplObject */
47 | $tplObject = $this->modx->newObject(CollectionTemplate::class);
48 | $tplObject->fromArray($template);
49 |
50 | $columns = array();
51 | foreach ($template['columns'] as $column) {
52 | /** @var CollectionTemplateColumn $colObject */
53 | $colObject = $this->modx->newObject(CollectionTemplateColumn::class);
54 | $colObject->fromArray($column);
55 |
56 | $columns[] = $colObject;
57 | }
58 |
59 | $tplObject->addMany($columns, 'Columns');
60 | $tplObject->save();
61 | }
62 |
63 | return $this->success();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/Remove.php:
--------------------------------------------------------------------------------
1 | modx->getCount($this->classKey);
17 | if ($templatesCount == 1) {
18 | return $this->modx->lexicon('collections.err.template_remove_last');
19 | }
20 |
21 | if ($this->object->global_template == 1) {
22 | return $this->modx->lexicon('collections.err.template_remove_global');
23 | }
24 |
25 | return parent::beforeRemove();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/core/components/collections/src/Processors/Template/UpdateFromGrid.php:
--------------------------------------------------------------------------------
1 | getProperty('data');
18 | if (empty($data)) return $this->modx->lexicon('invalid_data');
19 | $data = json_decode($data, true);
20 | if (empty($data)) return $this->modx->lexicon('invalid_data');
21 |
22 | if (isset($data['id'])) {
23 | $this->setProperty('id', $data['id']);
24 | }
25 |
26 | if (isset($data['name'])) {
27 | $this->setProperty('name', $data['name']);
28 | }
29 |
30 | if (isset($data['description'])) {
31 | $this->setProperty('description', $data['description']);
32 | }
33 |
34 | if (isset($data['global_template'])) {
35 | $this->setProperty('global_template', $data['global_template']);
36 | }
37 |
38 | $this->unsetProperty('data');
39 |
40 | return parent::initialize();
41 | }
42 |
43 | public function beforeSet()
44 | {
45 | $name = $this->getProperty('name');
46 |
47 | if (empty($name)) {
48 | $this->addFieldError('name', $this->modx->lexicon('collections.err.template_ns_name'));
49 | } else {
50 | if ($this->modx->getCount($this->classKey, ['name' => $name, 'id:!=' => $this->object->id]) > 0) {
51 | $this->addFieldError('name', $this->modx->lexicon('collections.err.template_ae_name'));
52 | }
53 | }
54 |
55 | $global = $this->getProperty('global_template');
56 |
57 | if ($global == false) {
58 | $templatesCount = $this->modx->getCount(CollectionTemplate::class, ['global_template' => 1, 'id:!=' => $this->object->id]);
59 | if ($templatesCount == 0) {
60 | $this->setProperty('global_template', true);
61 | }
62 | }
63 |
64 | return parent::beforeSet();
65 | }
66 |
67 | public function afterSave()
68 | {
69 | $global = $this->getProperty('global_template');
70 |
71 | if ($global == true) {
72 | $this->modx->updateCollection(CollectionTemplate::class, ['global_template' => false], ['id:!=' => $this->object->id]);
73 | }
74 |
75 | return parent::afterSave();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/core/components/collections/src/Utils.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/core/components/collections/templates/template/template.tpl:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/crowdin.yml:
--------------------------------------------------------------------------------
1 | files:
2 | - source: /core/components/collections/lexicon/en/*.inc.php
3 | translation: >-
4 | /core/components/collections/lexicon/%two_letters_code%/%original_file_name%
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "collections",
3 | "version": "3.7.0",
4 | "description": "",
5 | "main": "./_build/assets/index.js",
6 | "scripts": {
7 | "build": "webpack --progress --mode production",
8 | "dev": "webpack --watch --progress --mode development"
9 | },
10 | "license": "MIT",
11 | "files": [
12 | "LICENSE",
13 | "README.md",
14 | "index.js",
15 | "lib",
16 | "dist"
17 | ],
18 | "devDependencies": {
19 | "@babel/core": "^7.24.9",
20 | "@babel/plugin-transform-class-properties": "^7.24.7",
21 | "@babel/preset-env": "^7.24.8",
22 | "autoprefixer": "^10.4.17",
23 | "babel-loader": "^9.1.3",
24 | "css-loader": "^6.9.1",
25 | "cssnano": "^6.0.3",
26 | "mini-css-extract-plugin": "^2.8.1",
27 | "path-browserify": "^1.0.1",
28 | "postcss": "^8.4.38",
29 | "postcss-inline-svg": "^6.0.0",
30 | "postcss-loader": "^7.3.4",
31 | "postcss-svgo": "^6.0.3",
32 | "sass": "^1.70.0",
33 | "sass-loader": "^13.3.3",
34 | "ts-loader": "^9.5.1",
35 | "typescript": "^5.4.4",
36 | "url": "^0.11.3",
37 | "webpack": "^5.90.0",
38 | "webpack-cli": "^5.1.4"
39 | },
40 | "library": {
41 | "name": "FredCollections",
42 | "entry": "index.js",
43 | "dist-web": "fred_integration.js"
44 | },
45 | "dependencies": {
46 | "@types/tabulator-tables": "^5.6.0",
47 | "babel-plugin-add-module-exports": "^1.0.4",
48 | "tabulator-tables": "^5.6.1"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('postcss-inline-svg')({
4 | paths: ['./_build/assets/images']
5 | }),
6 | require('postcss-svgo'),
7 | require('autoprefixer'),
8 | require('cssnano'),
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./_build/assets/js",
4 | "paths": {
5 | },
6 | "outDir": "./assets/components/collections/web",
7 | "noImplicitAny": false,
8 | "moduleResolution": "node",
9 | "module": "es6",
10 | "target": "es6",
11 | "allowJs": true,
12 | "allowSyntheticDefaultImports": true
13 | },
14 | "include": [
15 | "_build/assets/js/**/*"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const MiniCssExtractPlugin = require("mini-css-extract-plugin");
3 |
4 | module.exports = (env, options) => {
5 | const isProd = options.mode === 'production';
6 |
7 | return {
8 | mode: options.mode,
9 | devtool: isProd ? false : 'source-map',
10 |
11 | entry: [
12 | './_build/assets/sass/collections.scss',
13 | './_build/assets/js/index.ts'
14 | ],
15 |
16 | output: {
17 | path: path.resolve(__dirname, './assets/components/collections/web'),
18 | library: 'FredCollections',
19 | libraryTarget: 'umd',
20 | libraryExport: 'default',
21 | filename: 'fred_integration.js'
22 | },
23 |
24 | module: {
25 | rules: [
26 | {
27 | test: /\.ts$/,
28 | use: 'ts-loader',
29 | exclude: /node_modules/,
30 | },
31 | {
32 | test: /\.js$/,
33 | exclude: /(node_modules)/,
34 | use: {
35 | loader: 'babel-loader'
36 | }
37 | },
38 | {
39 | test: /\.(sa|sc|c)ss$/,
40 | use: [
41 | {
42 | loader: MiniCssExtractPlugin.loader
43 | },
44 | {
45 | loader: "css-loader",
46 | options: {
47 | url: false,
48 | sourceMap: true
49 | }
50 | },
51 | {
52 | loader: "postcss-loader"
53 | },
54 | {
55 | loader: "sass-loader",
56 | options: {
57 | implementation: require("sass")
58 | }
59 | }
60 | ]
61 | }
62 | ]
63 | },
64 |
65 | resolve: {
66 | alias: {
67 | },
68 | extensions: [ '.ts', '.js' ],
69 | fallback: {
70 | "path": require.resolve("path-browserify"),
71 | "url": require.resolve("url/"),
72 | }
73 | },
74 |
75 | plugins: [
76 | new MiniCssExtractPlugin({
77 | filename: "fred_integration.css"
78 | })
79 | ]
80 | };
81 | };
82 |
--------------------------------------------------------------------------------