├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ ├── bug_report.yaml
│ ├── config.yml
│ ├── feature_request.yaml
│ └── support_request.yaml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── composer.json
├── config.codekit3
├── docs
├── .sidebar.json
├── README.md
├── feature-tour
│ └── usage.md
└── get-started
│ ├── installation-setup.md
│ └── requirements.md
└── src
├── ManyToMany.php
├── assetbundles
└── field
│ ├── ManyToManyFieldAsset.php
│ ├── dist
│ └── many-to-many.js
│ └── src
│ └── many-to-many.js
├── base
└── PluginTrait.php
├── fields
└── ManyToManyField.php
├── icon-mask.svg
├── icon.svg
├── services
└── Service.php
├── templates
└── field
│ ├── input.html
│ └── settings.html
└── translations
└── en
└── manytomany.php
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: verbb
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yaml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: Create a report to help us improve.
3 | body:
4 | - type: markdown
5 | attributes:
6 | value: |
7 | Before you send through your bug report, please ensure you have taken these steps first:
8 |
9 | ✅ I‘ve searched open and closed issues.
10 |
11 | - type: textarea
12 | id: bug-description
13 | attributes:
14 | label: Describe the bug
15 | description: Describe the bug and what behaviour you expect if the bug is fixed.
16 | placeholder: "I have an issue where..."
17 | validations:
18 | required: true
19 | - type: textarea
20 | id: steps-to-reproduce
21 | attributes:
22 | label: Steps to reproduce
23 | description: Detail how we can reproduce this issue.
24 | value: |
25 | 1.
26 | 2.
27 | validations:
28 | required: true
29 | - type: input
30 | id: craft-version
31 | attributes:
32 | label: Craft CMS version
33 | description: What version of Craft CMS you‘re using. **Do not write "latest"**.
34 | validations:
35 | required: true
36 | - type: input
37 | id: plugin-version
38 | attributes:
39 | label: Plugin version
40 | description: What version of the plugin you‘re using. **Do not write "latest"**.
41 | validations:
42 | required: true
43 | - type: input
44 | id: multi-site
45 | attributes:
46 | label: Multi-site?
47 | description: Whether your install is a multi-site.
48 | placeholder: |
49 | "Yes" or "No"
50 | - type: textarea
51 | id: additional-context
52 | attributes:
53 | label: Additional context
54 | description: Provide any additional information you think might be useful. The more information you provide the easier it‘ll be for use to fix this bug!
55 | placeholder: |
56 | "I also have X plugin installed..." or "This only happens on production..."
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Craft Discord
4 | url: https://craftcms.com/discord
5 | about: Community discussion and support.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yaml:
--------------------------------------------------------------------------------
1 | name: Feature Request
2 | description: Suggest an idea or enhancement.
3 | labels: 'feature request'
4 | body:
5 | - type: textarea
6 | id: feature-description
7 | attributes:
8 | label: What are you trying to do?
9 | description: A description of what you want to happen.
10 | placeholder: "I would like to see..."
11 | validations:
12 | required: true
13 | - type: textarea
14 | id: proposed-solution
15 | attributes:
16 | label: What's your proposed solution?
17 | description: A description of how you think this could be solved, including any alternatives that you considered.
18 | validations:
19 | required: true
20 | - type: textarea
21 | id: additional-context
22 | attributes:
23 | label: Additional context
24 | description: Add any other context or screenshots about the feature request here.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/support_request.yaml:
--------------------------------------------------------------------------------
1 | name: Question
2 | description: Ask a question about this plugin. DO NOT use this to submit bug reports.
3 | labels: 'question'
4 | body:
5 | - type: markdown
6 | attributes:
7 | value: |
8 | Before you send through your question, please ensure you have taken these steps first:
9 |
10 | ✅ I‘ve searched open and closed issues.
11 | ✅ This is not a bug report, just a general question.
12 |
13 | - type: textarea
14 | id: question
15 | attributes:
16 | label: Question
17 | description: A question about the plugin or how it works.
18 | placeholder: "Is it possible to do..."
19 | validations:
20 | required: true
21 | - type: textarea
22 | id: additional-context
23 | attributes:
24 | label: Additional context
25 | description: Add any other context or screenshots about your question here.
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # CRAFT ENVIRONMENT
2 | .env.php
3 | .env.sh
4 | .env
5 |
6 | # COMPOSER
7 | /vendor
8 |
9 | # BUILD FILES
10 | /bower_components/*
11 | /node_modules/*
12 | /build/*
13 | /yarn-error.log
14 |
15 | # MISC FILES
16 | .cache
17 | .DS_Store
18 | .idea
19 | .project
20 | .settings
21 | .map
22 | *.esproj
23 | *.sublime-workspace
24 | *.sublime-project
25 | *.tmproj
26 | *.tmproject
27 | .vscode/*
28 | !.vscode/settings.json
29 | !.vscode/tasks.json
30 | !.vscode/launch.json
31 | !.vscode/extensions.json
32 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 4.0.2 - 2025-02-05
4 |
5 | ### Fixed
6 | - Craft 5 updates and fixes.
7 |
8 | ## 4.0.1 - 2024-09-07
9 |
10 | ### Added
11 | - Add `valueType()` to field. (thanks @markhuot).
12 |
13 | ### Fixed
14 | - Fix `getTableAttributeHtml` not using default CP rendering. (thanks @regularlabs).
15 |
16 | ## 4.0.0 - 2024-05-13
17 |
18 | ### Changed
19 | - Now requires PHP `8.2.0+`.
20 | - Now requires Craft `5.0.0+`.
21 |
22 | ## 3.0.5 - 2024-09-07
23 |
24 | ### Added
25 | - Add `valueType()` to field. (thanks @markhuot).
26 |
27 | ### Fixed
28 | - Fix `getTableAttributeHtml` not using default CP rendering. (thanks @regularlabs).
29 |
30 | ## 3.0.4 - 2023-10-05
31 |
32 | ### Fixed
33 | - Fix GraphQL queries not allowing arguments on field.
34 |
35 | ## 3.0.3 - 2023-09-14
36 |
37 | ### Fixed
38 | - Fix inverse relations not working.
39 |
40 | ## 3.0.2 - 2022-12-06
41 |
42 | ### Fixed
43 | - Migrate field settings to uid instead of ids.
44 |
45 | ## 3.0.1 - 2022-11-30
46 |
47 | ### Fixed
48 | - Fix fields not migrating to new package name correctly.
49 |
50 | ## 3.0.0 - 2022-11-24
51 |
52 | ### Changed
53 | - Now requires PHP `8.0.2+`.
54 | - Now requires Craft `4.0.0+`.
55 |
56 | ## 2.0.2 - 2022-12-06
57 |
58 | ### Fixed
59 | - Migrate field settings to uid instead of ids.
60 |
61 | ## 2.0.1 - 2022-11-30
62 |
63 | ### Fixed
64 | - Fix fields not migrating to new package name correctly.
65 |
66 | ## 2.0.0 - 2022-11-24
67 |
68 | > {note} The plugin’s package name has changed to `verbb/many-to-many`. Many To Many will need be updated to 2.0 from a terminal, by running `composer require verbb/many-to-many && composer remove page-8/craft-manytomany`.
69 |
70 | ### Added
71 | - Add GraphQL support for querying the field.
72 | - Add “Selection Label” to field settings.
73 | - Add preview in CP content index table. (thanks @svale).
74 |
75 | ### Changed
76 | - Migration to `verbb/many-to-many`.
77 | - Now requires Craft 3.7+.
78 | - Update input.js to use boolean value. (thanks @matthisamoto).
79 | - Refactor field to use `normalizeValue` so it has a proper value for front-end, control panel, element index, and GraphQL.
80 |
81 | ## 1.0.2.2 - 2018-05-17
82 |
83 | ### Fixed
84 | - Injected Javascript HTML should reflect updated template HTML.
85 |
86 | ## 1.0.2.1 - 2018-05-15
87 |
88 | ### Added
89 | - Update input template to better display elements.
90 |
91 | ## 0.1.2 - 2016-06-15
92 |
93 | ### Added
94 | - Translatable text.
95 |
96 | ## 0.1.1
97 |
98 | ### Added
99 | - Optimized the cache control. Instead of clearing all Entry types from the cache, just clears records related to the changed element.
100 |
101 | ## 0.1.0
102 |
103 | ### Added
104 | - Initial Release.
105 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2022 Verbb, 2014 Page 8
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | Many to Many for Craft CMS
3 |
4 | Many to Many is a Craft CMS plugin to enable two-way relationships from either of the entries that belong to the association. For example, if you have a recipe with many ingredients, and ingredients that belong to many recipes, you can manage the relationship from either the Recipe's entry or the Ingredient's entry.
5 |
6 | ## Documentation
7 | Visit the [Many to Many Plugin page](https://verbb.io/craft-plugins/many-to-many) for all documentation, guides, pricing and developer resources.
8 |
9 | ## Credit & Thanks
10 | Originally created by [Oberon](https://www.oberon.nl) and [page.works](https://www.page.works).
11 |
12 | ## Support
13 | Get in touch with us via the [Many to Many Support page](https://verbb.io/craft-plugins/many-to-many/support) or by [creating a Github issue](https://github.com/verbb/many-to-many/issues)
14 |
15 | ## Sponsor
16 | Many to Many is licensed under the MIT license, meaning it will always be free and open source – we love free stuff! If you'd like to show your support to the plugin regardless, [Sponsor](https://github.com/sponsors/verbb) development.
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "verbb/many-to-many",
3 | "description": "A field type to manage relationships from both sides.",
4 | "type": "craft-plugin",
5 | "version": "4.0.2",
6 | "keywords": [
7 | "craft",
8 | "cms",
9 | "craftcms",
10 | "craft-plugin",
11 | "fieldtype",
12 | "entries"
13 | ],
14 | "support": {
15 | "email": "support@verbb.io",
16 | "issues": "https://github.com/verbb/many-to-many/issues?state=open",
17 | "source": "https://github.com/verbb/many-to-many",
18 | "docs": "https://github.com/verbb/many-to-many",
19 | "rss": "https://github.com/verbb/many-to-many/commits/v2.atom"
20 | },
21 | "license": "MIT",
22 | "authors": [
23 | {
24 | "name": "Verbb",
25 | "homepage": "https://verbb.io"
26 | },
27 | {
28 | "name": "Page 8",
29 | "homepage": "http://page-8.com/"
30 | },
31 | {
32 | "name": "Oberon Amsterdam",
33 | "homepage": "https://www.oberon.nl"
34 | }
35 | ],
36 | "require": {
37 | "craftcms/cms": "^5.0.0",
38 | "verbb/base": "^3.0.0"
39 | },
40 | "autoload": {
41 | "psr-4": {
42 | "verbb\\manytomany\\": "src/"
43 | }
44 | },
45 | "extra": {
46 | "name": "Many to Many",
47 | "handle": "manytomany",
48 | "changelogUrl": "https://raw.githubusercontent.com/verbb/many-to-many/craft-5/CHANGELOG.md",
49 | "class": "verbb\\manytomany\\ManyToMany"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/config.codekit3:
--------------------------------------------------------------------------------
1 | {
2 | "AAInfo" : "This is a CodeKit 3 project config file. EDITING THIS FILE IS A POOR LIFE DECISION. Doing so may cause CodeKit to crash and\/or corrupt your project. Several critical values in this file are 64-bit integers, which JavaScript JSON parsers do not support because JavaScript cannot handle 64-bit integers. These values will be corrupted if the file is parsed with JavaScript. This file is not backwards-compatible with CodeKit 1 or 2. For details, see https:\/\/codekitapp.com\/",
3 | "buildSteps" : [
4 | {
5 | "name" : "Process All Remaining Files and Folders",
6 | "stepType" : 1,
7 | "uuidString" : "1B985AEF-BD59-4457-8269-EEBFCD342117"
8 | }
9 | ],
10 | "creatorBuild" : "34518",
11 | "files" : {
12 | "\/.github\/FUNDING.yml" : {
13 | "cB" : 0,
14 | "ft" : 8192,
15 | "hM" : 0,
16 | "oA" : 0,
17 | "oAP" : "\/.github\/FUNDING.yml",
18 | "oF" : 0
19 | },
20 | "\/.github\/ISSUE_TEMPLATE\/bug_report.yaml" : {
21 | "cB" : 0,
22 | "ft" : 8192,
23 | "hM" : 0,
24 | "oA" : 0,
25 | "oAP" : "\/.github\/ISSUE_TEMPLATE\/bug_report.yaml",
26 | "oF" : 0
27 | },
28 | "\/.github\/ISSUE_TEMPLATE\/config.yml" : {
29 | "cB" : 0,
30 | "ft" : 8192,
31 | "hM" : 0,
32 | "oA" : 0,
33 | "oAP" : "\/.github\/ISSUE_TEMPLATE\/config.yml",
34 | "oF" : 0
35 | },
36 | "\/.github\/ISSUE_TEMPLATE\/feature_request.yaml" : {
37 | "cB" : 0,
38 | "ft" : 8192,
39 | "hM" : 0,
40 | "oA" : 0,
41 | "oAP" : "\/.github\/ISSUE_TEMPLATE\/feature_request.yaml",
42 | "oF" : 0
43 | },
44 | "\/.github\/ISSUE_TEMPLATE\/support_request.yaml" : {
45 | "cB" : 0,
46 | "ft" : 8192,
47 | "hM" : 0,
48 | "oA" : 0,
49 | "oAP" : "\/.github\/ISSUE_TEMPLATE\/support_request.yaml",
50 | "oF" : 0
51 | },
52 | "\/.gitignore" : {
53 | "cB" : 0,
54 | "ft" : 8192,
55 | "hM" : 0,
56 | "oA" : 0,
57 | "oAP" : "\/.gitignore",
58 | "oF" : 0
59 | },
60 | "\/CHANGELOG.md" : {
61 | "cB" : 0,
62 | "cS" : 0,
63 | "eF" : 1,
64 | "eL" : 1,
65 | "ema" : 1,
66 | "eSQ" : 1,
67 | "ft" : 4096,
68 | "hM" : 0,
69 | "oA" : 1,
70 | "oAP" : "\/CHANGELOG.html",
71 | "oF" : 0,
72 | "oFM" : 0,
73 | "oS" : 0,
74 | "pHT" : 0,
75 | "pME" : 1,
76 | "rFN" : 0,
77 | "uCM" : 0
78 | },
79 | "\/composer.json" : {
80 | "ft" : 524288,
81 | "oA" : 1,
82 | "oAP" : "\/composer-min.json",
83 | "oF" : 0,
84 | "oO" : 1,
85 | "oS" : 1
86 | },
87 | "\/docs\/.sidebar.json" : {
88 | "ft" : 524288,
89 | "oA" : 1,
90 | "oAP" : "\/docs\/.sidebar-min.json",
91 | "oF" : 0,
92 | "oO" : 1,
93 | "oS" : 1
94 | },
95 | "\/docs\/feature-tour\/usage.md" : {
96 | "cB" : 0,
97 | "cS" : 0,
98 | "eF" : 1,
99 | "eL" : 1,
100 | "ema" : 1,
101 | "eSQ" : 1,
102 | "ft" : 4096,
103 | "hM" : 0,
104 | "oA" : 1,
105 | "oAP" : "\/docs\/feature-tour\/usage.html",
106 | "oF" : 0,
107 | "oFM" : 0,
108 | "oS" : 0,
109 | "pHT" : 0,
110 | "pME" : 1,
111 | "rFN" : 0,
112 | "uCM" : 0
113 | },
114 | "\/docs\/get-started\/installation-setup.md" : {
115 | "cB" : 0,
116 | "cS" : 0,
117 | "eF" : 1,
118 | "eL" : 1,
119 | "ema" : 1,
120 | "eSQ" : 1,
121 | "ft" : 4096,
122 | "hM" : 0,
123 | "oA" : 1,
124 | "oAP" : "\/docs\/get-started\/installation-setup.html",
125 | "oF" : 0,
126 | "oFM" : 0,
127 | "oS" : 0,
128 | "pHT" : 0,
129 | "pME" : 1,
130 | "rFN" : 0,
131 | "uCM" : 0
132 | },
133 | "\/docs\/get-started\/requirements.md" : {
134 | "cB" : 0,
135 | "cS" : 0,
136 | "eF" : 1,
137 | "eL" : 1,
138 | "ema" : 1,
139 | "eSQ" : 1,
140 | "ft" : 4096,
141 | "hM" : 0,
142 | "oA" : 1,
143 | "oAP" : "\/docs\/get-started\/requirements.html",
144 | "oF" : 0,
145 | "oFM" : 0,
146 | "oS" : 0,
147 | "pHT" : 0,
148 | "pME" : 1,
149 | "rFN" : 0,
150 | "uCM" : 0
151 | },
152 | "\/docs\/README.md" : {
153 | "cB" : 0,
154 | "cS" : 0,
155 | "eF" : 1,
156 | "eL" : 1,
157 | "ema" : 1,
158 | "eSQ" : 1,
159 | "ft" : 4096,
160 | "hM" : 0,
161 | "oA" : 1,
162 | "oAP" : "\/docs\/README.html",
163 | "oF" : 0,
164 | "oFM" : 0,
165 | "oS" : 0,
166 | "pHT" : 0,
167 | "pME" : 1,
168 | "rFN" : 0,
169 | "uCM" : 0
170 | },
171 | "\/LICENSE.md" : {
172 | "cB" : 0,
173 | "cS" : 0,
174 | "eF" : 1,
175 | "eL" : 1,
176 | "ema" : 1,
177 | "eSQ" : 1,
178 | "ft" : 4096,
179 | "hM" : 0,
180 | "oA" : 1,
181 | "oAP" : "\/LICENSE.html",
182 | "oF" : 0,
183 | "oFM" : 0,
184 | "oS" : 0,
185 | "pHT" : 0,
186 | "pME" : 1,
187 | "rFN" : 0,
188 | "uCM" : 0
189 | },
190 | "\/README.md" : {
191 | "cB" : 0,
192 | "cS" : 0,
193 | "eF" : 1,
194 | "eL" : 1,
195 | "ema" : 1,
196 | "eSQ" : 1,
197 | "ft" : 4096,
198 | "hM" : 0,
199 | "oA" : 1,
200 | "oAP" : "\/README.html",
201 | "oF" : 0,
202 | "oFM" : 0,
203 | "oS" : 0,
204 | "pHT" : 0,
205 | "pME" : 1,
206 | "rFN" : 0,
207 | "uCM" : 0
208 | },
209 | "\/src\/assetbundles\/field\/dist\/many-to-many.js" : {
210 | "bF" : 0,
211 | "ft" : 64,
212 | "ma" : 1,
213 | "mi" : 1,
214 | "oA" : 0,
215 | "oAP" : "\/src\/assetbundles\/dist\/js\/many-to-many.js",
216 | "oF" : 0,
217 | "sC" : 0,
218 | "tS" : 0
219 | },
220 | "\/src\/assetbundles\/field\/ManyToManyFieldAsset.php" : {
221 | "cB" : 0,
222 | "ft" : 8192,
223 | "hM" : 0,
224 | "oA" : 0,
225 | "oAP" : "\/src\/assetbundles\/field\/ManyToManyFieldAsset.php",
226 | "oF" : 0
227 | },
228 | "\/src\/assetbundles\/field\/src\/many-to-many.js" : {
229 | "bF" : 0,
230 | "ft" : 64,
231 | "ma" : 1,
232 | "mi" : 1,
233 | "oA" : 0,
234 | "oAP" : "\/src\/assetbundles\/dist\/js\/many-to-many.js",
235 | "oF" : 0,
236 | "sC" : 0,
237 | "tS" : 0
238 | },
239 | "\/src\/base\/PluginTrait.php" : {
240 | "cB" : 0,
241 | "ft" : 8192,
242 | "hM" : 0,
243 | "oA" : 0,
244 | "oAP" : "\/src\/base\/PluginTrait.php",
245 | "oF" : 0
246 | },
247 | "\/src\/fields\/ManyToManyField.php" : {
248 | "cB" : 0,
249 | "ft" : 8192,
250 | "hM" : 0,
251 | "oA" : 0,
252 | "oAP" : "\/src\/fields\/ManyToManyField.php",
253 | "oF" : 0
254 | },
255 | "\/src\/icon-mask.svg" : {
256 | "ft" : 2097152,
257 | "miP" : 0,
258 | "oA" : 2,
259 | "oAP" : "\/src\/icon-mask.svg",
260 | "oF" : 0,
261 | "opt" : 0,
262 | "plM" : 52780316221407,
263 | "prP" : 0
264 | },
265 | "\/src\/icon.svg" : {
266 | "ft" : 2097152,
267 | "miP" : 0,
268 | "oA" : 2,
269 | "oAP" : "\/src\/icon.svg",
270 | "oF" : 0,
271 | "opt" : 0,
272 | "plM" : 52780316221407,
273 | "prP" : 0
274 | },
275 | "\/src\/ManyToMany.php" : {
276 | "cB" : 0,
277 | "ft" : 8192,
278 | "hM" : 0,
279 | "oA" : 0,
280 | "oAP" : "\/src\/ManyToMany.php",
281 | "oF" : 0
282 | },
283 | "\/src\/services\/Service.php" : {
284 | "cB" : 0,
285 | "ft" : 8192,
286 | "hM" : 0,
287 | "oA" : 0,
288 | "oAP" : "\/src\/services\/Service.php",
289 | "oF" : 0
290 | },
291 | "\/src\/templates\/field\/input.html" : {
292 | "cB" : 0,
293 | "ft" : 8192,
294 | "hM" : 0,
295 | "oA" : 0,
296 | "oAP" : "\/src\/templates\/field\/input.html",
297 | "oF" : 0
298 | },
299 | "\/src\/templates\/field\/settings.html" : {
300 | "cB" : 0,
301 | "ft" : 8192,
302 | "hM" : 0,
303 | "oA" : 0,
304 | "oAP" : "\/src\/templates\/field\/settings.html",
305 | "oF" : 0
306 | },
307 | "\/src\/translations\/en\/manytomany.php" : {
308 | "cB" : 0,
309 | "ft" : 8192,
310 | "hM" : 0,
311 | "oA" : 0,
312 | "oAP" : "\/src\/translations\/en\/manytomany.php",
313 | "oF" : 0
314 | }
315 | },
316 | "hooks" : [
317 |
318 | ],
319 | "manualImportLinks" : {
320 |
321 | },
322 | "projectAttributes" : {
323 | "creationDate" : 718148775.96866202,
324 | "displayValue" : "many-to-many",
325 | "displayValueWasSetByUser" : 0,
326 | "iconImageName" : "brackets-verd",
327 | "iconImageWasSetByUser" : 0
328 | },
329 | "projectSettings" : {
330 | "abortBuildOnError" : 1,
331 | "allowInjectionReloads" : 1,
332 | "alwaysUseExternalServer" : 0,
333 | "animateCSSInjections" : 0,
334 | "autoBuildNewItems" : 1,
335 | "autoprefixerEnableIEGrid" : 0,
336 | "babel7PresetType" : 1,
337 | "babelAllowRCFiles" : 0,
338 | "babelAuxiliaryCommentAfter" : "",
339 | "babelAuxiliaryCommentBefore" : "",
340 | "babelConfigType" : 0,
341 | "babelCustomPluginsList" : "",
342 | "babelCustomPresetsList" : "",
343 | "babelExcludeString" : "\/\\\/node_modules\\\/\/, \/\\\/core-js\\\/\/, \/\\\/bower_components\\\/\/",
344 | "babelInsertModuleIDs" : 0,
345 | "babelModuleID" : "",
346 | "babelNoComments" : 0,
347 | "babelPlugins" : {
348 | "arrow-functions" : {
349 | "active" : 0
350 | },
351 | "async-generator-functions" : {
352 | "active" : 0
353 | },
354 | "async-to-generator" : {
355 | "active" : 0
356 | },
357 | "block-scoped-functions" : {
358 | "active" : 0
359 | },
360 | "block-scoping" : {
361 | "active" : 0
362 | },
363 | "class-properties" : {
364 | "active" : 0
365 | },
366 | "classes" : {
367 | "active" : 0
368 | },
369 | "computed-properties" : {
370 | "active" : 0
371 | },
372 | "decorators" : {
373 | "active" : 0
374 | },
375 | "destructuring" : {
376 | "active" : 0
377 | },
378 | "do-expressions" : {
379 | "active" : 0
380 | },
381 | "dotall-regex" : {
382 | "active" : 0
383 | },
384 | "duplicate-keys" : {
385 | "active" : 0
386 | },
387 | "exponentiation-operator" : {
388 | "active" : 0
389 | },
390 | "export-default-from" : {
391 | "active" : 0
392 | },
393 | "export-namespace-from" : {
394 | "active" : 0
395 | },
396 | "external-helpers" : {
397 | "active" : 0
398 | },
399 | "flow-strip-types" : {
400 | "active" : 0
401 | },
402 | "for-of" : {
403 | "active" : 0
404 | },
405 | "function-bind" : {
406 | "active" : 0
407 | },
408 | "function-name" : {
409 | "active" : 0
410 | },
411 | "function-sent" : {
412 | "active" : 0
413 | },
414 | "inline-consecutive-adds" : {
415 | "active" : 0
416 | },
417 | "inline-environment-variables" : {
418 | "active" : 0
419 | },
420 | "instanceof" : {
421 | "active" : 0
422 | },
423 | "jscript" : {
424 | "active" : 0
425 | },
426 | "literals" : {
427 | "active" : 0
428 | },
429 | "logical-assignment-operators" : {
430 | "active" : 0
431 | },
432 | "member-expression-literals" : {
433 | "active" : 0
434 | },
435 | "merge-sibling-variables" : {
436 | "active" : 0
437 | },
438 | "minify-booleans" : {
439 | "active" : 0
440 | },
441 | "minify-builtins" : {
442 | "active" : 0
443 | },
444 | "minify-constant-folding" : {
445 | "active" : 0
446 | },
447 | "minify-dead-code-elimination" : {
448 | "active" : 0
449 | },
450 | "minify-flip-comparisons" : {
451 | "active" : 0
452 | },
453 | "minify-guarded-expressions" : {
454 | "active" : 0
455 | },
456 | "minify-infinity" : {
457 | "active" : 0
458 | },
459 | "minify-mangle-names" : {
460 | "active" : 0
461 | },
462 | "minify-numeric-literals" : {
463 | "active" : 0
464 | },
465 | "minify-simplify" : {
466 | "active" : 0
467 | },
468 | "minify-type-constructors" : {
469 | "active" : 0
470 | },
471 | "modules-amd" : {
472 | "active" : 0
473 | },
474 | "modules-commonjs" : {
475 | "active" : 0
476 | },
477 | "modules-systemjs" : {
478 | "active" : 0
479 | },
480 | "modules-umd" : {
481 | "active" : 0
482 | },
483 | "named-capturing-groups-regex" : {
484 | "active" : 0
485 | },
486 | "new-target" : {
487 | "active" : 0
488 | },
489 | "node-env-inline" : {
490 | "active" : 0
491 | },
492 | "nullish-coalescing-operator" : {
493 | "active" : 0
494 | },
495 | "numeric-separator" : {
496 | "active" : 0
497 | },
498 | "object-assign" : {
499 | "active" : 0
500 | },
501 | "object-rest-spread" : {
502 | "active" : 0
503 | },
504 | "object-set-prototype-of-to-assign" : {
505 | "active" : 0
506 | },
507 | "object-super" : {
508 | "active" : 0
509 | },
510 | "optional-catch-binding" : {
511 | "active" : 0
512 | },
513 | "optional-chaining" : {
514 | "active" : 0
515 | },
516 | "parameters" : {
517 | "active" : 0
518 | },
519 | "partial-application" : {
520 | "active" : 0
521 | },
522 | "pipeline-operator" : {
523 | "active" : 0
524 | },
525 | "private-methods" : {
526 | "active" : 0
527 | },
528 | "property-literals" : {
529 | "active" : 0
530 | },
531 | "property-mutators" : {
532 | "active" : 0
533 | },
534 | "proto-to-assign" : {
535 | "active" : 0
536 | },
537 | "react-constant-elements" : {
538 | "active" : 0
539 | },
540 | "react-display-name" : {
541 | "active" : 0
542 | },
543 | "react-inline-elements" : {
544 | "active" : 0
545 | },
546 | "react-jsx" : {
547 | "active" : 0
548 | },
549 | "react-jsx-compat" : {
550 | "active" : 0
551 | },
552 | "react-jsx-self" : {
553 | "active" : 0
554 | },
555 | "react-jsx-source" : {
556 | "active" : 0
557 | },
558 | "regenerator" : {
559 | "active" : 0
560 | },
561 | "regexp-constructors" : {
562 | "active" : 0
563 | },
564 | "remove-console" : {
565 | "active" : 0
566 | },
567 | "remove-debugger" : {
568 | "active" : 0
569 | },
570 | "remove-undefined" : {
571 | "active" : 0
572 | },
573 | "reserved-words" : {
574 | "active" : 0
575 | },
576 | "runtime" : {
577 | "active" : 0
578 | },
579 | "shorthand-properties" : {
580 | "active" : 0
581 | },
582 | "simplify-comparison-operators" : {
583 | "active" : 0
584 | },
585 | "spread" : {
586 | "active" : 0
587 | },
588 | "sticky-regex" : {
589 | "active" : 0
590 | },
591 | "strict-mode" : {
592 | "active" : 0
593 | },
594 | "template-literals" : {
595 | "active" : 0
596 | },
597 | "throw-expressions" : {
598 | "active" : 0
599 | },
600 | "typeof-symbol" : {
601 | "active" : 0
602 | },
603 | "undefined-to-void" : {
604 | "active" : 0
605 | },
606 | "unicode-property-regex" : {
607 | "active" : 0
608 | },
609 | "unicode-regex" : {
610 | "active" : 0
611 | }
612 | },
613 | "babelRetainLines" : 0,
614 | "babelUseBuiltInsType" : 0,
615 | "bowerAbbreviatedPath" : "bower_components",
616 | "bowerForceLatestOnConflict" : 1,
617 | "bowerTargetDependencyListType" : 1,
618 | "bowerUseExactVersion" : 0,
619 | "browserRefreshDelay" : 0,
620 | "browserslistString" : ">0.2%, last 2 versions, Firefox ESR, not dead",
621 | "buildEnvironment" : 0,
622 | "buildFolderActive" : 0,
623 | "buildFolderName" : "build",
624 | "cleanBuild" : 1,
625 | "cssoForceMediaMerge" : 0,
626 | "cssoRestructure" : 1,
627 | "environmentVariableEntries" : [
628 | "NODE_ENV:::production"
629 | ],
630 | "esLintConfigFileHandlingType" : 0,
631 | "esLintECMAVersion" : 7,
632 | "esLintEnvironmentsMask" : 1,
633 | "esLintRules" : {
634 | "accessor-pairs" : {
635 | "active" : 0,
636 | "optionString" : "{'setWithoutGet': true, 'getWithoutSet': false, 'enforceForClassMembers': true}"
637 | },
638 | "array-bracket-newline" : {
639 | "active" : 0,
640 | "optionString" : "{'multiline': true, 'minItems': null}"
641 | },
642 | "array-bracket-spacing" : {
643 | "active" : 0,
644 | "optionString" : "'never', {'singleValue': false, 'objectsInArrays': false, 'arraysInArrays': false}"
645 | },
646 | "array-callback-return" : {
647 | "active" : 0,
648 | "optionString" : "{'allowImplicit': false}"
649 | },
650 | "array-element-newline" : {
651 | "active" : 0,
652 | "optionString" : "'always'"
653 | },
654 | "arrow-body-style" : {
655 | "active" : 0,
656 | "optionString" : "'as-needed', {'requireReturnForObjectLiteral': false}"
657 | },
658 | "arrow-parens" : {
659 | "active" : 0,
660 | "optionString" : "'always'"
661 | },
662 | "arrow-spacing" : {
663 | "active" : 0,
664 | "optionString" : "{'before': true, 'after': true}"
665 | },
666 | "block-scoped-var" : {
667 | "active" : 0
668 | },
669 | "block-spacing" : {
670 | "active" : 0,
671 | "optionString" : "'always'"
672 | },
673 | "brace-style" : {
674 | "active" : 0,
675 | "optionString" : "'1tbs', {'allowSingleLine': true}"
676 | },
677 | "camelcase" : {
678 | "active" : 0,
679 | "optionString" : "{'properties': 'always', 'ignoreDestructuring': false, 'ignoreImports': false}"
680 | },
681 | "capitalized-comments" : {
682 | "active" : 0,
683 | "optionString" : "'always', {'ignoreInlineComments': false, 'ignoreConsecutiveComments': false}"
684 | },
685 | "class-methods-use-this" : {
686 | "active" : 0,
687 | "optionString" : "{'exceptMethods': [], 'enforceForClassFields': true}"
688 | },
689 | "comma-dangle" : {
690 | "active" : 1,
691 | "optionString" : "'never'"
692 | },
693 | "comma-spacing" : {
694 | "active" : 0,
695 | "optionString" : "{'before': false, 'after': true}"
696 | },
697 | "comma-style" : {
698 | "active" : 0,
699 | "optionString" : "'last'"
700 | },
701 | "complexity" : {
702 | "active" : 0,
703 | "optionString" : "20"
704 | },
705 | "computed-property-spacing" : {
706 | "active" : 0,
707 | "optionString" : "'never', {'enforceForClassMembers': true}"
708 | },
709 | "consistent-return" : {
710 | "active" : 0,
711 | "optionString" : "{'treatUndefinedAsUnspecified': false}"
712 | },
713 | "consistent-this" : {
714 | "active" : 0,
715 | "optionString" : "'that'"
716 | },
717 | "constructor-super" : {
718 | "active" : 1
719 | },
720 | "curly" : {
721 | "active" : 0,
722 | "optionString" : "'all'"
723 | },
724 | "default-case" : {
725 | "active" : 0
726 | },
727 | "default-case-last" : {
728 | "active" : 0
729 | },
730 | "default-param-last" : {
731 | "active" : 0
732 | },
733 | "dot-location" : {
734 | "active" : 0,
735 | "optionString" : "'object'"
736 | },
737 | "dot-notation" : {
738 | "active" : 0,
739 | "optionString" : "{'allowKeywords': false}"
740 | },
741 | "eol-last" : {
742 | "active" : 0,
743 | "optionString" : "'always'"
744 | },
745 | "eqeqeq" : {
746 | "active" : 0,
747 | "optionString" : "'always', {'null': 'always'}"
748 | },
749 | "for-direction" : {
750 | "active" : 1
751 | },
752 | "func-call-spacing" : {
753 | "active" : 0,
754 | "optionString" : "'never'"
755 | },
756 | "func-name-matching" : {
757 | "active" : 0,
758 | "optionString" : "'always', {'considerPropertyDescriptor': false, 'includeCommonJSModuleExports': false}"
759 | },
760 | "func-names" : {
761 | "active" : 0,
762 | "optionString" : "'always', {'generators': 'always'}"
763 | },
764 | "func-style" : {
765 | "active" : 0,
766 | "optionString" : "'expression'"
767 | },
768 | "function-call-argument-newline" : {
769 | "active" : 0,
770 | "optionString" : "'always'"
771 | },
772 | "function-paren-newline" : {
773 | "active" : 0,
774 | "optionString" : "'multiline'"
775 | },
776 | "generator-star-spacing" : {
777 | "active" : 0,
778 | "optionString" : "{'before': true, 'after': false}"
779 | },
780 | "getter-return" : {
781 | "active" : 1,
782 | "optionString" : "{'allowImplicit': false}"
783 | },
784 | "grouped-accessor-pairs" : {
785 | "active" : 0,
786 | "optionString" : "'anyOrder'"
787 | },
788 | "guard-for-in" : {
789 | "active" : 0
790 | },
791 | "id-denylist" : {
792 | "active" : 0,
793 | "optionString" : "'data', 'err', 'e', 'cb', 'callback'"
794 | },
795 | "id-length" : {
796 | "active" : 0,
797 | "optionString" : "{'min': 2, 'max': 1000, 'properties': 'always', 'exceptions': ['x', 'i', 'y']}"
798 | },
799 | "id-match" : {
800 | "active" : 0,
801 | "optionString" : "'^[a-z]+([A-Z][a-z]+)*$', {'properties': false, 'onlyDeclarations': true, 'ignoreDestructuring': false}"
802 | },
803 | "implicit-arrow-linebreak" : {
804 | "active" : 0,
805 | "optionString" : "'beside'"
806 | },
807 | "indent" : {
808 | "active" : 0,
809 | "optionString" : "4, {'SwitchCase': 0, 'VariableDeclarator': 1, 'outerIIFEBody': 1 }"
810 | },
811 | "init-declarations" : {
812 | "active" : 0,
813 | "optionString" : "'always', {'ignoreForLoopInit': true}"
814 | },
815 | "jsx-quotes" : {
816 | "active" : 0,
817 | "optionString" : "'prefer-double'"
818 | },
819 | "key-spacing" : {
820 | "active" : 0,
821 | "optionString" : "{'singleLine': {'beforeColon': false, 'afterColon': true, 'mode':'strict'}, 'multiLine': {'beforeColon': false, 'afterColon': true, 'align': 'value', 'mode':'minimum'}}"
822 | },
823 | "keyword-spacing" : {
824 | "active" : 0,
825 | "optionString" : "{'before': true, 'after': true, 'overrides': {}}"
826 | },
827 | "line-comment-position" : {
828 | "active" : 0,
829 | "optionString" : "{'position': 'above'}"
830 | },
831 | "linebreak-style" : {
832 | "active" : 0,
833 | "optionString" : "'unix'"
834 | },
835 | "lines-around-comment" : {
836 | "active" : 0,
837 | "optionString" : "{'beforeBlockComment': true}"
838 | },
839 | "lines-between-class-members" : {
840 | "active" : 0,
841 | "optionString" : "'always', {exceptAfterSingleLine: false}"
842 | },
843 | "logical-assignment-operators" : {
844 | "active" : 0,
845 | "optionString" : "'always', {'enforceForIfStatements': false}"
846 | },
847 | "max-classes-per-file" : {
848 | "active" : 0,
849 | "optionString" : "{'ignoreExpressions': false, 'max': 1}"
850 | },
851 | "max-depth" : {
852 | "active" : 0,
853 | "optionString" : "{'max': 4}"
854 | },
855 | "max-len" : {
856 | "active" : 0,
857 | "optionString" : "{'code': 80, 'comments': 80, 'tabWidth': 4, 'ignoreUrls': true, 'ignoreStrings': true, 'ignoreTemplateLiterals': true, 'ignoreRegExpLiterals': true}"
858 | },
859 | "max-lines" : {
860 | "active" : 0,
861 | "optionString" : "{'max': 300, 'skipBlankLines': true, 'skipComments': true}"
862 | },
863 | "max-lines-per-function" : {
864 | "active" : 0,
865 | "optionString" : "{'max': 50, 'skipBlankLines': true, 'skipComments': true, 'IIFEs': false}"
866 | },
867 | "max-nested-callbacks" : {
868 | "active" : 0,
869 | "optionString" : "{'max': 10}"
870 | },
871 | "max-params" : {
872 | "active" : 0,
873 | "optionString" : "{'max': 4}"
874 | },
875 | "max-statements" : {
876 | "active" : 0,
877 | "optionString" : "{'max': 10}, {'ignoreTopLevelFunctions': true}"
878 | },
879 | "max-statements-per-line" : {
880 | "active" : 0,
881 | "optionString" : "{'max': 1}"
882 | },
883 | "multiline-comment-style" : {
884 | "active" : 0,
885 | "optionString" : "'starred-block'"
886 | },
887 | "multiline-ternary" : {
888 | "active" : 0,
889 | "optionString" : "'always'"
890 | },
891 | "new-cap" : {
892 | "active" : 0,
893 | "optionString" : "{'newIsCap': true, 'capIsNew': true, 'newIsCapExceptions': [], 'capIsNewExceptions': ['Array', 'Boolean', 'Date', 'Error', 'Function', 'Number', 'Object', 'RegExp', 'String', 'Symbol'], 'properties': true}"
894 | },
895 | "new-parens" : {
896 | "active" : 0,
897 | "optionString" : "'always'"
898 | },
899 | "newline-per-chained-call" : {
900 | "active" : 0,
901 | "optionString" : "{'ignoreChainWithDepth': 2}"
902 | },
903 | "no-alert" : {
904 | "active" : 0
905 | },
906 | "no-array-constructor" : {
907 | "active" : 0
908 | },
909 | "no-async-promise-executor" : {
910 | "active" : 1
911 | },
912 | "no-await-in-loop" : {
913 | "active" : 0
914 | },
915 | "no-bitwise" : {
916 | "active" : 0,
917 | "optionString" : "{'allow': ['~'], 'int32Hint': true}"
918 | },
919 | "no-caller" : {
920 | "active" : 0
921 | },
922 | "no-case-declarations" : {
923 | "active" : 1
924 | },
925 | "no-class-assign" : {
926 | "active" : 1
927 | },
928 | "no-compare-neg-zero" : {
929 | "active" : 0
930 | },
931 | "no-cond-assign" : {
932 | "active" : 1,
933 | "optionString" : "'except-parens'"
934 | },
935 | "no-confusing-arrow" : {
936 | "active" : 0,
937 | "optionString" : "{'allowParens': true, 'onlyOneSimpleParam': false}"
938 | },
939 | "no-console" : {
940 | "active" : 1,
941 | "optionString" : "{'allow': ['warn', 'error']}"
942 | },
943 | "no-const-assign" : {
944 | "active" : 1
945 | },
946 | "no-constant-binary-expression" : {
947 | "active" : 0
948 | },
949 | "no-constant-condition" : {
950 | "active" : 1,
951 | "optionString" : "{'checkLoops': true}"
952 | },
953 | "no-constructor-return" : {
954 | "active" : 0
955 | },
956 | "no-continue" : {
957 | "active" : 0
958 | },
959 | "no-control-regex" : {
960 | "active" : 1
961 | },
962 | "no-debugger" : {
963 | "active" : 1
964 | },
965 | "no-delete-var" : {
966 | "active" : 1
967 | },
968 | "no-div-regex" : {
969 | "active" : 0
970 | },
971 | "no-dupe-args" : {
972 | "active" : 1
973 | },
974 | "no-dupe-class-members" : {
975 | "active" : 1
976 | },
977 | "no-dupe-else-if" : {
978 | "active" : 1
979 | },
980 | "no-dupe-keys" : {
981 | "active" : 1
982 | },
983 | "no-duplicate-case" : {
984 | "active" : 1
985 | },
986 | "no-duplicate-imports" : {
987 | "active" : 0,
988 | "optionString" : "{'includeExports': false}"
989 | },
990 | "no-else-return" : {
991 | "active" : 0
992 | },
993 | "no-empty" : {
994 | "active" : 1,
995 | "optionString" : "{'allowEmptyCatch': false}"
996 | },
997 | "no-empty-character-class" : {
998 | "active" : 1
999 | },
1000 | "no-empty-function" : {
1001 | "active" : 0,
1002 | "optionString" : "{'allow': []}"
1003 | },
1004 | "no-empty-pattern" : {
1005 | "active" : 1
1006 | },
1007 | "no-empty-static-block" : {
1008 | "active" : 0
1009 | },
1010 | "no-eq-null" : {
1011 | "active" : 0
1012 | },
1013 | "no-eval" : {
1014 | "active" : 0,
1015 | "optionString" : "{'allowIndirect': false}"
1016 | },
1017 | "no-ex-assign" : {
1018 | "active" : 1
1019 | },
1020 | "no-extend-native" : {
1021 | "active" : 0,
1022 | "optionString" : "{'exceptions': []}"
1023 | },
1024 | "no-extra-bind" : {
1025 | "active" : 0
1026 | },
1027 | "no-extra-boolean-cast" : {
1028 | "active" : 1
1029 | },
1030 | "no-extra-label" : {
1031 | "active" : 0
1032 | },
1033 | "no-extra-parens" : {
1034 | "active" : 0,
1035 | "optionString" : "'all'"
1036 | },
1037 | "no-extra-semi" : {
1038 | "active" : 1
1039 | },
1040 | "no-fallthrough" : {
1041 | "active" : 1,
1042 | "optionString" : "{'allowEmptyCase': false}"
1043 | },
1044 | "no-floating-decimal" : {
1045 | "active" : 0
1046 | },
1047 | "no-func-assign" : {
1048 | "active" : 1
1049 | },
1050 | "no-global-assign" : {
1051 | "active" : 1,
1052 | "optionString" : "{'exceptions': []}"
1053 | },
1054 | "no-implicit-coercion" : {
1055 | "active" : 0,
1056 | "optionString" : "{'boolean': true, 'number': true, 'string': true, 'disallowTemplateShorthand': false, 'allow': []}"
1057 | },
1058 | "no-implicit-globals" : {
1059 | "active" : 0
1060 | },
1061 | "no-implied-eval" : {
1062 | "active" : 0
1063 | },
1064 | "no-import-assign" : {
1065 | "active" : 1
1066 | },
1067 | "no-inline-comments" : {
1068 | "active" : 0
1069 | },
1070 | "no-inner-declarations" : {
1071 | "active" : 1,
1072 | "optionString" : "'functions'"
1073 | },
1074 | "no-invalid-regexp" : {
1075 | "active" : 1,
1076 | "optionString" : "{'allowConstructorFlags': ['u', 'y']}"
1077 | },
1078 | "no-invalid-this" : {
1079 | "active" : 0,
1080 | "optionString" : "{'capIsConstructor': true}"
1081 | },
1082 | "no-irregular-whitespace" : {
1083 | "active" : 1,
1084 | "optionString" : "{'skipStrings': true, 'skipComments': false, 'skipRegExps': true, 'skipTemplates': true}"
1085 | },
1086 | "no-iterator" : {
1087 | "active" : 0
1088 | },
1089 | "no-label-var" : {
1090 | "active" : 0
1091 | },
1092 | "no-labels" : {
1093 | "active" : 0,
1094 | "optionString" : "{'allowLoop': false, 'allowSwitch': false}"
1095 | },
1096 | "no-lone-blocks" : {
1097 | "active" : 0
1098 | },
1099 | "no-lonely-if" : {
1100 | "active" : 0
1101 | },
1102 | "no-loop-func" : {
1103 | "active" : 0
1104 | },
1105 | "no-loss-of-precision" : {
1106 | "active" : 1
1107 | },
1108 | "no-magic-numbers" : {
1109 | "active" : 0,
1110 | "optionString" : "{'ignore': [], 'ignoreArrayIndexes': true, 'ignoreDefaultValues': false, 'enforceConst': false, 'detectObjects': false}"
1111 | },
1112 | "no-misleading-character-class" : {
1113 | "active" : 0
1114 | },
1115 | "no-mixed-operators" : {
1116 | "active" : 0,
1117 | "optionString" : "{'groups': [['+', '-', '*', '\/', '%', '**'], ['&', '|', '^', '~', '<<', '>>', '>>>'], ['==', '!=', '===', '!==', '>', '>=', '<', '<='], ['&&', '||'], ['in', 'instanceof']], 'allowSamePrecedence': true}"
1118 | },
1119 | "no-mixed-spaces-and-tabs" : {
1120 | "active" : 1,
1121 | "optionString" : ""
1122 | },
1123 | "no-multi-assign" : {
1124 | "active" : 0,
1125 | "optionString" : "{'ignoreNonDeclaration': false}"
1126 | },
1127 | "no-multi-spaces" : {
1128 | "active" : 0,
1129 | "optionString" : "{'exceptions': {'Property': true, 'BinaryExpression': false, 'VariableDeclarator': false, 'ImportDeclaration': false}}"
1130 | },
1131 | "no-multi-str" : {
1132 | "active" : 0
1133 | },
1134 | "no-multiple-empty-lines" : {
1135 | "active" : 0,
1136 | "optionString" : "{'max': 2, 'maxBOF': 2, 'maxEOF': 2}"
1137 | },
1138 | "no-negated-condition" : {
1139 | "active" : 0
1140 | },
1141 | "no-nested-ternary" : {
1142 | "active" : 0
1143 | },
1144 | "no-new" : {
1145 | "active" : 0
1146 | },
1147 | "no-new-func" : {
1148 | "active" : 0
1149 | },
1150 | "no-new-native-nonconstructor" : {
1151 | "active" : 0
1152 | },
1153 | "no-new-object" : {
1154 | "active" : 0
1155 | },
1156 | "no-new-symbol" : {
1157 | "active" : 1
1158 | },
1159 | "no-new-wrappers" : {
1160 | "active" : 0
1161 | },
1162 | "no-nonoctal-decimal-escape" : {
1163 | "active" : 1
1164 | },
1165 | "no-obj-calls" : {
1166 | "active" : 1
1167 | },
1168 | "no-octal" : {
1169 | "active" : 1
1170 | },
1171 | "no-octal-escape" : {
1172 | "active" : 0
1173 | },
1174 | "no-param-reassign" : {
1175 | "active" : 0,
1176 | "optionString" : "{'props': false}"
1177 | },
1178 | "no-plusplus" : {
1179 | "active" : 0,
1180 | "optionString" : "{'allowForLoopAfterthoughts': false}"
1181 | },
1182 | "no-promise-executor-return" : {
1183 | "active" : 0
1184 | },
1185 | "no-proto" : {
1186 | "active" : 0
1187 | },
1188 | "no-prototype-builtins" : {
1189 | "active" : 1
1190 | },
1191 | "no-redeclare" : {
1192 | "active" : 1,
1193 | "optionString" : "{'builtinGlobals': false}"
1194 | },
1195 | "no-regex-spaces" : {
1196 | "active" : 1
1197 | },
1198 | "no-restricted-exports" : {
1199 | "active" : 0,
1200 | "optionString" : "{'restrictedNamedExports': []}"
1201 | },
1202 | "no-restricted-globals" : {
1203 | "active" : 0,
1204 | "optionString" : "'event', 'fdescribe'"
1205 | },
1206 | "no-restricted-imports" : {
1207 | "active" : 0,
1208 | "optionString" : ""
1209 | },
1210 | "no-restricted-properties" : {
1211 | "active" : 0,
1212 | "optionString" : "[{'object': 'disallowedObjectName', 'property': 'disallowedPropertyName'}, {'object': 'disallowedObjectName', 'property': 'anotherDisallowedPropertyName', 'message': 'Please use allowedObjectName.allowedPropertyName.'}]"
1213 | },
1214 | "no-restricted-syntax" : {
1215 | "active" : 0,
1216 | "optionString" : "'FunctionExpression', 'WithStatement'"
1217 | },
1218 | "no-return-assign" : {
1219 | "active" : 0,
1220 | "optionString" : "'except-parens'"
1221 | },
1222 | "no-script-url" : {
1223 | "active" : 0
1224 | },
1225 | "no-self-assign" : {
1226 | "active" : 1,
1227 | "optionString" : "{'props': true}"
1228 | },
1229 | "no-self-compare" : {
1230 | "active" : 0
1231 | },
1232 | "no-sequences" : {
1233 | "active" : 0,
1234 | "optionString" : "{'allowInParentheses': true}"
1235 | },
1236 | "no-setter-return" : {
1237 | "active" : 1
1238 | },
1239 | "no-shadow" : {
1240 | "active" : 0,
1241 | "optionString" : "{'builtinGlobals': false, 'hoist': 'functions', 'allow': [], 'ignoreOnInitialization': false}"
1242 | },
1243 | "no-shadow-restricted-names" : {
1244 | "active" : 1
1245 | },
1246 | "no-sparse-arrays" : {
1247 | "active" : 1
1248 | },
1249 | "no-tabs" : {
1250 | "active" : 0,
1251 | "optionString" : "{allowIndentationTabs: false}"
1252 | },
1253 | "no-template-curly-in-string" : {
1254 | "active" : 0
1255 | },
1256 | "no-ternary" : {
1257 | "active" : 0
1258 | },
1259 | "no-this-before-super" : {
1260 | "active" : 1
1261 | },
1262 | "no-throw-literal" : {
1263 | "active" : 0
1264 | },
1265 | "no-trailing-spaces" : {
1266 | "active" : 0,
1267 | "optionString" : "{'skipBlankLines': false, 'ignoreComments': false}"
1268 | },
1269 | "no-undef" : {
1270 | "active" : 1,
1271 | "optionString" : "{'typeof': false}"
1272 | },
1273 | "no-undef-init" : {
1274 | "active" : 0
1275 | },
1276 | "no-undefined" : {
1277 | "active" : 0
1278 | },
1279 | "no-underscore-dangle" : {
1280 | "active" : 0,
1281 | "optionString" : "{'allow': [], 'allowAfterThis': false, 'allowAfterSuper': false, 'allowAfterThisConstructor': false, 'enforceInMethodNames': false, 'allowFunctionParams': true}"
1282 | },
1283 | "no-unexpected-multiline" : {
1284 | "active" : 1
1285 | },
1286 | "no-unmodified-loop-condition" : {
1287 | "active" : 0
1288 | },
1289 | "no-unneeded-ternary" : {
1290 | "active" : 0,
1291 | "optionString" : "{'defaultAssignment': true}"
1292 | },
1293 | "no-unreachable" : {
1294 | "active" : 1
1295 | },
1296 | "no-unreachable-loop" : {
1297 | "active" : 0,
1298 | "optionString" : "{'ignore': []}"
1299 | },
1300 | "no-unsafe-finally" : {
1301 | "active" : 1
1302 | },
1303 | "no-unsafe-negation" : {
1304 | "active" : 1,
1305 | "optionString" : "{'enforceForOrderingRelations': false}"
1306 | },
1307 | "no-unsafe-optional-chaining" : {
1308 | "active" : 1,
1309 | "optionString" : "{'disallowArithmeticOperators': false}"
1310 | },
1311 | "no-unused-expressions" : {
1312 | "active" : 0,
1313 | "optionString" : "{'allowShortCircuit': false, 'allowTernary': false, 'allowTaggedTemplates': false, 'enforceForJSX': false}"
1314 | },
1315 | "no-unused-labels" : {
1316 | "active" : 1
1317 | },
1318 | "no-unused-private-class-members" : {
1319 | "active" : 0
1320 | },
1321 | "no-unused-vars" : {
1322 | "active" : 1,
1323 | "optionString" : "{'vars': 'all', 'args': 'after-used', 'caughtErrors': 'none', 'ignoreRestSiblings': false}"
1324 | },
1325 | "no-use-before-define" : {
1326 | "active" : 0,
1327 | "optionString" : "{'functions': true, 'classes': true, 'variables': true}"
1328 | },
1329 | "no-useless-backreference" : {
1330 | "active" : 1
1331 | },
1332 | "no-useless-call" : {
1333 | "active" : 0
1334 | },
1335 | "no-useless-catch" : {
1336 | "active" : 1
1337 | },
1338 | "no-useless-computed-key" : {
1339 | "active" : 0,
1340 | "optionString" : "{'enforceForClassMembers': false}"
1341 | },
1342 | "no-useless-concat" : {
1343 | "active" : 0
1344 | },
1345 | "no-useless-constructor" : {
1346 | "active" : 0
1347 | },
1348 | "no-useless-escape" : {
1349 | "active" : 1
1350 | },
1351 | "no-useless-rename" : {
1352 | "active" : 0,
1353 | "optionString" : "{'ignoreDestructuring': false, 'ignoreImport': false, 'ignoreExport': false}"
1354 | },
1355 | "no-useless-return" : {
1356 | "active" : 0
1357 | },
1358 | "no-var" : {
1359 | "active" : 0
1360 | },
1361 | "no-void" : {
1362 | "active" : 0,
1363 | "optionString" : "{'allowAsStatement': false}"
1364 | },
1365 | "no-warning-comments" : {
1366 | "active" : 0,
1367 | "optionString" : "{'terms': ['todo', 'fixme', 'xxx'], 'location': 'start'}"
1368 | },
1369 | "no-whitespace-before-property" : {
1370 | "active" : 0
1371 | },
1372 | "no-with" : {
1373 | "active" : 1
1374 | },
1375 | "nonblock-statement-body-position" : {
1376 | "active" : 0,
1377 | "optionString" : "'beside'"
1378 | },
1379 | "object-curly-newline" : {
1380 | "active" : 0,
1381 | "optionString" : "{'ObjectExpression': {'multiline': true, 'consistent': true}, 'ObjectPattern': {'multiline': true, 'consistent': true}}"
1382 | },
1383 | "object-curly-spacing" : {
1384 | "active" : 0,
1385 | "optionString" : "'never'"
1386 | },
1387 | "object-property-newline" : {
1388 | "active" : 0,
1389 | "optionString" : "{'allowAllPropertiesOnSameLine': true}"
1390 | },
1391 | "object-shorthand" : {
1392 | "active" : 0,
1393 | "optionString" : "'always', {'avoidQuotes': false, 'ignoreConstructors': false}"
1394 | },
1395 | "one-var" : {
1396 | "active" : 0,
1397 | "optionString" : "'always'"
1398 | },
1399 | "one-var-declaration-per-line" : {
1400 | "active" : 0,
1401 | "optionString" : "'always'"
1402 | },
1403 | "operator-assignment" : {
1404 | "active" : 0,
1405 | "optionString" : "'always'"
1406 | },
1407 | "operator-linebreak" : {
1408 | "active" : 0,
1409 | "optionString" : "'after', {'overrides': {'?': 'after', '+=': 'none'}}"
1410 | },
1411 | "padded-blocks" : {
1412 | "active" : 0,
1413 | "optionString" : "{'blocks': 'always', 'switches': 'always', 'classes': 'always'}"
1414 | },
1415 | "padding-line-between-statements" : {
1416 | "active" : 0,
1417 | "optionString" : "{blankLine: 'always', prev:'*', next:'return'}"
1418 | },
1419 | "prefer-arrow-callback" : {
1420 | "active" : 0
1421 | },
1422 | "prefer-const" : {
1423 | "active" : 0,
1424 | "optionString" : "{'destructuring': 'any', 'ignoreReadBeforeAssign': false}"
1425 | },
1426 | "prefer-destructuring" : {
1427 | "active" : 0,
1428 | "optionString" : "{'array': true, 'object': true}, {'enforceForRenamedProperties': false}"
1429 | },
1430 | "prefer-exponentiation-operator" : {
1431 | "active" : 0
1432 | },
1433 | "prefer-named-capture-group" : {
1434 | "active" : 0
1435 | },
1436 | "prefer-numeric-literals" : {
1437 | "active" : 0
1438 | },
1439 | "prefer-object-has-own" : {
1440 | "active" : 0
1441 | },
1442 | "prefer-object-spread" : {
1443 | "active" : 0
1444 | },
1445 | "prefer-promise-reject-errors" : {
1446 | "active" : 0,
1447 | "optionString" : "{'allowEmptyReject': false}"
1448 | },
1449 | "prefer-regex-literals" : {
1450 | "active" : 0
1451 | },
1452 | "prefer-rest-params" : {
1453 | "active" : 0
1454 | },
1455 | "prefer-spread" : {
1456 | "active" : 0
1457 | },
1458 | "prefer-template" : {
1459 | "active" : 0
1460 | },
1461 | "quote-props" : {
1462 | "active" : 0,
1463 | "optionString" : "'always'"
1464 | },
1465 | "quotes" : {
1466 | "active" : 0,
1467 | "optionString" : "'double', {'avoidEscape': true, 'allowTemplateLiterals': true}"
1468 | },
1469 | "radix" : {
1470 | "active" : 0,
1471 | "optionString" : "'always'"
1472 | },
1473 | "require-atomic-updates" : {
1474 | "active" : 0,
1475 | "optionString" : "{'allowProperties': false}"
1476 | },
1477 | "require-await" : {
1478 | "active" : 0
1479 | },
1480 | "require-unicode-regexp" : {
1481 | "active" : 0
1482 | },
1483 | "require-yield" : {
1484 | "active" : 1
1485 | },
1486 | "rest-spread-spacing" : {
1487 | "active" : 0,
1488 | "optionString" : "'never'"
1489 | },
1490 | "semi" : {
1491 | "active" : 0,
1492 | "optionString" : "'always', {'omitLastInOneLineBlock': false}"
1493 | },
1494 | "semi-spacing" : {
1495 | "active" : 0,
1496 | "optionString" : "{'before': false, 'after': true}"
1497 | },
1498 | "semi-style" : {
1499 | "active" : 0,
1500 | "optionString" : "'last'"
1501 | },
1502 | "sort-imports" : {
1503 | "active" : 0,
1504 | "optionString" : "{'ignoreCase': false, 'ignoreMemberSort': true, 'memberSyntaxSortOrder': ['none', 'all', 'multiple', 'single'], 'allowSeparatedGroups': false}"
1505 | },
1506 | "sort-keys" : {
1507 | "active" : 0,
1508 | "optionString" : "'asc', {'caseSensitive': true, 'natural': false, 'minKeys': 2}"
1509 | },
1510 | "sort-vars" : {
1511 | "active" : 0,
1512 | "optionString" : "{'ignoreCase': false}"
1513 | },
1514 | "space-before-blocks" : {
1515 | "active" : 0,
1516 | "optionString" : "{'functions': 'always', 'keywords': 'always', 'classes': 'always'}"
1517 | },
1518 | "space-before-function-paren" : {
1519 | "active" : 0,
1520 | "optionString" : "{'anonymous': 'always', 'named': 'never'}"
1521 | },
1522 | "space-in-parens" : {
1523 | "active" : 0,
1524 | "optionString" : "'never', {'exceptions': []}"
1525 | },
1526 | "space-infix-ops" : {
1527 | "active" : 0,
1528 | "optionString" : "{'int32Hint': false}"
1529 | },
1530 | "space-unary-ops" : {
1531 | "active" : 0,
1532 | "optionString" : "{'words': true, 'nonwords': false, 'overrides': {}}"
1533 | },
1534 | "spaced-comment" : {
1535 | "active" : 0,
1536 | "optionString" : "'always', {'line': {'markers': ['\/'], 'exceptions': ['-', '+']}, 'block': {'markers': ['!'], 'exceptions': ['*'], 'balanced': false}}"
1537 | },
1538 | "strict" : {
1539 | "active" : 0,
1540 | "optionString" : "'safe'"
1541 | },
1542 | "switch-colon-spacing" : {
1543 | "active" : 0,
1544 | "optionString" : "{'after': true, 'before': false}"
1545 | },
1546 | "symbol-description" : {
1547 | "active" : 0
1548 | },
1549 | "template-curly-spacing" : {
1550 | "active" : 0,
1551 | "optionString" : "'never'"
1552 | },
1553 | "template-tag-spacing" : {
1554 | "active" : 0,
1555 | "optionString" : "'never'"
1556 | },
1557 | "unicode-bom" : {
1558 | "active" : 0,
1559 | "optionString" : "'never'"
1560 | },
1561 | "use-isnan" : {
1562 | "active" : 1,
1563 | "optionString" : "{'enforceForSwitchCase': true, 'enforceForIndexOf': false}"
1564 | },
1565 | "valid-typeof" : {
1566 | "active" : 1,
1567 | "optionString" : "{'requireStringLiterals': true}"
1568 | },
1569 | "vars-on-top" : {
1570 | "active" : 0
1571 | },
1572 | "wrap-iife" : {
1573 | "active" : 0,
1574 | "optionString" : "'outside'"
1575 | },
1576 | "wrap-regex" : {
1577 | "active" : 0
1578 | },
1579 | "yield-star-spacing" : {
1580 | "active" : 0,
1581 | "optionString" : "{'before': false, 'after': true}"
1582 | },
1583 | "yoda" : {
1584 | "active" : 0,
1585 | "optionString" : "'never', {'exceptRange': false, 'onlyEquality': false}"
1586 | }
1587 | },
1588 | "esLintSourceType" : 0,
1589 | "externalServerAddress" : "http:\/\/localhost:8888",
1590 | "gitIgnoreBuildFolder" : 1,
1591 | "hideConfigFile" : 0,
1592 | "jsCheckerReservedNamesString" : "",
1593 | "languageDefaultsCOFFEE" : {
1594 | "autoOutputAction" : 0,
1595 | "autoOutputPathFilenamePattern" : "*.js",
1596 | "autoOutputPathRelativePath" : "",
1597 | "autoOutputPathReplace1" : "",
1598 | "autoOutputPathReplace2" : "",
1599 | "autoOutputPathStyle" : 0,
1600 | "minifierStyle" : 0,
1601 | "outputStyle" : 0,
1602 | "sourceMapStyle" : 0,
1603 | "transpilerStyle" : 1
1604 | },
1605 | "languageDefaultsCSS" : {
1606 | "autoOutputAction" : 0,
1607 | "autoOutputPathFilenamePattern" : "*-min.css",
1608 | "autoOutputPathRelativePath" : "",
1609 | "autoOutputPathReplace1" : "",
1610 | "autoOutputPathReplace2" : "",
1611 | "autoOutputPathStyle" : 0,
1612 | "combineImports" : 0,
1613 | "cssoStyle" : 0,
1614 | "purgeCSSStyle" : 0,
1615 | "shouldRunAutoprefixer" : 1,
1616 | "shouldRunBless" : 0,
1617 | "sourceMapStyle" : 0
1618 | },
1619 | "languageDefaultsGIF" : {
1620 | "autoOutputAction" : 0,
1621 | "autoOutputPathFilenamePattern" : "*.gif",
1622 | "autoOutputPathRelativePath" : "",
1623 | "autoOutputPathReplace1" : "",
1624 | "autoOutputPathReplace2" : "",
1625 | "autoOutputPathStyle" : 0,
1626 | "webpOptimizationPresetUUID" : "lpckwebp-none",
1627 | "webpRGBQuality" : 75
1628 | },
1629 | "languageDefaultsHAML" : {
1630 | "autoOutputAction" : 0,
1631 | "autoOutputPathFilenamePattern" : "*.html",
1632 | "autoOutputPathRelativePath" : "",
1633 | "autoOutputPathReplace1" : "",
1634 | "autoOutputPathReplace2" : "",
1635 | "autoOutputPathStyle" : 0,
1636 | "escapeHTMLCharacters" : 0,
1637 | "htmlMinifierStyle" : 0,
1638 | "noEscapeInAttributes" : 0,
1639 | "outputFormat" : 2,
1640 | "shouldRunCacheBuster" : 0,
1641 | "useCDATA" : 0,
1642 | "useDoubleQuotes" : 0,
1643 | "useUnixNewlines" : 0
1644 | },
1645 | "languageDefaultsJPG" : {
1646 | "autoOutputAction" : 0,
1647 | "autoOutputPathFilenamePattern" : "*.jpg",
1648 | "autoOutputPathRelativePath" : "",
1649 | "autoOutputPathReplace1" : "",
1650 | "autoOutputPathReplace2" : "",
1651 | "autoOutputPathStyle" : 0,
1652 | "outputFormat" : 0,
1653 | "quality" : 100,
1654 | "webpOptimizationPresetUUID" : "lpckwebp-none",
1655 | "webpRGBQuality" : 75
1656 | },
1657 | "languageDefaultsJS" : {
1658 | "autoOutputAction" : 0,
1659 | "autoOutputPathFilenamePattern" : "*.js",
1660 | "autoOutputPathRelativePath" : "..\/..\/dist\/js",
1661 | "autoOutputPathReplace1" : "",
1662 | "autoOutputPathReplace2" : "",
1663 | "autoOutputPathStyle" : 2,
1664 | "bundleFormat" : 0,
1665 | "minifierStyle" : 1,
1666 | "sourceMapStyle" : 1,
1667 | "syntaxCheckerStyle" : 0,
1668 | "transpilerStyle" : 0
1669 | },
1670 | "languageDefaultsJSON" : {
1671 | "autoOutputAction" : 1,
1672 | "autoOutputPathFilenamePattern" : "*-min.json",
1673 | "autoOutputPathRelativePath" : "",
1674 | "autoOutputPathReplace1" : "",
1675 | "autoOutputPathReplace2" : "",
1676 | "autoOutputPathStyle" : 0,
1677 | "orderOutput" : 1,
1678 | "outputStyle" : 1
1679 | },
1680 | "languageDefaultsKIT" : {
1681 | "autoOutputAction" : 0,
1682 | "autoOutputPathFilenamePattern" : "*.html",
1683 | "autoOutputPathRelativePath" : "",
1684 | "autoOutputPathReplace1" : "kit",
1685 | "autoOutputPathReplace2" : "html",
1686 | "autoOutputPathStyle" : 0,
1687 | "htmlMinifierStyle" : 0,
1688 | "shouldRunCacheBuster" : 0
1689 | },
1690 | "languageDefaultsLESS" : {
1691 | "allowInsecureImports" : 0,
1692 | "autoOutputAction" : 0,
1693 | "autoOutputPathFilenamePattern" : "*.css",
1694 | "autoOutputPathRelativePath" : "..\/css",
1695 | "autoOutputPathReplace1" : "less",
1696 | "autoOutputPathReplace2" : "css",
1697 | "autoOutputPathStyle" : 0,
1698 | "cssoStyle" : 0,
1699 | "enableJavascript" : 0,
1700 | "mathStyle" : 0,
1701 | "outputStyle" : 0,
1702 | "purgeCSSStyle" : 0,
1703 | "rewriteURLStyle" : 0,
1704 | "shouldRunAutoprefixer" : 0,
1705 | "shouldRunBless" : 0,
1706 | "sourceMapStyle" : 0,
1707 | "strictImports" : 0,
1708 | "strictUnits" : 0
1709 | },
1710 | "languageDefaultsMARKDOWN" : {
1711 | "autoOutputAction" : 1,
1712 | "autoOutputPathFilenamePattern" : "*.html",
1713 | "autoOutputPathRelativePath" : "",
1714 | "autoOutputPathReplace1" : "",
1715 | "autoOutputPathReplace2" : "",
1716 | "autoOutputPathStyle" : 0,
1717 | "criticStyle" : 0,
1718 | "enableFootnotes" : 1,
1719 | "enableLabels" : 1,
1720 | "enableSmartQuotes" : 1,
1721 | "htmlMinifierStyle" : 0,
1722 | "maskEmailAddresses" : 1,
1723 | "outputFormat" : 0,
1724 | "outputStyle" : 0,
1725 | "parseMetadata" : 1,
1726 | "processHTML" : 0,
1727 | "randomFootnoteNumbers" : 0,
1728 | "shouldRunCacheBuster" : 0,
1729 | "useCompatibilityMode" : 0
1730 | },
1731 | "languageDefaultsOTHER" : {
1732 | "autoOutputAction" : 0,
1733 | "autoOutputPathFilenamePattern" : "*.*",
1734 | "autoOutputPathRelativePath" : "",
1735 | "autoOutputPathReplace1" : "",
1736 | "autoOutputPathReplace2" : "",
1737 | "autoOutputPathStyle" : 0,
1738 | "htmlMinifierStyle" : 0,
1739 | "shouldRunCacheBuster" : 0
1740 | },
1741 | "languageDefaultsPNG" : {
1742 | "autoOutputAction" : 0,
1743 | "autoOutputPathFilenamePattern" : "*.png",
1744 | "autoOutputPathRelativePath" : "",
1745 | "autoOutputPathReplace1" : "",
1746 | "autoOutputPathReplace2" : "",
1747 | "autoOutputPathStyle" : 0,
1748 | "optimizerType" : 1,
1749 | "quality" : 100,
1750 | "webpOptimizationPresetUUID" : "lpckwebp-none",
1751 | "webpRGBQuality" : 75
1752 | },
1753 | "languageDefaultsPUG" : {
1754 | "autoOutputAction" : 0,
1755 | "autoOutputPathFilenamePattern" : "*.html",
1756 | "autoOutputPathRelativePath" : "",
1757 | "autoOutputPathReplace1" : "",
1758 | "autoOutputPathReplace2" : "",
1759 | "autoOutputPathStyle" : 0,
1760 | "compileDebug" : 1,
1761 | "htmlMinifierStyle" : 0,
1762 | "outputStyle" : 1,
1763 | "shouldRunCacheBuster" : 0
1764 | },
1765 | "languageDefaultsSASS" : {
1766 | "autoOutputAction" : 0,
1767 | "autoOutputPathFilenamePattern" : "*.css",
1768 | "autoOutputPathRelativePath" : "..\/..\/dist\/css",
1769 | "autoOutputPathReplace1" : "sass",
1770 | "autoOutputPathReplace2" : "css",
1771 | "autoOutputPathStyle" : 2,
1772 | "compilerType" : 0,
1773 | "cssoStyle" : 0,
1774 | "decimalPrecision" : 10,
1775 | "emitCharset" : 1,
1776 | "outputStyle" : 3,
1777 | "purgeCSSStyle" : 0,
1778 | "shouldRunAutoprefixer" : 1,
1779 | "shouldRunBless" : 0,
1780 | "sourceMapStyle" : 0
1781 | },
1782 | "languageDefaultsSLIM" : {
1783 | "autoOutputAction" : 0,
1784 | "autoOutputPathFilenamePattern" : "*.html",
1785 | "autoOutputPathRelativePath" : "",
1786 | "autoOutputPathReplace1" : "",
1787 | "autoOutputPathReplace2" : "",
1788 | "autoOutputPathStyle" : 0,
1789 | "compileOnly" : 0,
1790 | "htmlMinifierStyle" : 0,
1791 | "logicless" : 0,
1792 | "outputFormat" : 0,
1793 | "outputStyle" : 1,
1794 | "railsCompatible" : 0,
1795 | "shouldRunCacheBuster" : 0
1796 | },
1797 | "languageDefaultsSTYLUS" : {
1798 | "autoOutputAction" : 0,
1799 | "autoOutputPathFilenamePattern" : "*.css",
1800 | "autoOutputPathRelativePath" : "..\/css",
1801 | "autoOutputPathReplace1" : "stylus",
1802 | "autoOutputPathReplace2" : "css",
1803 | "autoOutputPathStyle" : 0,
1804 | "cssoStyle" : 0,
1805 | "debugStyle" : 0,
1806 | "importCSS" : 0,
1807 | "outputStyle" : 0,
1808 | "purgeCSSStyle" : 0,
1809 | "resolveRelativeURLS" : 0,
1810 | "shouldRunAutoprefixer" : 0,
1811 | "shouldRunBless" : 0,
1812 | "sourceMapStyle" : 0
1813 | },
1814 | "languageDefaultsSVG" : {
1815 | "autoOutputAction" : 2,
1816 | "autoOutputPathFilenamePattern" : "*.svg",
1817 | "autoOutputPathRelativePath" : "",
1818 | "autoOutputPathReplace1" : "",
1819 | "autoOutputPathReplace2" : "",
1820 | "autoOutputPathStyle" : 0,
1821 | "pluginMask" : 52780316221407
1822 | },
1823 | "languageDefaultsTS" : {
1824 | "autoOutputAction" : 0,
1825 | "autoOutputPathFilenamePattern" : "*.js",
1826 | "autoOutputPathRelativePath" : "\/js",
1827 | "autoOutputPathReplace1" : "",
1828 | "autoOutputPathReplace2" : "",
1829 | "autoOutputPathStyle" : 0,
1830 | "createDeclarationFile" : 0,
1831 | "jsxMode" : 0,
1832 | "minifierStyle" : 0,
1833 | "moduleDetectionType" : 0,
1834 | "moduleResolutionType" : 0,
1835 | "moduleType" : 2,
1836 | "removeComments" : 0,
1837 | "sourceMapStyle" : 0,
1838 | "targetECMAVersion" : 2018
1839 | },
1840 | "languageDefaultsUserDefined" : [
1841 |
1842 | ],
1843 | "npmAbbreviatedPath" : "",
1844 | "npmCreatePackageLock" : 1,
1845 | "npmInstallOptionalDependencies" : 0,
1846 | "npmSaveExactVersion" : 0,
1847 | "npmTargetDependencyListType" : 1,
1848 | "overrideExternalServerCSS" : 0,
1849 | "previewPathAddition" : "",
1850 | "purgeCSS" : {
1851 | "blocklistEntries" : [
1852 |
1853 | ],
1854 | "contentEntries" : [
1855 | "**\/*.html",
1856 | "**\/*.htm",
1857 | "**\/*.shtml",
1858 | "**\/*.xhtml",
1859 | "**\/*.php",
1860 | "**\/*.js",
1861 | "**\/*.ts",
1862 | "**\/*.coffee",
1863 | "**\/*.erb",
1864 | "**\/*.pug",
1865 | "**\/*.jade",
1866 | "**\/*.slim",
1867 | "**\/*.haml",
1868 | "**\/*.md",
1869 | "**\/*.kit"
1870 | ],
1871 | "removeFontFace" : 0,
1872 | "removeKeyframes" : 0,
1873 | "removeVariables" : 0,
1874 | "safelistEntries" : [
1875 |
1876 | ],
1877 | "skippedEntries" : [
1878 | "node_modules\/**"
1879 | ]
1880 | },
1881 | "rollupContext" : "",
1882 | "rollupExternalEntries" : [
1883 |
1884 | ],
1885 | "rollupReplacementEntries" : [
1886 | "process.env.NODE_ENV:::$NODE_ENV",
1887 | "ENVIRONMENT:::$NODE_ENV"
1888 | ],
1889 | "rollupTreeshakingEnabled" : 1,
1890 | "rollupTreeshakingModuleSideEffects" : 1,
1891 | "skippedFoldersString" : "log, _logs, logs, _cache, cache, .idea, \/storage\/framework\/sessions, node_modules",
1892 | "sourceFolderName" : "source",
1893 | "susyVersion" : 3,
1894 | "tsAllowArbitraryExtensions" : 0,
1895 | "tsAllowImportingTSExtensions" : 0,
1896 | "tsAllowSyntheticDefaultImports" : 0,
1897 | "tsAllowUMDGlobalAccess" : 0,
1898 | "tsAllowUnreachableCode" : 0,
1899 | "tsAllowUnusedLabels" : 0,
1900 | "tsAlwaysStrict" : 0,
1901 | "tsDownlevelIteration" : 0,
1902 | "tsEmitBOM" : 0,
1903 | "tsEmitDecoratorMetadata" : 0,
1904 | "tsESModuleInterop" : 0,
1905 | "tsExactOptionalPropertyTypes" : 0,
1906 | "tsExperimentalDecorators" : 0,
1907 | "tsForceConsistentCasingInFileNames" : 0,
1908 | "tsImportHelpers" : 0,
1909 | "tsIsolatedModules" : 0,
1910 | "tsJSXFactory" : "React.createElement",
1911 | "tsNoEmitHelpers" : 0,
1912 | "tsNoFallthroughCasesInSwitch" : 0,
1913 | "tsNoImplicitAny" : 0,
1914 | "tsNoImplicitOverride" : 0,
1915 | "tsNoImplicitReturns" : 0,
1916 | "tsNoImplicitThis" : 0,
1917 | "tsNoLib" : 0,
1918 | "tsNoPropertyAccessFromIndexSignature" : 0,
1919 | "tsNoResolve" : 0,
1920 | "tsNoUncheckedIndexAccess" : 0,
1921 | "tsNoUnusedLocals" : 0,
1922 | "tsNoUnusedParameters" : 0,
1923 | "tsPreserveConstEnums" : 0,
1924 | "tsPreserveSymlinks" : 0,
1925 | "tsResolveJsonModule" : 0,
1926 | "tsSkipDefaultLibCheck" : 0,
1927 | "tsSkipLibCheck" : 0,
1928 | "tsStrictBindCallApply" : 0,
1929 | "tsStrictFunctionTypes" : 0,
1930 | "tsStrictNullChecks" : 0,
1931 | "tsStrictPropertyInitialization" : 0,
1932 | "tsStripInternal" : 0,
1933 | "tsUseDefineForClassFields" : 0,
1934 | "tsUseUnknownInCatchVariables" : 0,
1935 | "tsVerbatimModuleSyntax" : 0,
1936 | "uglifyDefinesString" : "",
1937 | "uglifyFlags2" : {
1938 | "arguments" : {
1939 | "active" : 1,
1940 | "flagValue" : -1
1941 | },
1942 | "arrows" : {
1943 | "active" : 1,
1944 | "flagValue" : -1
1945 | },
1946 | "ascii_only" : {
1947 | "active" : 0,
1948 | "flagValue" : -1
1949 | },
1950 | "booleans" : {
1951 | "active" : 1,
1952 | "flagValue" : -1
1953 | },
1954 | "booleans_as_integers" : {
1955 | "active" : 0,
1956 | "flagValue" : -1
1957 | },
1958 | "braces" : {
1959 | "active" : 0,
1960 | "flagValue" : -1
1961 | },
1962 | "collapse_vars" : {
1963 | "active" : 1,
1964 | "flagValue" : -1
1965 | },
1966 | "comments" : {
1967 | "active" : 0,
1968 | "flagValue" : 1
1969 | },
1970 | "comparisons" : {
1971 | "active" : 1,
1972 | "flagValue" : -1
1973 | },
1974 | "computed_props" : {
1975 | "active" : 1,
1976 | "flagValue" : -1
1977 | },
1978 | "conditionals" : {
1979 | "active" : 1,
1980 | "flagValue" : -1
1981 | },
1982 | "dead_code" : {
1983 | "active" : 1,
1984 | "flagValue" : -1
1985 | },
1986 | "directives" : {
1987 | "active" : 1,
1988 | "flagValue" : -1
1989 | },
1990 | "drop_console" : {
1991 | "active" : 0,
1992 | "flagValue" : -1
1993 | },
1994 | "drop_debugger" : {
1995 | "active" : 1,
1996 | "flagValue" : -1
1997 | },
1998 | "ecma" : {
1999 | "active" : 1,
2000 | "flagValue" : 5
2001 | },
2002 | "eval" : {
2003 | "active" : 0,
2004 | "flagValue" : -1
2005 | },
2006 | "evaluate" : {
2007 | "active" : 1,
2008 | "flagValue" : -1
2009 | },
2010 | "expression" : {
2011 | "active" : 0,
2012 | "flagValue" : -1
2013 | },
2014 | "hoist_funs" : {
2015 | "active" : 0,
2016 | "flagValue" : -1
2017 | },
2018 | "hoist_props" : {
2019 | "active" : 1,
2020 | "flagValue" : -1
2021 | },
2022 | "hoist_vars" : {
2023 | "active" : 0,
2024 | "flagValue" : -1
2025 | },
2026 | "ie8" : {
2027 | "active" : 0,
2028 | "flagValue" : -1
2029 | },
2030 | "if_return" : {
2031 | "active" : 1,
2032 | "flagValue" : -1
2033 | },
2034 | "indent_level" : {
2035 | "active" : 0,
2036 | "flagValue" : 4
2037 | },
2038 | "indent_start" : {
2039 | "active" : 0,
2040 | "flagValue" : 0
2041 | },
2042 | "inline" : {
2043 | "active" : 1,
2044 | "flagValue" : 3
2045 | },
2046 | "inline_script" : {
2047 | "active" : 1,
2048 | "flagValue" : -1
2049 | },
2050 | "join_vars" : {
2051 | "active" : 1,
2052 | "flagValue" : -1
2053 | },
2054 | "keep_classnames" : {
2055 | "active" : 0,
2056 | "flagValue" : -1
2057 | },
2058 | "keep_fargs" : {
2059 | "active" : 1,
2060 | "flagValue" : -1
2061 | },
2062 | "keep_fnames" : {
2063 | "active" : 0,
2064 | "flagValue" : -1
2065 | },
2066 | "keep_infinity" : {
2067 | "active" : 0,
2068 | "flagValue" : -1
2069 | },
2070 | "keep_numbers" : {
2071 | "active" : 0,
2072 | "flagValue" : -1
2073 | },
2074 | "keep_quoted_props" : {
2075 | "active" : 0,
2076 | "flagValue" : -1
2077 | },
2078 | "loops" : {
2079 | "active" : 1,
2080 | "flagValue" : -1
2081 | },
2082 | "max_line_len" : {
2083 | "active" : 1,
2084 | "flagValue" : 32000
2085 | },
2086 | "module" : {
2087 | "active" : 0,
2088 | "flagValue" : -1
2089 | },
2090 | "negate_iife" : {
2091 | "active" : 1,
2092 | "flagValue" : -1
2093 | },
2094 | "passes" : {
2095 | "active" : 1,
2096 | "flagValue" : 1
2097 | },
2098 | "preserve_annotations" : {
2099 | "active" : 0,
2100 | "flagValue" : -1
2101 | },
2102 | "properties" : {
2103 | "active" : 1,
2104 | "flagValue" : -1
2105 | },
2106 | "pure_getters" : {
2107 | "active" : 0,
2108 | "flagValue" : -1
2109 | },
2110 | "quote_keys" : {
2111 | "active" : 0,
2112 | "flagValue" : -1
2113 | },
2114 | "quote_style" : {
2115 | "active" : 1,
2116 | "flagValue" : 0
2117 | },
2118 | "reduce_funcs" : {
2119 | "active" : 1,
2120 | "flagValue" : -1
2121 | },
2122 | "reduce_vars" : {
2123 | "active" : 1,
2124 | "flagValue" : -1
2125 | },
2126 | "safari10" : {
2127 | "active" : 0,
2128 | "flagValue" : -1
2129 | },
2130 | "semicolons" : {
2131 | "active" : 1,
2132 | "flagValue" : -1
2133 | },
2134 | "sequences" : {
2135 | "active" : 1,
2136 | "flagValue" : -1
2137 | },
2138 | "shebang" : {
2139 | "active" : 1,
2140 | "flagValue" : -1
2141 | },
2142 | "side_effects" : {
2143 | "active" : 1,
2144 | "flagValue" : -1
2145 | },
2146 | "switches" : {
2147 | "active" : 1,
2148 | "flagValue" : -1
2149 | },
2150 | "toplevel" : {
2151 | "active" : 0,
2152 | "flagValue" : -1
2153 | },
2154 | "typeofs" : {
2155 | "active" : 1,
2156 | "flagValue" : -1
2157 | },
2158 | "unsafe" : {
2159 | "active" : 0,
2160 | "flagValue" : -1
2161 | },
2162 | "unsafe_arrows" : {
2163 | "active" : 0,
2164 | "flagValue" : -1
2165 | },
2166 | "unsafe_comps" : {
2167 | "active" : 0,
2168 | "flagValue" : -1
2169 | },
2170 | "unsafe_Function" : {
2171 | "active" : 0,
2172 | "flagValue" : -1
2173 | },
2174 | "unsafe_math" : {
2175 | "active" : 0,
2176 | "flagValue" : -1
2177 | },
2178 | "unsafe_methods" : {
2179 | "active" : 0,
2180 | "flagValue" : -1
2181 | },
2182 | "unsafe_proto" : {
2183 | "active" : 0,
2184 | "flagValue" : -1
2185 | },
2186 | "unsafe_regexp" : {
2187 | "active" : 0,
2188 | "flagValue" : -1
2189 | },
2190 | "unsafe_undefined" : {
2191 | "active" : 0,
2192 | "flagValue" : -1
2193 | },
2194 | "unused" : {
2195 | "active" : 1,
2196 | "flagValue" : -1
2197 | },
2198 | "warnings" : {
2199 | "active" : 0,
2200 | "flagValue" : -1
2201 | },
2202 | "webkit" : {
2203 | "active" : 0,
2204 | "flagValue" : -1
2205 | },
2206 | "wrap_func_args" : {
2207 | "active" : 1,
2208 | "flagValue" : -1
2209 | },
2210 | "wrap_iife" : {
2211 | "active" : 0,
2212 | "flagValue" : -1
2213 | }
2214 | },
2215 | "uglifyMangleNames" : 1,
2216 | "uglifyReservedNamesString" : "$,exports,require",
2217 | "webpPresets" : {
2218 |
2219 | },
2220 | "websiteRelativeRoot" : ""
2221 | },
2222 | "settingsFileVersion" : "3"
2223 | }
--------------------------------------------------------------------------------
/docs/.sidebar.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "title": "Get Started",
4 | "collapsable": false,
5 | "children": [
6 | "get-started/installation-setup",
7 | "get-started/requirements"
8 | ]
9 | },
10 | {
11 | "title": "Feature Tour",
12 | "collapsable": false,
13 | "children": [
14 | "feature-tour/usage"
15 | ]
16 | }
17 | ]
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/verbb/many-to-many/29fe8634acdad31843f3e54167fb81fb30d3f2c4/docs/README.md
--------------------------------------------------------------------------------
/docs/feature-tour/usage.md:
--------------------------------------------------------------------------------
1 | # Usage
2 | 1. Create your initial relationship field using the Entries Field Type and attach it to your first section.
3 | 2. Create another field that attaches the relationship using the Many to Many field type.
4 | * *Linked Section* will be the initial section that contains the relationship. (for example, Recipes).
5 | * *Associated Field* is the field on the other end of this relationship. (for example, Related Ingredients).
6 | 3. Attach the newly created Many to Many field to your section.
7 |
8 | ## Template Usage
9 | Since this plugin relies on Craft's built in relationships, you can continue to use relationships just as you always have.
10 |
11 | ```twig
12 | Related Ingredients
13 |
14 | {% set relatedIngredients = craft.entries.section('ingredients').relatedTo(entry).all() %}
15 |
16 | {% for ingredient in relatedIngredients %}
17 | {{ ingredient.title }}
18 | {% endfor %}
19 | ```
20 |
21 | ```twig
22 | Related Recipes
23 |
24 | {% set relatedRecipes = craft.entries.section('recipes').relatedTo(entry).all() %}
25 |
26 | {% for recipe in relatedRecipes %}
27 | {{ recipe.title }}
28 | {% endfor %}
29 | ```
30 |
--------------------------------------------------------------------------------
/docs/get-started/installation-setup.md:
--------------------------------------------------------------------------------
1 | # Installation & Setup
2 | You can install Many to Many via the plugin store, or through Composer.
3 |
4 | ## Craft Plugin Store
5 | To install **Many to Many**, navigate to the _Plugin Store_ section of your Craft control panel, search for `Many to Many`, and click the _Try_ button.
6 |
7 | ## Composer
8 | You can also add the package to your project using Composer and the command line.
9 |
10 | 1. Open your terminal and go to your Craft project:
11 | ```shell
12 | cd /path/to/project
13 | ```
14 |
15 | 2. Then tell Composer to require the plugin, and Craft to install it:
16 | ```shell
17 | composer require verbb/many-to-many && php craft plugin/install manytomany
18 | ```
19 |
--------------------------------------------------------------------------------
/docs/get-started/requirements.md:
--------------------------------------------------------------------------------
1 | # Requirements
2 |
3 | ## Craft CMS
4 | Many to Many requires Craft CMS 5.0 or greater.
5 |
6 | ## PHP
7 | Many to Many requires PHP 8.2 or greater.
8 |
--------------------------------------------------------------------------------
/src/ManyToMany.php:
--------------------------------------------------------------------------------
1 | _registerFieldTypes();
37 | }
38 |
39 |
40 | // Private Methods
41 | // =========================================================================
42 |
43 | private function _registerFieldTypes(): void
44 | {
45 | Event::on(Fields::class, Fields::EVENT_REGISTER_FIELD_TYPES, function(RegisterComponentTypesEvent $event) {
46 | $event->types[] = ManyToManyField::class;
47 | });
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/assetbundles/field/ManyToManyFieldAsset.php:
--------------------------------------------------------------------------------
1 | sourcePath = __DIR__ . '/dist';
15 |
16 | $this->depends = [
17 | CpAsset::class,
18 | ];
19 |
20 | $this->js = [
21 | 'many-to-many.js',
22 | ];
23 |
24 | parent::init();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/assetbundles/field/dist/many-to-many.js:
--------------------------------------------------------------------------------
1 | void 0===Craft.ManyToMany&&(Craft.ManyToMany={}),function($){Craft.ManyToMany.Field=Garnish.Base.extend({elementsToDelete:[],init:function(e){this.id=e.id,this.name=e.name,this.elementIds=e.elementIds,this.$container=$("#"+e.id+"-field .js-mtm-field"),this.$deleteContainer=this.$container.find(".js-mtm-delete"),this.$elementSelect=this.$container.find(".js-mtm-element-select"),this.elementSelect=this.$elementSelect.data("elementSelect"),this.elementSelect.onSelectElements=$.proxy(this,"onSelectElements"),this.elementSelect.onRemoveElements=$.proxy(this,"onRemoveElements")},onSelectElements:function(e){const t=this;$.each(e,(function(e,n){var l=t.elementsToDelete.indexOf(n.id);-1!==l&&t.elementsToDelete.splice(l,1)}))},onRemoveElements:function(){const e=this;$.each(this.elementIds,(function(t,n){e.elementSelect.$elements.find('[data-id="'+n+'"]').length||e.elementsToDelete.push(n)})),this.updateDeletedElements()},updateDeletedElements:function(){const e=this;this.$deleteContainer.html(""),$.each(this.elementsToDelete,(function(t,n){let l=' ';e.$deleteContainer.append(l)}))}})}(jQuery);
--------------------------------------------------------------------------------
/src/assetbundles/field/src/many-to-many.js:
--------------------------------------------------------------------------------
1 | // ==========================================================================
2 |
3 | // Many to Many Plugin for Craft CMS
4 | // Author: Verbb - https://verbb.io/
5 |
6 | // ==========================================================================
7 |
8 | if (typeof Craft.ManyToMany === typeof undefined) {
9 | Craft.ManyToMany = {};
10 | }
11 |
12 | (function($) {
13 |
14 | Craft.ManyToMany.Field = Garnish.Base.extend({
15 | elementsToDelete: [],
16 |
17 | init: function(settings) {
18 | this.id = settings.id;
19 | this.name = settings.name;
20 | this.elementIds = settings.elementIds;
21 | this.$container = $('#' + settings.id + '-field .js-mtm-field');
22 | this.$deleteContainer = this.$container.find('.js-mtm-delete');
23 | this.$elementSelect = this.$container.find('.js-mtm-element-select');
24 | this.elementSelect = this.$elementSelect.data('elementSelect');
25 |
26 | this.elementSelect.onSelectElements = $.proxy(this, 'onSelectElements');
27 | this.elementSelect.onRemoveElements = $.proxy(this, 'onRemoveElements');
28 | },
29 |
30 | onSelectElements: function(elements) {
31 | const self = this;
32 |
33 | $.each(elements, function(index, value) {
34 | var i = self.elementsToDelete.indexOf(value.id);
35 |
36 | if (i !== -1) {
37 | self.elementsToDelete.splice(i, 1);
38 | }
39 | });
40 | },
41 |
42 | onRemoveElements: function() {
43 | const self = this;
44 |
45 | $.each(this.elementIds, function(index, value) {
46 | if (!self.elementSelect.$elements.find('[data-id="' + value + '"]').length) {
47 | self.elementsToDelete.push(value);
48 | }
49 | });
50 |
51 | this.updateDeletedElements();
52 | },
53 |
54 | updateDeletedElements: function() {
55 | const self = this;
56 |
57 | this.$deleteContainer.html('');
58 |
59 | $.each(this.elementsToDelete, function(index, value) {
60 | let html = ' ';
61 |
62 | self.$deleteContainer.append(html);
63 | });
64 | },
65 | });
66 |
67 | })(jQuery);
68 |
--------------------------------------------------------------------------------
/src/base/PluginTrait.php:
--------------------------------------------------------------------------------
1 | [
33 | 'service' => Service::class,
34 | ],
35 | ];
36 | }
37 |
38 |
39 | // Public Methods
40 | // =========================================================================
41 |
42 | public function getService(): Service
43 | {
44 | return $this->get('service');
45 | }
46 |
47 | }
--------------------------------------------------------------------------------
/src/fields/ManyToManyField.php:
--------------------------------------------------------------------------------
1 | source['value'] ?? null;
68 |
69 | // Save the raw value for add/delete elements to use in `saveRelationship()`. We have to use the cache
70 | // as this isn't retained in `afterElementSave()`, and we want to wait until after the element has saved
71 | // to save the relationship, in case something went wrong with the element saving.
72 | $cacheKey = implode('--', ['many-to-many', $this->handle, $element->canonicalUid]);
73 | Craft::$app->getCache()->set($cacheKey, ($value ?? []));
74 |
75 | if ($element && $sourceValue && $this->singleField) {
76 | $relatedSection = Craft::$app->getEntries()->getSectionByUid($sourceValue);
77 |
78 | // Get all the entries that this has already been attached to
79 | if ($relatedSection) {
80 | return ManyToMany::$plugin->getService()->getRelatedEntries($element, $relatedSection, $this->singleField);
81 | }
82 | }
83 |
84 | return $value;
85 | }
86 |
87 | public function getSettingsHtml(): string
88 | {
89 | $elements = [];
90 | $fields = [];
91 |
92 | // Group the Sections into an array
93 | foreach (Craft::$app->getEntries()->getAllSections() as $section) {
94 | $elements[$section->uid] = $section->name;
95 | }
96 |
97 | // Group Field Types into an array
98 | foreach (Craft::$app->getFields()->getAllFields() as $field) {
99 | $fields[$field->uid] = $field->name;
100 | }
101 |
102 | // Get the Section Source
103 | if (empty($this->source)) {
104 | $this->source = ['type' => '', 'value' => ''];
105 | }
106 |
107 | return Craft::$app->getView()->renderTemplate('manytomany/field/settings', [
108 | 'field' => $this,
109 | 'elements' => $elements,
110 | 'fields' => $fields,
111 | ]);
112 | }
113 |
114 | public function afterElementSave(ElementInterface $element, bool $isNew): void
115 | {
116 | ManyToMany::$plugin->getService()->saveRelationship($this, $element);
117 |
118 | parent::afterElementSave($element, $isNew);
119 | }
120 |
121 | public function getPreviewHtml($value, ElementInterface $element): string
122 | {
123 | return Cp::elementPreviewHtml($value);
124 | }
125 |
126 | public function getContentGqlType(): array
127 | {
128 | return [
129 | 'name' => $this->handle,
130 | 'type' => Type::nonNull(Type::listOf(EntryInterface::getType())),
131 | 'args' => EntryArguments::getArguments(),
132 | 'resolve' => function($source, $arguments, $context, $resolveInfo) {
133 | // Convert the already-resolved entries to an entries query. This is because `normalizeValue`
134 | // doesn't return the traditional EntryElementQuery value.
135 | $target = $source->{$this->handle};
136 | $arguments['id'] = ArrayHelper::getColumn($target, 'id');
137 | $arguments['siteId'] = $target[0]->siteId ?? null;
138 |
139 | return EntryResolver::resolve(null, $arguments, $context, $resolveInfo);
140 | },
141 | 'complexity' => GqlHelper::relatedArgumentComplexity(GqlService::GRAPHQL_COMPLEXITY_EAGER_LOAD),
142 | ];
143 | }
144 |
145 |
146 | // Protected Methods
147 | // =========================================================================
148 |
149 | protected function inputHtml(mixed $value, ?ElementInterface $element, bool $inline): string
150 | {
151 | $view = Craft::$app->getView();
152 |
153 | // Validate settings
154 | if (empty($this->source)) {
155 | return Craft::t('manytomany', 'To use the Many to Many plugin you need to set a source.');
156 | }
157 |
158 | if (empty($this->singleField)) {
159 | return Craft::t('manytomany', 'To use the Many to Many plugin you need associate it with a related field.');
160 | }
161 |
162 | $singleFieldModel = Craft::$app->getFields()->getFieldByUid($this->singleField);
163 |
164 | if ($singleFieldModel && $singleFieldModel->getIsTranslatable($element)) {
165 | return Craft::t('manytomany', 'The Many to Many plugin does not currently work with localized content.');
166 | }
167 |
168 | // For this iteration of the plugin, everything is a SECTION, but it's setup, so it can be
169 | // refactored in the future to allow for multiple types
170 | if (!($element instanceof Entry)) {
171 | return Craft::t('manytomany', 'For this version of the Many to Many plugin, you can only use this field with Entries.');
172 | }
173 |
174 | return $view->renderTemplate('manytomany/field/input', [
175 | 'name' => $this->handle,
176 | 'value' => $value,
177 | 'id' => Html::id($this->handle),
178 | 'section' => $this->source['value'] ?? null,
179 | 'selectionLabel' => $this->selectionLabel ? Craft::t('site', $this->selectionLabel) : static::defaultSelectionLabel(),
180 | ]);
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/src/icon-mask.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
9 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
10 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/services/Service.php:
--------------------------------------------------------------------------------
1 | section = $section;
37 | $query->limit = null;
38 | $query->status = null;
39 | $query->siteId = $element->siteId;
40 | $query->relatedTo = [
41 | 'targetElement' => $element,
42 | 'field' => $fieldId,
43 | ];
44 |
45 | return $query->all();
46 | }
47 |
48 | /**
49 | * Save relationships on external field.
50 | *
51 | * @param ManyToManyField $fieldType
52 | * @param ElementInterface $element
53 | */
54 | public function saveRelationship(ManyToManyField $fieldType, ElementInterface $element): void
55 | {
56 | if (ElementHelper::isDraftOrRevision($element)) {
57 | return;
58 | }
59 |
60 | $cacheKey = implode('--', ['many-to-many', $fieldType->handle, $element->canonicalUid]);
61 | $content = Craft::$app->getCache()->get($cacheKey);
62 |
63 | // Get element ID of the current element. Be sure to use the canonicalId when dealing with autosave
64 | $targetId = $element->getCanonicalId();
65 |
66 | // Delete cache related to this element ID
67 | Craft::$app->getElements()->invalidateCachesForElement($element);
68 |
69 | // Get submitted field value - note that we're fetching `rawValue` not the normalized value
70 | Craft::$app->getCache()->delete($cacheKey);
71 |
72 | // There are 3 Items we need to make up a unique relationship in the craft_relations table:
73 | // fieldId --> We define this in the Field settings when creating it
74 | // sourceId --> The elementIds that create the relationship initially. This is currently stored in the $content array
75 | // targetId --> $elementId, this is the reverse of the relationship
76 | $fieldId = Db::idByUid(Table::FIELDS, $fieldType->singleField);
77 |
78 | $field = Craft::$app->fields->getFieldByUid($fieldType->singleField);
79 |
80 | // The relationships we either want to add or leave
81 | $toAdd = !empty($content['add']) ? $content['add'] : [];
82 |
83 | // The relationships we want to remove
84 | $toDelete = !empty($content['delete']) ? $content['delete'] : [];
85 |
86 | foreach ($toAdd as $sourceId) {
87 | $sourceElement = Entry::find()->id($sourceId)->one();
88 | $currentRelations = array_map(fn($r) => $r->Id, $sourceElement->getFieldValue($field->handle)->all());
89 | $currentRelations = array_unique(array_merge($currentRelations, [$targetId]));
90 | $sourceElement->setFieldValue($field->handle, $currentRelations);
91 | Craft::$app->elements->saveElement($sourceElement);
92 | }
93 |
94 | foreach ($toDelete as $sourceId) {
95 | $sourceElement = Entry::find()->id($sourceId)->one();
96 | $currentRelations = array_map(fn($r) => $r->Id, $sourceElement->getFieldValue($field->handle)->all());
97 | $currentRelations = array_filter($currentRelations, fn($r) => $r != $targetId);
98 | $sourceElement->setFieldValue($field->handle, $currentRelations);
99 | Craft::$app->elements->saveElement($sourceElement);
100 | }
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/templates/field/input.html:
--------------------------------------------------------------------------------
1 | {% import '_includes/forms' as forms %}
2 |
3 | {% do view.registerAssetBundle('verbb\\manytomany\\assetbundles\\field\\ManyToManyFieldAsset') %}
4 |
5 | {{ hiddenInput(name, '') }}
6 |
7 |
8 | {{ forms.elementSelect({
9 | name: name ~ '[add]',
10 | elementType: 'craft\\elements\\Entry',
11 | sources: section ? ['section:' ~ section] : [],
12 | selectionLabel: selectionLabel,
13 | class: 'js-mtm-element-select',
14 | elements: value,
15 | sortable: false,
16 | }) }}
17 |
18 |
19 |
20 |
21 | {% set jsSettings = {
22 | id: id | namespaceInputId,
23 | name: name | namespaceInputName,
24 | elementIds: value | map(v => v.id),
25 | } %}
26 |
27 | {% js %}
28 | new Craft.ManyToMany.Field({{ jsSettings | json_encode | raw }});
29 | {% endjs %}
--------------------------------------------------------------------------------
/src/templates/field/settings.html:
--------------------------------------------------------------------------------
1 | {% import '_includes/forms' as forms %}
2 |
3 | {{ forms.selectField({
4 | label: 'Linked Section' | t('manytomany'),
5 | instructions: 'What is the section you want to link in this relationship?' | t('manytomany'),
6 | id: 'source',
7 | name: 'source[value]',
8 | options: elements,
9 | value: field.source.value,
10 | errors: field.getErrors('source'),
11 | }) }}
12 |
13 | {{ forms.hidden({
14 | name: 'source[type]',
15 | value: 'section',
16 | }) }}
17 |
18 | {{ forms.selectField({
19 | label: 'Associated Field' | t('manytomany'),
20 | instructions: 'This is the field you are using to create the initial association. This has to be created first.' | t('manytomany'),
21 | id: 'singleField',
22 | name: 'singleField',
23 | options: fields,
24 | value: field.singleField,
25 | errors: field.getErrors('singleField'),
26 | }) }}
27 |
28 | {{ forms.textField({
29 | label: 'Selection Label' | t('app'),
30 | instructions: 'Enter the text you want to appear on the selection input.' | t('app'),
31 | id: 'selectionLabel',
32 | name: 'selectionLabel',
33 | value: field.selectionLabel,
34 | placeholder: field.defaultSelectionLabel(),
35 | errors: field.getErrors('selectionLabel'),
36 | }) }}
37 |
--------------------------------------------------------------------------------
/src/translations/en/manytomany.php:
--------------------------------------------------------------------------------
1 | 'Many to Many',
5 | 'Linked Section' => 'Linked Section',
6 | 'What is the section you want to link in this relationship?' => 'What is the section you want to link in this relationship?',
7 | 'Associated Field' => 'Associated Field',
8 | 'This is the field you are using to create the initial association. This has to be created first.' => 'This is the field you are using to create the initial association. This has to be created first.',
9 |
10 | 'For this version of the Many to Many plugin, you can only use this field with Entries.' => 'For this version of the Many to Many plugin, you can only use this field with Entries.',
11 | 'The Many to Many plugin does not currently work with localized content.' => 'The Many to Many plugin does not currently work with localized content.',
12 | 'To use the Many to Many plugin you need associate it with a related field.' => 'To use the Many to Many plugin you need associate it with a related field.',
13 | 'To use the Many to Many plugin you need to set a source.' => 'To use the Many to Many plugin you need to set a source.'
14 | ];
15 |
--------------------------------------------------------------------------------