├── .github
└── FUNDING.yml
├── .gitignore
├── LICENSE.md
├── README.md
├── _build
├── config.json
├── gpm_resolvers
│ └── gpm.resolve.tables.php
├── resolvers
│ ├── resolve.synctables.php
│ └── resolve.treehillstudio.php
└── setup.options.php
├── _packages
├── customrequest-1.0.3-pl.transport.zip
├── customrequest-1.1.0-pl.transport.zip
├── customrequest-1.1.1-pl.transport.zip
├── customrequest-1.1.2-pl.transport.zip
├── customrequest-1.1.3-pl.transport.zip
├── customrequest-1.1.4-pl.transport.zip
├── customrequest-1.2.0-pl.transport.zip
├── customrequest-1.2.1-pl.transport.zip
├── customrequest-1.2.2-pl.transport.zip
├── customrequest-1.2.3-pl.transport.zip
├── customrequest-1.2.4-pl.transport.zip
├── customrequest-1.2.5-pl.transport.zip
├── customrequest-1.2.6-pl.transport.zip
├── customrequest-1.2.7-pl.transport.zip
├── customrequest-1.3.0-pl.transport.zip
├── customrequest-1.3.1-pl.transport.zip
├── customrequest-1.3.10-pl.transport.zip
├── customrequest-1.3.2-pl.transport.zip
├── customrequest-1.3.3-pl2.transport.zip
├── customrequest-1.3.4-pl.transport.zip
├── customrequest-1.3.5-pl.transport.zip
├── customrequest-1.3.6-pl.transport.zip
├── customrequest-1.3.7-pl.transport.zip
├── customrequest-1.3.8-pl.transport.zip
└── customrequest-1.3.9-pl.transport.zip
├── assets
└── components
│ └── customrequest
│ ├── connector.php
│ ├── css
│ └── mgr
│ │ └── customrequest.min.css
│ ├── img
│ └── mgr
│ │ ├── treehill-studio-small.png
│ │ ├── treehill-studio-small@2x.png
│ │ ├── treehill-studio.png
│ │ └── treehill-studio@2x.png
│ └── js
│ └── mgr
│ └── customrequest.min.js
├── core
└── components
│ └── customrequest
│ ├── composer.json
│ ├── composer.lock
│ ├── controllers
│ └── home.class.php
│ ├── docs
│ ├── changelog.md
│ ├── license.md
│ └── readme.md
│ ├── elements
│ └── plugins
│ │ └── customrequest.plugin.php
│ ├── lexicon
│ ├── de
│ │ ├── default.inc.php
│ │ └── setting.inc.php
│ ├── en
│ │ ├── default.inc.php
│ │ └── setting.inc.php
│ └── ru
│ │ ├── default.inc.php
│ │ └── setting.inc.php
│ ├── model
│ ├── customrequest
│ │ ├── customrequest.class.php
│ │ ├── customrequestconfigs.class.php
│ │ ├── metadata.mysql.php
│ │ └── mysql
│ │ │ ├── customrequestconfigs.class.php
│ │ │ └── customrequestconfigs.map.inc.php
│ └── schema
│ │ └── customrequest.mysql.schema.xml
│ ├── processors
│ └── mgr
│ │ ├── configs
│ │ ├── create.class.php
│ │ ├── getlist.class.php
│ │ ├── remove.class.php
│ │ ├── sortindex.class.php
│ │ └── update.class.php
│ │ ├── resources
│ │ └── getlist.class.php
│ │ └── settings
│ │ ├── getlist.class.php
│ │ ├── update.class.php
│ │ └── updatefromgrid.class.php
│ ├── src
│ ├── CustomRequest.php
│ ├── Plugins
│ │ ├── Events
│ │ │ ├── OnDocFormDelete.php
│ │ │ ├── OnDocFormSave.php
│ │ │ ├── OnDocPublished.php
│ │ │ ├── OnDocUnPublished.php
│ │ │ ├── OnPageNotFound.php
│ │ │ └── OnSiteRefresh.php
│ │ └── Plugin.php
│ └── Processors
│ │ ├── ObjectCreateProcessor.php
│ │ ├── ObjectGetListProcessor.php
│ │ ├── ObjectRemoveProcessor.php
│ │ ├── ObjectSortindexProcessor.php
│ │ ├── ObjectUpdateProcessor.php
│ │ └── Processor.php
│ └── templates
│ └── home.tpl
├── docs
├── contributors.md
├── examples.md
├── index.md
├── installation.md
└── usage.md
├── gulpfile.js
├── icon
├── customrequest.ai
└── customrequest.png
├── mkdocs.yml
├── package-lock.json
├── package.json
└── source
├── css
└── mgr
│ └── customrequest.css
├── img
└── mgr
│ ├── treehill-studio-small.png
│ ├── treehill-studio-small@2x.png
│ ├── treehill-studio.png
│ └── treehill-studio@2x.png
├── js
└── mgr
│ ├── customrequest.js
│ ├── helper
│ ├── combo.js
│ └── util.js
│ ├── sections
│ └── home.js
│ └── widgets
│ ├── configs.grid.js
│ ├── home.panel.js
│ └── settings.panel.js
└── sass
└── mgr
├── _modx3.scss
└── customrequest.scss
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: Jako
4 | ko_fi: treehillstudio
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | _build/build.config.php
2 | config.core.php
3 |
4 | _build/site
5 |
6 | icon/*.svg
7 |
8 | _packages/*.*
9 | !_packages/.gitignore
10 | !_packages/*.zip
11 |
12 | node_modules/
13 | core/components/*/vendor/
14 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 | --------------------------
4 |
5 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
6 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7 |
8 | Everyone is permitted to copy and distribute verbatim copies
9 | of this license document, but changing it is not allowed.
10 |
11 | Preamble
12 | --------
13 |
14 | The licenses for most software are designed to take away your
15 | freedom to share and change it. By contrast, the GNU General Public
16 | License is intended to guarantee your freedom to share and change free
17 | software--to make sure the software is free for all its users. This
18 | General Public License applies to most of the Free Software
19 | Foundation's software and to any other program whose authors commit to
20 | using it. (Some other Free Software Foundation software is covered by
21 | the GNU Library General Public License instead.) You can apply it to
22 | your programs, too.
23 |
24 | When we speak of free software, we are referring to freedom, not
25 | price. Our General Public Licenses are designed to make sure that you
26 | have the freedom to distribute copies of free software (and charge for
27 | this service if you wish), that you receive source code or can get it
28 | if you want it, that you can change the software or use pieces of it
29 | in new free programs; and that you know you can do these things.
30 |
31 | To protect your rights, we need to make restrictions that forbid
32 | anyone to deny you these rights or to ask you to surrender the rights.
33 | These restrictions translate to certain responsibilities for you if you
34 | distribute copies of the software, or if you modify it.
35 |
36 | For example, if you distribute copies of such a program, whether
37 | gratis or for a fee, you must give the recipients all the rights that
38 | you have. You must make sure that they, too, receive or can get the
39 | source code. And you must show them these terms so they know their
40 | rights.
41 |
42 | We protect your rights with two steps: (1) copyright the software, and
43 | (2) offer you this license which gives you legal permission to copy,
44 | distribute and/or modify the software.
45 |
46 | Also, for each author's protection and ours, we want to make certain
47 | that everyone understands that there is no warranty for this free
48 | software. If the software is modified by someone else and passed on, we
49 | want its recipients to know that what they have is not the original, so
50 | that any problems introduced by others will not reflect on the original
51 | authors' reputations.
52 |
53 | Finally, any free program is threatened constantly by software
54 | patents. We wish to avoid the danger that redistributors of a free
55 | program will individually obtain patent licenses, in effect making the
56 | program proprietary. To prevent this, we have made it clear that any
57 | patent must be licensed for everyone's free use or not licensed at all.
58 |
59 | The precise terms and conditions for copying, distribution and
60 | modification follow.
61 |
62 |
63 | GNU GENERAL PUBLIC LICENSE
64 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
65 | ---------------------------------------------------------------
66 |
67 | 0. This License applies to any program or other work which contains
68 | a notice placed by the copyright holder saying it may be distributed
69 | under the terms of this General Public License. The "Program", below,
70 | refers to any such program or work, and a "work based on the Program"
71 | means either the Program or any derivative work under copyright law:
72 | that is to say, a work containing the Program or a portion of it,
73 | either verbatim or with modifications and/or translated into another
74 | language. (Hereinafter, translation is included without limitation in
75 | the term "modification".) Each licensee is addressed as "you".
76 |
77 | Activities other than copying, distribution and modification are not
78 | covered by this License; they are outside its scope. The act of
79 | running the Program is not restricted, and the output from the Program
80 | is covered only if its contents constitute a work based on the
81 | Program (independent of having been made by running the Program).
82 | Whether that is true depends on what the Program does.
83 |
84 | 1. You may copy and distribute verbatim copies of the Program's
85 | source code as you receive it, in any medium, provided that you
86 | conspicuously and appropriately publish on each copy an appropriate
87 | copyright notice and disclaimer of warranty; keep intact all the
88 | notices that refer to this License and to the absence of any warranty;
89 | and give any other recipients of the Program a copy of this License
90 | along with the Program.
91 |
92 | You may charge a fee for the physical act of transferring a copy, and
93 | you may at your option offer warranty protection in exchange for a fee.
94 |
95 | 2. You may modify your copy or copies of the Program or any portion
96 | of it, thus forming a work based on the Program, and copy and
97 | distribute such modifications or work under the terms of Section 1
98 | above, provided that you also meet all of these conditions:
99 |
100 | a) You must cause the modified files to carry prominent notices
101 | stating that you changed the files and the date of any change.
102 |
103 | b) You must cause any work that you distribute or publish, that in
104 | whole or in part contains or is derived from the Program or any
105 | part thereof, to be licensed as a whole at no charge to all third
106 | parties under the terms of this License.
107 |
108 | c) If the modified program normally reads commands interactively
109 | when run, you must cause it, when started running for such
110 | interactive use in the most ordinary way, to print or display an
111 | announcement including an appropriate copyright notice and a
112 | notice that there is no warranty (or else, saying that you provide
113 | a warranty) and that users may redistribute the program under
114 | these conditions, and telling the user how to view a copy of this
115 | License. (Exception: if the Program itself is interactive but
116 | does not normally print such an announcement, your work based on
117 | the Program is not required to print an announcement.)
118 |
119 | These requirements apply to the modified work as a whole. If
120 | identifiable sections of that work are not derived from the Program,
121 | and can be reasonably considered independent and separate works in
122 | themselves, then this License, and its terms, do not apply to those
123 | sections when you distribute them as separate works. But when you
124 | distribute the same sections as part of a whole which is a work based
125 | on the Program, the distribution of the whole must be on the terms of
126 | this License, whose permissions for other licensees extend to the
127 | entire whole, and thus to each and every part regardless of who wrote it.
128 |
129 | Thus, it is not the intent of this section to claim rights or contest
130 | your rights to work written entirely by you; rather, the intent is to
131 | exercise the right to control the distribution of derivative or
132 | collective works based on the Program.
133 |
134 | In addition, mere aggregation of another work not based on the Program
135 | with the Program (or with a work based on the Program) on a volume of
136 | a storage or distribution medium does not bring the other work under
137 | the scope of this License.
138 |
139 | 3. You may copy and distribute the Program (or a work based on it,
140 | under Section 2) in object code or executable form under the terms of
141 | Sections 1 and 2 above provided that you also do one of the following:
142 |
143 | a) Accompany it with the complete corresponding machine-readable
144 | source code, which must be distributed under the terms of Sections
145 | 1 and 2 above on a medium customarily used for software interchange; or,
146 |
147 | b) Accompany it with a written offer, valid for at least three
148 | years, to give any third party, for a charge no more than your
149 | cost of physically performing source distribution, a complete
150 | machine-readable copy of the corresponding source code, to be
151 | distributed under the terms of Sections 1 and 2 above on a medium
152 | customarily used for software interchange; or,
153 |
154 | c) Accompany it with the information you received as to the offer
155 | to distribute corresponding source code. (This alternative is
156 | allowed only for noncommercial distribution and only if you
157 | received the program in object code or executable form with such
158 | an offer, in accord with Subsection b above.)
159 |
160 | The source code for a work means the preferred form of the work for
161 | making modifications to it. For an executable work, complete source
162 | code means all the source code for all modules it contains, plus any
163 | associated interface definition files, plus the scripts used to
164 | control compilation and installation of the executable. However, as a
165 | special exception, the source code distributed need not include
166 | anything that is normally distributed (in either source or binary
167 | form) with the major components (compiler, kernel, and so on) of the
168 | operating system on which the executable runs, unless that component
169 | itself accompanies the executable.
170 |
171 | If distribution of executable or object code is made by offering
172 | access to copy from a designated place, then offering equivalent
173 | access to copy the source code from the same place counts as
174 | distribution of the source code, even though third parties are not
175 | compelled to copy the source along with the object code.
176 |
177 | 4. You may not copy, modify, sublicense, or distribute the Program
178 | except as expressly provided under this License. Any attempt
179 | otherwise to copy, modify, sublicense or distribute the Program is
180 | void, and will automatically terminate your rights under this License.
181 | However, parties who have received copies, or rights, from you under
182 | this License will not have their licenses terminated so long as such
183 | parties remain in full compliance.
184 |
185 | 5. You are not required to accept this License, since you have not
186 | signed it. However, nothing else grants you permission to modify or
187 | distribute the Program or its derivative works. These actions are
188 | prohibited by law if you do not accept this License. Therefore, by
189 | modifying or distributing the Program (or any work based on the
190 | Program), you indicate your acceptance of this License to do so, and
191 | all its terms and conditions for copying, distributing or modifying
192 | the Program or works based on it.
193 |
194 | 6. Each time you redistribute the Program (or any work based on the
195 | Program), the recipient automatically receives a license from the
196 | original licensor to copy, distribute or modify the Program subject to
197 | these terms and conditions. You may not impose any further
198 | restrictions on the recipients' exercise of the rights granted herein.
199 | You are not responsible for enforcing compliance by third parties to
200 | this License.
201 |
202 | 7. If, as a consequence of a court judgment or allegation of patent
203 | infringement or for any other reason (not limited to patent issues),
204 | conditions are imposed on you (whether by court order, agreement or
205 | otherwise) that contradict the conditions of this License, they do not
206 | excuse you from the conditions of this License. If you cannot
207 | distribute so as to satisfy simultaneously your obligations under this
208 | License and any other pertinent obligations, then as a consequence you
209 | may not distribute the Program at all. For example, if a patent
210 | license would not permit royalty-free redistribution of the Program by
211 | all those who receive copies directly or indirectly through you, then
212 | the only way you could satisfy both it and this License would be to
213 | refrain entirely from distribution of the Program.
214 |
215 | If any portion of this section is held invalid or unenforceable under
216 | any particular circumstance, the balance of the section is intended to
217 | apply and the section as a whole is intended to apply in other
218 | circumstances.
219 |
220 | It is not the purpose of this section to induce you to infringe any
221 | patents or other property right claims or to contest validity of any
222 | such claims; this section has the sole purpose of protecting the
223 | integrity of the free software distribution system, which is
224 | implemented by public license practices. Many people have made
225 | generous contributions to the wide range of software distributed
226 | through that system in reliance on consistent application of that
227 | system; it is up to the author/donor to decide if he or she is willing
228 | to distribute software through any other system and a licensee cannot
229 | impose that choice.
230 |
231 | This section is intended to make thoroughly clear what is believed to
232 | be a consequence of the rest of this License.
233 |
234 | 8. If the distribution and/or use of the Program is restricted in
235 | certain countries either by patents or by copyrighted interfaces, the
236 | original copyright holder who places the Program under this License
237 | may add an explicit geographical distribution limitation excluding
238 | those countries, so that distribution is permitted only in or among
239 | countries not thus excluded. In such case, this License incorporates
240 | the limitation as if written in the body of this License.
241 |
242 | 9. The Free Software Foundation may publish revised and/or new versions
243 | of the General Public License from time to time. Such new versions will
244 | be similar in spirit to the present version, but may differ in detail to
245 | address new problems or concerns.
246 |
247 | Each version is given a distinguishing version number. If the Program
248 | specifies a version number of this License which applies to it and "any
249 | later version", you have the option of following the terms and conditions
250 | either of that version or of any later version published by the Free
251 | Software Foundation. If the Program does not specify a version number of
252 | this License, you may choose any version ever published by the Free Software
253 | Foundation.
254 |
255 | 10. If you wish to incorporate parts of the Program into other free
256 | programs whose distribution conditions are different, write to the author
257 | to ask for permission. For software which is copyrighted by the Free
258 | Software Foundation, write to the Free Software Foundation; we sometimes
259 | make exceptions for this. Our decision will be guided by the two goals
260 | of preserving the free status of all derivatives of our free software and
261 | of promoting the sharing and reuse of software generally.
262 |
263 | NO WARRANTY
264 | -----------
265 |
266 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
267 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
268 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
269 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
270 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
271 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
272 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
273 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
274 | REPAIR OR CORRECTION.
275 |
276 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
277 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
278 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
279 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
280 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
281 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
282 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
283 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
284 | POSSIBILITY OF SUCH DAMAGES.
285 |
286 | ---------------------------
287 | END OF TERMS AND CONDITIONS
288 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://hosted.weblate.org/projects/modx-extras/customrequest/standard/)
2 |
3 | # CustomRequest
4 |
5 | Use pretty URLs everywhere in the MODX Revolution frontend
6 |
7 | ## Features
8 |
9 | CustomRequest is an effective routing plugin for MODX Revolution to map pretty
10 | but not found URLs to a MODX resource and set the request parameters by
11 | separating the URI path at the URI separators or by a regular expression.
12 |
13 | ## Installation
14 |
15 | MODX Package Management
16 |
17 | ## Usage
18 |
19 | Install via package manager and create your routings with the custom manager
20 | page that could be found in the extras menu.
21 |
22 | ## Documentation
23 |
24 | For more information please read the [documentation](https://jako.github.io/CustomRequest/).
25 |
26 | ## Translations
27 |
28 | Translations of the package can be made for the [Default Lexicon](https://hosted.weblate.org/projects/modx-extras/customrequest/standard/) and the [System Setting Lexicon](https://hosted.weblate.org/projects/modx-extras/customrequest/system-settings/)
29 |
--------------------------------------------------------------------------------
/_build/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "CustomRequest",
3 | "lowCaseName": "customrequest",
4 | "description": "Use friendly URLs everywhere",
5 | "author": "Thomas Jakobi",
6 | "version": "1.3.10",
7 | "package": {
8 | "menus": [
9 | {
10 | "text": "customrequest.menu_home",
11 | "description": "customrequest.menu_home_desc",
12 | "action": "home",
13 | "parent": "components"
14 | }
15 | ],
16 | "elements": {
17 | "plugins": [
18 | {
19 | "name": "CustomRequest",
20 | "description": "Use friendly URLs everywhere",
21 | "file": "customrequest.plugin.php",
22 | "events": [
23 | "OnDocFormDelete",
24 | "OnDocFormSave",
25 | "OnDocPublished",
26 | "OnDocUnPublished",
27 | "OnPageNotFound",
28 | "OnSiteRefresh"
29 | ]
30 | }
31 | ]
32 | },
33 | "systemSettings": [
34 | {
35 | "key": "debug",
36 | "type": "combo-boolean",
37 | "area": "system",
38 | "value": "0"
39 | }
40 | ]
41 | },
42 | "database": {
43 | "tables": [
44 | "CustomrequestConfigs"
45 | ]
46 | },
47 | "dependencies": [
48 | {
49 | "name": "php",
50 | "version": ">=7.2"
51 | },
52 | {
53 | "name": "modx",
54 | "version": ">=2.6"
55 | }
56 | ],
57 | "build": {
58 | "readme": "docs/readme.md",
59 | "license": "docs/license.md",
60 | "changelog": "docs/changelog.md",
61 | "setupOptions": {
62 | "source": "setup.options.php"
63 | },
64 | "resolver": {
65 | "after": [
66 | "resolve.synctables.php",
67 | "resolve.treehillstudio.php"
68 | ]
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/_build/gpm_resolvers/gpm.resolve.tables.php:
--------------------------------------------------------------------------------
1 | xpdo) {
16 | $modx =& $object->xpdo;
17 | switch ($options[xPDOTransport::PACKAGE_ACTION]) {
18 | case xPDOTransport::ACTION_INSTALL:
19 | case xPDOTransport::ACTION_UPGRADE:
20 | $modelPath = $modx->getOption('customrequest.core_path', null, $modx->getOption('core_path') . 'components/customrequest/') . 'model/';
21 |
22 | $modx->addPackage('customrequest', $modelPath, null);
23 |
24 |
25 | $manager = $modx->getManager();
26 |
27 | $manager->createObjectContainer('CustomrequestConfigs');
28 |
29 | break;
30 | }
31 | }
32 |
33 | return true;
--------------------------------------------------------------------------------
/_build/resolvers/resolve.synctables.php:
--------------------------------------------------------------------------------
1 | getTableName($table);
20 | $tableName = str_replace('`', '', $tableName);
21 | $dbname = $modx->getOption('dbname');
22 |
23 | $c = $modx->prepare('SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = :dbName AND table_name = :tableName');
24 | $c->bindParam(':dbName', $dbname);
25 | $c->bindParam(':tableName', $tableName);
26 | $c->execute();
27 |
28 | $unusedColumns = $c->fetchAll(PDO::FETCH_COLUMN, 0);
29 | $unusedColumns = array_flip($unusedColumns);
30 |
31 | $meta = $modx->getFieldMeta($table);
32 | $columns = array_keys($meta);
33 |
34 | $m = $modx->getManager();
35 |
36 | foreach ($columns as $column) {
37 | if (isset($unusedColumns[$column])) {
38 | $m->alterField($table, $column);
39 | $modx->log(xPDO::LOG_LEVEL_INFO, ' -- altered column: ' . $column);
40 | unset($unusedColumns[$column]);
41 | } else {
42 | $m->addField($table, $column);
43 | $modx->log(xPDO::LOG_LEVEL_INFO, ' -- added column: ' . $column);
44 | }
45 | }
46 |
47 | foreach ($unusedColumns as $column => $v) {
48 | $m->removeField($table, $column);
49 | $modx->log(xPDO::LOG_LEVEL_INFO, ' -- removed column: ' . $column);
50 | }
51 | }
52 | }
53 |
54 | if (!function_exists('updateTableIndexes')) {
55 | /**
56 | * @param modX $modx
57 | * @param string $table
58 | */
59 | function updateTableIndexes($modx, $table)
60 | {
61 | $tableName = $modx->getTableName($table);
62 | $tableName = str_replace('`', '', $tableName);
63 | $dbname = $modx->getOption('dbname');
64 |
65 | $c = $modx->prepare("SELECT DISTINCT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE table_schema = :dbName AND table_name = :tableName AND INDEX_NAME != 'PRIMARY'");
66 | $c->bindParam(':dbName', $dbname);
67 | $c->bindParam(':tableName', $tableName);
68 | $c->execute();
69 |
70 | $oldIndexes = $c->fetchAll(PDO::FETCH_COLUMN, 0);
71 |
72 | $m = $modx->getManager();
73 |
74 | foreach ($oldIndexes as $oldIndex) {
75 | $m->removeIndex($table, $oldIndex);
76 | $modx->log(xPDO::LOG_LEVEL_INFO, ' -- removed index: ' . $oldIndex);
77 | }
78 |
79 | $meta = $modx->getIndexMeta($table);
80 | $indexes = array_keys($meta);
81 |
82 | foreach ($indexes as $index) {
83 | if ($index == 'PRIMARY') continue;
84 | $m->addIndex($table, $index);
85 | $modx->log(xPDO::LOG_LEVEL_INFO, ' -- added index: ' . $index);
86 | }
87 | }
88 | }
89 |
90 | if (!function_exists('alterTable')) {
91 | /**
92 | * @param modX $modx
93 | * @param string $table
94 | */
95 | function alterTable($modx, $table)
96 | {
97 | $modx->log(xPDO::LOG_LEVEL_INFO, ' - Updating columns');
98 | updateTableColumns($modx, $table);
99 |
100 | $modx->log(xPDO::LOG_LEVEL_INFO, ' - Updating indexes');
101 | updateTableIndexes($modx, $table);
102 | }
103 | }
104 |
105 | if ($object->xpdo) {
106 | switch ($options[xPDOTransport::PACKAGE_ACTION]) {
107 | case xPDOTransport::ACTION_INSTALL:
108 | case xPDOTransport::ACTION_UPGRADE:
109 | /** @var modX $modx */
110 | $modx =& $object->xpdo;
111 |
112 | $tables = [
113 | 'CustomrequestConfigs'
114 | ];
115 |
116 | $modelPath = $modx->getOption('customrequest.core_path', null, $modx->getOption('core_path') . 'components/customrequest/') . 'model/';
117 | $modx->addPackage('customrequest', $modelPath);
118 |
119 | foreach ($tables as $table) {
120 | $modx->log(xPDO::LOG_LEVEL_INFO, 'Altering table: ' . $table);
121 | alterTable($modx, $table);
122 | }
123 |
124 | break;
125 | }
126 | }
127 | return true;
128 |
--------------------------------------------------------------------------------
/_build/resolvers/resolve.treehillstudio.php:
--------------------------------------------------------------------------------
1 | xpdo;
18 | $c = $modx->newQuery('transport.modTransportPackage');
19 | $c->where(
20 | [
21 | 'workspace' => 1,
22 | "(SELECT
23 | `signature`
24 | FROM {$modx->getTableName('transport.modTransportPackage')} AS `latestPackage`
25 | WHERE `latestPackage`.`package_name` = `modTransportPackage`.`package_name`
26 | ORDER BY
27 | `latestPackage`.`version_major` DESC,
28 | `latestPackage`.`version_minor` DESC,
29 | `latestPackage`.`version_patch` DESC,
30 | IF(`release` = '' OR `release` = 'ga' OR `release` = 'pl','z',`release`) DESC,
31 | `latestPackage`.`release_index` DESC
32 | LIMIT 1,1) = `modTransportPackage`.`signature`",
33 | ]
34 | );
35 | $c->where(
36 | [
37 | 'modTransportPackage.signature:LIKE' => $options['namespace'] . '-%',
38 | 'modTransportPackage.installed:IS NOT' => null
39 | ]
40 | );
41 | $c->limit(1);
42 |
43 | /** @var modTransportPackage $oldPackage */
44 | $oldPackage = $modx->getObject('transport.modTransportPackage', $c);
45 |
46 | $oldVersion = '';
47 | if ($oldPackage) {
48 | $oldVersion = $oldPackage->get('version_major') .
49 | '.' . $oldPackage->get('version_minor') .
50 | '.' . $oldPackage->get('version_patch') .
51 | '-' . $oldPackage->get('release');
52 | }
53 |
54 | $version = '';
55 | if ($transport->version) {
56 | $version = $transport->version;
57 | }
58 |
59 | $modxVersionObj = $modx->getObject('modSystemSetting', ['key' => 'settings_version']);
60 | $modxVersion = ($modxVersionObj) ? $modxVersionObj->get('value') : '';
61 | $managerLang = $modx->getOption('manager_language');
62 |
63 | $action = '';
64 | switch ($options[xPDOTransport::PACKAGE_ACTION]) {
65 | case xPDOTransport::ACTION_INSTALL:
66 | $action = 'install';
67 | break;
68 | case xPDOTransport::ACTION_UPGRADE:
69 | $action = 'upgrade';
70 | break;
71 | case xPDOTransport::ACTION_UNINSTALL:
72 | $action = 'uninstall';
73 | break;
74 | }
75 |
76 | $params = [
77 | 'name' => $options['namespace'],
78 | 'uuid' => $modx->uuid ?? 'unknown',
79 | 'host' => $modx->getOption('http_host', null, 'unknown'),
80 | 'php_version' => phpversion(),
81 | 'modx_version' => $modxVersion,
82 | 'manager_lang' => $managerLang,
83 | 'installation_type' => $action,
84 | 'package_version_from' => $oldVersion,
85 | 'package_version' => $version,
86 | 'date' => time()
87 | ];
88 |
89 | /**
90 | * Curl POST.
91 | */
92 | $curl = curl_init();
93 | if ($curl) {
94 | curl_setopt($curl, CURLOPT_URL, $url);
95 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
96 | curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
97 | curl_setopt($curl, CURLOPT_POST, true);
98 | curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
99 | curl_setopt($curl, CURLOPT_TIMEOUT, 5);
100 |
101 | $response = curl_exec($curl);
102 | $responseInfo = curl_getinfo($curl);
103 | $curlError = curl_error($curl);
104 | curl_close($curl);
105 | }
106 |
107 | return true;
108 |
--------------------------------------------------------------------------------
/_build/setup.options.php:
--------------------------------------------------------------------------------
1 |
12 | #modx-setupoptions-panel { display: none; }
13 | #modx-setupoptions-form p { margin-bottom: 10px; }
14 | #modx-setupoptions-form h2 { margin-bottom: 15px; }
15 | ';
16 |
17 | $values = [];
18 | switch ($options[xPDOTransport::PACKAGE_ACTION]) {
19 | case xPDOTransport::ACTION_INSTALL:
20 | $output .= '
Install CustomRequest
21 |
22 |
Thanks for installing CustomRequest. This open source extra was
23 | developed by Treehill Studio - MODX development in Münsterland.
24 |
25 |
During the installation, we will collect some statistical data (the
26 | hostname, the MODX UUID, the PHP version and the MODX version of your
27 | MODX installation). Your data will be kept confidential and under no
28 | circumstances be used for promotional purposes or disclosed to third
29 | parties. We only like to know the usage count of this package.
30 |
31 |
If you install this package, you are giving us your permission to
32 | collect, process and use that data for statistical purposes.
CustomRequest will be upgraded. This open source extra was developed by
39 | Treehill Studio - MODX development in Münsterland.
40 |
41 |
During the installation, we will collect some statistical data (the
42 | hostname, the MODX UUID, the PHP version and the MODX version of your
43 | MODX installation). Your data will be kept confidential and under no
44 | circumstances be used for promotional purposes or disclosed to third
45 | parties. We only like to know the usage count of this package.
46 |
47 |
If you upgrade this package, you are giving us your permission to
48 | collect, process and use that data for statistical purposes.
",border:!1,cls:"panel-desc"},{xtype:"customrequest-grid-system-settings",id:"customrequest-grid-system-settings",cls:"main-wrapper",preventSaveRefresh:!0}]}),CustomRequest.panel.Settings.superclass.constructor.call(this,e)},Ext.extend(CustomRequest.panel.Settings,MODx.Panel),Ext.reg("customrequest-panel-settings",CustomRequest.panel.Settings),CustomRequest.grid.SystemSettings=function(e){e=e||{},Ext.applyIf(e,{id:"customrequest-grid-systemsettings",url:CustomRequest.config.connectorUrl,baseParams:{action:"mgr/settings/getlist",area:MODx.request.area||""},save_action:"mgr/settings/updatefromgrid",tbar:[],queryParam:3<=CustomRequest.config.modxversion?"query":"key"}),CustomRequest.grid.SystemSettings.superclass.constructor.call(this,e)},Ext.extend(CustomRequest.grid.SystemSettings,MODx.grid.SettingsGrid,{_showMenu:function(e,t,s){s.stopEvent(),s.preventDefault(),this.menu.record=this.getStore().getAt(t).data,this.getSelectionModel().isSelected(t)||this.getSelectionModel().selectRow(t),this.menu.removeAll();t=[];this.menu.record.menu?t=this.menu.record.menu:t.push({text:_("setting_update")||_("edit"),handler:this.updateSetting}),0=7.2.5",
19 | "ext-json": "*"
20 | },
21 | "autoload": {
22 | "psr-4": {
23 | "TreehillStudio\\CustomRequest\\": "src/"
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/core/components/customrequest/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "8091a07e94a54872ee605f99c6fb3e8a",
8 | "packages": [],
9 | "packages-dev": [],
10 | "aliases": [],
11 | "minimum-stability": "stable",
12 | "stability-flags": [],
13 | "prefer-stable": false,
14 | "prefer-lowest": false,
15 | "platform": {
16 | "php": ">=7.2.5"
17 | },
18 | "platform-dev": [],
19 | "platform-overrides": {
20 | "php": "7.2.5"
21 | },
22 | "plugin-api-version": "2.2.0"
23 | }
24 |
--------------------------------------------------------------------------------
/core/components/customrequest/controllers/home.class.php:
--------------------------------------------------------------------------------
1 | modx->getOption('customrequest.core_path', null, $this->modx->getOption('core_path') . 'components/customrequest/');
23 | $this->customrequest = $this->modx->getService('customrequest', 'CustomRequest', $path . 'model/customrequest/', [
24 | 'core_path' => $path
25 | ]);
26 |
27 | parent::initialize();
28 | }
29 |
30 | /**
31 | * {@inheritDoc}
32 | */
33 | public function loadCustomCssJs()
34 | {
35 | $assetsUrl = $this->customrequest->getOption('assetsUrl');
36 | $jsUrl = $this->customrequest->getOption('jsUrl') . 'mgr/';
37 | $jsSourceUrl = $assetsUrl . '../../../source/js/mgr/';
38 | $cssUrl = $this->customrequest->getOption('cssUrl') . 'mgr/';
39 | $cssSourceUrl = $assetsUrl . '../../../source/css/mgr/';
40 |
41 | if ($this->customrequest->getOption('debug') && ($assetsUrl != MODX_ASSETS_URL . 'components/customrequest/')) {
42 | $this->addCss($cssSourceUrl . 'customrequest.css?v=v' . $this->customrequest->version);
43 | $this->addJavascript($jsSourceUrl . 'customrequest.js?v=v' . $this->customrequest->version);
44 | $this->addJavascript($jsSourceUrl . 'helper/combo.js?v=v' . $this->customrequest->version);
45 | $this->addJavascript($jsSourceUrl . 'helper/util.js?v=v' . $this->customrequest->version);
46 | $this->addJavascript($jsSourceUrl . 'widgets/home.panel.js?v=v' . $this->customrequest->version);
47 | $this->addJavascript($jsSourceUrl . 'widgets/configs.grid.js?v=v' . $this->customrequest->version);
48 | $this->addJavascript(MODX_MANAGER_URL . 'assets/modext/widgets/core/modx.grid.settings.js');
49 | $this->addJavascript($jsSourceUrl . 'widgets/settings.panel.js?v=v' . $this->customrequest->version);
50 | $this->addLastJavascript($jsSourceUrl . 'sections/home.js?v=v' . $this->customrequest->version);
51 | } else {
52 | $this->addCss($cssUrl . 'customrequest.min.css?v=v' . $this->customrequest->version);
53 | $this->addJavascript(MODX_MANAGER_URL . 'assets/modext/widgets/core/modx.grid.settings.js');
54 | $this->addLastJavascript($jsUrl . 'customrequest.min.js?v=v' . $this->customrequest->version);
55 | }
56 | $this->addHtml('');
62 | }
63 |
64 | /**
65 | * {@inheritDoc}
66 | * @return string[]
67 | */
68 | public function getLanguageTopics()
69 | {
70 | return ['core:setting', 'customrequest:default'];
71 | }
72 |
73 | /**
74 | * {@inheritDoc}
75 | * @param array $scriptProperties
76 | */
77 | public function process(array $scriptProperties = [])
78 | {
79 | }
80 |
81 | /**
82 | * {@inheritDoc}
83 | * @return string|null
84 | */
85 | public function getPageTitle()
86 | {
87 | return $this->modx->lexicon('customrequest');
88 | }
89 |
90 | /**
91 | * {@inheritDoc}
92 | * @return string
93 | */
94 | public function getTemplateFile()
95 | {
96 | return $this->customrequest->getOption('templatesPath') . 'home.tpl';
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/core/components/customrequest/docs/changelog.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [1.3.10] - 2024-06-11
9 |
10 | ### Fixed
11 |
12 | - Fix warning: Undefined array key "q"
13 |
14 | ## [1.3.9] - 2023-10-13
15 |
16 | ### Fixed
17 |
18 | - Use the right setlocale property to get the current locale
19 |
20 | ## [1.3.8] - 2022-12-07
21 |
22 | ### Added
23 |
24 | - Use the alias from the resource uri field and fallback to makeUrl
25 |
26 | ### Fixed
27 |
28 | - Remove superfluous beforeSubmit code
29 |
30 | ## [1.3.7] - 2022-12-06
31 |
32 | ### Added
33 |
34 | - Duplicate configuration by button or context menu
35 |
36 | ## [1.3.6] - 2022-11-30
37 |
38 | ### Fixed
39 |
40 | - Fix search in the resource combo of a configuration
41 |
42 | ## [1.3.5] - 2022-01-11
43 |
44 | ### Added
45 |
46 | - Help button
47 |
48 | ## [1.3.4] - 2022-01-10
49 |
50 | ### Changed
51 |
52 | - Code refactoring
53 | - Full MODX 3 compatibility
54 |
55 | ## [1.3.3] - 2021-01-19
56 |
57 | ### Changed
58 |
59 | - Fix a not used configuration cache
60 |
61 | ## [1.3.2] - 2019-03-20
62 |
63 | ### Added
64 |
65 | - Edit CustomRequest system settings in the custom manager page
66 |
67 | ### Changed
68 |
69 | - Use $_REQUEST variable instead of $_SERVER variable to avoid subfolder installation issues
70 | - Retrieve $requestUri only during OnPageNotFound
71 |
72 | ## [1.3.1] - 2018-11-13
73 |
74 | ### Added
75 |
76 | - Log found configuration and the set request parameters
77 |
78 | ### Changed
79 |
80 | - Cache valid configurations, even if one configuration is invalid
81 | - Change the log level of debug messages
82 |
83 | ## [1.3.0] - 2018-07-06
84 |
85 | ### Added
86 |
87 | - Equal aliases in different contexts are now possible
88 | - Switch the context to the requested resource context
89 | - Change the default engine to InnoDB
90 |
91 | ### Changed
92 |
93 | - Calculate the alias on base of the resource context
94 |
95 | ## [1.2.7] - 2017-09-28
96 |
97 | ### Changed
98 |
99 | - Regard the order of the configs
100 |
101 | ## [1.2.6] - 2016-06-13
102 |
103 | ### Added
104 |
105 | - Automatic urldecode of the remaining URL parameter part
106 |
107 | ## [1.2.5] - 2016-05-19
108 |
109 | ### Changed
110 |
111 | - Bugfix: Save configurations issue
112 |
113 | ## [1.2.4] - 2016-02-04
114 |
115 | ### Changed
116 |
117 | - Fixing a cache issue with URLs in different contexts than the current
118 |
119 | ## [1.2.3] - 2016-01-27
120 |
121 | ### Changed
122 |
123 | - Fixing a configuration caching issue
124 |
125 | ## [1.2.2] - 2016-01-19
126 |
127 | ### Added
128 |
129 | - Fixing a GPM table prefix issue
130 |
131 | ## [1.2.1] - 2016-01-13
132 |
133 | ### Added
134 |
135 | - Enhanced validation rules for a configuration during create/update
136 |
137 | ## [1.2.0] - 2016-01-11
138 |
139 | ### Added
140 |
141 | - Configurations are cached
142 | - The alias of a configuration could contain a regular expression
143 |
144 | ## [1.1.4] - 2015-09-10
145 |
146 | ### Changed
147 |
148 | - Fixing the RegEx evaluation
149 |
150 | ## [1.1.3] - 2015-04-18
151 |
152 | ### Changed
153 |
154 | - Fixing the cultureKey replacement
155 |
156 | ## [1.1.2] - 2015-03-17
157 |
158 | ### Changed
159 |
160 | - Fixing the cultureKey replacement
161 |
162 | ## [1.1.1] - 2015-03-03
163 |
164 | ### Changed
165 |
166 | - Bugfixes
167 |
168 | ## [1.1.0] - 2015-03-03
169 |
170 | ### Added
171 |
172 | - Custom manager page that replaces the config files
173 | - Automatic Import for old config files
174 |
175 | ## [1.0.3] - 2015-01-29
176 |
177 | ### Added
178 |
179 | - Build by Git-Package-Management
180 |
181 | ### Changed
182 |
183 | - Bugfix: Existing url parameters issue
184 |
185 | ## [1.0.2] - 2014-05-27
186 |
187 | ### Added
188 |
189 | - Detect/Log missing/not valid config files
190 |
191 | ### Changed
192 |
193 | - Debug logging
194 |
195 | ## [1.0.1] - 2013-1-27
196 |
197 | ### Changed
198 |
199 | - Updated documentation and examples ('resourceId' instead of 'id')
200 |
201 | ## [1.0.0] - 2013-06-09
202 |
203 | ### Added
204 |
205 | - Initial release for MODX Revolution
206 |
--------------------------------------------------------------------------------
/core/components/customrequest/docs/license.md:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 | --------------------------
4 |
5 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
6 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7 |
8 | Everyone is permitted to copy and distribute verbatim copies
9 | of this license document, but changing it is not allowed.
10 |
11 | Preamble
12 | --------
13 |
14 | The licenses for most software are designed to take away your
15 | freedom to share and change it. By contrast, the GNU General Public
16 | License is intended to guarantee your freedom to share and change free
17 | software--to make sure the software is free for all its users. This
18 | General Public License applies to most of the Free Software
19 | Foundation's software and to any other program whose authors commit to
20 | using it. (Some other Free Software Foundation software is covered by
21 | the GNU Library General Public License instead.) You can apply it to
22 | your programs, too.
23 |
24 | When we speak of free software, we are referring to freedom, not
25 | price. Our General Public Licenses are designed to make sure that you
26 | have the freedom to distribute copies of free software (and charge for
27 | this service if you wish), that you receive source code or can get it
28 | if you want it, that you can change the software or use pieces of it
29 | in new free programs; and that you know you can do these things.
30 |
31 | To protect your rights, we need to make restrictions that forbid
32 | anyone to deny you these rights or to ask you to surrender the rights.
33 | These restrictions translate to certain responsibilities for you if you
34 | distribute copies of the software, or if you modify it.
35 |
36 | For example, if you distribute copies of such a program, whether
37 | gratis or for a fee, you must give the recipients all the rights that
38 | you have. You must make sure that they, too, receive or can get the
39 | source code. And you must show them these terms so they know their
40 | rights.
41 |
42 | We protect your rights with two steps: (1) copyright the software, and
43 | (2) offer you this license which gives you legal permission to copy,
44 | distribute and/or modify the software.
45 |
46 | Also, for each author's protection and ours, we want to make certain
47 | that everyone understands that there is no warranty for this free
48 | software. If the software is modified by someone else and passed on, we
49 | want its recipients to know that what they have is not the original, so
50 | that any problems introduced by others will not reflect on the original
51 | authors' reputations.
52 |
53 | Finally, any free program is threatened constantly by software
54 | patents. We wish to avoid the danger that redistributors of a free
55 | program will individually obtain patent licenses, in effect making the
56 | program proprietary. To prevent this, we have made it clear that any
57 | patent must be licensed for everyone's free use or not licensed at all.
58 |
59 | The precise terms and conditions for copying, distribution and
60 | modification follow.
61 |
62 |
63 | GNU GENERAL PUBLIC LICENSE
64 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
65 | ---------------------------------------------------------------
66 |
67 | 0. This License applies to any program or other work which contains
68 | a notice placed by the copyright holder saying it may be distributed
69 | under the terms of this General Public License. The "Program", below,
70 | refers to any such program or work, and a "work based on the Program"
71 | means either the Program or any derivative work under copyright law:
72 | that is to say, a work containing the Program or a portion of it,
73 | either verbatim or with modifications and/or translated into another
74 | language. (Hereinafter, translation is included without limitation in
75 | the term "modification".) Each licensee is addressed as "you".
76 |
77 | Activities other than copying, distribution and modification are not
78 | covered by this License; they are outside its scope. The act of
79 | running the Program is not restricted, and the output from the Program
80 | is covered only if its contents constitute a work based on the
81 | Program (independent of having been made by running the Program).
82 | Whether that is true depends on what the Program does.
83 |
84 | 1. You may copy and distribute verbatim copies of the Program's
85 | source code as you receive it, in any medium, provided that you
86 | conspicuously and appropriately publish on each copy an appropriate
87 | copyright notice and disclaimer of warranty; keep intact all the
88 | notices that refer to this License and to the absence of any warranty;
89 | and give any other recipients of the Program a copy of this License
90 | along with the Program.
91 |
92 | You may charge a fee for the physical act of transferring a copy, and
93 | you may at your option offer warranty protection in exchange for a fee.
94 |
95 | 2. You may modify your copy or copies of the Program or any portion
96 | of it, thus forming a work based on the Program, and copy and
97 | distribute such modifications or work under the terms of Section 1
98 | above, provided that you also meet all of these conditions:
99 |
100 | a) You must cause the modified files to carry prominent notices
101 | stating that you changed the files and the date of any change.
102 |
103 | b) You must cause any work that you distribute or publish, that in
104 | whole or in part contains or is derived from the Program or any
105 | part thereof, to be licensed as a whole at no charge to all third
106 | parties under the terms of this License.
107 |
108 | c) If the modified program normally reads commands interactively
109 | when run, you must cause it, when started running for such
110 | interactive use in the most ordinary way, to print or display an
111 | announcement including an appropriate copyright notice and a
112 | notice that there is no warranty (or else, saying that you provide
113 | a warranty) and that users may redistribute the program under
114 | these conditions, and telling the user how to view a copy of this
115 | License. (Exception: if the Program itself is interactive but
116 | does not normally print such an announcement, your work based on
117 | the Program is not required to print an announcement.)
118 |
119 | These requirements apply to the modified work as a whole. If
120 | identifiable sections of that work are not derived from the Program,
121 | and can be reasonably considered independent and separate works in
122 | themselves, then this License, and its terms, do not apply to those
123 | sections when you distribute them as separate works. But when you
124 | distribute the same sections as part of a whole which is a work based
125 | on the Program, the distribution of the whole must be on the terms of
126 | this License, whose permissions for other licensees extend to the
127 | entire whole, and thus to each and every part regardless of who wrote it.
128 |
129 | Thus, it is not the intent of this section to claim rights or contest
130 | your rights to work written entirely by you; rather, the intent is to
131 | exercise the right to control the distribution of derivative or
132 | collective works based on the Program.
133 |
134 | In addition, mere aggregation of another work not based on the Program
135 | with the Program (or with a work based on the Program) on a volume of
136 | a storage or distribution medium does not bring the other work under
137 | the scope of this License.
138 |
139 | 3. You may copy and distribute the Program (or a work based on it,
140 | under Section 2) in object code or executable form under the terms of
141 | Sections 1 and 2 above provided that you also do one of the following:
142 |
143 | a) Accompany it with the complete corresponding machine-readable
144 | source code, which must be distributed under the terms of Sections
145 | 1 and 2 above on a medium customarily used for software interchange; or,
146 |
147 | b) Accompany it with a written offer, valid for at least three
148 | years, to give any third party, for a charge no more than your
149 | cost of physically performing source distribution, a complete
150 | machine-readable copy of the corresponding source code, to be
151 | distributed under the terms of Sections 1 and 2 above on a medium
152 | customarily used for software interchange; or,
153 |
154 | c) Accompany it with the information you received as to the offer
155 | to distribute corresponding source code. (This alternative is
156 | allowed only for noncommercial distribution and only if you
157 | received the program in object code or executable form with such
158 | an offer, in accord with Subsection b above.)
159 |
160 | The source code for a work means the preferred form of the work for
161 | making modifications to it. For an executable work, complete source
162 | code means all the source code for all modules it contains, plus any
163 | associated interface definition files, plus the scripts used to
164 | control compilation and installation of the executable. However, as a
165 | special exception, the source code distributed need not include
166 | anything that is normally distributed (in either source or binary
167 | form) with the major components (compiler, kernel, and so on) of the
168 | operating system on which the executable runs, unless that component
169 | itself accompanies the executable.
170 |
171 | If distribution of executable or object code is made by offering
172 | access to copy from a designated place, then offering equivalent
173 | access to copy the source code from the same place counts as
174 | distribution of the source code, even though third parties are not
175 | compelled to copy the source along with the object code.
176 |
177 | 4. You may not copy, modify, sublicense, or distribute the Program
178 | except as expressly provided under this License. Any attempt
179 | otherwise to copy, modify, sublicense or distribute the Program is
180 | void, and will automatically terminate your rights under this License.
181 | However, parties who have received copies, or rights, from you under
182 | this License will not have their licenses terminated so long as such
183 | parties remain in full compliance.
184 |
185 | 5. You are not required to accept this License, since you have not
186 | signed it. However, nothing else grants you permission to modify or
187 | distribute the Program or its derivative works. These actions are
188 | prohibited by law if you do not accept this License. Therefore, by
189 | modifying or distributing the Program (or any work based on the
190 | Program), you indicate your acceptance of this License to do so, and
191 | all its terms and conditions for copying, distributing or modifying
192 | the Program or works based on it.
193 |
194 | 6. Each time you redistribute the Program (or any work based on the
195 | Program), the recipient automatically receives a license from the
196 | original licensor to copy, distribute or modify the Program subject to
197 | these terms and conditions. You may not impose any further
198 | restrictions on the recipients' exercise of the rights granted herein.
199 | You are not responsible for enforcing compliance by third parties to
200 | this License.
201 |
202 | 7. If, as a consequence of a court judgment or allegation of patent
203 | infringement or for any other reason (not limited to patent issues),
204 | conditions are imposed on you (whether by court order, agreement or
205 | otherwise) that contradict the conditions of this License, they do not
206 | excuse you from the conditions of this License. If you cannot
207 | distribute so as to satisfy simultaneously your obligations under this
208 | License and any other pertinent obligations, then as a consequence you
209 | may not distribute the Program at all. For example, if a patent
210 | license would not permit royalty-free redistribution of the Program by
211 | all those who receive copies directly or indirectly through you, then
212 | the only way you could satisfy both it and this License would be to
213 | refrain entirely from distribution of the Program.
214 |
215 | If any portion of this section is held invalid or unenforceable under
216 | any particular circumstance, the balance of the section is intended to
217 | apply and the section as a whole is intended to apply in other
218 | circumstances.
219 |
220 | It is not the purpose of this section to induce you to infringe any
221 | patents or other property right claims or to contest validity of any
222 | such claims; this section has the sole purpose of protecting the
223 | integrity of the free software distribution system, which is
224 | implemented by public license practices. Many people have made
225 | generous contributions to the wide range of software distributed
226 | through that system in reliance on consistent application of that
227 | system; it is up to the author/donor to decide if he or she is willing
228 | to distribute software through any other system and a licensee cannot
229 | impose that choice.
230 |
231 | This section is intended to make thoroughly clear what is believed to
232 | be a consequence of the rest of this License.
233 |
234 | 8. If the distribution and/or use of the Program is restricted in
235 | certain countries either by patents or by copyrighted interfaces, the
236 | original copyright holder who places the Program under this License
237 | may add an explicit geographical distribution limitation excluding
238 | those countries, so that distribution is permitted only in or among
239 | countries not thus excluded. In such case, this License incorporates
240 | the limitation as if written in the body of this License.
241 |
242 | 9. The Free Software Foundation may publish revised and/or new versions
243 | of the General Public License from time to time. Such new versions will
244 | be similar in spirit to the present version, but may differ in detail to
245 | address new problems or concerns.
246 |
247 | Each version is given a distinguishing version number. If the Program
248 | specifies a version number of this License which applies to it and "any
249 | later version", you have the option of following the terms and conditions
250 | either of that version or of any later version published by the Free
251 | Software Foundation. If the Program does not specify a version number of
252 | this License, you may choose any version ever published by the Free Software
253 | Foundation.
254 |
255 | 10. If you wish to incorporate parts of the Program into other free
256 | programs whose distribution conditions are different, write to the author
257 | to ask for permission. For software which is copyrighted by the Free
258 | Software Foundation, write to the Free Software Foundation; we sometimes
259 | make exceptions for this. Our decision will be guided by the two goals
260 | of preserving the free status of all derivatives of our free software and
261 | of promoting the sharing and reuse of software generally.
262 |
263 | NO WARRANTY
264 | -----------
265 |
266 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
267 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
268 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
269 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
270 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
271 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
272 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
273 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
274 | REPAIR OR CORRECTION.
275 |
276 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
277 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
278 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
279 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
280 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
281 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
282 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
283 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
284 | POSSIBILITY OF SUCH DAMAGES.
285 |
286 | ---------------------------
287 | END OF TERMS AND CONDITIONS
288 |
--------------------------------------------------------------------------------
/core/components/customrequest/docs/readme.md:
--------------------------------------------------------------------------------
1 | # CustomRequest
2 |
3 | Use pretty URLs everywhere
4 |
5 | ## Features
6 |
7 | CustomRequest is an effective routing plugin for MODX Revolution to map pretty
8 | but not found URLs to a MODX resource and set the request parameters by
9 | separating the URI path at the URI separators or by a regular expression.
10 |
11 | As standard option the first characters of the not found URI will be compared
12 | with the alias value of each config entry. If found, this config entry is used.
13 | The alias path is stripped from the not found URI and the remaining string is
14 | used to set the request parameters.
15 |
16 | As a second option, the alias value of a config entry could contain a valid
17 | regular expression and the not found URI will be matched with that expression.
18 | If matched, this config entry is used. The first subpattern part of the
19 | expression is stripped from the found pattern and the remaining string is used
20 | to identify the resource where the user is forwarded to later. At least the
21 | found pattern is removed from the not found URI and the remaining string is
22 | used to set the request parameters.
23 |
24 | ## Installation
25 |
26 | MODX Package Management
27 |
28 | ## Documentation
29 |
30 | For more information please read the documentation on https://jako.github.io/CustomRequest/
31 |
32 | ## GitHub Repository
33 |
34 | https://github.com/Jako/CustomRequest
35 |
--------------------------------------------------------------------------------
/core/components/customrequest/elements/plugins/customrequest.plugin.php:
--------------------------------------------------------------------------------
1 | event->name;
13 |
14 | $corePath = $modx->getOption('customrequest.core_path', null, $modx->getOption('core_path') . 'components/customrequest/');
15 | /** @var CustomRequest $customrequest */
16 | $customrequest = $modx->getService('customrequest', 'CustomRequest', $corePath . 'model/customrequest/', [
17 | 'core_path' => $corePath
18 | ]);
19 |
20 | if ($customrequest) {
21 | if (class_exists($className)) {
22 | $handler = new $className($modx, $scriptProperties);
23 | if (get_class($handler) == $className) {
24 | $handler->run();
25 | } else {
26 | $modx->log(xPDO::LOG_LEVEL_ERROR, $className. ' could not be initialized!', '', 'CustomRequest Plugin');
27 | }
28 | } else {
29 | $modx->log(xPDO::LOG_LEVEL_ERROR, $className. ' was not found!', '', 'CustomRequest Plugin');
30 | }
31 | }
32 |
33 | return;
--------------------------------------------------------------------------------
/core/components/customrequest/lexicon/de/default.inc.php:
--------------------------------------------------------------------------------
1 | ';
35 | $_lang['customrequest.settings_desc'] = 'Bearbeiten Sie die Einstellungen von CustomRequest. Sie können den Wert einer Systemeinstellung mit einem Doppelklick auf die ‚Wert‘-Tabellenzelle oder die Systemeinstellung mit einem Rechtsklick in der Tabellenzelle bearbeiten.';
36 | $_lang['customrequest.systemsetting_key_err_nv'] = 'Sie dürfen nur Einstellungen mit dem Prefix customrequest bearbeiten.';
37 | $_lang['customrequest.systemsetting_usergroup_err_nv'] = 'Nur Benutzer mit einer settings Berechtigung oder einer settings_customrequest Berechtigung können die Einstellungen ändern.';
38 | $_lang['customrequest.configs_duplicate'] = 'Konfiguration Duplizieren';
39 | $_lang['customrequest.duplicate'] = 'Duplikat von';
40 | $_lang['customrequest.refresh_cache'] = 'Leeren des [[+packagename]]-Caches';
41 |
--------------------------------------------------------------------------------
/core/components/customrequest/lexicon/de/setting.inc.php:
--------------------------------------------------------------------------------
1 | ';
38 | $_lang['customrequest.settings_desc'] = 'Edit the settings of CustomRequest. You can edit the value of a system setting by double-clicking on the ‘Value’ table cell or by right-clicking in the table cell.';
39 | $_lang['customrequest.systemsetting_key_err_nv'] = 'You could only edit settings with the prefix customrequest.';
40 | $_lang['customrequest.systemsetting_usergroup_err_nv'] = 'Only users with a settings permission or a settings_customrequest permission are allowed to change settings.';
41 |
--------------------------------------------------------------------------------
/core/components/customrequest/lexicon/en/setting.inc.php:
--------------------------------------------------------------------------------
1 | ';
35 | $_lang['customrequest.settings_desc'] = 'Редактировать настройки CustomRequest. Вы можете редактировать значение системной настройки, дважды щелкнув по ячейке таблицы «значений» или щелкнув правой кнопкой мыши по ячейке таблицы.';
36 | $_lang['customrequest.systemsetting_key_err_nv'] = 'Вы можете редактировать настройки только с помощью обычного запроса префикса.';
37 | $_lang['customrequest.systemsetting_usergroup_err_nv'] = 'Разрешается изменять настройки только пользователям с разрешением настроек или разрешением settings_customrequest.';
38 | $_lang['customrequest.configs_duplicate'] = 'Дублирование конфигурации';
39 | $_lang['customrequest.duplicate'] = 'Дубликат';
40 | $_lang['customrequest.refresh_cache'] = 'Очистка кэша [[+packagename]]';
41 |
--------------------------------------------------------------------------------
/core/components/customrequest/lexicon/ru/setting.inc.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * @package customrequest
8 | * @subpackage classfile
9 | */
10 |
11 | require_once dirname(__DIR__, 2) . '/vendor/autoload.php';
12 |
13 | /**
14 | * class CustomRequest
15 | */
16 | class CustomRequest extends \TreehillStudio\CustomRequest\CustomRequest
17 | {
18 | }
19 |
--------------------------------------------------------------------------------
/core/components/customrequest/model/customrequest/customrequestconfigs.class.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/core/components/customrequest/model/customrequest/metadata.mysql.php:
--------------------------------------------------------------------------------
1 |
5 | array (
6 | 0 => 'CustomrequestConfigs',
7 | ),
8 | );
--------------------------------------------------------------------------------
/core/components/customrequest/model/customrequest/mysql/customrequestconfigs.class.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/core/components/customrequest/model/customrequest/mysql/customrequestconfigs.map.inc.php:
--------------------------------------------------------------------------------
1 | 'customrequest',
7 | 'version' => '1.1',
8 | 'table' => 'customrequest_configs',
9 | 'extends' => 'xPDOSimpleObject',
10 | 'tableMeta' =>
11 | array (
12 | 'engine' => 'InnoDB',
13 | ),
14 | 'fields' =>
15 | array (
16 | 'name' => NULL,
17 | 'menuindex' => 0,
18 | 'alias' => NULL,
19 | 'resourceid' => 0,
20 | 'urlparams' => NULL,
21 | 'regex' => NULL,
22 | ),
23 | 'fieldMeta' =>
24 | array (
25 | 'name' =>
26 | array (
27 | 'dbtype' => 'varchar',
28 | 'precision' => '100',
29 | 'phptype' => 'string',
30 | 'null' => true,
31 | ),
32 | 'menuindex' =>
33 | array (
34 | 'dbtype' => 'int',
35 | 'precision' => '10',
36 | 'phptype' => 'integer',
37 | 'null' => false,
38 | 'default' => 0,
39 | ),
40 | 'alias' =>
41 | array (
42 | 'dbtype' => 'varchar',
43 | 'precision' => '100',
44 | 'phptype' => 'string',
45 | 'null' => true,
46 | ),
47 | 'resourceid' =>
48 | array (
49 | 'dbtype' => 'int',
50 | 'precision' => '10',
51 | 'phptype' => 'integer',
52 | 'null' => false,
53 | 'default' => 0,
54 | ),
55 | 'urlparams' =>
56 | array (
57 | 'dbtype' => 'text',
58 | 'phptype' => 'string',
59 | 'null' => true,
60 | ),
61 | 'regex' =>
62 | array (
63 | 'dbtype' => 'text',
64 | 'phptype' => 'string',
65 | 'null' => true,
66 | ),
67 | ),
68 | );
69 |
--------------------------------------------------------------------------------
/core/components/customrequest/model/schema/customrequest.mysql.schema.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/configs/create.class.php:
--------------------------------------------------------------------------------
1 | getProperty('alias');
25 | $regex = $this->getProperty('regex');
26 | $resourceid = $this->getProperty('resourceid');
27 |
28 | if (empty($alias) && empty($resourceid)) {
29 | $this->addFieldError('alias', $this->modx->lexicon('customrequest.configs_err_ns_alias_resourceid'));
30 | $this->addFieldError('resourceid', $this->modx->lexicon('customrequest.configs_err_ns_alias_resourceid'));
31 | }
32 |
33 | if (empty($resourceid) && !$this->customrequest->isRegularExpression($alias)) {
34 | $this->addFieldError('alias', $this->modx->lexicon('customrequest.configs_err_nv_alias_regex'));
35 | }
36 |
37 | if (!empty($regex) && !$this->customrequest->isRegularExpression($regex)) {
38 | $this->addFieldError('regex', $this->modx->lexicon('customrequest.configs_err_nv_regex'));
39 | }
40 |
41 | $count = $this->modx->getCount($this->classKey);
42 | $this->object->set('menuindex', $count);
43 |
44 | return parent::beforeSave();
45 | }
46 |
47 | /**
48 | * {@inheritDoc}
49 | * @return bool
50 | */
51 | public function afterSave()
52 | {
53 | $this->customrequest->reset();
54 |
55 | return parent::afterSave();
56 | }
57 | }
58 |
59 | return 'CustomrequestConfigsCreateProcessor';
60 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/configs/getlist.class.php:
--------------------------------------------------------------------------------
1 | toArray('', false, true);
28 | /** @var modResource $resource */
29 | $resource = $this->modx->getObject('modResource', $ta['resourceid']);
30 | if ($resource) {
31 | $context = $this->modx->getContext($resource->get('context_key'));
32 | // If the alias could be retrieved by a resource id or if the alias is a valid regular rexpression
33 | $ta['pagetitle'] = $resource->get('pagetitle') . ' (' . $ta['resourceid'] . ')';
34 | $ta['alias_gen'] = ($ta['alias']) ?: '' . $this->makeUrl($ta['resourceid'], $resource->get('context_key')) . '';
35 | $ta['context'] = ($context->get('name')) ? $context->get('name') . ' (' . $resource->get('context_key') . ')' : $resource->get('context_key');
36 | } else {
37 | $ta['resourceid'] = '';
38 | if (!$this->customrequest->isRegularExpression($ta['alias'])) {
39 | $ta['alias_gen'] = '' . $ta['alias'] . '';
40 | }
41 | }
42 | return $ta;
43 | }
44 |
45 | /**
46 | * @param integer $id
47 | * @param string $context
48 | * @return string
49 | */
50 | private function makeUrl($id, $context)
51 | {
52 | $resource = $this->modx->getObject('modResource', $id);
53 | $tmpKey = $this->modx->context->key;
54 | $contextKey = $resource->get('context_key');
55 | $this->modx->switchContext($contextKey);
56 | $url = $this->modx->makeUrl($id, $context);
57 | $this->modx->switchContext($tmpKey);
58 | return str_replace($this->modx->getOption('site_url'), '', $url);
59 | }
60 | }
61 |
62 | return 'CustomrequestConfigsGetListProcessor';
63 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/configs/remove.class.php:
--------------------------------------------------------------------------------
1 | customrequest->reset();
23 |
24 | return parent::afterRemove();
25 | }
26 | }
27 |
28 | return 'CustomRequestConfigsRemoveProcessor';
29 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/configs/sortindex.class.php:
--------------------------------------------------------------------------------
1 | customrequest->reset();
23 | }
24 | }
25 |
26 | return 'CustomrequestConfigsSortindexProcessor';
27 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/configs/update.class.php:
--------------------------------------------------------------------------------
1 | getProperty('alias');
25 | $regex = $this->getProperty('regex');
26 | $resourceid = $this->getProperty('resourceid');
27 |
28 | if (empty($alias) && empty($resourceid)) {
29 | $this->addFieldError('alias', $this->modx->lexicon('customrequest.configs_err_ns_alias_resourceid'));
30 | $this->addFieldError('resourceid', $this->modx->lexicon('customrequest.configs_err_ns_alias_resourceid'));
31 | }
32 |
33 | if (empty($resourceid) && !$this->customrequest->isRegularExpression($alias)) {
34 | $this->addFieldError('alias', $this->modx->lexicon('customrequest.configs_err_nv_alias_regex'));
35 | }
36 |
37 | if (!empty($regex) && !$this->customrequest->isRegularExpression($regex)) {
38 | $this->addFieldError('regex', $this->modx->lexicon('customrequest.configs_err_nv_regex'));
39 | }
40 |
41 | return parent::beforeSave();
42 | }
43 |
44 | /**
45 | * {@inheritDoc}
46 | * @return bool
47 | */
48 | public function afterSave()
49 | {
50 | $this->customrequest->reset();
51 |
52 | return parent::afterSave();
53 | }
54 | }
55 |
56 | return 'CustomrequestConfigsUpdateProcessor';
57 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/resources/getlist.class.php:
--------------------------------------------------------------------------------
1 | where([
29 | 'deleted' => false,
30 | 'published' => true
31 | ]);
32 | return $c;
33 | }
34 |
35 | /**
36 | * (@inheritDoc}
37 | * @param xPDOObject $object
38 | * @return array
39 | */
40 | public function prepareRow(xPDOObject $object)
41 | {
42 | $ta = $object->toArray('', false, true);
43 | $ta['pagetitle'] = $ta['pagetitle'] . ' (' . $ta['id'] . ')';
44 | return $ta;
45 | }
46 | }
47 |
48 | return 'CustomrequestResourcesGetListProcessor';
49 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/settings/getlist.class.php:
--------------------------------------------------------------------------------
1 | permission) ? $this->modx->hasPermission($this->permission) || $this->modx->hasPermission('customrequest_' . $this->permission) : true;
32 | }
33 |
34 | /**
35 | * {@inheritDoc}
36 | * @return array
37 | */
38 | public function prepareCriteria()
39 | {
40 | return ['namespace' => 'customrequest'];
41 | }
42 | }
43 |
44 | return 'CustomRequestSystemSettingsGetlistProcessor';
45 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/settings/update.class.php:
--------------------------------------------------------------------------------
1 | permission) ? $this->modx->hasPermission($this->permission) || $this->modx->hasPermission('customrequest_' . $this->permission) : true;
31 | }
32 |
33 | /**
34 | * {@inheritDoc}
35 | * @return bool
36 | */
37 | public function beforeSave()
38 | {
39 | $this->setProperty('namespace', 'customrequest');
40 | $this->checkForBooleanValue();
41 | $this->checkCanSave();
42 | return parent::beforeSave();
43 | }
44 |
45 | /**
46 | * {@inheritDoc}
47 | * @return bool
48 | */
49 | public function afterSave()
50 | {
51 | $this->updateTranslations($this->getProperties());
52 | $this->clearCache();
53 | return parent::afterSave();
54 | }
55 |
56 | /**
57 | * Verify the namespace passed is a valid namespace
58 | */
59 | protected function checkCanSave()
60 | {
61 | $key = $this->getProperty('key');
62 | if (strpos($key, 'customrequest.') !== 0) {
63 | $this->addFieldError('key', $this->modx->lexicon('customrequest.systemsetting_key_err_nv'));
64 | }
65 | if (!$this->modx->hasPermission($this->permission) && !$this->modx->hasPermission('customrequest_' . $this->permission)) {
66 | $this->addFieldError('usergroup', $this->modx->lexicon('customrequest.systemsetting_usergroup_err_nv'));
67 | }
68 | }
69 | }
70 |
71 | return 'CustomRequestSystemSettingsUpdateProcessor';
72 |
--------------------------------------------------------------------------------
/core/components/customrequest/processors/mgr/settings/updatefromgrid.class.php:
--------------------------------------------------------------------------------
1 | getProperty('data');
19 | if (empty($data)) return $this->modx->lexicon('invalid_data');
20 | $properties = json_decode($data, true);
21 | $this->setProperties($properties);
22 | $this->unsetProperty('data');
23 |
24 | return parent::initialize();
25 | }
26 | }
27 |
28 | return 'CustomRequestSystemSettingsUpdateFromGridProcessor';
29 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/CustomRequest.php:
--------------------------------------------------------------------------------
1 |
6 | *
7 | * @package customrequest
8 | * @subpackage classfile
9 | */
10 |
11 | namespace TreehillStudio\CustomRequest;
12 |
13 | use CustomrequestConfigs;
14 | use modResource;
15 | use modX;
16 | use xPDO;
17 |
18 | /**
19 | * class CustomRequest
20 | */
21 | class CustomRequest
22 | {
23 | /**
24 | * A reference to the modX instance
25 | * @var modX $modx
26 | */
27 | public $modx;
28 |
29 | /**
30 | * The namespace
31 | * @var string $namespace
32 | */
33 | public $namespace = 'customrequest';
34 |
35 | /**
36 | * The package name
37 | * @var string $packageName
38 | */
39 | public $packageName = 'CustomRequest';
40 |
41 | /**
42 | * The version
43 | * @var string $version
44 | */
45 | public $version = '1.3.10';
46 |
47 | /**
48 | * The class options
49 | * @var array $options
50 | */
51 | public $options = [];
52 |
53 | /**
54 | * The requests array
55 | * @var array $requests
56 | */
57 | public $requests = [];
58 |
59 | /**
60 | * The found request
61 | * @var array $found
62 | */
63 | public $found = [];
64 |
65 | /**
66 | * CustomRequest constructor
67 | *
68 | * @param modX $modx A reference to the modX instance.
69 | * @param array $options An array of options. Optional.
70 | */
71 | public function __construct(modX &$modx, $options = [])
72 | {
73 | $this->modx =& $modx;
74 | $this->namespace = $this->getOption('namespace', $options, $this->namespace);
75 |
76 | $corePath = $this->getOption('core_path', $options, $this->modx->getOption('core_path', null, MODX_CORE_PATH) . 'components/' . $this->namespace . '/');
77 | $assetsPath = $this->getOption('assets_path', $options, $this->modx->getOption('assets_path', null, MODX_ASSETS_PATH) . 'components/' . $this->namespace . '/');
78 | $assetsUrl = $this->getOption('assets_url', $options, $this->modx->getOption('assets_url', null, MODX_ASSETS_URL) . 'components/' . $this->namespace . '/');
79 | $modxversion = $this->modx->getVersionData();
80 |
81 | // Load some default paths for easier management
82 | $this->options = array_merge([
83 | 'namespace' => $this->namespace,
84 | 'version' => $this->version,
85 | 'corePath' => $corePath,
86 | 'modelPath' => $corePath . 'model/',
87 | 'vendorPath' => $corePath . 'vendor/',
88 | 'chunksPath' => $corePath . 'elements/chunks/',
89 | 'pagesPath' => $corePath . 'elements/pages/',
90 | 'snippetsPath' => $corePath . 'elements/snippets/',
91 | 'pluginsPath' => $corePath . 'elements/plugins/',
92 | 'controllersPath' => $corePath . 'controllers/',
93 | 'processorsPath' => $corePath . 'processors/',
94 | 'templatesPath' => $corePath . 'templates/',
95 | 'assetsPath' => $assetsPath,
96 | 'assetsUrl' => $assetsUrl,
97 | 'jsUrl' => $assetsUrl . 'js/',
98 | 'cssUrl' => $assetsUrl . 'css/',
99 | 'imagesUrl' => $assetsUrl . 'images/',
100 | 'connectorUrl' => $assetsUrl . 'connector.php',
101 | ], $options);
102 |
103 | $lexicon = $this->modx->getService('lexicon', 'modLexicon');
104 | $lexicon->load($this->namespace . ':default');
105 |
106 | $this->packageName = $this->modx->lexicon('customrequest');
107 |
108 | $this->modx->addPackage($this->namespace, $this->getOption('modelPath'));
109 |
110 | // Add default options
111 | $this->options = array_merge($this->options, [
112 | 'debug' => (bool)$this->getOption('debug', $options, false),
113 | 'modxversion' => $modxversion['version'],
114 | 'is_admin' => $this->modx->user && $this->modx->context && ($modx->hasPermission('settings') || $modx->hasPermission($this->namespace . '_settings')),
115 | 'configsPath' => $this->getOption('configsPath', null, $corePath . 'configs/'),
116 | 'cachePath' => $this->modx->getOption('core_path') . 'cache/',
117 | 'cacheKey' => 'requests',
118 | 'cacheOptions' => [
119 | xPDO::OPT_CACHE_KEY => 'customrequest',
120 | xPDO::OPT_CACHE_HANDLER => $modx->getOption('cache_resource_handler', null, $this->modx->getOption(xPDO::OPT_CACHE_HANDLER, null, 'xPDOFileCache')),
121 | ],
122 | ]);
123 |
124 | if ($this->getOption('aliases')) {
125 | $this->requests = json_decode($this->getOption('aliases'), true);
126 | }
127 | if (!$this->requests) {
128 | $this->requests = [];
129 | }
130 | }
131 |
132 | /**
133 | * Get a local configuration option or a namespaced system setting by key.
134 | *
135 | * @param string $key The option key to search for.
136 | * @param array $options An array of options that override local options.
137 | * @param mixed $default The default value returned if the option is not found locally or as a
138 | * namespaced system setting; by default this value is null.
139 | * @return mixed The option value or the default value specified.
140 | */
141 | public function getOption($key, $options = [], $default = null)
142 | {
143 | $option = $default;
144 | if (!empty($key) && is_string($key)) {
145 | if ($options != null && array_key_exists($key, $options)) {
146 | $option = $options[$key];
147 | } elseif (array_key_exists($key, $this->options)) {
148 | $option = $this->options[$key];
149 | } elseif (array_key_exists("$this->namespace.$key", $this->modx->config)) {
150 | $option = $this->modx->getOption("$this->namespace.$key");
151 | }
152 | }
153 | return $option;
154 | }
155 |
156 | /**
157 | * Load all config files and prepare the values.
158 | *
159 | * @access public
160 | * @return void
161 | */
162 | public function initialize()
163 | {
164 | $this->requests = $this->modx->cacheManager->get($this->getOption('cacheKey'), $this->getOption('cacheOptions'));
165 |
166 | if (empty($this->requests) || $this->getOption('debug')) {
167 | // Clear the requests in debug mode
168 | $this->requests = [];
169 |
170 | // Import config records
171 | $c = $this->modx->newQuery('CustomrequestConfigs');
172 | $c->sortby('menuindex');
173 | /** @var CustomrequestConfigs[] $configs */
174 | $configs = $this->modx->getCollection('CustomrequestConfigs', $c);
175 | foreach ($configs as $config) {
176 | // Fill additional urlParams if defined
177 | $urlParams = json_decode($config->get('urlparams')) ? json_decode($config->get('urlparams')) : [];
178 | $resourceId = $config->get('resourceid');
179 | $alias = $config->get('alias');
180 | $aliasRegEx = false;
181 | $regEx = $config->get('regex');
182 | $contextKey = '';
183 | if ($alias) {
184 | // If alias is defined, calculate the other values
185 | if (!$resourceId) {
186 | $resourceId = 0;
187 | if (!$this->isRegularExpression($alias)) {
188 | $resourceId = $this->modx->findResource($alias);
189 | if (!$resourceId) {
190 | // If resourceId could not be calculated and alias is not a valid regular expression, don't use that setting
191 | if ($this->getOption('debug')) {
192 | $this->modx->log(xPDO::LOG_LEVEL_ERROR, 'Could not calculate the resourceId for the given alias "' . $alias . '".', '', 'CustomRequest Plugin');
193 | }
194 | break;
195 | }
196 | } else {
197 | $aliasRegEx = true;
198 | }
199 | }
200 | if ($resourceId) {
201 | $resource = $this->modx->getObject('modResource', $resourceId);
202 | if ($resource) {
203 | $contextKey = $resource->get('context_key');
204 | }
205 | }
206 | } else {
207 | $resourceId = $config->get('resourceid');
208 | if ($resourceId) {
209 | // If alias is not defined and resourceId is defined, calculate the other values
210 | if ($config->get('alias')) {
211 | $alias = $config->get('alias');
212 | } else {
213 | /** @var modResource $resource */
214 | $resource = $this->modx->getObject('modResource', $resourceId);
215 | if ($resource) {
216 | $contextKey = $resource->get('context_key');
217 | $alias = $resource->get('uri');
218 | // If the resource uri field is empty try to get it with make url
219 | if (!$alias) {
220 | $tmpKey = $this->modx->context->key;
221 | $this->modx->switchContext($contextKey);
222 | $alias = $this->modx->makeUrl($resourceId);
223 | $this->modx->switchContext($tmpKey);
224 | }
225 | if ($alias) {
226 | // Cutoff trailing .html or /
227 | $alias = trim(str_replace('.html', '', $alias), '/');
228 | } else {
229 | // If alias could not be calculated, don't use that setting
230 | if ($this->getOption('debug')) {
231 | $this->modx->log(xPDO::LOG_LEVEL_ERROR, 'Could not calculate the alias for the given resourceId "' . $resourceId . '".', '', 'CustomRequest Plugin');
232 | }
233 | continue;
234 | }
235 | } else {
236 | // If alias could not be calculated, don't use that setting
237 | if ($this->getOption('debug')) {
238 | $this->modx->log(xPDO::LOG_LEVEL_ERROR, 'No resource with ID "' . $resourceId . '" found.', '', 'CustomRequest Plugin');
239 | }
240 | continue;
241 | }
242 | }
243 | }
244 | }
245 | $this->requests[$contextKey . ':' . $alias] = [
246 | 'resourceId' => $resourceId,
247 | 'alias' => $alias,
248 | 'aliasRegEx' => $aliasRegEx,
249 | 'urlParams' => $urlParams,
250 | 'regEx' => $regEx,
251 | 'contextKey' => $contextKey
252 | ];
253 | }
254 | $this->modx->cacheManager->set($this->getOption('cacheKey'), $this->requests, 0, $this->getOption('cacheOptions'));
255 | }
256 | }
257 |
258 | /**
259 | * Reset the customrequest cache partition
260 | */
261 | public function reset()
262 | {
263 | $this->modx->cacheManager->delete($this->getOption('cacheKey'), $this->getOption('cacheOptions'));
264 | }
265 |
266 | /**
267 | * Check if the search string starts with one of the allowed aliases and
268 | * prepare the url param string if successful.
269 | *
270 | * @access public
271 | * @param string $search A string to search the allowed aliases in
272 | * @return boolean
273 | */
274 | public function searchAliases($search)
275 | {
276 | // Strip cultureKey i.e. in Babel installations.
277 | if (0 === strpos($search, $this->modx->cultureKey . '/')) {
278 | $search = substr($search, strlen($this->modx->cultureKey) + 1);
279 | }
280 |
281 | $valid = false;
282 | // Loop through the allowed aliases
283 | if (is_array($this->requests) && count($this->requests)) {
284 | foreach ($this->requests as $request) {
285 | if (!$request['aliasRegEx']) {
286 | // Check if searched string starts with the alias and for the contextKey
287 | if ($request['alias'] && 0 === strpos($search, $request['alias']) && $request['contextKey'] == $this->modx->context->key) {
288 | $this->found = [
289 | // Strip alias from seached string and urldecode it
290 | 'urlParams' => urldecode(substr($search, strlen($request['alias']))),
291 | // Set the found resource id
292 | 'resourceId' => $request['resourceId'],
293 | // Set the found alias
294 | 'alias' => $request['alias'],
295 | // Set the found regEx
296 | 'regEx' => $request['regEx'],
297 | // Set the found regEx
298 | 'contextKey' => $request['contextKey']
299 | ];
300 | $valid = true;
301 | break;
302 | }
303 | } else {
304 | if (preg_match($request['alias'], $search, $matches)) {
305 | $alias = trim(str_replace($matches[1], '', $matches[0]), '/');
306 | $resourceId = $this->modx->findResource($alias . '/', $request['contextKey']);
307 | if ($resourceId) {
308 | $this->found = [
309 | // Strip alias from seached string and urldecode it
310 | 'urlParams' => urldecode(substr($search, strlen($matches[0]))),
311 | // Set the found resource id
312 | 'resourceId' => $resourceId,
313 | // Set the found alias
314 | 'alias' => $request['alias'],
315 | // Set the found regEx
316 | 'regEx' => $request['regEx'],
317 | // Set the found regEx
318 | 'contextKey' => $request['contextKey']
319 | ];
320 | $valid = true;
321 | break;
322 | }
323 | }
324 | }
325 | }
326 | } else {
327 | if ($this->getOption('debug')) {
328 | $this->modx->log(xPDO::LOG_LEVEL_ERROR, 'No valid configs found.', '', 'CustomRequest Plugin');
329 | }
330 | }
331 |
332 | return $valid;
333 | }
334 |
335 | /**
336 | * Prepare the request parameters.
337 | *
338 | * @access public
339 | * @return void
340 | */
341 | public function setRequest()
342 | {
343 | $params = str_replace('.html', '', $this->found['urlParams']);
344 | if ($this->found['regEx']) {
345 | if (!preg_match($this->found['regEx'], $params, $matches)) {
346 | // Return without redirecting
347 | return;
348 | }
349 | // $matches[0] contains the full match, we don't want that
350 | array_shift($matches);
351 | $params = $matches;
352 | } else {
353 | $params = explode('/', trim($params, '/'));
354 | }
355 | if (count($params) >= 1) {
356 | $setting = $this->requests[$this->found['contextKey'] . ':' . $this->found['alias']];
357 |
358 | $foundParams = [];
359 | // Set the request parameters
360 | foreach ($params as $key => $value) {
361 | if (isset($setting['urlParams'][$key])) {
362 | $_REQUEST[$setting['urlParams'][$key]] = $value;
363 | $_GET[$setting['urlParams'][$key]] = $value;
364 | $foundParams[$setting['urlParams'][$key]] = $value;
365 | } else {
366 | $_REQUEST['p' . ($key + 1)] = $value;
367 | $_GET['p' . ($key + 1)] = $value;
368 | $foundParams['p' . ($key + 1)] = $value;
369 | }
370 | }
371 | if ($this->getOption('debug')) {
372 | $this->modx->log(xPDO::LOG_LEVEL_ERROR, 'Used configuration:' . "\n" . print_r($setting, true) . "\n" . 'Set params:' . "\n" . print_r($foundParams, true), '', 'CustomRequest Plugin');
373 | }
374 | }
375 | if ($resource = $this->modx->getObject('modResource', $this->found['resourceId'])) {
376 | if ($this->modx->context->key != $resource->get('context_key')) {
377 | $this->modx->switchContext($resource->get('context_key'));
378 |
379 | // Set locale after context switch since $this->modx->_initCulture is called before OnPageNotFound
380 | if ($this->modx->context && $this->modx->getOption('setlocale', null, true)) {
381 | $locale = setlocale(LC_ALL, '0');
382 | setlocale(LC_ALL, $this->modx->context->getOption('locale', null, $locale));
383 | }
384 | }
385 | }
386 | $this->modx->sendForward($this->found['resourceId']);
387 | }
388 |
389 | /**
390 | * Check for a valid regular expression
391 | *
392 | * @param $string
393 | * @return bool
394 | */
395 | public function isRegularExpression($string) {
396 | set_error_handler(function() {}, E_WARNING);
397 | $isRegularExpression = preg_match($string, '') !== FALSE;
398 | restore_error_handler();
399 | return $isRegularExpression;
400 | }
401 | }
402 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/Plugins/Events/OnDocFormDelete.php:
--------------------------------------------------------------------------------
1 | customrequest->initialize();
16 | if ($this->modx->context->get('key') !== 'mgr') {
17 | $requestParamAlias = $this->modx->getOption('request_param_alias', null, 'q');
18 | $requestUri = trim(strtok($_REQUEST[$requestParamAlias] ?? '', '?'), '/');
19 | if ($this->customrequest->searchAliases($requestUri)) {
20 | $this->customrequest->setRequest();
21 | }
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/Plugins/Events/OnSiteRefresh.php:
--------------------------------------------------------------------------------
1 | customrequest->reset();
17 | $this->modx->log(xPDO::LOG_LEVEL_INFO, $this->modx->lexicon('customrequest.refresh_cache', [
18 | 'packagename' => $this->customrequest->packageName
19 | ]));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/Plugins/Plugin.php:
--------------------------------------------------------------------------------
1 | scriptProperties = &$scriptProperties;
35 | $this->modx =& $modx;
36 | $corePath = $this->modx->getOption('customrequest.core_path', null, $this->modx->getOption('core_path') . 'components/customrequest/');
37 | $this->customrequest = $this->modx->getService('customrequest', 'CustomRequest', $corePath . 'model/customrequest/', [
38 | 'core_path' => $corePath
39 | ]);
40 | }
41 |
42 | /**
43 | * Run the plugin event.
44 | */
45 | public function run()
46 | {
47 | $init = $this->init();
48 | if ($init !== true) {
49 | return;
50 | }
51 |
52 | $this->process();
53 | }
54 |
55 | /**
56 | * Initialize the plugin event.
57 | *
58 | * @return bool
59 | */
60 | public function init()
61 | {
62 | return true;
63 | }
64 |
65 | /**
66 | * Process the plugin event code.
67 | *
68 | * @return mixed
69 | */
70 | abstract public function process();
71 | }
--------------------------------------------------------------------------------
/core/components/customrequest/src/Processors/ObjectCreateProcessor.php:
--------------------------------------------------------------------------------
1 | modx->getOption('customrequest.core_path', null, $this->modx->getOption('core_path') . 'components/customrequest/');
37 | $this->customrequest = $this->modx->getService('customrequest', 'CustomRequest', $corePath . 'model/customrequest/');
38 | }
39 |
40 | /**
41 | * Get a boolean property.
42 | * @param string $k
43 | * @param mixed $default
44 | * @return bool
45 | */
46 | public function getBooleanProperty($k, $default = null)
47 | {
48 | return ($this->getProperty($k, $default) === 'true' || $this->getProperty($k, $default) === true || $this->getProperty($k, $default) === '1' || $this->getProperty($k, $default) === 1);
49 | }
50 |
51 | /**
52 | * {@inheritDoc}
53 | * @return bool
54 | */
55 | public function beforeSave()
56 | {
57 | foreach ($this->required as $required) {
58 | $value = $this->getProperty($required);
59 | if (empty($value)) {
60 | $this->addFieldError($required, $this->modx->lexicon('field_required'));
61 | }
62 | }
63 |
64 | return parent::beforeSave();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/Processors/ObjectGetListProcessor.php:
--------------------------------------------------------------------------------
1 | modx->getOption('customrequest.core_path', null, $this->modx->getOption('core_path') . 'components/customrequest/');
39 | $this->customrequest = $this->modx->getService('customrequest', 'CustomRequest', $corePath . 'model/customrequest/');
40 | }
41 |
42 | /**
43 | * Get a boolean property.
44 | * @param string $k
45 | * @param mixed $default
46 | * @return bool
47 | */
48 | public function getBooleanProperty($k, $default = null)
49 | {
50 | return ($this->getProperty($k, $default) === 'true' || $this->getProperty($k, $default) === true || $this->getProperty($k, $default) === '1' || $this->getProperty($k, $default) === 1);
51 | }
52 |
53 | /**
54 | * {@inheritDoc}
55 | * @return string[]
56 | */
57 | public function getLanguageTopics()
58 | {
59 | if (file_exists($this->customrequest->getOption('corePath') . 'lexicon/' . $this->modx->getOption('manager_language', [], 'en') . '/custom.inc.php')) {
60 | $this->languageTopics[] = 'customrequest:custom';
61 | }
62 | return $this->languageTopics;
63 | }
64 |
65 | /**
66 | * {@inheritDoc}
67 | * @return bool
68 | */
69 | public function beforeQuery()
70 | {
71 | if ($this->getProperty('valuesqry')) {
72 | $this->setProperty('limit', 0);
73 | }
74 |
75 | return parent::beforeQuery();
76 | }
77 |
78 | /**
79 | * {@inheritDoc}
80 | * @param xPDOQuery $c
81 | * @return xPDOQuery
82 | */
83 | public function prepareQueryBeforeCount(xPDOQuery $c)
84 | {
85 | $valuesQuery = $this->getProperty('valuesqry');
86 | $query = (!$valuesQuery) ? $this->getProperty('query') : '';
87 | if (!empty($query)) {
88 | $conditions = ['id' => intval($query)];
89 | foreach ($this->search as $search) {
90 | $conditions['OR:' . $search . ':LIKE'] = '%' . $query . '%';
91 | }
92 | $c->where([$conditions]);
93 | }
94 |
95 | return $c;
96 | }
97 |
98 | /**
99 | * {@inheritDoc}
100 | * @param xPDOQuery $c
101 | * @return xPDOQuery
102 | */
103 | public function prepareQueryAfterCount(xPDOQuery $c)
104 | {
105 | $valuesQuery = $this->getProperty('valuesqry');
106 | $id = (!$valuesQuery) ? $this->getProperty('id') : $this->getProperty('query');
107 | if (!empty($id)) {
108 | $c->where([
109 | $this->classKey . '.id:IN' => array_map('intval', explode('|', $id))
110 | ]);
111 | }
112 |
113 | return $c;
114 | }
115 |
116 | /**
117 | * {@inheritDoc}
118 | * @param array $list
119 | * @return array
120 | */
121 | public function beforeIteration(array $list)
122 | {
123 | if (!$this->getProperty('id') && $this->getBooleanProperty('combo', false)) {
124 | $empty = [
125 | 'id' => 0,
126 | $this->nameField => $this->modx->lexicon('ext_emptygroup')
127 | ];
128 | $list[] = $empty;
129 | }
130 |
131 | return $list;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/Processors/ObjectRemoveProcessor.php:
--------------------------------------------------------------------------------
1 | modx->getOption('customrequest.core_path', null, $this->modx->getOption('core_path') . 'components/customrequest/');
35 | $this->customrequest = $this->modx->getService('customrequest', 'CustomRequest', $corePath . 'model/customrequest/');
36 | }
37 |
38 | /**
39 | * Get a boolean property.
40 | * @param string $k
41 | * @param mixed $default
42 | * @return bool
43 | */
44 | public function getBooleanProperty($k, $default = null)
45 | {
46 | return ($this->getProperty($k, $default) === 'true' || $this->getProperty($k, $default) === true || $this->getProperty($k, $default) === '1' || $this->getProperty($k, $default) === 1);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/Processors/ObjectSortindexProcessor.php:
--------------------------------------------------------------------------------
1 | modx->getOption('customrequest.core_path', null, $this->modx->getOption('core_path') . 'components/customrequest/');
37 | $this->customrequest = $this->modx->getService('customrequest', 'CustomRequest', $corePath . 'model/customrequest/');
38 | }
39 |
40 | /**
41 | * {@inheritDoc}
42 | * @return array|string
43 | */
44 | public function process()
45 | {
46 | if (!$this->cleanSorting()) {
47 | return $this->failure();
48 | }
49 |
50 | $targetId = $this->getProperty('targetId');
51 | $targetIndex = $this->modx->getObject($this->classKey, $targetId)->get($this->indexKey);
52 |
53 | // Prepare the moving ids
54 | $movingIds = explode(',', $this->getProperty('movingIds', 0));
55 | $c = $this->modx->newQuery($this->classKey);
56 | $c->where([
57 | 'id:IN' => $movingIds
58 | ]);
59 | $c->sortby($this->indexKey);
60 | $c->sortby('id');
61 | /** @var xPDOObject[] $movingObjects */
62 | $movingObjects = $this->modx->getIterator($this->classKey, $c);
63 | foreach ($movingObjects as $movingObject) {
64 | $c = $this->modx->newQuery($this->classKey);
65 | $movingIndex = $movingObject->get($this->indexKey);
66 | if ($movingIndex < $targetIndex) {
67 | $c->where([
68 | $this->indexKey . ':>' => $movingIndex,
69 | $this->indexKey . ':<=' => $targetIndex,
70 | ]);
71 | } else {
72 | $c->where([
73 | $this->indexKey . ':<' => $movingIndex,
74 | $this->indexKey . ':>=' => $targetIndex,
75 | ]);
76 | }
77 | $c->sortby($this->indexKey);
78 | $c->sortby('id');
79 | /** @var xPDOObject[] $affectedObjects */
80 | $affectedObjects = $this->modx->getIterator($this->classKey, $c);
81 | foreach ($affectedObjects as $affectedObject) {
82 | $affectedIndex = $affectedObject->get($this->indexKey);
83 | if ($movingIndex < $targetIndex) {
84 | $newIndex = $affectedIndex - 1;
85 | } else {
86 | $newIndex = $affectedIndex + 1;
87 | }
88 | $affectedObject->set($this->indexKey, $newIndex);
89 | $affectedObject->save();
90 | }
91 | $movingObject->set($this->indexKey, $targetIndex);
92 | $movingObject->save();
93 | }
94 |
95 | if (!$this->hasErrors()) {
96 | $this->afterSortindex();
97 | }
98 |
99 | return $this->success();
100 | }
101 |
102 | /**
103 | * Get a boolean property.
104 | * @param string $k
105 | * @param mixed $default
106 | * @return bool
107 | */
108 | public function getBooleanProperty($k, $default = null)
109 | {
110 | return ($this->getProperty($k, $default) === 'true' || $this->getProperty($k, $default) === true || $this->getProperty($k, $default) === '1' || $this->getProperty($k, $default) === 1);
111 | }
112 |
113 | /**
114 | * Override in your derivative class to do functionality after sorting objects
115 | */
116 | protected function afterSorting()
117 | {
118 | }
119 |
120 | /**
121 | * Clean the current sorting.
122 | *
123 | * @return bool
124 | */
125 | private function cleanSorting()
126 | {
127 | $c = $this->modx->newQuery($this->classKey);
128 | $c->sortby($this->indexKey);
129 | $c->sortby('id');
130 |
131 | /** @var xPDOObject[] $objects */
132 | $objects = $this->modx->getIterator($this->classKey, $c);
133 | if (!$objects) {
134 | return false;
135 | }
136 |
137 | $i = 0;
138 | foreach ($objects as $object) {
139 | $object->set($this->indexKey, $i);
140 | $object->save();
141 | $i++;
142 | }
143 | return true;
144 | }
145 | }
146 |
147 | return 'CustomRequestCategorySortindexProcessor';
148 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/Processors/ObjectUpdateProcessor.php:
--------------------------------------------------------------------------------
1 | modx->getOption('customrequest.core_path', null, $this->modx->getOption('core_path') . 'components/customrequest/');
37 | $this->customrequest = $this->modx->getService('customrequest', 'CustomRequest', $corePath . 'model/customrequest/');
38 | }
39 |
40 | /**
41 | * Get a boolean property.
42 | * @param string $k
43 | * @param mixed $default
44 | * @return bool
45 | */
46 | public function getBooleanProperty($k, $default = null)
47 | {
48 | return ($this->getProperty($k, $default) === 'true' || $this->getProperty($k, $default) === true || $this->getProperty($k, $default) === '1' || $this->getProperty($k, $default) === 1);
49 | }
50 |
51 | /**
52 | * {@inheritDoc}
53 | * @return bool
54 | */
55 | public function beforeSave()
56 | {
57 | foreach ($this->required as $required) {
58 | $value = $this->getProperty($required);
59 | if (empty($value)) {
60 | $this->addFieldError($required, $this->modx->lexicon('field_required'));
61 | }
62 | }
63 |
64 | return parent::beforeSave();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/core/components/customrequest/src/Processors/Processor.php:
--------------------------------------------------------------------------------
1 | modx->getOption('customrequest.core_path', null, $this->modx->getOption('core_path') . 'components/customrequest/');
35 | $this->customrequest = $this->modx->getService('customrequest', 'CustomRequest', $corePath . 'model/customrequest/');
36 | }
37 |
38 | /**
39 | * {@inheritDoc}
40 | * @return bool
41 | */
42 | public function checkPermissions()
43 | {
44 | return !empty($this->permission) ? $this->modx->hasPermission($this->permission) : true;
45 | }
46 |
47 | abstract public function process();
48 |
49 | /**
50 | * Get a boolean property.
51 | * @param string $k
52 | * @param mixed $default
53 | * @return bool
54 | */
55 | public function getBooleanProperty($k, $default = null)
56 | {
57 | return ($this->getProperty($k, $default) === 'true' || $this->getProperty($k, $default) === true || $this->getProperty($k, $default) === '1' || $this->getProperty($k, $default) === 1);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/core/components/customrequest/templates/home.tpl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jako/CustomRequest/f91885e1941b374f8ee4ab0d3bb72ca6a513b1c5/core/components/customrequest/templates/home.tpl
--------------------------------------------------------------------------------
/docs/contributors.md:
--------------------------------------------------------------------------------
1 | The CustomRequest project was started in 2013 by [Thomas Jakobi](https://github.com/jako).
2 |
3 | Many thanks to all who contributed, whether by creating pull requests, submitting bug reports, or donating.
--------------------------------------------------------------------------------
/docs/examples.md:
--------------------------------------------------------------------------------
1 | ### Calendar
2 |
3 | With the **Date** configuration you could use an calendar snippet on the
4 | resource with the URI `calendar/date/`. The snippet on that resource would
5 | use the request parameters `year`, `month`, `day`, `title` to identify the
6 | event. An example URI triggering this configuration:
7 | `/calendar/date/2015/09/01/eventname.html`
8 |
9 | The **Calendar** configuration sends the request parameters `year`, `month`,
10 | `day` to another snippet on the resource with the URI `calendar/`. Example
11 | triggering URI: `/calendar/2015/09/01/` [^1]
12 |
13 | Name | Alias Path | Resource | URI Parameter | Regular Expression
14 | --------------|------------|----------|---------------|-------------------
15 | Date | calendar/date/ | | ["year", "month", "day", "title"] |
16 | Calendar | calendar/ | | ["year", "month", "day"] |
17 |
18 | [^1]: If you are using two or more nested aliases in your configs, the deeper alias should be defined before the narrower alias in the configs. You could drag and drop the configurations in the grid of the custom manager page.
19 |
20 | ### Gallery
21 |
22 | With the **Gallery** configuration you could use the Gallery snippet on the
23 | selected resource `Gallery Folder`. The Gallery snippet on that resource would
24 | use the request parameters `galAlbum`, `galItem` to identify the gallery and
25 | the image. An example URI triggering this configuration: `/gallery/01/02/`
26 |
27 | Name | Alias Path | Resource | URI Parameter | Regular Expression
28 | --------------|------------|----------|---------------|-------------------
29 | Gallery | | Gallery Folder | ["galAlbum", "galItem"] |
30 |
31 | ### Different URI
32 |
33 | With the **Different URI** configuration you could call the resource `Test`
34 | with a complete different URI using the request parameters `parameter1`,
35 | `parameter2`. [^2]
36 |
37 | Name | Alias Path | Resource | URI Parameter | Regular Expression
38 | --------------|------------|----------|---------------|-------------------
39 | Different URI | complete/different/uri/ | Test | ["parameter1", "parameter2"] |
40 |
41 | [^2]: The Alias Path does not have to match the alias of the Resource.
42 |
43 | ### Regular Expression
44 |
45 | You could even use regular expressions[^5] to set the request parameters [^3]
46 |
47 | Name | Alias Path | Resource | URI Parameter | Regular Expression
48 | --------------|------------|----------|---------------|-------------------
49 | Expression | | Expression | ["string", "numeric"] | #(.*?)-(\d+)#
50 |
51 | [^3]: This rule does not make much sense. If you have a real world example, please ...
52 |
53 | ### Pagination
54 |
55 | The Alias Path field could be filled with a valid regular expression[^5] (the
56 | color of the grid field is changed to blue then[^4]) and the Resource field
57 | could stay empty. Thay way you could use one pagination configuration for all
58 | pagination calls on the page. The first subpattern part (`page/`) of the
59 | expression is stripped from the not found url and the remaining string is used
60 | to identify the resource where the user is forwarded to later.
61 |
62 | Name | Alias Path | Resource | URI Parameter | Regular Expression
63 | --------------|------------|----------|---------------|-------------------
64 | Pagination | #.*?(page/)# | | ["page"] | #(\d+)#
65 |
66 | [^4]: The regular expression[^5] has to be valid and it should contain [delimiters](https://www.php.net/manual/en/regexp.reference.delimiters.php)
67 |
68 | [^5]: To build and check regular expressions you could i.e. use the [regex101](https://regex101.com/) website.
69 |
70 | ## System Settings
71 |
72 | CustomRequest uses the following system settings in the namespace `customrequest`:
73 |
74 | Key | Description | Default
75 | ----|-------------|--------
76 | customrequest.debug | Log debug information in the MODX error log | No
77 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # CustomRequest
2 |
3 | CustomRequest is an effective routing plugin for MODX Revolution to map pretty
4 | but not found URLs to a MODX resource and set the request parameters by
5 | separating the URI path at the URI separators or by a regular expression.
6 |
7 | ### Requirements
8 |
9 | * MODX Revolution 2.6+
10 | * PHP 7.2+
11 |
12 | ### Features
13 |
14 | * Use pretty URLs everywhere in the MODX Revolution frontend.
15 |
16 | ### License
17 |
18 | The project is licensed under the [GPLv2 license](https://github.com/Jako/CustomRequest/LICENSE.md).
19 |
20 | ### Translations [](https://hosted.weblate.org/projects/modx-extras/customrequest/)
21 |
22 | Translations of the package can be made for the [Default Lexicon](https://hosted.weblate.org/projects/modx-extras/customrequest/standard/) and the [System Setting Lexicon](https://hosted.weblate.org/projects/modx-extras/customrequest/system-settings/)
23 |
24 |
--------------------------------------------------------------------------------
/docs/installation.md:
--------------------------------------------------------------------------------
1 | ## Install from MODX Extras
2 |
3 | Search for CustomRequest in the Package Manager of your MODX installation and
4 | install it in there.
5 |
6 | ## Manual installation
7 |
8 | If you can't access the MODX Extras Repository in your MODX installation, you
9 | can manually install CustomRequest.
10 |
11 | * Download the transport package from [MODX Extras](https://modx.com/extras/package/customrequest) (or one of the pre built transport packages in [_packages](https://github.com/Jako/CustomRequest/tree/master/_packages))
12 | * Upload the zip file to your MODX installation's `core/packages` folder or upload it manually in the MODX Package Manager.
13 | * In the MODX Manager, navigate to the Package Manager page, and select 'Search locally for packages' from the dropdown button.
14 | * CustomRequest should now show up in the list of available packages. Click the corresponding 'Install' button and follow the instructions to complete the installation.
15 |
16 | ## Build it from source
17 |
18 | To build and install the package from source you could use [Git Package
19 | Management](https://github.com/TheBoxer/Git-Package-Management). The GitHub
20 | repository of CustomRequest contains a
21 | [config.json](https://github.com/Jako/CustomRequest/blob/master/_build/config.json)
22 | to build that package locally. Use this option, if you want to debug
23 | CustomRequest and/or contribute bugfixes and enhancements.
24 |
--------------------------------------------------------------------------------
/docs/usage.md:
--------------------------------------------------------------------------------
1 | ## How it works
2 |
3 | CustomRequest works as routing plugin and maps not found URLs to a MODX resource
4 | and set additional request parameters by separating the URI path at the URI
5 | separators or by a regular expression.
6 |
7 | As standard option the first characters of the not found URI will be compared
8 | with the alias value of each config entry. If found, this config entry is used.
9 | The alias path is stripped from the not found URI and the remaining string is
10 | used to set the request parameters.
11 |
12 | As a second option, the alias value of a config entry could contain a valid
13 | regular expression and the not found URI will be matched with that expression.
14 | If matched, this config entry is used. The first subpattern part of the
15 | expression is stripped from the found pattern and the remaining string is used
16 | to identify the resource where the user is forwarded to later. At least the
17 | found pattern is removed from the not found URI and the remaining string is
18 | used to set the request parameters.
19 |
20 | ## Custom Manager Page
21 |
22 | You could configure CustomRequest in a custom manager page in the extras menu.
23 | The CustomRequest configurations could be created on that page.
24 |
25 | The configurations are executed in the order of the grid on this page. If there
26 | are two configurations starting with the same alias path, the first
27 | configuration is used. You can change the order of the configurations by
28 | drag and drop.
29 |
30 | The following settings could be set in each configuration:
31 |
32 | | Key | Description |
33 | |--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
34 | | Name | A name to identify this configuration. |
35 | | Alias Path |
Normally the first characters of a not found URI are compared with this string. If both strings are matching, this configuration is used. If the alias path field is not set, the alias path of the selected resource in this form is used **(The grid value is shown with green text then)**. The alias path is stripped from the not found URI and the remaining string is used to set the request parameters.