1930795f by Jeremy Groot

CPT UI

1 parent 7e7ce19d
Showing 32 changed files with 11508 additions and 0 deletions
1 GNU GENERAL PUBLIC LICENSE
2 Version 2, June 1991
3
4 Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/>
5 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 Everyone is permitted to copy and distribute verbatim copies
7 of this license document, but changing it is not allowed.
8
9 Preamble
10
11 The licenses for most software are designed to take away your
12 freedom to share and change it. By contrast, the GNU General Public
13 License is intended to guarantee your freedom to share and change free
14 software--to make sure the software is free for all its users. This
15 General Public License applies to most of the Free Software
16 Foundation's software and to any other program whose authors commit to
17 using it. (Some other Free Software Foundation software is covered by
18 the GNU Lesser General Public License instead.) You can apply it to
19 your programs, too.
20
21 When we speak of free software, we are referring to freedom, not
22 price. Our General Public Licenses are designed to make sure that you
23 have the freedom to distribute copies of free software (and charge for
24 this service if you wish), that you receive source code or can get it
25 if you want it, that you can change the software or use pieces of it
26 in new free programs; and that you know you can do these things.
27
28 To protect your rights, we need to make restrictions that forbid
29 anyone to deny you these rights or to ask you to surrender the rights.
30 These restrictions translate to certain responsibilities for you if you
31 distribute copies of the software, or if you modify it.
32
33 For example, if you distribute copies of such a program, whether
34 gratis or for a fee, you must give the recipients all the rights that
35 you have. You must make sure that they, too, receive or can get the
36 source code. And you must show them these terms so they know their
37 rights.
38
39 We protect your rights with two steps: (1) copyright the software, and
40 (2) offer you this license which gives you legal permission to copy,
41 distribute and/or modify the software.
42
43 Also, for each author's protection and ours, we want to make certain
44 that everyone understands that there is no warranty for this free
45 software. If the software is modified by someone else and passed on, we
46 want its recipients to know that what they have is not the original, so
47 that any problems introduced by others will not reflect on the original
48 authors' reputations.
49
50 Finally, any free program is threatened constantly by software
51 patents. We wish to avoid the danger that redistributors of a free
52 program will individually obtain patent licenses, in effect making the
53 program proprietary. To prevent this, we have made it clear that any
54 patent must be licensed for everyone's free use or not licensed at all.
55
56 The precise terms and conditions for copying, distribution and
57 modification follow.
58
59 GNU GENERAL PUBLIC LICENSE
60 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
62 0. This License applies to any program or other work which contains
63 a notice placed by the copyright holder saying it may be distributed
64 under the terms of this General Public License. The "Program", below,
65 refers to any such program or work, and a "work based on the Program"
66 means either the Program or any derivative work under copyright law:
67 that is to say, a work containing the Program or a portion of it,
68 either verbatim or with modifications and/or translated into another
69 language. (Hereinafter, translation is included without limitation in
70 the term "modification".) Each licensee is addressed as "you".
71
72 Activities other than copying, distribution and modification are not
73 covered by this License; they are outside its scope. The act of
74 running the Program is not restricted, and the output from the Program
75 is covered only if its contents constitute a work based on the
76 Program (independent of having been made by running the Program).
77 Whether that is true depends on what the Program does.
78
79 1. You may copy and distribute verbatim copies of the Program's
80 source code as you receive it, in any medium, provided that you
81 conspicuously and appropriately publish on each copy an appropriate
82 copyright notice and disclaimer of warranty; keep intact all the
83 notices that refer to this License and to the absence of any warranty;
84 and give any other recipients of the Program a copy of this License
85 along with the Program.
86
87 You may charge a fee for the physical act of transferring a copy, and
88 you may at your option offer warranty protection in exchange for a fee.
89
90 2. You may modify your copy or copies of the Program or any portion
91 of it, thus forming a work based on the Program, and copy and
92 distribute such modifications or work under the terms of Section 1
93 above, provided that you also meet all of these conditions:
94
95 a) You must cause the modified files to carry prominent notices
96 stating that you changed the files and the date of any change.
97
98 b) You must cause any work that you distribute or publish, that in
99 whole or in part contains or is derived from the Program or any
100 part thereof, to be licensed as a whole at no charge to all third
101 parties under the terms of this License.
102
103 c) If the modified program normally reads commands interactively
104 when run, you must cause it, when started running for such
105 interactive use in the most ordinary way, to print or display an
106 announcement including an appropriate copyright notice and a
107 notice that there is no warranty (or else, saying that you provide
108 a warranty) and that users may redistribute the program under
109 these conditions, and telling the user how to view a copy of this
110 License. (Exception: if the Program itself is interactive but
111 does not normally print such an announcement, your work based on
112 the Program is not required to print an announcement.)
113
114 These requirements apply to the modified work as a whole. If
115 identifiable sections of that work are not derived from the Program,
116 and can be reasonably considered independent and separate works in
117 themselves, then this License, and its terms, do not apply to those
118 sections when you distribute them as separate works. But when you
119 distribute the same sections as part of a whole which is a work based
120 on the Program, the distribution of the whole must be on the terms of
121 this License, whose permissions for other licensees extend to the
122 entire whole, and thus to each and every part regardless of who wrote it.
123
124 Thus, it is not the intent of this section to claim rights or contest
125 your rights to work written entirely by you; rather, the intent is to
126 exercise the right to control the distribution of derivative or
127 collective works based on the Program.
128
129 In addition, mere aggregation of another work not based on the Program
130 with the Program (or with a work based on the Program) on a volume of
131 a storage or distribution medium does not bring the other work under
132 the scope of this License.
133
134 3. You may copy and distribute the Program (or a work based on it,
135 under Section 2) in object code or executable form under the terms of
136 Sections 1 and 2 above provided that you also do one of the following:
137
138 a) Accompany it with the complete corresponding machine-readable
139 source code, which must be distributed under the terms of Sections
140 1 and 2 above on a medium customarily used for software interchange; or,
141
142 b) Accompany it with a written offer, valid for at least three
143 years, to give any third party, for a charge no more than your
144 cost of physically performing source distribution, a complete
145 machine-readable copy of the corresponding source code, to be
146 distributed under the terms of Sections 1 and 2 above on a medium
147 customarily used for software interchange; or,
148
149 c) Accompany it with the information you received as to the offer
150 to distribute corresponding source code. (This alternative is
151 allowed only for noncommercial distribution and only if you
152 received the program in object code or executable form with such
153 an offer, in accord with Subsection b above.)
154
155 The source code for a work means the preferred form of the work for
156 making modifications to it. For an executable work, complete source
157 code means all the source code for all modules it contains, plus any
158 associated interface definition files, plus the scripts used to
159 control compilation and installation of the executable. However, as a
160 special exception, the source code distributed need not include
161 anything that is normally distributed (in either source or binary
162 form) with the major components (compiler, kernel, and so on) of the
163 operating system on which the executable runs, unless that component
164 itself accompanies the executable.
165
166 If distribution of executable or object code is made by offering
167 access to copy from a designated place, then offering equivalent
168 access to copy the source code from the same place counts as
169 distribution of the source code, even though third parties are not
170 compelled to copy the source along with the object code.
171
172 4. You may not copy, modify, sublicense, or distribute the Program
173 except as expressly provided under this License. Any attempt
174 otherwise to copy, modify, sublicense or distribute the Program is
175 void, and will automatically terminate your rights under this License.
176 However, parties who have received copies, or rights, from you under
177 this License will not have their licenses terminated so long as such
178 parties remain in full compliance.
179
180 5. You are not required to accept this License, since you have not
181 signed it. However, nothing else grants you permission to modify or
182 distribute the Program or its derivative works. These actions are
183 prohibited by law if you do not accept this License. Therefore, by
184 modifying or distributing the Program (or any work based on the
185 Program), you indicate your acceptance of this License to do so, and
186 all its terms and conditions for copying, distributing or modifying
187 the Program or works based on it.
188
189 6. Each time you redistribute the Program (or any work based on the
190 Program), the recipient automatically receives a license from the
191 original licensor to copy, distribute or modify the Program subject to
192 these terms and conditions. You may not impose any further
193 restrictions on the recipients' exercise of the rights granted herein.
194 You are not responsible for enforcing compliance by third parties to
195 this License.
196
197 7. If, as a consequence of a court judgment or allegation of patent
198 infringement or for any other reason (not limited to patent issues),
199 conditions are imposed on you (whether by court order, agreement or
200 otherwise) that contradict the conditions of this License, they do not
201 excuse you from the conditions of this License. If you cannot
202 distribute so as to satisfy simultaneously your obligations under this
203 License and any other pertinent obligations, then as a consequence you
204 may not distribute the Program at all. For example, if a patent
205 license would not permit royalty-free redistribution of the Program by
206 all those who receive copies directly or indirectly through you, then
207 the only way you could satisfy both it and this License would be to
208 refrain entirely from distribution of the Program.
209
210 If any portion of this section is held invalid or unenforceable under
211 any particular circumstance, the balance of the section is intended to
212 apply and the section as a whole is intended to apply in other
213 circumstances.
214
215 It is not the purpose of this section to induce you to infringe any
216 patents or other property right claims or to contest validity of any
217 such claims; this section has the sole purpose of protecting the
218 integrity of the free software distribution system, which is
219 implemented by public license practices. Many people have made
220 generous contributions to the wide range of software distributed
221 through that system in reliance on consistent application of that
222 system; it is up to the author/donor to decide if he or she is willing
223 to distribute software through any other system and a licensee cannot
224 impose that choice.
225
226 This section is intended to make thoroughly clear what is believed to
227 be a consequence of the rest of this License.
228
229 8. If the distribution and/or use of the Program is restricted in
230 certain countries either by patents or by copyrighted interfaces, the
231 original copyright holder who places the Program under this License
232 may add an explicit geographical distribution limitation excluding
233 those countries, so that distribution is permitted only in or among
234 countries not thus excluded. In such case, this License incorporates
235 the limitation as if written in the body of this License.
236
237 9. The Free Software Foundation may publish revised and/or new versions
238 of the General Public License from time to time. Such new versions will
239 be similar in spirit to the present version, but may differ in detail to
240 address new problems or concerns.
241
242 Each version is given a distinguishing version number. If the Program
243 specifies a version number of this License which applies to it and "any
244 later version", you have the option of following the terms and conditions
245 either of that version or of any later version published by the Free
246 Software Foundation. If the Program does not specify a version number of
247 this License, you may choose any version ever published by the Free Software
248 Foundation.
249
250 10. If you wish to incorporate parts of the Program into other free
251 programs whose distribution conditions are different, write to the author
252 to ask for permission. For software which is copyrighted by the Free
253 Software Foundation, write to the Free Software Foundation; we sometimes
254 make exceptions for this. Our decision will be guided by the two goals
255 of preserving the free status of all derivatives of our free software and
256 of promoting the sharing and reuse of software generally.
257
258 NO WARRANTY
259
260 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 REPAIR OR CORRECTION.
269
270 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 POSSIBILITY OF SUCH DAMAGES.
279
280 END OF TERMS AND CONDITIONS
281
282 How to Apply These Terms to Your New Programs
283
284 If you develop a new program, and you want it to be of the greatest
285 possible use to the public, the best way to achieve this is to make it
286 free software which everyone can redistribute and change under these terms.
287
288 To do so, attach the following notices to the program. It is safest
289 to attach them to the start of each source file to most effectively
290 convey the exclusion of warranty; and each file should have at least
291 the "copyright" line and a pointer to where the full notice is found.
292
293 {description}
294 Copyright (C) {year} {fullname}
295
296 This program is free software; you can redistribute it and/or modify
297 it under the terms of the GNU General Public License as published by
298 the Free Software Foundation; either version 2 of the License, or
299 (at your option) any later version.
300
301 This program is distributed in the hope that it will be useful,
302 but WITHOUT ANY WARRANTY; without even the implied warranty of
303 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 GNU General Public License for more details.
305
306 You should have received a copy of the GNU General Public License along
307 with this program; if not, write to the Free Software Foundation, Inc.,
308 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
310 Also add information on how to contact you by electronic and paper mail.
311
312 If the program is interactive, make it output a short notice like this
313 when it starts in an interactive mode:
314
315 Gnomovision version 69, Copyright (C) year name of author
316 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 This is free software, and you are welcome to redistribute it
318 under certain conditions; type `show c' for details.
319
320 The hypothetical commands `show w' and `show c' should show the appropriate
321 parts of the General Public License. Of course, the commands you use may
322 be called something other than `show w' and `show c'; they could even be
323 mouse-clicks or menu items--whatever suits your program.
324
325 You should also get your employer (if you work as a programmer) or your
326 school, if any, to sign a "copyright disclaimer" for the program, if
327 necessary. Here is a sample; alter the names:
328
329 Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
332 {signature of Ty Coon}, 1 April 1989
333 Ty Coon, President of Vice
334
335 This General Public License does not permit incorporating your program into
336 proprietary programs. If your program is a subroutine library, you may
337 consider it more useful to permit linking proprietary applications with the
338 library. If this is what you want to do, use the GNU Lesser General
339 Public License instead of this License.
340
1 postboxes.add_postbox_toggles(pagenow);
2
3 (function($) {
4 $("#cptui_select_post_type_submit").hide();
5 $("#cptui_select_taxonomy_submit").hide();
6 if ("edit" === getParameterByName("action")) {
7 var original_slug = $("#name").val();
8 }
9 $("#hierarchical").on("change", function() {
10 var hierarchical = $(this).val();
11 if ("1" === hierarchical) {
12 $("#page-attributes").prop("checked", true);
13 } else {
14 $("#page-attributes").prop("checked", false);
15 }
16 });
17 $("#post_type").on("change", function() {
18 $("#cptui_select_post_type").submit();
19 });
20 $("#taxonomy").on("change", function() {
21 $("#cptui_select_taxonomy").submit();
22 });
23 $(".cptui-delete-top, .cptui-delete-bottom").on("click", function(e) {
24 e.preventDefault();
25 var msg = "";
26 if (typeof cptui_type_data !== "undefined") {
27 msg = cptui_type_data.confirm;
28 } else if (typeof cptui_tax_data !== "undefined") {
29 msg = cptui_tax_data.confirm;
30 }
31 var submit_delete_warning = $('<div class="cptui-submit-delete-dialog">' + msg + "</div>").appendTo("#poststuff").dialog({
32 dialogClass: "wp-dialog",
33 modal: true,
34 autoOpen: true,
35 buttons: {
36 OK: function() {
37 var form = $(e.target).closest("form");
38 $(e.target).off("click").click();
39 },
40 Cancel: function() {
41 $(this).dialog("close");
42 }
43 }
44 });
45 });
46 $("#support .question").each(function() {
47 var tis = $(this), state = false, answer = tis.next("div").slideUp();
48 tis.on("click keydown", function(e) {
49 if (e.type === "keydown" && e.keyCode !== 32 && e.keyCode !== 13) {
50 return;
51 }
52 e.preventDefault();
53 state = !state;
54 answer.slideToggle(state);
55 tis.toggleClass("active", state);
56 tis.attr("aria-expanded", state.toString());
57 tis.focus();
58 });
59 });
60 $("#name").on("keyup", function(e) {
61 var value, original_value;
62 value = original_value = $(this).val();
63 if (e.keyCode !== 9 && e.keyCode !== 37 && e.keyCode !== 38 && e.keyCode !== 39 && e.keyCode !== 40) {
64 value = value.replace(/ /g, "_");
65 value = value.toLowerCase();
66 value = replaceDiacritics(value);
67 value = transliterate(value);
68 value = replaceSpecialCharacters(value);
69 if (value !== original_value) {
70 $(this).prop("value", value);
71 }
72 }
73 if (typeof original_slug !== "undefined") {
74 var $slugchanged = $("#slugchanged");
75 if (value != original_slug) {
76 $slugchanged.removeClass("hidemessage");
77 } else {
78 $slugchanged.addClass("hidemessage");
79 }
80 }
81 var $slugexists = $("#slugexists");
82 if (typeof cptui_type_data != "undefined") {
83 if (cptui_type_data.existing_post_types.hasOwnProperty(value) && value !== original_slug) {
84 $slugexists.removeClass("hidemessage");
85 } else {
86 $slugexists.addClass("hidemessage");
87 }
88 }
89 if (typeof cptui_tax_data != "undefined") {
90 if (cptui_tax_data.existing_taxonomies.hasOwnProperty(value) && value !== original_slug) {
91 $slugexists.removeClass("hidemessage");
92 } else {
93 $slugexists.addClass("hidemessage");
94 }
95 }
96 });
97 function replaceDiacritics(s) {
98 var diacritics = [ /[\300-\306]/g, /[\340-\346]/g, /[\310-\313]/g, /[\350-\353]/g, /[\314-\317]/g, /[\354-\357]/g, /[\322-\330]/g, /[\362-\370]/g, /[\331-\334]/g, /[\371-\374]/g, /[\321]/g, /[\361]/g, /[\307]/g, /[\347]/g ];
99 var chars = [ "A", "a", "E", "e", "I", "i", "O", "o", "U", "u", "N", "n", "C", "c" ];
100 for (var i = 0; i < diacritics.length; i++) {
101 s = s.replace(diacritics[i], chars[i]);
102 }
103 return s;
104 }
105 function replaceSpecialCharacters(s) {
106 s = s.replace(/[^a-z0-9\s-]/gi, "_");
107 return s;
108 }
109 function composePreviewContent(value) {
110 var re = /(http|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/;
111 var is_url = re.test(value);
112 if (!value) {
113 return "";
114 } else if (0 === value.indexOf("dashicons-")) {
115 return $('<div class="dashicons-before"><br></div>').addClass(htmlEncode(value));
116 } else if (is_url) {
117 var imgsrc = encodeURI(value);
118 var theimg = document.createElement("IMG");
119 theimg.src = imgsrc;
120 return theimg;
121 }
122 }
123 function htmlEncode(str) {
124 return String(str).replace(/[^-\w. ]/gi, function(c) {
125 return "&#" + c.charCodeAt(0) + ";";
126 });
127 }
128 var cyrillic = {
129 "Ё": "YO",
130 "Й": "I",
131 "Ц": "TS",
132 "У": "U",
133 "К": "K",
134 "Е": "E",
135 "Н": "N",
136 "Г": "G",
137 "Ш": "SH",
138 "Щ": "SCH",
139 "З": "Z",
140 "Х": "H",
141 "Ъ": "'",
142 "ё": "yo",
143 "й": "i",
144 "ц": "ts",
145 "у": "u",
146 "к": "k",
147 "е": "e",
148 "н": "n",
149 "г": "g",
150 "ш": "sh",
151 "щ": "sch",
152 "з": "z",
153 "х": "h",
154 "ъ": "'",
155 "Ф": "F",
156 "Ы": "I",
157 "В": "V",
158 "А": "a",
159 "П": "P",
160 "Р": "R",
161 "О": "O",
162 "Л": "L",
163 "Д": "D",
164 "Ж": "ZH",
165 "Э": "E",
166 "ф": "f",
167 "ы": "i",
168 "в": "v",
169 "а": "a",
170 "п": "p",
171 "р": "r",
172 "о": "o",
173 "л": "l",
174 "д": "d",
175 "ж": "zh",
176 "э": "e",
177 "Я": "Ya",
178 "Ч": "CH",
179 "С": "S",
180 "М": "M",
181 "И": "I",
182 "Т": "T",
183 "Ь": "'",
184 "Б": "B",
185 "Ю": "YU",
186 "я": "ya",
187 "ч": "ch",
188 "с": "s",
189 "м": "m",
190 "и": "i",
191 "т": "t",
192 "ь": "'",
193 "б": "b",
194 "ю": "yu"
195 };
196 function transliterate(word) {
197 return word.split("").map(function(char) {
198 return cyrillic[char] || char;
199 }).join("");
200 }
201 if (undefined != wp.media) {
202 var _custom_media = true, _orig_send_attachment = wp.media.editor.send.attachment;
203 }
204 function getParameterByName(name, url) {
205 if (!url) url = window.location.href;
206 name = name.replace(/[\[\]]/g, "\\$&");
207 var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url);
208 if (!results) return null;
209 if (!results[2]) return "";
210 return decodeURIComponent(results[2].replace(/\+/g, " "));
211 }
212 $("#cptui_choose_icon").on("click", function(e) {
213 e.preventDefault();
214 var button = $(this);
215 var id = jQuery("#menu_icon").attr("id");
216 _custom_media = true;
217 wp.media.editor.send.attachment = function(props, attachment) {
218 if (_custom_media) {
219 $("#" + id).val(attachment.url).change();
220 } else {
221 return _orig_send_attachment.apply(this, [ props, attachment ]);
222 }
223 };
224 wp.media.editor.open(button);
225 return false;
226 });
227 $("#menu_icon").on("change", function() {
228 var value = $(this).val();
229 value = value.trim();
230 $("#menu_icon_preview").html(composePreviewContent(value));
231 });
232 $(".cptui-help").on("click", function(e) {
233 e.preventDefault();
234 });
235 $(".cptui-taxonomy-submit").on("click", function(e) {
236 if ($(".cptui-table :checkbox:checked").length == 0) {
237 e.preventDefault();
238 var no_associated_type_warning = $('<div class="cptui-taxonomy-empty-types-dialog">' + cptui_tax_data.no_associated_type + "</div>").appendTo("#poststuff").dialog({
239 dialogClass: "wp-dialog",
240 modal: true,
241 autoOpen: true,
242 buttons: {
243 OK: function() {
244 $(this).dialog("close");
245 }
246 }
247 });
248 }
249 });
250 $("#auto-populate").on("click tap", function(e) {
251 e.preventDefault();
252 var slug = $("#name").val();
253 var plural = $("#label").val();
254 var singular = $("#singular_label").val();
255 var fields = $('.cptui-labels input[type="text"]');
256 if ("" === slug) {
257 return;
258 }
259 if ("" === plural) {
260 plural = slug;
261 }
262 if ("" === singular) {
263 singular = slug;
264 }
265 $(fields).each(function(i, el) {
266 var newval = $(el).data("label");
267 var plurality = $(el).data("plurality");
268 if ("undefined" !== newval) {
269 if ("plural" === plurality) {
270 newval = newval.replace(/item/gi, plural);
271 } else {
272 newval = newval.replace(/item/gi, singular);
273 }
274 if ($(el).val() === "") {
275 $(el).val(newval);
276 }
277 }
278 });
279 });
280 $("#auto-clear").on("click tap", function(e) {
281 e.preventDefault();
282 var fields = $('.cptui-labels input[type="text"]');
283 $(fields).each(function(i, el) {
284 $(el).val("");
285 });
286 });
287 })(jQuery);
...\ No newline at end of file ...\ No newline at end of file
1 postboxes.add_postbox_toggles(pagenow),function(c){var i;function t(e){var t=/(http|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/.test(e);return e?0===e.indexOf("dashicons-")?c('<div class="dashicons-before"><br></div>').addClass(String(e).replace(/[^-\w. ]/gi,function(e){return"&#"+e.charCodeAt(0)+";"})):t?(t=encodeURI(e),(e=document.createElement("IMG")).src=t,e):void 0:""}c("#cptui_select_post_type_submit").hide(),c("#cptui_select_taxonomy_submit").hide(),"edit"===function(e,t){t=t||window.location.href;e=e.replace(/[\[\]]/g,"\\$&");e=new RegExp("[?&]"+e+"(=([^&#]*)|&|#|$)").exec(t);return e?e[2]?decodeURIComponent(e[2].replace(/\+/g," ")):"":null}("action")&&(i=c("#name").val()),c("#hierarchical").on("change",function(){"1"===c(this).val()?c("#page-attributes").prop("checked",!0):c("#page-attributes").prop("checked",!1)}),c("#post_type").on("change",function(){c("#cptui_select_post_type").submit()}),c("#taxonomy").on("change",function(){c("#cptui_select_taxonomy").submit()}),c(".cptui-delete-top, .cptui-delete-bottom").on("click",function(e){e.preventDefault();var t="";"undefined"!=typeof cptui_type_data?t=cptui_type_data.confirm:"undefined"!=typeof cptui_tax_data&&(t=cptui_tax_data.confirm),c('<div class="cptui-submit-delete-dialog">'+t+"</div>").appendTo("#poststuff").dialog({dialogClass:"wp-dialog",modal:!0,autoOpen:!0,buttons:{OK:function(){c(e.target).closest("form");c(e.target).off("click").click()},Cancel:function(){c(this).dialog("close")}}})}),c("#support .question").each(function(){var t=c(this),a=!1,i=t.next("div").slideUp();t.on("click keydown",function(e){"keydown"===e.type&&32!==e.keyCode&&13!==e.keyCode||(e.preventDefault(),a=!a,i.slideToggle(a),t.toggleClass("active",a),t.attr("aria-expanded",a.toString()),t.focus())})}),c("#name").on("keyup",function(e){var t=a=c(this).val(),a=(9!==e.keyCode&&37!==e.keyCode&&38!==e.keyCode&&39!==e.keyCode&&40!==e.keyCode&&(t=(t=function(e){for(var t=[/[\300-\306]/g,/[\340-\346]/g,/[\310-\313]/g,/[\350-\353]/g,/[\314-\317]/g,/[\354-\357]/g,/[\322-\330]/g,/[\362-\370]/g,/[\331-\334]/g,/[\371-\374]/g,/[\321]/g,/[\361]/g,/[\307]/g,/[\347]/g],a=["A","a","E","e","I","i","O","o","U","u","N","n","C","c"],i=0;i<t.length;i++)e=e.replace(t[i],a[i]);return e}(t=(t=t.replace(/ /g,"_")).toLowerCase())).split("").map(function(e){return s[e]||e}).join(""),(t=t.replace(/[^a-z0-9\s-]/gi,"_"))!==a&&c(this).prop("value",t)),void 0!==i&&(e=c("#slugchanged"),t!=i?e.removeClass("hidemessage"):e.addClass("hidemessage")),c("#slugexists"));"undefined"!=typeof cptui_type_data&&(cptui_type_data.existing_post_types.hasOwnProperty(t)&&t!==i?a.removeClass("hidemessage"):a.addClass("hidemessage")),"undefined"!=typeof cptui_tax_data&&(cptui_tax_data.existing_taxonomies.hasOwnProperty(t)&&t!==i?a.removeClass("hidemessage"):a.addClass("hidemessage"))});var n,o,s={"Ё":"YO","Й":"I","Ц":"TS","У":"U","К":"K","Е":"E","Н":"N","Г":"G","Ш":"SH","Щ":"SCH","З":"Z","Х":"H","Ъ":"'","ё":"yo","й":"i","ц":"ts","у":"u","к":"k","е":"e","н":"n","г":"g","ш":"sh","щ":"sch","з":"z","х":"h","ъ":"'","Ф":"F","Ы":"I","В":"V","А":"a","П":"P","Р":"R","О":"O","Л":"L","Д":"D","Ж":"ZH","Э":"E","ф":"f","ы":"i","в":"v","а":"a","п":"p","р":"r","о":"o","л":"l","д":"d","ж":"zh","э":"e","Я":"Ya","Ч":"CH","С":"S","М":"M","И":"I","Т":"T","Ь":"'","Б":"B","Ю":"YU","я":"ya","ч":"ch","с":"s","м":"m","и":"i","т":"t","ь":"'","б":"b","ю":"yu"};null!=wp.media&&(n=!0,o=wp.media.editor.send.attachment),c("#cptui_choose_icon").on("click",function(e){e.preventDefault();var e=c(this),a=jQuery("#menu_icon").attr("id");return n=!0,wp.media.editor.send.attachment=function(e,t){if(!n)return o.apply(this,[e,t]);c("#"+a).val(t.url).change()},wp.media.editor.open(e),!1}),c("#menu_icon").on("change",function(){var e=(e=c(this).val()).trim();c("#menu_icon_preview").html(t(e))}),c(".cptui-help").on("click",function(e){e.preventDefault()}),c(".cptui-taxonomy-submit").on("click",function(e){0==c(".cptui-table :checkbox:checked").length&&(e.preventDefault(),c('<div class="cptui-taxonomy-empty-types-dialog">'+cptui_tax_data.no_associated_type+"</div>").appendTo("#poststuff").dialog({dialogClass:"wp-dialog",modal:!0,autoOpen:!0,buttons:{OK:function(){c(this).dialog("close")}}}))}),c("#auto-populate").on("click tap",function(e){e.preventDefault();var e=c("#name").val(),n=c("#label").val(),o=c("#singular_label").val(),t=c('.cptui-labels input[type="text"]');""!==e&&(""===n&&(n=e),""===o&&(o=e),c(t).each(function(e,t){var a=c(t).data("label"),i=c(t).data("plurality");"undefined"!==a&&(a="plural"===i?a.replace(/item/gi,n):a.replace(/item/gi,o),""===c(t).val()&&c(t).val(a))}))}),c("#auto-clear").on("click tap",function(e){e.preventDefault();e=c('.cptui-labels input[type="text"]');c(e).each(function(e,t){c(t).val("")})})}(jQuery);
...\ No newline at end of file ...\ No newline at end of file
1 {"version":3,"sources":["src/js/cptui-scripts.js"],"names":["postboxes","add_postbox_toggles","pagenow","$","original_slug","composePreviewContent","value","is_url","test","indexOf","addClass","String","replace","c","charCodeAt","imgsrc","encodeURI","theimg","document","createElement","src","hide","name","url","window","location","href","results","RegExp","exec","decodeURIComponent","getParameterByName","val","on","this","prop","submit","e","preventDefault","msg","cptui_type_data","confirm","cptui_tax_data","appendTo","dialog","dialogClass","modal","autoOpen","buttons","OK","target","closest","off","click","Cancel","each","tis","state","answer","next","slideUp","type","keyCode","slideToggle","toggleClass","attr","toString","focus","original_value","$slugexists","s","diacritics","chars","i","length","replaceDiacritics","toLowerCase","split","map","char","cyrillic","join","$slugchanged","removeClass","existing_post_types","hasOwnProperty","existing_taxonomies","_custom_media","_orig_send_attachment","Ё","Й","Ц","У","К","Е","Н","Г","Ш","Щ","З","Х","Ъ","ё","й","ц","у","к","е","н","г","ш","щ","з","х","ъ","Ф","Ы","В","А","П","Р","О","Л","Д","Ж","Э","ф","ы","в","а","п","р","о","л","д","ж","э","Я","Ч","С","М","И","Т","Ь","Б","Ю","я","ч","с","м","и","т","ь","б","ю","undefined","wp","media","editor","send","attachment","button","id","jQuery","props","apply","change","open","trim","html","no_associated_type","slug","plural","singular","fields","el","newval","data","plurality"],"mappings":"AAGAA,UAAUC,oBAAoBC,SAK9B,SAAUC,GAKT,IAEKC,EAqIL,SAASC,EAAsBC,GAE9B,IACIC,EADK,4EACOC,KAAKF,GAErB,OAAKA,EAEM,IAAMA,EAAMG,QAAQ,cACvBN,EAAE,4CAA4CO,SAU/CC,OAVmEL,GAUvDM,QAAQ,aAAc,SAAUC,GAClD,MAAO,KAAOA,EAAEC,WAAW,GAAK,OAVrBP,GACPQ,EAASC,UAAUV,IACnBW,EAASC,SAASC,cAAc,QAC7BC,IAAML,EACNE,QAJD,EAHC,GAhJTd,EAAE,kCAAkCkB,OACpClB,EAAE,iCAAiCkB,OAE/B,SA6KJ,SAA4BC,EAAMC,GACvBA,EAALA,GAAWC,OAAOC,SAASC,KAChCJ,EAAOA,EAAKV,QAAQ,UAAW,QAE9Be,EADW,IAAIC,OAAO,OAASN,EAAO,qBACtBO,KAAKN,GACtB,OAAKI,EACAA,EAAQ,GACNG,mBAAmBH,EAAQ,GAAGf,QAAQ,MAAO,MAD5B,GADH,KAlLPmB,CAAmB,YAE7B3B,EAAgBD,EAAE,SAAS6B,OAKhC7B,EAAE,iBAAiB8B,GAAG,SAAU,WAE3B,MADe9B,EAAE+B,MAAMF,MAE1B7B,EAAE,oBAAoBgC,KAAK,WAAW,GAEtChC,EAAE,oBAAoBgC,KAAK,WAAW,KAKxChC,EAAE,cAAc8B,GAAG,SAAS,WAC3B9B,EAAE,2BAA2BiC,WAG9BjC,EAAE,aAAa8B,GAAG,SAAS,WAC1B9B,EAAG,0BAA2BiC,WAI/BjC,EAAE,2CAA2C8B,GAAG,QAAQ,SAASI,GAChEA,EAAEC,iBACF,IAAIC,EAAM,GACqB,oBAApBC,gBACVD,EAAMC,gBAAgBC,QACc,oBAAnBC,iBACjBH,EAAMG,eAAeD,SAEMtC,EAAE,2CAA6CoC,EAAM,UAAUI,SAAS,cAAcC,OAAO,CACxHC,YAAkB,YAClBC,OAAkB,EAClBC,UAAkB,EAClBC,QAAkB,CACjBC,GAAM,WACM9C,EAAEkC,EAAEa,QAAQC,QAAQ,QAC/BhD,EAAEkC,EAAEa,QAAQE,IAAI,SAASC,SAE1BC,OAAU,WACTnD,EAAE+B,MAAMU,OAAO,eAOnBzC,EAAE,sBAAsBoD,KAAK,WAC5B,IAAIC,EAAMrD,EAAE+B,MAAOuB,GAAQ,EAAOC,EAASF,EAAIG,KAAK,OAAOC,UAC3DJ,EAAIvB,GAAG,gBAAgB,SAASI,GAEnB,YAATA,EAAEwB,MAAgC,KAAZxB,EAAEyB,SAA4B,KAAZzB,EAAEyB,UAG7CzB,EAAEC,iBACFmB,GAASA,EACTC,EAAOK,YAAYN,GACnBD,EAAIQ,YAAY,SAASP,GACzBD,EAAIS,KAAK,gBAAiBR,EAAMS,YAChCV,EAAIW,aAKNhE,EAAE,SAAS8B,GAAG,QAAQ,SAASI,GAC9B,IACA/B,EAAQ8D,EAAiBjE,EAAE+B,MAAMF,MAsB7BqC,GArBe,IAAdhC,EAAEyB,SAA+B,KAAdzB,EAAEyB,SAAgC,KAAdzB,EAAEyB,SAAgC,KAAdzB,EAAEyB,SAAgC,KAAdzB,EAAEyB,UAIrFxD,GADAA,EAoCF,SAA2BgE,GAa1B,IAZA,IAAIC,EAAa,CAChB,eAAgB,eAChB,eAAgB,eAChB,eAAgB,eAChB,eAAgB,eAChB,eAAgB,eAChB,UAAW,UACX,UAAW,WAGRC,EAAQ,CAAC,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAErEC,EAAI,EAAGA,EAAIF,EAAWG,OAAQD,IACtCH,EAAIA,EAAE1D,QAAQ2D,EAAWE,GAAID,EAAMC,IAGpC,OAAOH,EArDEK,CADRrE,GADAA,EAAQA,EAAMM,QAAQ,KAAM,MACdgE,gBA0FHC,MAAM,IAAIC,IAAI,SAAUC,GACnC,OAAOC,EAASD,IAASA,IACvBE,KAAK,KAzFP3E,EAAiCA,EAuD5BM,QAAQ,iBAAkB,QAtDhBwD,GACdjE,EAAE+B,MAAMC,KAAK,QAAS7B,SAKI,IAAlBF,IACL8E,EAAe/E,EAAE,gBAClBG,GAASF,EACX8E,EAAaC,YAAY,eAEzBD,EAAaxE,SAAS,gBAINP,EAAE,gBACW,oBAAnBqC,kBACPA,gBAAgB4C,oBAAoBC,eAAe/E,IAAUA,IAAUF,EAC1EiE,EAAYc,YAAY,eAExBd,EAAY3D,SAAS,gBAGO,oBAAlBgC,iBACPA,eAAe4C,oBAAoBD,eAAe/E,IAAUA,IAAUF,EACzEiE,EAAYc,YAAY,eAExBd,EAAY3D,SAAS,kBAsDxB,IAWK6E,EACHC,EAZER,EAAW,CACdS,IAAK,KAAMC,IAAK,IAAKC,IAAK,KAAMC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,KAAMC,IAAK,MAAOC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,KAAMC,IAAK,IAAKC,IAAK,KAAMC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,KAAMC,IAAK,MAAOC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,KAAMC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,KAAMC,IAAK,IAAKC,IAAK,KAAMC,IAAK,KAAMC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,KAAMC,IAAK,KAAMC,IAAK,KAAMC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,IAAKC,IAAK,MAS5pBC,MAAaC,GAAGC,QAChBtE,GAAgB,EACnBC,EAAwBoE,GAAGC,MAAMC,OAAOC,KAAKC,YAa/C7J,EAAE,sBAAsB8B,GAAG,QAAQ,SAASI,GAC3CA,EAAEC,iBAEF,IAAI2H,EAAS9J,EAAE+B,MACXgI,EAAKC,OAAO,cAAclG,KAAK,MAWnC,OAVAsB,GAAgB,EAChBqE,GAAGC,MAAMC,OAAOC,KAAKC,WAAa,SAAUI,EAAOJ,GAClD,IAAIzE,EAGH,OAAOC,EAAsB6E,MAAMnI,KAAM,CAACkI,EAAOJ,IAFjD7J,EAAE,IAAM+J,GAAIlI,IAAIgI,EAAWzI,KAAK+I,UAMlCV,GAAGC,MAAMC,OAAOS,KAAKN,IACd,IAGR9J,EAAE,cAAc8B,GAAG,SAAU,WAC5B,IACA3B,GAAQA,EADIH,EAAE+B,MAAMF,OACNwI,OACdrK,EAAE,sBAAsBsK,KAAKpK,EAAsBC,MAGpDH,EAAE,eAAe8B,GAAG,QAAQ,SAASI,GACpCA,EAAEC,mBAGHnC,EAAE,0BAA0B8B,GAAG,QAAQ,SAASI,GACI,GAA9ClC,EAAE,kCAAkCuE,SACxCrC,EAAEC,iBAC+BnC,EAAE,kDAAoDuC,eAAegI,mBAAqB,UAAU/H,SAAS,cAAcC,OAAO,CAClKC,YAAkB,YAClBC,OAAkB,EAClBC,UAAkB,EAClBC,QAAkB,CACjBC,GAAM,WACL9C,EAAE+B,MAAMU,OAAO,gBAOpBzC,EAAE,kBAAkB8B,GAAI,YAAa,SAASI,GAC7CA,EAAEC,iBAEF,IAAIqI,EAAWxK,EAAE,SAAS6B,MACtB4I,EAAWzK,EAAE,UAAU6B,MACvB6I,EAAW1K,EAAE,mBAAmB6B,MAChC8I,EAAW3K,EAAE,oCAEZ,KAAOwK,IAGP,KAAOC,IACXA,EAASD,GAEL,KAAOE,IACXA,EAAWF,GAGZxK,EAAE2K,GAAQvH,KAAM,SAAUkB,EAAGsG,GAC5B,IAAIC,EAAS7K,EAAG4K,GAAKE,KAAM,SACvBC,EAAY/K,EAAG4K,GAAKE,KAAM,aACzB,cAAgBD,IAGnBA,EADI,WAAaE,EACRF,EAAOpK,QAAQ,SAAUgK,GAEzBI,EAAOpK,QAAQ,SAAUiK,GAEZ,KAAlB1K,EAAG4K,GAAK/I,OACZ7B,EAAE4K,GAAI/I,IAAIgJ,SAMd7K,EAAE,eAAe8B,GAAI,YAAa,SAASI,GAC1CA,EAAEC,iBAEEwI,EAAS3K,EAAE,oCAEfA,EAAE2K,GAAQvH,KAAM,SAAUkB,EAAGsG,GAC5B5K,EAAE4K,GAAI/I,IAAI,QAjRb,CAqRGmI"}
...\ No newline at end of file ...\ No newline at end of file
1 .posttypesui, .taxonomiesui {
2 width: calc(100% - 300px); }
3 .posttypesui .cptui-section:first-child, .taxonomiesui .cptui-section:first-child {
4 margin-top: 30px; }
5 .posttypesui .postbox-container, .taxonomiesui .postbox-container {
6 width: 100%; }
7 .posttypesui .postbox .toggle-indicator:before, .taxonomiesui .postbox .toggle-indicator:before {
8 content: "\f142";
9 display: inline-block;
10 font: normal 20px/1 dashicons;
11 speak: none;
12 -webkit-font-smoothing: antialiased;
13 -moz-osx-font-smoothing: grayscale;
14 text-decoration: none !important; }
15 .posttypesui .postbox.closed .handlediv .toggle-indicator::before, .taxonomiesui .postbox.closed .handlediv .toggle-indicator::before {
16 content: "\f140"; }
17 .posttypesui .postbox .hndle, .taxonomiesui .postbox .hndle {
18 cursor: pointer; }
19 .posttypesui .required, .taxonomiesui .required {
20 color: red; }
21
22 .cptui-table td.outer {
23 vertical-align: top;
24 width: 50%; }
25
26 .cptui-table input[type="text"] {
27 width: 75%; }
28
29 .cptui-table .question:hover {
30 cursor: pointer; }
31
32 .cptui-table th p {
33 font-weight: 400;
34 font-size: 12px; }
35
36 .cptui-table .cptui-slug-details {
37 margin-top: 15px; }
38
39 .cptui-table #slugchanged, .cptui-table #slugexists {
40 color: red;
41 font-weight: bold; }
42 .cptui-table #slugchanged.hidemessage, .cptui-table #slugexists.hidemessage {
43 display: none; }
44
45 .cptui-support #support .question {
46 font-size: 18px;
47 font-weight: bold; }
48 .cptui-support #support .question:before {
49 content: "\f139";
50 display: inline-block;
51 font: normal 25px/1 'dashicons';
52 margin-left: -25px;
53 position: absolute;
54 -webkit-font-smoothing: antialiased; }
55 .cptui-support #support .question.active:before {
56 content: "\f140"; }
57
58 .cptui-support #support .answer {
59 margin: 10px 0 0 20px; }
60
61 .cptui-support #support ol li {
62 list-style: none; }
63
64 .cptui-support #support li {
65 position: relative; }
66
67 .cptui-field-description {
68 font-style: italic; }
69
70 #cptui_select_post_type,
71 #cptui_select_taxonomy {
72 margin-top: 15px; }
73
74 .cptui_post_import,
75 .cptui_tax_import {
76 height: 200px;
77 margin-bottom: 10px;
78 resize: vertical;
79 width: 100%; }
80
81 .cptui_post_type_get_code,
82 .cptui_tax_get_code {
83 height: 300px;
84 resize: vertical; }
85
86 .about-wrap .cptui-feature {
87 overflow: visible !important;
88 *zoom: 1; }
89 .about-wrap .cptui-feature:before, .about-wrap .cptui-feature:after {
90 content: " ";
91 display: table; }
92 .about-wrap .cptui-feature:after {
93 clear: both; }
94
95 .about-wrap h3 + .cptui-feature {
96 margin-top: 0; }
97
98 .about-wrap .changelog h2 {
99 text-align: center; }
100
101 .about-wrap .feature-rest div {
102 width: 50% !important;
103 padding-right: 100px;
104 -moz-box-sizing: border-box;
105 box-sizing: border-box;
106 margin: 0 !important; }
107 .about-wrap .feature-rest div.last-feature {
108 padding-left: 100px;
109 padding-right: 0; }
110 .about-wrap .feature-rest div.icon {
111 width: 0 !important;
112 padding: 0;
113 margin: 0; }
114 .about-wrap .feature-rest div.icon:before {
115 font-weight: normal;
116 width: 100%;
117 font-size: 170px;
118 line-height: 125px;
119 color: #9c5d90;
120 display: inline-block;
121 position: relative;
122 text-align: center;
123 speak: none;
124 margin: 0 0 0 -100px;
125 content: "\e01d";
126 -webkit-font-smoothing: antialiased;
127 -moz-osx-font-smoothing: grayscale; }
128
129 .about-wrap .about-integrations {
130 background: #fff;
131 margin: 20px 0;
132 padding: 1px 20px 10px; }
133
134 .about-wrap .changelog h4 {
135 line-height: 1.4; }
136
137 .about-wrap .cptui-about-text {
138 margin-bottom: 1em !important;
139 margin-right: 0;
140 max-width: calc(100% - 173px); }
141
142 .email-octopus-form-row input::placeholder {
143 color: #cccccc; }
144
145 .email-octopus-form-row-hp {
146 visibility: hidden; }
147
148 .cptui-intro-devblock {
149 display: flex;
150 flex-direction: row; }
151
152 .cptui-help {
153 color: #424242;
154 margin-left: 4px;
155 opacity: 0.5;
156 text-decoration: none;
157 width: 16px; }
158 fieldset .cptui-help {
159 position: relative;
160 top: 4px; }
161 .cptui-help:hover {
162 color: #0074a2;
163 opacity: 1; }
164 .cptui-help:focus {
165 box-shadow: none; }
166
167 #menu_icon_preview {
168 float: right;
169 padding-left: 8px; }
170 #menu_icon_preview img {
171 display: block;
172 height: 20px;
173 width: 20px; }
174
175 .visuallyhidden {
176 position: absolute;
177 left: -10000px;
178 top: auto;
179 width: 1px;
180 height: 1px;
181 overflow: hidden; }
182
183 .cptui-spacer {
184 display: block;
185 margin-top: 25px; }
186
187 .email-octopus-form-wrapper {
188 background: #fff;
189 margin-bottom: 10px;
190 padding: 20px; }
191 .email-octopus-form-wrapper label {
192 margin-bottom: 10px; }
193
194 .wdsoctosignup h2 {
195 text-align: left; }
196
197 .wdspromos {
198 float: right;
199 margin-left: 20px;
200 margin-top: 10px;
201 width: 275px; }
202
203 .wdspromos-about {
204 display: -ms-flexbox;
205 display: -webkit-flex;
206 display: flex;
207 -webkit-flex-direction: row;
208 -ms-flex-direction: row;
209 flex-direction: row;
210 -webkit-flex-wrap: nowrap;
211 -ms-flex-wrap: nowrap;
212 flex-wrap: nowrap;
213 -webkit-justify-content: space-between;
214 -ms-flex-pack: justify;
215 justify-content: space-between;
216 -webkit-align-content: stretch;
217 align-content: stretch;
218 -webkit-align-items: flex-start;
219 -ms-flex-align: start;
220 align-items: flex-start;
221 margin: 20px 0; }
222 .wdspromos-about a:nth-child(1) {
223 -ms-flex-order: 0;
224 order: 0;
225 -webkit-flex: 0 1 auto;
226 -ms-flex: 0 1 auto;
227 flex: 0 1 auto;
228 -webkit-align-self: auto;
229 align-self: auto; }
230 .wdspromos-about a:nth-child(2) {
231 -ms-flex-order: 0;
232 order: 0;
233 -webkit-flex: 0 1 auto;
234 -ms-flex: 0 1 auto;
235 flex: 0 1 auto;
236 -webkit-align-self: auto;
237 align-self: auto; }
238 .wdspromos-about a:nth-child(3) {
239 -ms-flex-order: 0;
240 order: 0;
241 -webkit-flex: 0 1 auto;
242 -ms-flex: 0 1 auto;
243 flex: 0 1 auto;
244 -webkit-align-self: auto;
245 align-self: auto; }
246 .wdspromos-about p {
247 padding: 0 5px; }
248 .wdspromos-about p:nth-child(1) {
249 padding-left: 0; }
250 .wdspromos-about p:nth-child(4) {
251 padding-right: 0; }
252
253 .no-js #cptui_choose_icon {
254 display: none; }
255
256 .cptui-listings th {
257 font-weight: bold; }
258
259 .cptui-listings .post-type-listing th {
260 width: 16.66667%; }
261
262 .cptui-listings .taxonomy-listing th {
263 width: 20%; }
264
265 #poststuff {
266 min-width: 463px; }
267
268 .dashicon-picker-container {
269 position: absolute;
270 width: 220px;
271 height: 252px;
272 font-size: 14px;
273 background-color: #fff;
274 box-shadow: -1px 2px 5px 3px rgba(0, 0, 0, 0.41);
275 overflow: hidden;
276 padding: 5px;
277 box-sizing: border-box; }
278 .dashicon-picker-container ul {
279 margin: 0 0 10px;
280 padding: 0; }
281 .dashicon-picker-container ul .dashicons {
282 width: 20px;
283 height: 20px;
284 font-size: 20px; }
285 .dashicon-picker-container ul li {
286 display: inline-block;
287 margin: 5px;
288 float: left; }
289 .dashicon-picker-container ul li a {
290 display: block;
291 text-decoration: none;
292 color: #373737;
293 padding: 5px 5px;
294 border: 1px solid #dfdfdf; }
295 .dashicon-picker-container ul li a:hover {
296 border-color: #999;
297 background: #efefef; }
298
299 .dashicon-picker-control {
300 height: 32px; }
301 .dashicon-picker-control a {
302 padding: 5px;
303 text-decoration: none;
304 line-height: 32px;
305 width: 25px; }
306 .dashicon-picker-control a span {
307 display: inline;
308 vertical-align: middle; }
309 .dashicon-picker-control input {
310 font-size: 12px;
311 width: 140px; }
312
313 @media screen and (min-width: 769px) {
314 .cptui-badge {
315 margin-top: -42px;
316 height: 173px;
317 width: 173px;
318 color: #fafafa;
319 font-weight: bold;
320 font-size: 14px;
321 text-align: center;
322 margin-bottom: 10px;
323 background: url(../images/cptui-icon-173x173.png) no-repeat;
324 background-size: contain; } }
325
326 @media screen and (max-width: 768px) {
327 .cptui-table #description {
328 width: 100%; }
329 .wdspromos-about {
330 flex-wrap: wrap; }
331 .wdspromos-about p {
332 margin: 5px auto; }
333 .wdspromos-about p:nth-child(1) {
334 padding-left: 5px; }
335 .wdspromos-about p:nth-child(4) {
336 padding-right: 5px; }
337 .cptui-table td.outer {
338 width: 100%; }
339 #cptui_debug_info_email {
340 width: 100%; } }
341
342 /*# sourceMappingURL=cptui-styles.css.map */
...\ No newline at end of file ...\ No newline at end of file
1 {
2 "version": 3,
3 "file": "cptui-styles.css",
4 "sources": [
5 "../src/scss/cptui-styles.scss"
6 ],
7 "names": [],
8 "mappings": "AAGA,AAAA,YAAY,EAAE,aAAa,CAAC;EAI3B,KAAK,EAAE,kBAAkB,GAsBzB;EA1BD,AACC,YADW,CACX,cAAc,AAAA,YAAY,EADb,aAAa,CAC1B,cAAc,AAAA,YAAY,CAAC;IAC1B,UAAU,EAAE,IAAI,GAChB;EAHF,AAKC,YALW,CAKX,kBAAkB,EALL,aAAa,CAK1B,kBAAkB,CAAC;IACjB,KAAK,EAAE,IAAI,GACZ;EAPF,AAQC,YARW,CAQX,QAAQ,CAAC,iBAAiB,AAAA,OAAO,EARpB,aAAa,CAQ1B,QAAQ,CAAC,iBAAiB,AAAA,OAAO,CAAC;IACjC,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,YAAY;IACrB,IAAI,EAAE,uBAAuB;IAC7B,KAAK,EAAE,IAAI;IACX,sBAAsB,EAAE,WAAW;IACnC,uBAAuB,EAAE,SAAS;IAClC,eAAe,EAAE,eAAe,GAChC;EAhBF,AAiBC,YAjBW,CAiBX,QAAQ,AAAA,OAAO,CAAC,UAAU,CAAC,iBAAiB,AAAA,QAAQ,EAjBvC,aAAa,CAiB1B,QAAQ,AAAA,OAAO,CAAC,UAAU,CAAC,iBAAiB,AAAA,QAAQ,CAAC;IACpD,OAAO,EAAE,OAAO,GAChB;EAnBF,AAoBC,YApBW,CAoBX,QAAQ,CAAC,MAAM,EApBF,aAAa,CAoB1B,QAAQ,CAAC,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,GACf;EAtBF,AAuBC,YAvBW,CAuBX,SAAS,EAvBI,aAAa,CAuB1B,SAAS,CAAC;IACT,KAAK,EAAE,GAAc,GACrB;;AAEF,AACC,YADW,CACX,EAAE,AAAA,MAAM,CAAC;EACR,cAAc,EAAE,GAAG;EACnB,KAAK,EAAE,GAAG,GACV;;AAJF,AAKC,YALW,CAKX,KAAK,CAAA,AAAA,IAAC,CAAK,MAAM,AAAX,EAAa;EAClB,KAAK,EAAE,GAAG,GACV;;AAPF,AAQC,YARW,CAQX,SAAS,AAAA,MAAM,CAAC;EACf,MAAM,EAAE,OAAO,GACf;;AAVF,AAWC,YAXW,CAWX,EAAE,CAAC,CAAC,CAAC;EACJ,WAAW,EAAE,GAAG;EAChB,SAAS,EAAE,IAAI,GACf;;AAdF,AAeC,YAfW,CAeX,mBAAmB,CAAC;EACnB,UAAU,EAAE,IAAI,GAChB;;AAjBF,AAmBC,YAnBW,CAmBX,YAAY,EAnBb,YAAY,CAmBG,WAAW,CAAC;EACzB,KAAK,EAAE,GAAG;EACV,WAAW,EAAE,IAAI,GAIjB;EAzBF,AAsBE,YAtBU,CAmBX,YAAY,AAGV,YAAY,EAtBf,YAAY,CAmBG,WAAW,AAGvB,YAAY,CAAC;IACb,OAAO,EAAE,IAAI,GACb;;AAIH,AACC,cADa,CAAC,QAAQ,CACtB,SAAS,CAAC;EACT,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,IAAI,GAYjB;EAfF,AAIE,cAJY,CAAC,QAAQ,CACtB,SAAS,AAGP,OAAO,CAAC;IACR,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,YAAY;IACrB,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,KAAK;IAClB,QAAQ,EAAE,QAAQ;IAClB,sBAAsB,EAAE,WAAW,GACnC;EAXH,AAYE,cAZY,CAAC,QAAQ,CACtB,SAAS,AAWP,OAAO,AAAA,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,GAChB;;AAdH,AAgBC,cAhBa,CAAC,QAAQ,CAgBtB,OAAO,CAAC;EACP,MAAM,EAAE,aAAa,GACrB;;AAlBF,AAmBC,cAnBa,CAAC,QAAQ,CAmBtB,EAAE,CAAC,EAAE,CAAC;EACL,UAAU,EAAE,IAAI,GAChB;;AArBF,AAsBC,cAtBa,CAAC,QAAQ,CAsBtB,EAAE,CAAC;EACF,QAAQ,EAAE,QAAQ,GAClB;;AAEF,AAAA,wBAAwB,CAAC;EACxB,UAAU,EAAE,MAAM,GAClB;;AACD,AAAA,uBAAuB;AACvB,sBAAsB,CAAC;EACtB,UAAU,EAAE,IAAI,GAChB;;AACD,AAAA,kBAAkB;AAClB,iBAAiB,CAAC;EACjB,MAAM,EAAE,KAAK;EACb,aAAa,EAAE,IAAI;EACnB,MAAM,EAAE,QAAQ;EAChB,KAAK,EAAE,IAAI,GACX;;AACD,AAAA,yBAAyB;AACzB,mBAAmB,CAAC;EACnB,MAAM,EAAE,KAAK;EACb,MAAM,EAAE,QAAQ,GAChB;;AACD,AACC,WADU,CACV,cAAc,CAAC;EACd,QAAQ,EAAE,kBAAkB;EAC5B,KAAK,EAAC,CAAC,GASP;EAZF,AAIE,WAJS,CACV,cAAc,AAGZ,OAAO,EAJV,WAAW,CACV,cAAc,AAIZ,MAAM,CAAC;IACP,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,KAAK,GACd;EARH,AASE,WATS,CACV,cAAc,AAQZ,MAAM,CAAC;IACP,KAAK,EAAE,IAAI,GACX;;AAXH,AAaC,WAbU,CAaV,EAAE,GAAG,cAAc,CAAC;EACnB,UAAU,EAAE,CAAC,GACb;;AAfF,AAiBG,WAjBQ,CAgBR,UAAU,CACV,EAAE,CAAC;EACJ,UAAU,EAAE,MAAM,GAChB;;AAnBJ,AAsBE,WAtBS,CAqBV,aAAa,CACZ,GAAG,CAAC;EACH,KAAK,EAAE,cAAc;EACrB,aAAa,EAAE,KAAK;EACpB,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,YAAY,GAyBpB;EApDH,AA4BG,WA5BQ,CAqBV,aAAa,CACZ,GAAG,AAMD,aAAa,CAAC;IACd,YAAY,EAAE,KAAK;IACnB,aAAa,EAAE,CAAC,GAChB;EA/BJ,AAgCG,WAhCQ,CAqBV,aAAa,CACZ,GAAG,AAUD,KAAK,CAAC;IACN,KAAK,EAAE,YAAY;IACnB,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,CAAC,GAgBT;IAnDJ,AAoCI,WApCO,CAqBV,aAAa,CACZ,GAAG,AAUD,KAAK,AAIJ,OAAO,CAAC;MACR,WAAW,EAAE,MAAM;MACnB,KAAK,EAAE,IAAI;MACX,SAAS,EAAE,KAAK;MAChB,WAAW,EAAE,KAAK;MAClB,KAAK,EAAE,OAAO;MACd,OAAO,EAAE,YAAY;MACrB,QAAQ,EAAE,QAAQ;MAClB,UAAU,EAAE,MAAM;MAClB,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,YAAY;MACpB,OAAO,EAAE,OAAO;MAChB,sBAAsB,EAAE,WAAW;MACnC,uBAAuB,EAAE,SAAS,GAClC;;AAKL,AACC,WADU,CACV,mBAAmB,CAAC;EACnB,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,aAAa,GACtB;;AALF,AAOE,WAPS,CAMV,UAAU,CACT,EAAE,CAAC;EACF,WAAW,EAAE,GAAG,GAChB;;AATH,AAWC,WAXU,CAWV,iBAAiB,CAAC;EACjB,aAAa,EAAE,cAAc;EAC7B,YAAY,EAAE,CAAC;EACf,SAAS,EAAE,kBAAkB,GAC7B;;AAEF,AACC,uBADsB,CACtB,KAAK,AAAA,aAAa,CAAC;EAClB,KAAK,EAAE,OAAO,GACd;;AAEF,AAAA,0BAA0B,CAAC;EAC1B,UAAU,EAAE,MAAM,GAClB;;AACD,AAAA,qBAAqB,CAAA;EACjB,OAAO,EAAE,IAAI;EACb,cAAc,EAAE,GAAG,GACtB;;AAED,AAAA,WAAW,CAAC;EACX,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,GAAG;EAChB,OAAO,EAAE,GAAG;EACZ,eAAe,EAAE,IAAI;EACrB,KAAK,EAAE,IAAI,GAYX;EAXA,AAAA,QAAQ,CANT,WAAW,CAMC;IACV,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,GAAG,GACR;EATF,AAUC,WAVU,AAUT,MAAM,CAAC;IACP,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,CAAC,GACV;EAbF,AAcC,WAdU,AAcT,MAAM,CAAC;IACP,UAAU,EAAE,IAAI,GAChB;;AAEF,AAAA,kBAAkB,CAAC;EAClB,KAAK,EAAE,KAAK;EACZ,YAAY,EAAE,GAAG,GAOjB;EATD,AAIC,kBAJiB,CAIjB,GAAG,CAAC;IACH,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI,GACX;;AAGF,AAAA,eAAe,CAAC;EACf,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,QAAQ;EACd,GAAG,EAAE,IAAI;EACT,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,GAAG;EACX,QAAQ,EAAE,MAAM,GAChB;;AACD,AAAA,aAAa,CAAC;EACb,OAAO,EAAE,KAAK;EACd,UAAU,EAAE,IAAI,GAChB;;AAED,AAAA,2BAA2B,CAAC;EAC3B,UAAU,EAAE,IAAI;EAChB,aAAa,EAAE,IAAI;EACnB,OAAO,EAAE,IAAI,GAIb;EAPD,AAIC,2BAJ0B,CAI1B,KAAK,CAAC;IACL,aAAa,EAAE,IAAI,GACnB;;AAGF,AACC,cADa,CACb,EAAE,CAAC;EACF,UAAU,EAAC,IAAI,GACf;;AAGF,AAAA,UAAU,CAAC;EACV,KAAK,EAAE,KAAK;EACZ,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,IAAI;EAChB,KAAK,EAAE,KAAK,GACZ;;AACD,AAAA,gBAAgB,CAAC;EAChB,OAAO,EAAE,WAAW;EACpB,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,IAAI;EACb,sBAAsB,EAAE,GAAG;EAC3B,kBAAkB,EAAE,GAAG;EACvB,cAAc,EAAE,GAAG;EACnB,iBAAiB,EAAE,MAAM;EACzB,aAAa,EAAE,MAAM;EACrB,SAAS,EAAE,MAAM;EACjB,uBAAuB,EAAE,aAAa;EACtC,aAAa,EAAE,OAAO;EACtB,eAAe,EAAE,aAAa;EAC9B,qBAAqB,EAAE,OAAO;EAC9B,aAAa,EAAE,OAAO;EACtB,mBAAmB,EAAE,UAAU;EAC/B,cAAc,EAAE,KAAK;EACrB,WAAW,EAAE,UAAU;EACvB,MAAM,EAAE,MAAM,GAwCd;EA1DD,AAoBC,gBApBe,CAoBf,CAAC,AAAA,UAAW,CAAA,CAAC,EAAE;IACd,cAAc,EAAE,CAAC;IACjB,KAAK,EAAE,CAAC;IACR,YAAY,EAAE,QAAQ;IACtB,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,QAAQ;IACd,kBAAkB,EAAE,IAAI;IACxB,UAAU,EAAE,IAAI,GAChB;EA5BF,AA8BC,gBA9Be,CA8Bf,CAAC,AAAA,UAAW,CAAA,CAAC,EAAE;IACd,cAAc,EAAE,CAAC;IACjB,KAAK,EAAE,CAAC;IACR,YAAY,EAAE,QAAQ;IACtB,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,QAAQ;IACd,kBAAkB,EAAE,IAAI;IACxB,UAAU,EAAE,IAAI,GAChB;EAtCF,AAwCC,gBAxCe,CAwCf,CAAC,AAAA,UAAW,CAAA,CAAC,EAAE;IACd,cAAc,EAAE,CAAC;IACjB,KAAK,EAAE,CAAC;IACR,YAAY,EAAE,QAAQ;IACtB,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,QAAQ;IACd,kBAAkB,EAAE,IAAI;IACxB,UAAU,EAAE,IAAI,GAChB;EAhDF,AAiDC,gBAjDe,CAiDf,CAAC,CAAC;IACA,OAAO,EAAE,KAAK,GAOf;IAzDF,AAmDG,gBAnDa,CAiDf,CAAC,AAEE,UAAW,CAAA,CAAC,EAAE;MAChB,YAAY,EAAE,CAAC,GACb;IArDJ,AAsDG,gBAtDa,CAiDf,CAAC,AAKE,UAAW,CAAA,CAAC,EAAE;MAChB,aAAa,EAAE,CAAC,GACd;;AAGJ,AACC,MADK,CACL,kBAAkB,CAAC;EAClB,OAAO,EAAE,IACV,GAAC;;AAEF,AACC,eADc,CACd,EAAE,CAAC;EACF,WAAW,EAAE,IAAI,GACjB;;AAHF,AAKE,eALa,CAId,kBAAkB,CACjB,EAAE,CAAC;EACF,KAAK,EAAE,SAAS,GAChB;;AAPH,AAUE,eAVa,CASd,iBAAiB,CAChB,EAAE,CAAC;EACF,KAAK,EAAE,GAAG,GACV;;AAGH,AAAA,UAAU,CAAC;EACV,SAAS,EAAE,KAAK,GAChB;;AAED,AAAA,0BAA0B,CAAC;EAC1B,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,KAAK;EACb,SAAS,EAAE,IAAI;EACf,gBAAgB,EAAE,IAAI;EACtB,UAAU,EAAG,IAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,mBAAmB;EAChD,QAAQ,EAAE,MAAM;EAChB,OAAO,EAAE,GAAG;EACZ,UAAU,EAAE,UAAU,GA+BtB;EAxCD,AAWC,0BAXyB,CAWzB,EAAE,CAAC;IACF,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,CAAC,GA0BV;IAvCF,AAeE,0BAfwB,CAWzB,EAAE,CAID,UAAU,CAAC;MACV,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,SAAS,EAAE,IAAI,GACf;IAnBH,AAqBE,0BArBwB,CAWzB,EAAE,CAUD,EAAE,CAAC;MACF,OAAO,EAAE,YAAY;MACrB,MAAM,EAAE,GAAG;MACX,KAAK,EAAE,IAAI,GAcX;MAtCH,AA0BG,0BA1BuB,CAWzB,EAAE,CAUD,EAAE,CAKD,CAAC,CAAC;QACD,OAAO,EAAE,KAAK;QACd,eAAe,EAAE,IAAI;QACrB,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,OAAO;QAChB,MAAM,EAAE,iBAAiB,GAMzB;QArCJ,AAiCI,0BAjCsB,CAWzB,EAAE,CAUD,EAAE,CAKD,CAAC,AAOC,MAAM,CAAC;UACP,YAAY,EAAE,IAAI;UAClB,UAAU,EAAE,OAAO,GACnB;;AAML,AAAA,wBAAwB,CAAC;EACxB,MAAM,EAAE,IAAI,GAkBZ;EAnBD,AAGC,wBAHuB,CAGvB,CAAC,CAAC;IACD,OAAO,EAAE,GAAG;IACZ,eAAe,EAAE,IAAI;IACrB,WAAW,EAAE,IAAI;IACjB,KAAK,EAAE,IAAI,GAMX;IAbF,AASE,wBATsB,CAGvB,CAAC,CAMA,IAAI,CAAC;MACJ,OAAO,EAAE,MAAM;MACf,cAAc,EAAE,MAAM,GACtB;EAZH,AAeC,wBAfuB,CAevB,KAAK,CAAC;IACL,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,KAAK,GACZ;;AAGF,MAAM,CAAC,MAAM,MAAM,SAAS,EAAE,KAAK;EAClC,AAAA,YAAY,CAAC;IACZ,UAAU,EAAE,KAAK;IACd,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,MAAM;IAClB,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,qCAAqC,CAAC,SAAS;IAC9D,eAAe,EAAE,OAAO,GACxB;;AAGF,MAAM,CAAC,MAAM,MAAM,SAAS,EAAE,KAAK;EACjC,AACD,YADa,CACb,YAAY,CAAC;IACX,KAAK,EAAE,IAAI,GACZ;EAEA,AAAA,gBAAgB,CAAC;IAClB,SAAS,EAAE,IAAI,GAUb;IAXD,AAED,gBAFiB,CAEjB,CAAC,CAAC;MACA,MAAM,EAAE,QAAQ,GAOjB;MAVA,AAIC,gBAJe,CAEjB,CAAC,AAEE,UAAW,CAAA,CAAC,EAAE;QAChB,YAAY,EAAE,GAAG,GACf;MANF,AAOC,gBAPe,CAEjB,CAAC,AAKE,UAAW,CAAA,CAAC,EAAE;QAChB,aAAa,EAAE,GAAG,GAChB;EAGF,AACD,YADa,CACb,EAAE,AAAA,MAAM,CAAC;IACP,KAAK,EAAE,IAAI,GACZ;EAGA,AAAA,uBAAuB,CAAC;IACzB,KAAK,EAAE,IAAI,GACT"
9 }
...\ No newline at end of file ...\ No newline at end of file
1 .posttypesui,.taxonomiesui{width:calc(100% - 300px)}.posttypesui .cptui-section:first-child,.taxonomiesui .cptui-section:first-child{margin-top:30px}.posttypesui .postbox-container,.taxonomiesui .postbox-container{width:100%}.posttypesui .postbox .toggle-indicator:before,.taxonomiesui .postbox .toggle-indicator:before{content:"\f142";display:inline-block;font:normal 20px/1 dashicons;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none !important}.posttypesui .postbox.closed .handlediv .toggle-indicator::before,.taxonomiesui .postbox.closed .handlediv .toggle-indicator::before{content:"\f140"}.posttypesui .postbox .hndle,.taxonomiesui .postbox .hndle{cursor:pointer}.posttypesui .required,.taxonomiesui .required{color:red}.cptui-table td.outer{vertical-align:top;width:50%}.cptui-table input[type="text"]{width:75%}.cptui-table .question:hover{cursor:pointer}.cptui-table th p{font-weight:400;font-size:12px}.cptui-table .cptui-slug-details{margin-top:15px}.cptui-table #slugchanged,.cptui-table #slugexists{color:red;font-weight:bold}.cptui-table #slugchanged.hidemessage,.cptui-table #slugexists.hidemessage{display:none}.cptui-support #support .question{font-size:18px;font-weight:bold}.cptui-support #support .question:before{content:"\f139";display:inline-block;font:normal 25px/1 'dashicons';margin-left:-25px;position:absolute;-webkit-font-smoothing:antialiased}.cptui-support #support .question.active:before{content:"\f140"}.cptui-support #support .answer{margin:10px 0 0 20px}.cptui-support #support ol li{list-style:none}.cptui-support #support li{position:relative}.cptui-field-description{font-style:italic}#cptui_select_post_type,#cptui_select_taxonomy{margin-top:15px}.cptui_post_import,.cptui_tax_import{height:200px;margin-bottom:10px;resize:vertical;width:100%}.cptui_post_type_get_code,.cptui_tax_get_code{height:300px;resize:vertical}.about-wrap .cptui-feature{overflow:visible !important;*zoom:1}.about-wrap .cptui-feature:before,.about-wrap .cptui-feature:after{content:" ";display:table}.about-wrap .cptui-feature:after{clear:both}.about-wrap h3+.cptui-feature{margin-top:0}.about-wrap .changelog h2{text-align:center}.about-wrap .feature-rest div{width:50% !important;padding-right:100px;-moz-box-sizing:border-box;box-sizing:border-box;margin:0 !important}.about-wrap .feature-rest div.last-feature{padding-left:100px;padding-right:0}.about-wrap .feature-rest div.icon{width:0 !important;padding:0;margin:0}.about-wrap .feature-rest div.icon:before{font-weight:normal;width:100%;font-size:170px;line-height:125px;color:#9c5d90;display:inline-block;position:relative;text-align:center;speak:none;margin:0 0 0 -100px;content:"\e01d";-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.about-wrap .about-integrations{background:#fff;margin:20px 0;padding:1px 20px 10px}.about-wrap .changelog h4{line-height:1.4}.about-wrap .cptui-about-text{margin-bottom:1em !important;margin-right:0;max-width:calc(100% - 173px)}.email-octopus-form-row input::placeholder{color:#cccccc}.email-octopus-form-row-hp{visibility:hidden}.cptui-intro-devblock{display:flex;flex-direction:row}.cptui-help{color:#424242;margin-left:4px;opacity:0.5;text-decoration:none;width:16px}fieldset .cptui-help{position:relative;top:4px}.cptui-help:hover{color:#0074a2;opacity:1}.cptui-help:focus{box-shadow:none}#menu_icon_preview{float:right;padding-left:8px}#menu_icon_preview img{display:block;height:20px;width:20px}.visuallyhidden{position:absolute;left:-10000px;top:auto;width:1px;height:1px;overflow:hidden}.cptui-spacer{display:block;margin-top:25px}.email-octopus-form-wrapper{background:#fff;margin-bottom:10px;padding:20px}.email-octopus-form-wrapper label{margin-bottom:10px}.wdsoctosignup h2{text-align:left}.wdspromos{float:right;margin-left:20px;margin-top:10px;width:275px}.wdspromos-about{display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-content:stretch;align-content:stretch;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;margin:20px 0}.wdspromos-about a:nth-child(1){-ms-flex-order:0;order:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;-webkit-align-self:auto;align-self:auto}.wdspromos-about a:nth-child(2){-ms-flex-order:0;order:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;-webkit-align-self:auto;align-self:auto}.wdspromos-about a:nth-child(3){-ms-flex-order:0;order:0;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;-webkit-align-self:auto;align-self:auto}.wdspromos-about p{padding:0 5px}.wdspromos-about p:nth-child(1){padding-left:0}.wdspromos-about p:nth-child(4){padding-right:0}.no-js #cptui_choose_icon{display:none}.cptui-listings th{font-weight:bold}.cptui-listings .post-type-listing th{width:16.66667%}.cptui-listings .taxonomy-listing th{width:20%}#poststuff{min-width:463px}.dashicon-picker-container{position:absolute;width:220px;height:252px;font-size:14px;background-color:#fff;box-shadow:-1px 2px 5px 3px rgba(0,0,0,0.41);overflow:hidden;padding:5px;box-sizing:border-box}.dashicon-picker-container ul{margin:0 0 10px;padding:0}.dashicon-picker-container ul .dashicons{width:20px;height:20px;font-size:20px}.dashicon-picker-container ul li{display:inline-block;margin:5px;float:left}.dashicon-picker-container ul li a{display:block;text-decoration:none;color:#373737;padding:5px 5px;border:1px solid #dfdfdf}.dashicon-picker-container ul li a:hover{border-color:#999;background:#efefef}.dashicon-picker-control{height:32px}.dashicon-picker-control a{padding:5px;text-decoration:none;line-height:32px;width:25px}.dashicon-picker-control a span{display:inline;vertical-align:middle}.dashicon-picker-control input{font-size:12px;width:140px}@media screen and (min-width: 769px){.cptui-badge{margin-top:-42px;height:173px;width:173px;color:#fafafa;font-weight:bold;font-size:14px;text-align:center;margin-bottom:10px;background:url(../images/cptui-icon-173x173.png) no-repeat;background-size:contain}}@media screen and (max-width: 768px){.cptui-table #description{width:100%}.wdspromos-about{flex-wrap:wrap}.wdspromos-about p{margin:5px auto}.wdspromos-about p:nth-child(1){padding-left:5px}.wdspromos-about p:nth-child(4){padding-right:5px}.cptui-table td.outer{width:100%}#cptui_debug_info_email{width:100%}}
1 (function($) {
2 "use strict";
3 $.fn.dashiconsPicker = function() {
4 var icons = [ "menu", "admin-site", "dashboard", "admin-media", "admin-page", "admin-comments", "admin-appearance", "admin-plugins", "admin-users", "admin-tools", "admin-settings", "admin-network", "admin-generic", "admin-home", "admin-collapse", "filter", "admin-customizer", "admin-multisite", "admin-links", "format-links", "admin-post", "format-standard", "format-image", "format-gallery", "format-audio", "format-video", "format-chat", "format-status", "format-aside", "format-quote", "welcome-write-blog", "welcome-edit-page", "welcome-add-page", "welcome-view-site", "welcome-widgets-menus", "welcome-comments", "welcome-learn-more", "image-crop", "image-rotate", "image-rotate-left", "image-rotate-right", "image-flip-vertical", "image-flip-horizontal", "image-filter", "undo", "redo", "editor-bold", "editor-italic", "editor-ul", "editor-ol", "editor-quote", "editor-alignleft", "editor-aligncenter", "editor-alignright", "editor-insertmore", "editor-spellcheck", "editor-distractionfree", "editor-expand", "editor-contract", "editor-kitchensink", "editor-underline", "editor-justify", "editor-textcolor", "editor-paste-word", "editor-paste-text", "editor-removeformatting", "editor-video", "editor-customchar", "editor-outdent", "editor-indent", "editor-help", "editor-strikethrough", "editor-unlink", "editor-rtl", "editor-break", "editor-code", "editor-paragraph", "editor-table", "align-left", "align-right", "align-center", "align-none", "lock", "unlock", "calendar", "calendar-alt", "visibility", "hidden", "post-status", "edit", "post-trash", "trash", "sticky", "external", "arrow-up", "arrow-down", "arrow-left", "arrow-right", "arrow-up-alt", "arrow-down-alt", "arrow-left-alt", "arrow-right-alt", "arrow-up-alt2", "arrow-down-alt2", "arrow-left-alt2", "arrow-right-alt2", "leftright", "sort", "randomize", "list-view", "excerpt-view", "grid-view", "hammer", "art", "migrate", "performance", "universal-access", "universal-access-alt", "tickets", "nametag", "clipboard", "heart", "megaphone", "schedule", "wordpress", "wordpress-alt", "pressthis", "update", "screenoptions", "cart", "feedback", "cloud", "translation", "tag", "category", "archive", "tagcloud", "text", "media-archive", "media-audio", "media-code", "media-default", "media-document", "media-interactive", "media-spreadsheet", "media-text", "media-video", "playlist-audio", "playlist-video", "controls-play", "controls-pause", "controls-forward", "controls-skipforward", "controls-back", "controls-skipback", "controls-repeat", "controls-volumeon", "controls-volumeoff", "yes", "no", "no-alt", "plus", "plus-alt", "plus-alt2", "minus", "dismiss", "marker", "star-filled", "star-half", "star-empty", "flag", "info", "warning", "share", "share1", "share-alt", "share-alt2", "twitter", "rss", "email", "email-alt", "facebook", "facebook-alt", "networking", "googleplus", "location", "location-alt", "camera", "images-alt", "images-alt2", "video-alt", "video-alt2", "video-alt3", "vault", "shield", "shield-alt", "sos", "search", "slides", "analytics", "chart-pie", "chart-bar", "chart-line", "chart-area", "groups", "businessman", "id", "id-alt", "products", "awards", "forms", "testimonial", "portfolio", "book", "book-alt", "download", "upload", "backup", "clock", "lightbulb", "microphone", "desktop", "tablet", "smartphone", "phone", "smiley", "index-card", "carrot", "building", "store", "album", "palmtree", "tickets-alt", "money", "thumbs-up", "thumbs-down", "layout", "align-pull-left", "align-pull-right", "block-default", "cloud-saved", "cloud-upload", "columns", "cover-image", "embed-audio", "embed-generic", "embed-photo", "embed-post", "embed-video", "exit", "html", "info-outline", "insert-after", "insert-before", "insert", "remove", "shortcode", "table-col-after", "table-col-before", "table-col-delete", "table-row-after", "table-row-before", "table-row-delete", "saved", "amazon", "google", "linkedin", "pinterest", "podio", "reddit", "spotify", "twitch", "whatsapp", "xing", "youtube", "database-add", "database-export", "database-import", "database-remove", "database-view", "database", "bell", "airplane", "car", "calculator", "ames", "printer", "beer", "coffee", "drumstick", "food", "bank", "hourglass", "money-alt", "open-folder", "pdf", "pets", "privacy", "superhero", "superhero-alt", "edit-page", "fullscreen-alt", "fullscreen-exit-alt" ];
5 return this.each(function() {
6 var button = $(this), offsetTop, offsetLeft;
7 button.on("click.dashiconsPicker", function(e) {
8 offsetTop = $(e.currentTarget).offset().top;
9 offsetLeft = $(e.currentTarget).offset().left;
10 createPopup(button);
11 });
12 function createPopup(button) {
13 var target = $("#menu_icon"), preview = $(button.data("preview")), popup = $('<div class="dashicon-picker-container">' + '<div class="dashicon-picker-control"></div>' + '<ul class="dashicon-picker-list"></ul>' + "</div>").css({
14 top: offsetTop,
15 left: offsetLeft
16 }), list = popup.find(".dashicon-picker-list");
17 for (var i in icons) {
18 if (icons.hasOwnProperty(i)) {
19 list.append('<li data-icon="' + icons[i] + '"><a href="#" title="' + icons[i] + '"><span class="dashicons dashicons-' + icons[i] + '"></span></a></li>');
20 }
21 }
22 $("a", list).on("click", function(e) {
23 e.preventDefault();
24 var title = $(this).attr("title");
25 target.val("dashicons-" + title).change();
26 preview.prop("class", "dashicons").addClass("dashicons-" + title);
27 removePopup();
28 });
29 var control = popup.find(".dashicon-picker-control");
30 control.html('<a data-direction="back" href="#">' + '<span class="dashicons dashicons-arrow-left-alt2"></span></a>' + '<input type="text" class="" placeholder="Search" />' + '<a data-direction="forward" href="#"><span class="dashicons dashicons-arrow-right-alt2"></span></a>');
31 $("a", control).on("click", function(e) {
32 e.preventDefault();
33 if ($(this).data("direction") === "back") {
34 $("li:gt(" + (icons.length - 26) + ")", list).prependTo(list);
35 } else {
36 $("li:lt(25)", list).appendTo(list);
37 }
38 });
39 popup.appendTo("body").show();
40 $("input", control).on("keyup", function(e) {
41 var search = $(this).val();
42 if (search === "") {
43 $("li:lt(25)", list).show();
44 } else {
45 $("li", list).each(function() {
46 if ($(this).data("icon").toLowerCase().indexOf(search.toLowerCase()) !== -1) {
47 $(this).show();
48 } else {
49 $(this).hide();
50 }
51 });
52 }
53 });
54 $(document).on("mouseup.dashicons-picker", function(e) {
55 if (!popup.is(e.target) && popup.has(e.target).length === 0) {
56 removePopup();
57 }
58 });
59 }
60 function removePopup() {
61 $(".dashicon-picker-container").remove();
62 $(document).off(".dashicons-picker");
63 }
64 });
65 };
66 $(function() {
67 $(".dashicons-picker").dashiconsPicker();
68 });
69 })(jQuery);
...\ No newline at end of file ...\ No newline at end of file
1 !function(m){"use strict";m.fn.dashiconsPicker=function(){var c=["menu","admin-site","dashboard","admin-media","admin-page","admin-comments","admin-appearance","admin-plugins","admin-users","admin-tools","admin-settings","admin-network","admin-generic","admin-home","admin-collapse","filter","admin-customizer","admin-multisite","admin-links","format-links","admin-post","format-standard","format-image","format-gallery","format-audio","format-video","format-chat","format-status","format-aside","format-quote","welcome-write-blog","welcome-edit-page","welcome-add-page","welcome-view-site","welcome-widgets-menus","welcome-comments","welcome-learn-more","image-crop","image-rotate","image-rotate-left","image-rotate-right","image-flip-vertical","image-flip-horizontal","image-filter","undo","redo","editor-bold","editor-italic","editor-ul","editor-ol","editor-quote","editor-alignleft","editor-aligncenter","editor-alignright","editor-insertmore","editor-spellcheck","editor-distractionfree","editor-expand","editor-contract","editor-kitchensink","editor-underline","editor-justify","editor-textcolor","editor-paste-word","editor-paste-text","editor-removeformatting","editor-video","editor-customchar","editor-outdent","editor-indent","editor-help","editor-strikethrough","editor-unlink","editor-rtl","editor-break","editor-code","editor-paragraph","editor-table","align-left","align-right","align-center","align-none","lock","unlock","calendar","calendar-alt","visibility","hidden","post-status","edit","post-trash","trash","sticky","external","arrow-up","arrow-down","arrow-left","arrow-right","arrow-up-alt","arrow-down-alt","arrow-left-alt","arrow-right-alt","arrow-up-alt2","arrow-down-alt2","arrow-left-alt2","arrow-right-alt2","leftright","sort","randomize","list-view","excerpt-view","grid-view","hammer","art","migrate","performance","universal-access","universal-access-alt","tickets","nametag","clipboard","heart","megaphone","schedule","wordpress","wordpress-alt","pressthis","update","screenoptions","cart","feedback","cloud","translation","tag","category","archive","tagcloud","text","media-archive","media-audio","media-code","media-default","media-document","media-interactive","media-spreadsheet","media-text","media-video","playlist-audio","playlist-video","controls-play","controls-pause","controls-forward","controls-skipforward","controls-back","controls-skipback","controls-repeat","controls-volumeon","controls-volumeoff","yes","no","no-alt","plus","plus-alt","plus-alt2","minus","dismiss","marker","star-filled","star-half","star-empty","flag","info","warning","share","share1","share-alt","share-alt2","twitter","rss","email","email-alt","facebook","facebook-alt","networking","googleplus","location","location-alt","camera","images-alt","images-alt2","video-alt","video-alt2","video-alt3","vault","shield","shield-alt","sos","search","slides","analytics","chart-pie","chart-bar","chart-line","chart-area","groups","businessman","id","id-alt","products","awards","forms","testimonial","portfolio","book","book-alt","download","upload","backup","clock","lightbulb","microphone","desktop","tablet","smartphone","phone","smiley","index-card","carrot","building","store","album","palmtree","tickets-alt","money","thumbs-up","thumbs-down","layout","align-pull-left","align-pull-right","block-default","cloud-saved","cloud-upload","columns","cover-image","embed-audio","embed-generic","embed-photo","embed-post","embed-video","exit","html","info-outline","insert-after","insert-before","insert","remove","shortcode","table-col-after","table-col-before","table-col-delete","table-row-after","table-row-before","table-row-delete","saved","amazon","google","linkedin","pinterest","podio","reddit","spotify","twitch","whatsapp","xing","youtube","database-add","database-export","database-import","database-remove","database-view","database","bell","airplane","car","calculator","ames","printer","beer","coffee","drumstick","food","bank","hourglass","money-alt","open-folder","pdf","pets","privacy","superhero","superhero-alt","edit-page","fullscreen-alt","fullscreen-exit-alt"];return this.each(function(){var s,l,n=m(this);function d(){m(".dashicon-picker-container").remove(),m(document).off(".dashicons-picker")}n.on("click.dashiconsPicker",function(e){s=m(e.currentTarget).offset().top,l=m(e.currentTarget).offset().left;var a,e=n,t=m("#menu_icon"),o=m(e.data("preview")),i=m('<div class="dashicon-picker-container"><div class="dashicon-picker-control"></div><ul class="dashicon-picker-list"></ul></div>').css({top:s,left:l}),r=i.find(".dashicon-picker-list");for(a in c)c.hasOwnProperty(a)&&r.append('<li data-icon="'+c[a]+'"><a href="#" title="'+c[a]+'"><span class="dashicons dashicons-'+c[a]+'"></span></a></li>');m("a",r).on("click",function(e){e.preventDefault();e=m(this).attr("title");t.val("dashicons-"+e).change(),o.prop("class","dashicons").addClass("dashicons-"+e),d()}),(e=i.find(".dashicon-picker-control")).html('<a data-direction="back" href="#"><span class="dashicons dashicons-arrow-left-alt2"></span></a><input type="text" class="" placeholder="Search" /><a data-direction="forward" href="#"><span class="dashicons dashicons-arrow-right-alt2"></span></a>'),m("a",e).on("click",function(e){e.preventDefault(),"back"===m(this).data("direction")?m("li:gt("+(c.length-26)+")",r).prependTo(r):m("li:lt(25)",r).appendTo(r)}),i.appendTo("body").show(),m("input",e).on("keyup",function(e){var a=m(this).val();""===a?m("li:lt(25)",r).show():m("li",r).each(function(){-1!==m(this).data("icon").toLowerCase().indexOf(a.toLowerCase())?m(this).show():m(this).hide()})}),m(document).on("mouseup.dashicons-picker",function(e){i.is(e.target)||0!==i.has(e.target).length||d()})})})},m(function(){m(".dashicons-picker").dashiconsPicker()})}(jQuery);
...\ No newline at end of file ...\ No newline at end of file
1 {"version":3,"sources":["src/js/dashicons-picker.js"],"names":["$","fn","dashiconsPicker","icons","this","each","offsetTop","offsetLeft","button","removePopup","remove","document","off","on","e","currentTarget","offset","top","left","createPopup","i","target","preview","data","popup","css","list","find","hasOwnProperty","append","preventDefault","title","attr","val","change","prop","addClass","control","html","length","prependTo","appendTo","show","search","toLowerCase","indexOf","hide","is","has","jQuery"],"mappings":"CAMG,SAAWA,gBAMbA,EAAEC,GAAGC,gBAAkB,WAOtB,IAAIC,EAAQ,CACX,OACA,aACA,YACA,cACA,aACA,iBACA,mBACA,gBACA,cACA,cACA,iBACA,gBACA,gBACA,aACA,iBACA,SACA,mBACA,kBACA,cACA,eACA,aACA,kBACA,eACA,iBACA,eACA,eACA,cACA,gBACA,eACA,eACA,qBACA,oBACA,mBACA,oBACA,wBACA,mBACA,qBACA,aACA,eACA,oBACA,qBACA,sBACA,wBACA,eACA,OACA,OACA,cACA,gBACA,YACA,YACA,eACA,mBACA,qBACA,oBACA,oBACA,oBACA,yBACA,gBACA,kBACA,qBACA,mBACA,iBACA,mBACA,oBACA,oBACA,0BACA,eACA,oBACA,iBACA,gBACA,cACA,uBACA,gBACA,aACA,eACA,cACA,mBACA,eACA,aACA,cACA,eACA,aACA,OACA,SACA,WACA,eACA,aACA,SACA,cACA,OACA,aACA,QACA,SACA,WACA,WACA,aACA,aACA,cACA,eACA,iBACA,iBACA,kBACA,gBACA,kBACA,kBACA,mBACA,YACA,OACA,YACA,YACA,eACA,YACA,SACA,MACA,UACA,cACA,mBACA,uBACA,UACA,UACA,YACA,QACA,YACA,WACA,YACA,gBACA,YACA,SACA,gBACA,OACA,WACA,QACA,cACA,MACA,WACA,UACA,WACA,OACA,gBACA,cACA,aACA,gBACA,iBACA,oBACA,oBACA,aACA,cACA,iBACA,iBACA,gBACA,iBACA,mBACA,uBACA,gBACA,oBACA,kBACA,oBACA,qBACA,MACA,KACA,SACA,OACA,WACA,YACA,QACA,UACA,SACA,cACA,YACA,aACA,OACA,OACA,UACA,QACA,SACA,YACA,aACA,UACA,MACA,QACA,YACA,WACA,eACA,aACA,aACA,WACA,eACA,SACA,aACA,cACA,YACA,aACA,aACA,QACA,SACA,aACA,MACA,SACA,SACA,YACA,YACA,YACA,aACA,aACA,SACA,cACA,KACA,SACA,WACA,SACA,QACA,cACA,YACA,OACA,WACA,WACA,SACA,SACA,QACA,YACA,aACA,UACA,SACA,aACA,QACA,SACA,aACA,SACA,WACA,QACA,QACA,WACA,cACA,QACA,YACA,cACA,SACA,kBACA,mBACA,gBACA,cACA,eACA,UACA,cACA,cACA,gBACA,cACA,aACA,cACA,OACA,OACA,eACA,eACA,gBACA,SACA,SACA,YACA,kBACA,mBACA,mBACA,kBACA,mBACA,mBACA,QACA,SACA,SACA,WACA,YACA,QACA,SACA,UACA,SACA,WACA,OACA,UACA,eACA,kBACA,kBACA,kBACA,gBACA,WACA,OACA,WACA,MACA,aACA,OACA,UACA,OACA,SACA,YACA,OACA,OACA,YACA,YACA,cACA,MACA,OACA,UACA,YACA,gBACA,YACA,iBACA,uBAGD,OAAOC,KAAKC,KAAM,WAEjB,IACCC,EACAC,EAFGC,EAASR,EAAGI,MAgFhB,SAASK,IACRT,EAAG,8BAA+BU,SAClCV,EAAGW,UAAWC,IAAK,qBA9EpBJ,EAAOK,GAAI,wBAAyB,SAAWC,GAC9CR,EAAYN,EAAGc,EAAEC,eAAgBC,SAASC,IAC1CV,EAAaP,EAAGc,EAAEC,eAAgBC,SAASE,KAC3CC,IAgBUC,EAbWZ,EAHRA,EAKTa,EAASrB,EAAG,cACfsB,EAAUtB,EAAGQ,EAAOe,KAAM,YAC1BC,EAASxB,EAAG,kIAGDyB,IAAK,CACfR,IAAQX,EACRY,KAAQX,IAETmB,EAAOF,EAAMG,KAAM,yBAEpB,IAAUP,KAAKjB,EACTA,EAAMyB,eAAeR,IACzBM,EAAKG,OAAO,kBAAoB1B,EAAMiB,GAAK,wBAA0BjB,EAAMiB,GAAK,sCAAwCjB,EAAMiB,GAAK,sBAIrIpB,EAAG,IAAK0B,GAAOb,GAAI,QAAS,SAAWC,GACtCA,EAAEgB,iBACEC,EAAQ/B,EAAGI,MAAO4B,KAAM,SAC5BX,EAAOY,IAAK,aAAeF,GAAQG,SACnCZ,EACEa,KAAK,QAAS,aACdC,SAAU,aAAeL,GAC3BtB,OAGG4B,EAAUb,EAAMG,KAAM,6BAElBW,KAAM,yPAMdtC,EAAG,IAAKqC,GAAUxB,GAAI,QAAS,SAAWC,GACzCA,EAAEgB,iBACqC,SAAlC9B,EAAGI,MAAOmB,KAAM,aACpBvB,EAAG,UAAaG,EAAMoC,OAAS,IAAO,IAAKb,GAAOc,UAAWd,GAE7D1B,EAAG,YAAa0B,GAAOe,SAAUf,KAInCF,EAAMiB,SAAU,QAASC,OAEzB1C,EAAG,QAASqC,GAAUxB,GAAI,QAAS,SAAWC,GAC7C,IAAI6B,EAAS3C,EAAGI,MAAO6B,MACP,KAAXU,EACJ3C,EAAG,YAAa0B,GAAOgB,OAEvB1C,EAAG,KAAM0B,GAAOrB,KAAM,YAC4D,IAA5EL,EAAGI,MAAOmB,KAAM,QAASqB,cAAcC,QAASF,EAAOC,eAC3D5C,EAAGI,MAAOsC,OAEV1C,EAAGI,MAAO0C,WAMd9C,EAAGW,UAAWE,GAAI,2BAA4B,SAAWC,GACjDU,EAAMuB,GAAIjC,EAAEO,SAA6C,IAAjCG,EAAMwB,IAAKlC,EAAEO,QAASkB,QACpD9B,WAYLT,EAAG,WACFA,EAAG,qBAAsBE,oBAzZ1B,CA4ZE+C"}
...\ No newline at end of file ...\ No newline at end of file
1 <?php
2 /**
3 * Custom Post Type UI Admin UI.
4 *
5 * @package CPTUI
6 * @subpackage AdminUI
7 * @author WebDevStudios
8 * @since 1.0.0
9 * @license GPL-2.0+
10 *
11 * phpcs:disable WebDevStudios.All.RequireAuthor
12 */
13
14 /**
15 * Custom Post Type UI Admin UI
16 *
17 * @since 1.0.0
18 */
19 class cptui_admin_ui {
20
21 /**
22 * Return an opening `<tr>` tag.
23 *
24 * @since 1.0.0
25 * @since 1.13.0 Added attributes parameter
26 *
27 * @param array $atts Array of custom attributes to add to the tag.
28 * @return string $value Opening `<tr>` tag with attributes.
29 */
30 public function get_tr_start( $atts = [] ) {
31
32 $atts_str = '';
33 if ( ! empty( $atts ) ) {
34 $atts_str = ' ' . $this->get_custom_attributes( $atts );
35 }
36 return '<tr' . $atts_str . '>';
37 }
38
39 /**
40 * Return a closing `</tr>` tag.
41 *
42 * @since 1.0.0
43 *
44 * @return string $value Closing `</tr>` tag.
45 */
46 public function get_tr_end() {
47 return '</tr>';
48 }
49
50 /**
51 * Return an opening `<th>` tag.
52 *
53 * @since 1.0.0
54 * @since 1.13.0 Added attributes parameter.
55 *
56 * @param array $atts Array of attributes to add to the tag.
57 * @return string $value Opening `<th>` tag with attributes.
58 */
59 public function get_th_start( $atts = [] ) {
60 $atts_str = '';
61 if ( ! empty( $atts ) ) {
62 $atts_str = ' ' . $this->get_custom_attributes( $atts );
63 }
64 return "<th scope=\"row\"{$atts_str}>";
65 }
66
67 /**
68 * Return a closing `</th>` tag.
69 *
70 * @since 1.0.0
71 *
72 * @return string $value Closing `</th>` tag.
73 */
74 public function get_th_end() {
75 return '</th>';
76 }
77
78 /**
79 * Return an opening `<td>` tag.
80 *
81 * @since 1.0.0
82 * @since 1.13.0 Added attributes parameter.
83 *
84 * @param array $atts Array of attributes to add to the tag.
85 * @return string $value Opening `<td>` tag.
86 */
87 public function get_td_start( $atts = [] ) {
88 $atts_str = '';
89 if ( ! empty( $atts ) ) {
90 $atts_str = ' ' . $this->get_custom_attributes( $atts );
91 }
92 return "<td{$atts_str}>";
93 }
94
95 /**
96 * Return a closing `</td>` tag.
97 *
98 * @since 1.0.0
99 *
100 * @return string $value Closing `</td>` tag.
101 */
102 public function get_td_end() {
103 return '</td>';
104 }
105
106 /**
107 * Return an opening `<fieldset>` tag.
108 *
109 * @since 1.2.0
110 * @since 1.3.0 Added $args parameter.
111 * @since 1.13.0 Added $atts parameter
112 *
113 * @param array $args Array of arguments.
114 * @param array $atts Array of custom attributes for the tag.
115 * @return string $value Opening `<fieldset>` tag.
116 */
117 public function get_fieldset_start( $args = [], $atts = [] ) {
118 $fieldset = '<fieldset';
119
120 if ( ! empty( $args['id'] ) ) {
121 $fieldset .= ' id="' . esc_attr( $args['id'] ) . '"';
122 }
123
124 if ( ! empty( $args['classes'] ) ) {
125 $classes = 'class="' . implode( ' ', $args['classes'] ) . '"';
126 $fieldset .= ' ' . $classes;
127 }
128
129 if ( ! empty( $args['aria-expanded'] ) ) {
130 $fieldset .= ' aria-expanded="' . $args['aria-expanded'] . '"';
131 }
132
133 if ( ! empty( $atts ) ) {
134 $fieldset .= ' ' . $this->get_custom_attributes( $atts );
135 }
136
137 $fieldset .= ' tabindex="0">';
138
139 return $fieldset;
140 }
141
142 /**
143 * Return an closing `<fieldset>` tag.
144 *
145 * @since 1.2.0
146 *
147 * @return string $value Closing `<fieldset>` tag.
148 */
149 public function get_fieldset_end() {
150 return '</fieldset>';
151 }
152
153 /**
154 * Return an opening `<legend>` tag.
155 *
156 * @since 1.3.0
157 *
158 * @return string
159 */
160 public function get_legend_start( $atts = [] ) {
161 $atts_str = '';
162 if ( ! empty( $atts ) ) {
163 $atts_str = ' ' . $this->get_custom_attributes( $atts );
164 }
165 return "<legend class=\"screen-reader-text\"{$atts_str}>";
166 }
167
168 /**
169 * Return a closing `</legend>` tag.
170 *
171 * @since 1.3.0
172 *
173 * @return string
174 */
175 public function get_legend_end() {
176 return '</legend>';
177 }
178
179 /**
180 * Return string wrapped in a `<p>` tag.
181 *
182 * @since 1.0.0
183 *
184 * @param string $text Content to wrap in a `<p>` tag.
185 * @return string $value Content wrapped in a `<p>` tag.
186 */
187 public function get_p( $text = '' ) {
188 return '<p>' . $text . '</p>';
189 }
190
191 /**
192 * Return a form <label> with for attribute.
193 *
194 * @since 1.0.0
195 *
196 * @param string $label_for Form input to associate `<label>` with.
197 * @param string $label_text Text to display in the `<label>` tag.
198 * @return string $value `<label>` tag with filled out parts.
199 */
200 public function get_label( $label_for = '', $label_text = '' ) {
201 return '<label for="' . esc_attr( $label_for ) . '">' . wp_strip_all_tags( $label_text ) . '</label>';
202 }
203
204 /**
205 * Return an html attribute denoting a required field.
206 *
207 * @since 1.3.0
208 *
209 * @param bool $required Whether or not the field is required.
210 * @return string `Required` attribute.
211 */
212 public function get_required_attribute( $required = false ) {
213 $attr = '';
214 if ( $required ) {
215 $attr .= 'required="true"';
216 }
217 return $attr;
218 }
219
220 /**
221 * Return a `<span>` to indicate required status, with class attribute.
222 *
223 * @since 1.0.0
224 *
225 * @return string Span tag.
226 */
227 public function get_required_span() {
228 return ' <span class="required">*</span>';
229 }
230
231 /**
232 * Return an aria-required attribute set to true.
233 *
234 * @since 1.3.0
235 *
236 * @param bool $required Whether or not the field is required.
237 * @return string Aria required attribute
238 */
239 public function get_aria_required( $required = false ) {
240 $attr = $required ? 'true' : 'false';
241 return 'aria-required="' . $attr . '"';
242 }
243
244 /**
245 * Return an `<a>` tag with title attribute holding help text.
246 *
247 * @since 1.0.0
248 *
249 * @param string $help_text Text to use in the title attribute.
250 * @return string <a> tag with filled out parts.
251 */
252 public function get_help( $help_text = '' ) {
253 return '<a href="#" class="cptui-help dashicons-before dashicons-editor-help" title="' . esc_attr( $help_text ) . '"></a>';
254 }
255
256 /**
257 * Return a `<span>` tag with the help text.
258 *
259 * @since 1.3.0
260 *
261 * @param string $help_text Text to display after the input.
262 * @return string
263 */
264 public function get_description( $help_text = '' ) {
265 return '<p class="cptui-field-description description">' . $help_text . '</p>';
266 }
267
268 /**
269 * Return a maxlength HTML attribute with a specified length.
270 *
271 * @since 1.0.0
272 *
273 * @param string $length How many characters the max length should be set to.
274 * @return string $value Maxlength HTML attribute.
275 */
276 public function get_maxlength( $length = '' ) {
277 return 'maxlength="' . esc_attr( $length ) . '"';
278 }
279
280 /**
281 * Return a onblur HTML attribute for a specified value.
282 *
283 * @since 1.0.0
284 *
285 * @param string $text Text to place in the onblur attribute.
286 * @return string $value Onblur HTML attribute.
287 */
288 public function get_onblur( $text = '' ) {
289 return 'onblur="' . esc_attr( $text ) . '"';
290 }
291
292 /**
293 * Return a placeholder HTML attribtue for a specified value.
294 *
295 * @since 1.3.0
296 *
297 * @param string $text Text to place in the placeholder attribute.
298 * @return string $value Placeholder HTML attribute.
299 */
300 public function get_placeholder( $text = '' ) {
301 return 'placeholder="' . esc_attr( $text ) . '"';
302 }
303
304 /**
305 * Return a span that will only be visible for screenreaders.
306 *
307 * @since 1.3.0
308 *
309 * @param string $text Text to visually hide.
310 * @return string $value Visually hidden text meant for screen readers.
311 */
312 public function get_hidden_text( $text = '' ) {
313 return '<span class="visuallyhidden">' . $text . '</span>';
314 }
315
316 /**
317 * Return a populated `<select>` input.
318 *
319 * @since 1.0.0
320 *
321 * @param array $args Arguments to use with the `<select>` input.
322 * @return string $value Complete <select> input with options and selected attribute.
323 */
324 public function get_select_input( $args = [] ) {
325 $defaults = $this->get_default_input_parameters(
326 [
327 'selections' => [],
328 ]
329 );
330
331 $args = wp_parse_args( $args, $defaults );
332
333 $value = '';
334 if ( $args['wrap'] ) {
335 $value = $this->get_tr_start();
336 $value .= $this->get_th_start();
337 $value .= $this->get_label( $args['name'], $args['labeltext'] );
338 if ( $args['required'] ) {
339 $value .= $this->get_required_span();
340 }
341 if ( ! empty( $args['helptext'] ) ) {
342 $value .= $this->get_help( $args['helptext'] );
343 }
344 $value .= $this->get_th_end();
345 $value .= $this->get_td_start();
346 }
347
348 $value .= '<select id="' . $args['name'] . '" name="' . $args['namearray'] . '[' . $args['name'] . ']">';
349 if ( ! empty( $args['selections']['options'] ) && is_array( $args['selections']['options'] ) ) {
350 foreach ( $args['selections']['options'] as $val ) {
351 $result = '';
352 $bool = disp_boolean( $val['attr'] );
353
354 if ( is_numeric( $args['selections']['selected'] ) ) {
355 $selected = disp_boolean( $args['selections']['selected'] );
356 } elseif ( in_array( $args['selections']['selected'], [ 'true', 'false' ], true ) ) {
357 $selected = $args['selections']['selected'];
358 }
359
360 if ( ! empty( $selected ) && $selected === $bool ) {
361 $result = ' selected="selected"';
362 } else {
363 if ( array_key_exists( 'default', $val ) && ! empty( $val['default'] ) ) {
364 if ( empty( $selected ) ) {
365 $result = ' selected="selected"';
366 }
367 }
368 }
369
370 if ( ! is_numeric( $args['selections']['selected'] ) && ( ! empty( $args['selections']['selected'] ) && $args['selections']['selected'] === $val['attr'] ) ) {
371 $result = ' selected="selected"';
372 }
373
374 $value .= '<option value="' . $val['attr'] . '"' . $result . '>' . $val['text'] . '</option>';
375 }
376 }
377 $value .= '</select>';
378
379 if ( ! empty( $args['aftertext'] ) ) {
380 $value .= ' ' . $this->get_description( $args['aftertext'] );
381 }
382
383 if ( $args['wrap'] ) {
384 $value .= $this->get_td_end();
385 $value .= $this->get_tr_end();
386 }
387
388 return $value;
389 }
390
391 /**
392 * Return a text input.
393 *
394 * @since 1.0.0
395 *
396 * @param array $args Arguments to use with the text input.
397 * @return string Complete text `<input>` with proper attributes.
398 */
399 public function get_text_input( $args = [] ) {
400 $defaults = $this->get_default_input_parameters(
401 [
402 'maxlength' => '',
403 'onblur' => '',
404 ]
405 );
406 $args = wp_parse_args( $args, $defaults );
407
408 $value = '';
409 if ( $args['wrap'] ) {
410 $value .= $this->get_tr_start();
411 $value .= $this->get_th_start();
412 $value .= $this->get_label( $args['name'], $args['labeltext'] );
413 if ( $args['required'] ) {
414 $value .= $this->get_required_span();
415 }
416 $value .= $this->get_th_end();
417 $value .= $this->get_td_start();
418 }
419
420 $value .= '<input type="text" id="' . $args['name'] . '" name="' . $args['namearray'] . '[' . $args['name'] . ']" value="' . $args['textvalue'] . '"';
421
422 if ( $args['maxlength'] ) {
423 $value .= ' ' . $this->get_maxlength( $args['maxlength'] );
424 }
425
426 if ( $args['onblur'] ) {
427 $value .= ' ' . $this->get_onblur( $args['onblur'] );
428 }
429
430 $value .= ' ' . $this->get_aria_required( $args['required'] );
431
432 $value .= ' ' . $this->get_required_attribute( $args['required'] );
433
434 if ( ! empty( $args['aftertext'] ) ) {
435 if ( $args['placeholder'] ) {
436 $value .= ' ' . $this->get_placeholder( $args['aftertext'] );
437 }
438 }
439
440 if ( ! empty( $args['data'] ) ) {
441 foreach ( $args['data'] as $dkey => $dvalue ) {
442 $value .= " data-{$dkey}=\"{$dvalue}\"";
443 }
444 }
445
446 $value .= ' />';
447
448 if ( ! empty( $args['aftertext'] ) ) {
449 $value .= $this->get_hidden_text( $args['aftertext'] );
450 }
451
452 if ( $args['helptext'] ) {
453 $value .= '<br/>' . $this->get_description( $args['helptext'] );
454 }
455
456 if ( $args['wrap'] ) {
457 $value .= $this->get_td_end();
458 $value .= $this->get_tr_end();
459 }
460
461 return $value;
462 }
463
464 /**
465 * Return a `<textarea>` input.
466 *
467 * @since 1.0.0
468 *
469 * @param array $args Arguments to use with the textarea input.
470 * @return string $value Complete <textarea> input with proper attributes.
471 */
472 public function get_textarea_input( $args = [] ) {
473 $defaults = $this->get_default_input_parameters(
474 [
475 'rows' => '',
476 'cols' => '',
477 ]
478 );
479 $args = wp_parse_args( $args, $defaults );
480
481 $value = '';
482
483 if ( $args['wrap'] ) {
484 $value .= $this->get_tr_start();
485 $value .= $this->get_th_start();
486 $value .= $this->get_label( $args['name'], $args['labeltext'] );
487 if ( $args['required'] ) {
488 $value .= $this->get_required_span();
489 }
490 $value .= $this->get_th_end();
491 $value .= $this->get_td_start();
492 }
493
494 $value .= '<textarea id="' . $args['name'] . '" name="' . $args['namearray'] . '[' . $args['name'] . ']" rows="' . $args['rows'] . '" cols="' . $args['cols'] . '">' . $args['textvalue'] . '</textarea>';
495
496 if ( ! empty( $args['aftertext'] ) ) {
497 $value .= $args['aftertext'];
498 }
499
500 if ( $args['helptext'] ) {
501 $value .= '<br/>' . $this->get_description( $args['helptext'] );
502 }
503
504 if ( $args['wrap'] ) {
505 $value .= $this->get_td_end();
506 $value .= $this->get_tr_end();
507 }
508
509 return $value;
510 }
511
512 /**
513 * Return a checkbox `<input>`.
514 *
515 * @since 1.0.0
516 *
517 * @param array $args Arguments to use with the checkbox input.
518 * @return string $value Complete checkbox `<input>` with proper attributes.
519 */
520 public function get_check_input( $args = [] ) {
521 $defaults = $this->get_default_input_parameters(
522 [
523 'checkvalue' => '',
524 'checked' => 'true',
525 'checklisttext' => '',
526 'default' => false,
527 ]
528 );
529 $args = wp_parse_args( $args, $defaults );
530
531 $value = '';
532 if ( $args['wrap'] ) {
533 $value .= $this->get_tr_start();
534 $value .= $this->get_th_start();
535 $value .= $args['checklisttext'];
536 if ( $args['required'] ) {
537 $value .= $this->get_required_span();
538 }
539 $value .= $this->get_th_end();
540 $value .= $this->get_td_start();
541 }
542
543 if ( isset( $args['checked'] ) && 'false' === $args['checked'] ) {
544 $value .= '<input type="checkbox" id="' . $args['name'] . '" name="' . $args['namearray'] . '[]" value="' . $args['checkvalue'] . '" />';
545 } else {
546 $value .= '<input type="checkbox" id="' . $args['name'] . '" name="' . $args['namearray'] . '[]" value="' . $args['checkvalue'] . '" checked="checked" />';
547 }
548 $value .= $this->get_label( $args['name'], $args['labeltext'] );
549 $value .= '<br/>';
550
551 if ( $args['wrap'] ) {
552 $value .= $this->get_td_end();
553 $value .= $this->get_tr_end();
554 }
555
556 return $value;
557 }
558
559 /**
560 * Return a button `<input>`.
561 *
562 * @since 1.3.0
563 *
564 * @param array $args Arguments to use with the button input.
565 * @return string Complete button `<input>`.
566 */
567 public function get_button( $args = [] ) {
568 $value = '';
569 $classes = isset( $args['classes'] ) ? $args['classes'] : '';
570 $value .= '<input id="' . $args['id'] . '" class="button ' . $classes . '" type="button" value="' . $args['textvalue'] . '" />';
571
572 return $value;
573 }
574
575 /**
576 * Returns an HTML block for previewing the menu icon.
577 *
578 * @param string $menu_icon URL or a name of the dashicons class.
579 *
580 * @return string $value HTML block with a layout of the menu icon preview.
581 * @since 1.8.1
582 */
583 public function get_menu_icon_preview( $menu_icon = '' ) {
584 $content = '';
585 if ( ! empty( $menu_icon ) ) {
586 $content = '<img src="' . $menu_icon . '">';
587 if ( 0 === strpos( $menu_icon, 'dashicons-' ) ) {
588 $content = '<div class="dashicons-before ' . $menu_icon . '"></div>';
589 }
590 }
591
592 return '<div id="menu_icon_preview">' . $content . '</div>';
593 }
594
595 /**
596 * Return some array_merged default arguments for all input types.
597 *
598 * @since 1.0.0
599 *
600 * @param array $additions Arguments array to merge with our defaults.
601 * @return array $value Merged arrays for our default parameters.
602 */
603 public function get_default_input_parameters( $additions = [] ) {
604 return array_merge(
605 [
606 'namearray' => '',
607 'name' => '',
608 'textvalue' => '',
609 'labeltext' => '',
610 'aftertext' => '',
611 'helptext' => '',
612 'helptext_after' => false,
613 'required' => false,
614 'wrap' => true,
615 'placeholder' => true,
616 ],
617 (array) $additions
618 );
619 }
620
621 /**
622 * Return combined attributes string.
623 *
624 * @param array $attributes Array of attributes to combine.
625 *
626 * @return string
627 * @since 1.13.0
628 */
629 public function get_custom_attributes( $attributes = [] ) {
630 $formatted = [];
631 if ( ! empty( $attributes ) ) {
632 foreach ( $attributes as $key => $attribute ) {
633 $formatted[] = "$key=\"$attribute\"";
634 }
635 }
636
637 return implode( ' ', $formatted );
638 }
639 }
1 <?php
2 /**
3 * Custom Post Type UI Debug Information.
4 *
5 * @package CPTUI
6 * @subpackage Debugging
7 * @author WebDevStudios
8 * @since 1.2.0
9 * @license GPL-2.0+
10 */
11
12 /**
13 * Custom Post Type UI Debug Info
14 */
15 class CPTUI_Debug_Info {
16
17 /**
18 * Tab content for the debug info tab.
19 *
20 * @since 1.2.0
21 */
22 public function tab_site_info() {
23 ?>
24 <p><?php esc_html_e( 'If you have sought support for Custom Post Type UI on the forums, you may be requested to send the information below to the plugin developer. Simply insert the email they provided in the input field at the bottom and click the "Send debug info" button. Only the data below will be sent to them.', 'custom-post-type-ui' ); ?></p>
25 <label for="cptui_audit_textarea">
26 <textarea readonly="readonly" aria-readonly="true" id="cptui-audit-textarea" name="cptui_audit_textarea" rows="20" cols="100" class="large-text code">
27 <?php echo esc_html( $this->system_status() ); ?>
28 </textarea></label>
29 <?php
30 }
31
32 /**
33 * Generate the debug information content.
34 *
35 * @since 1.2.0
36 *
37 * @return string
38 */
39 private function system_status() {
40 if ( ! current_user_can( 'manage_options' ) ) {
41 return '';
42 }
43
44 global $wpdb;
45
46 $theme_data = wp_get_theme();
47 $theme = $theme_data->Name . ' ' . $theme_data->Version; // phpcs:ignore.
48
49 ob_start();
50 ?>
51
52 ### Begin Custom Post Type UI Debug Info ###
53
54 Multisite: <?php echo is_multisite() ? 'Yes' . "\n" : 'No' . "\n"; ?>
55
56 SITE_URL: <?php echo esc_url( site_url() ) . "\n"; ?>
57 HOME_URL: <?php echo esc_url( home_url() ) . "\n"; ?>
58
59 WordPress Version: <?php echo get_bloginfo( 'version' ) . "\n"; // phpcs:ignore. ?>
60 Permalink Structure: <?php echo get_option( 'permalink_structure' ) . "\n"; // phpcs:ignore. ?>
61 Active Theme: <?php echo $theme . "\n"; // phpcs:ignore. ?>
62
63 Registered Post Types: <?php echo implode( ', ', get_post_types( '', 'names' ) ) . "\n"; // phpcs:ignore. ?>
64
65 PHP Version: <?php echo PHP_VERSION . "\n"; ?>
66 MySQL Version: <?php echo $wpdb->db_version() . "\n"; // phpcs:ignore. ?>
67 Web Server Info: <?php echo $_SERVER['SERVER_SOFTWARE'] . "\n"; // phpcs:ignore. ?>
68
69 Show On Front: <?php echo get_option( 'show_on_front' ) . "\n"; // phpcs:ignore. ?>
70 Page On Front: <?php $id = get_option( 'page_on_front' ); // phpcs:ignore.
71 echo get_the_title( $id ) . ' (#' . $id . ')' . "\n"; // phpcs:ignore. ?>
72 Page For Posts: <?php $id = get_option( 'page_for_posts' ); // phpcs:ignore.
73 echo get_the_title( $id ) . ' (#' . $id . ')' . "\n"; // phpcs:ignore. ?>
74
75 WordPress Memory Limit: <?php echo ( $this->num_convt( WP_MEMORY_LIMIT ) / ( 1024 ) ) . 'MB'; ?><?php echo "\n"; // phpcs:ignore. ?>
76
77 <?php
78 $plugins = get_plugins();
79 $pg_count = count( $plugins );
80 echo 'TOTAL PLUGINS: ' . $pg_count . "\n\n"; // phpcs:ignore.
81 // MU plugins.
82 $mu_plugins = get_mu_plugins();
83
84 if ( $mu_plugins ) :
85 echo "\t\t" . 'MU PLUGINS: (' . count( $mu_plugins ) . ')' . "\n\n";
86
87 foreach ( $mu_plugins as $mu_path => $mu_plugin ) {
88
89 echo "\t\t" . esc_html( $mu_plugin['Name'] ) . ': ' . esc_html( $mu_plugin['Version'] ) . "\n";
90 }
91 endif;
92 // Standard plugins - active.
93 echo "\n";
94
95 $active = get_option( 'active_plugins', [] );
96 $ac_count = count( $active );
97 $ic_count = $pg_count - $ac_count;
98
99 echo "\t\t" . 'ACTIVE PLUGINS: (' . $ac_count . ')' . "\n\n"; // phpcs:ignore.
100
101 foreach ( $plugins as $plugin_path => $plugin ) {
102 // If the plugin isn't active, don't show it.
103 if ( ! in_array( $plugin_path, $active, true ) ) {
104 continue;
105 }
106
107 echo "\t\t" . esc_html( $plugin['Name'] ) . ': ' . esc_html( $plugin['Version'] ) . "\n";
108 }
109 // Standard plugins - inactive.
110 echo "\n";
111 echo "\t\t" , 'INACTIVE PLUGINS: (' . $ic_count . ')' . "\n\n"; // phpcs:ignore.
112
113 foreach ( $plugins as $plugin_path => $plugin ) {
114 // If the plugin isn't active, show it here.
115 if ( in_array( $plugin_path, $active, true ) ) {
116 continue;
117 }
118
119 echo "\t\t" . esc_html( $plugin['Name'] ) . ': ' . esc_html( $plugin['Version'] ) . "\n";
120 }
121
122 // If multisite, grab network as well.
123 if ( is_multisite() ) :
124
125 $net_plugins = wp_get_active_network_plugins();
126 $net_active = get_site_option( 'active_sitewide_plugins', [] );
127
128 echo "\n";
129 echo 'NETWORK ACTIVE PLUGINS: (' . count( $net_plugins ) . ')' . "\n\n";
130
131 foreach ( $net_plugins as $plugin_path ) {
132 $plugin_base = plugin_basename( $plugin_path );
133
134 // If the plugin isn't active, don't show it.
135 if ( ! array_key_exists( $plugin_base, $net_active ) ) {
136 continue;
137 }
138
139 $plugin = get_plugin_data( $plugin_path );
140
141 echo esc_html( $plugin['Name'] ) . ' :' . esc_html( $plugin['Version'] ) . "\n";
142 }
143
144 endif;
145
146 echo "\n";
147 $cptui_post_types = cptui_get_post_type_data();
148 echo "\t\t" . 'Post Types: ' . "\n";
149 echo "\t\t" . wp_json_encode( $cptui_post_types ) . "\n";
150
151 echo "\n\n";
152
153 $cptui_taxonomies = cptui_get_taxonomy_data();
154 echo "\t\t" . 'Taxonomies: ' . "\n";
155 echo "\t\t" . wp_json_encode( $cptui_taxonomies ) . "\n";
156 echo "\n";
157
158 if ( has_action( 'cptui_custom_debug_info' ) ) {
159 echo "\t\t" . 'EXTRA DEBUG INFO';
160 }
161
162 /**
163 * Fires at the end of the debug info output.
164 *
165 * @since 1.3.0
166 */
167 do_action( 'cptui_custom_debug_info' );
168
169 echo "\n";
170 ?>
171 ### End Debug Info ###
172 <?php
173
174 return ob_get_clean();
175 }
176
177 /**
178 * Helper function for number conversions.
179 *
180 * @since 1.2.0
181 * @access public
182 *
183 * @param mixed $v Value.
184 * @return int
185 */
186 public function num_convt( $v ) {
187 $l = substr( $v, - 1 );
188 $ret = substr( $v, 0, - 1 );
189
190 switch ( strtoupper( $l ) ) {
191 case 'P': // Fall-through.
192 case 'T': // Fall-through.
193 case 'G': // Fall-through.
194 case 'M': // Fall-through.
195 case 'K': // Fall-through.
196 $ret *= 1024;
197 break;
198 default:
199 break;
200 }
201
202 return $ret;
203 }
204
205 /**
206 * Sends an email to the specified address, with the system status as the message.
207 *
208 * @since 1.2.0
209 *
210 * @param array $args Array of arguments for the method. Optional.
211 * @return bool
212 */
213 public function send_email( $args = [] ) {
214
215 if ( ! isset( $args['email'] ) || ! is_email( $args['email'] ) ) {
216 return false;
217 }
218
219 stripslashes_deep( $args );
220
221 $args['email'] = sanitize_email( $args['email'] );
222
223 $message = $this->system_status();
224
225 /**
226 * Filters the debug email subject.
227 *
228 * @since 1.3.0
229 *
230 * @param string $value Intended email subject.
231 */
232 $subject = apply_filters(
233 'cptui_debug_email_subject',
234 sprintf(
235 // translators: Placeholder will hold site home_url.
236 esc_html__( 'Custom Post Type UI debug information for %s', 'custom-post-type-ui' ),
237 esc_url( home_url( '/' ) )
238 )
239 );
240
241 $result = wp_mail( $args['email'], $subject, $message );
242
243 /**
244 * Fires after the debug email has been sent.
245 *
246 * @since 1.3.0
247 */
248 do_action( 'cptui_after_debug_email_sent' );
249
250 return $result;
251 }
252 }
1 <?php
2 /**
3 * Custom Post Type UI.
4 *
5 * For all your post type and taxonomy needs.
6 *
7 * @package CPTUI
8 * @subpackage Loader
9 * @author WebDevStudios
10 * @since 0.1.0.0
11 * @license GPL-2.0+
12 */
13
14 /**
15 * Plugin Name: Custom Post Type UI
16 * Plugin URI: https://github.com/WebDevStudios/custom-post-type-ui/
17 * Description: Admin UI panel for registering custom post types and taxonomies
18 * Author: WebDevStudios
19 * Version: 1.13.7
20 * Author URI: https://webdevstudios.com/
21 * Text Domain: custom-post-type-ui
22 * Domain Path: /languages
23 * License: GPL-2.0+
24 * Requires at least: 5.9
25 * Requires PHP: 5.6
26 */
27
28 // phpcs:disable WebDevStudios.All.RequireAuthor
29 // phpcs:set WordPress.WP.I18n check_translator_comments false
30
31 // Exit if accessed directly.
32 if ( ! defined( 'ABSPATH' ) ) {
33 exit;
34 }
35
36 define( 'CPT_VERSION', '1.13.7' ); // Left for legacy purposes.
37 define( 'CPTUI_VERSION', '1.13.7' );
38 define( 'CPTUI_WP_VERSION', get_bloginfo( 'version' ) );
39
40 /**
41 * Load our Admin UI class that powers our form inputs.
42 *
43 * @since 1.0.0
44 *
45 * @internal
46 */
47 function cptui_load_ui_class() {
48 require_once plugin_dir_path( __FILE__ ) . 'classes/class.cptui_admin_ui.php';
49 require_once plugin_dir_path( __FILE__ ) . 'classes/class.cptui_debug_info.php';
50 }
51 add_action( 'init', 'cptui_load_ui_class' );
52
53 /**
54 * Set a transient used for redirection upon activation.
55 *
56 * @since 1.4.0
57 */
58 function cptui_activation_redirect() {
59 // Bail if activating from network, or bulk.
60 if ( is_network_admin() ) {
61 return;
62 }
63
64 // Add the transient to redirect.
65 set_transient( 'cptui_activation_redirect', true, 30 );
66 }
67 add_action( 'activate_' . plugin_basename( __FILE__ ), 'cptui_activation_redirect' );
68
69 /**
70 * Redirect user to CPTUI about page upon plugin activation.
71 *
72 * @since 1.4.0
73 */
74 function cptui_make_activation_redirect() {
75
76 if ( ! get_transient( 'cptui_activation_redirect' ) ) {
77 return;
78 }
79
80 delete_transient( 'cptui_activation_redirect' );
81
82 // Bail if activating from network, or bulk.
83 if ( is_network_admin() ) {
84 return;
85 }
86
87 if ( ! cptui_is_new_install() ) {
88 return;
89 }
90
91 // Redirect to CPTUI about page.
92 wp_safe_redirect(
93 add_query_arg(
94 [ 'page' => 'cptui_main_menu' ],
95 cptui_admin_url( 'admin.php?page=cptui_main_menu' )
96 )
97 );
98 }
99 add_action( 'admin_init', 'cptui_make_activation_redirect', 1 );
100
101 /**
102 * Flush our rewrite rules on deactivation.
103 *
104 * @since 0.8.0
105 *
106 * @internal
107 */
108 function cptui_deactivation() {
109 flush_rewrite_rules();
110 }
111 register_deactivation_hook( __FILE__, 'cptui_deactivation' );
112
113 /**
114 * Register our text domain.
115 *
116 * @since 0.8.0
117 *
118 * @internal
119 */
120 function cptui_load_textdomain() {
121 load_plugin_textdomain( 'custom-post-type-ui' );
122 }
123 add_action( 'init', 'cptui_load_textdomain' );
124
125 /**
126 * Load our main menu.
127 *
128 * Submenu items added in version 1.1.0
129 *
130 * @since 0.1.0
131 *
132 * @internal
133 */
134 function cptui_plugin_menu() {
135
136 /**
137 * Filters the required capability to manage CPTUI settings.
138 *
139 * @since 1.3.0
140 *
141 * @param string $value Capability required.
142 */
143 $capability = apply_filters( 'cptui_required_capabilities', 'manage_options' );
144 $parent_slug = 'cptui_main_menu';
145
146 add_menu_page( esc_html__( 'Custom Post Types', 'custom-post-type-ui' ), esc_html__( 'CPT UI', 'custom-post-type-ui' ), $capability, $parent_slug, 'cptui_settings', cptui_menu_icon() );
147 add_submenu_page( $parent_slug, esc_html__( 'Add/Edit Post Types', 'custom-post-type-ui' ), esc_html__( 'Add/Edit Post Types', 'custom-post-type-ui' ), $capability, 'cptui_manage_post_types', 'cptui_manage_post_types' );
148 add_submenu_page( $parent_slug, esc_html__( 'Add/Edit Taxonomies', 'custom-post-type-ui' ), esc_html__( 'Add/Edit Taxonomies', 'custom-post-type-ui' ), $capability, 'cptui_manage_taxonomies', 'cptui_manage_taxonomies' );
149 add_submenu_page( $parent_slug, esc_html__( 'Registered Types and Taxes', 'custom-post-type-ui' ), esc_html__( 'Registered Types/Taxes', 'custom-post-type-ui' ), $capability, 'cptui_listings', 'cptui_listings' );
150 add_submenu_page( $parent_slug, esc_html__( 'Custom Post Type UI Tools', 'custom-post-type-ui' ), esc_html__( 'Tools', 'custom-post-type-ui' ), $capability, 'cptui_tools', 'cptui_tools' );
151 add_submenu_page( $parent_slug, esc_html__( 'Help/Support', 'custom-post-type-ui' ), esc_html__( 'Help/Support', 'custom-post-type-ui' ), $capability, 'cptui_support', 'cptui_support' );
152
153 /**
154 * Fires after the default submenu pages.
155 *
156 * @since 1.3.0
157 *
158 * @param string $value Parent slug for Custom Post Type UI menu.
159 * @param string $capability Capability required to manage CPTUI settings.
160 */
161 do_action( 'cptui_extra_menu_items', $parent_slug, $capability );
162
163 // Remove the default one so we can add our customized version.
164 remove_submenu_page( $parent_slug, 'cptui_main_menu' );
165 add_submenu_page( $parent_slug, esc_html__( 'About CPT UI', 'custom-post-type-ui' ), esc_html__( 'About CPT UI', 'custom-post-type-ui' ), $capability, 'cptui_main_menu', 'cptui_settings' );
166 }
167 add_action( 'admin_menu', 'cptui_plugin_menu' );
168
169 /**
170 * Fire our CPTUI Loaded hook.
171 *
172 * @since 1.3.0
173 *
174 * @internal Use `cptui_loaded` hook.
175 */
176 function cptui_loaded() {
177
178 if ( class_exists( 'WPGraphQL' ) ) {
179 require_once plugin_dir_path( __FILE__ ) . 'external/wpgraphql.php';
180 }
181
182 /**
183 * Fires upon plugins_loaded WordPress hook.
184 *
185 * CPTUI loads its required files on this hook.
186 *
187 * @since 1.3.0
188 */
189 do_action( 'cptui_loaded' );
190 }
191 add_action( 'plugins_loaded', 'cptui_loaded' );
192
193 /**
194 * Load our submenus.
195 *
196 * @since 1.0.0
197 *
198 * @internal
199 */
200 function cptui_create_submenus() {
201 require_once plugin_dir_path( __FILE__ ) . 'inc/about.php';
202 require_once plugin_dir_path( __FILE__ ) . 'inc/utility.php';
203 require_once plugin_dir_path( __FILE__ ) . 'inc/post-types.php';
204 require_once plugin_dir_path( __FILE__ ) . 'inc/taxonomies.php';
205 require_once plugin_dir_path( __FILE__ ) . 'inc/listings.php';
206 require_once plugin_dir_path( __FILE__ ) . 'inc/tools.php';
207 require_once plugin_dir_path( __FILE__ ) . 'inc/tools-sections/tools-post-types.php';
208 require_once plugin_dir_path( __FILE__ ) . 'inc/tools-sections/tools-taxonomies.php';
209 require_once plugin_dir_path( __FILE__ ) . 'inc/tools-sections/tools-get-code.php';
210 require_once plugin_dir_path( __FILE__ ) . 'inc/tools-sections/tools-debug.php';
211 require_once plugin_dir_path( __FILE__ ) . 'inc/support.php';
212
213 if ( defined( 'WP_CLI' ) && WP_CLI ) {
214 require_once plugin_dir_path( __FILE__ ) . 'inc/wp-cli.php';
215 }
216 }
217 add_action( 'cptui_loaded', 'cptui_create_submenus' );
218
219 /**
220 * Fire our CPTUI init hook.
221 *
222 * @since 1.3.0
223 *
224 * @internal Use `cptui_init` hook.
225 */
226 function cptui_init() {
227
228 /**
229 * Fires upon init WordPress hook.
230 *
231 * @since 1.3.0
232 */
233 do_action( 'cptui_init' );
234 }
235 add_action( 'init', 'cptui_init' );
236
237 /**
238 * Enqueue CPTUI admin styles.
239 *
240 * @since 1.0.0
241 *
242 * @internal
243 */
244 function cptui_add_styles() {
245 if ( wp_doing_ajax() ) {
246 return;
247 }
248 $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
249 wp_register_script( 'cptui', plugins_url( "build/cptui-scripts{$min}.js", __FILE__ ), [ 'jquery', 'jquery-ui-dialog', 'postbox' ], CPTUI_VERSION, true );
250 wp_register_script( 'dashicons-picker', plugins_url( "build/dashicons-picker{$min}.js", __FILE__ ), [ 'jquery'], '1.0.0', true );
251 wp_register_style( 'cptui-css', plugins_url( "build/cptui-styles{$min}.css", __FILE__ ), [ 'wp-jquery-ui-dialog' ], CPTUI_VERSION );
252 }
253 add_action( 'admin_enqueue_scripts', 'cptui_add_styles' );
254
255 /**
256 * Register our users' custom post types.
257 *
258 * @since 0.5.0
259 *
260 * @internal
261 */
262 function cptui_create_custom_post_types() {
263 $cpts = get_option( 'cptui_post_types', [] );
264 /**
265 * Filters an override array of post type data to be registered instead of our saved option.
266 *
267 * @since 1.10.0
268 *
269 * @param array $value Default override value.
270 */
271 $cpts_override = apply_filters( 'cptui_post_types_override', [] );
272
273 if ( empty( $cpts ) && empty( $cpts_override ) ) {
274 return;
275 }
276
277 // Assume good intent, and we're also not wrecking the option so things are always reversable.
278 if ( is_array( $cpts_override ) && ! empty( $cpts_override ) ) {
279 $cpts = $cpts_override;
280 }
281
282 /**
283 * Fires before the start of the post type registrations.
284 *
285 * @since 1.3.0
286 *
287 * @param array $cpts Array of post types to register.
288 */
289 do_action( 'cptui_pre_register_post_types', $cpts );
290
291 if ( is_array( $cpts ) ) {
292 foreach ( $cpts as $post_type ) {
293
294 if ( ! is_string( $post_type['name'] ) ) {
295 $post_type['name'] = (string) $post_type['name'];
296 }
297 /**
298 * Filters whether or not to skip registration of the current iterated post type.
299 *
300 * Dynamic part of the filter name is the chosen post type slug.
301 *
302 * @since 1.7.0
303 *
304 * @param bool $value Whether or not to skip the post type.
305 * @param array $post_type Current post type being registered.
306 */
307 if ( (bool) apply_filters( "cptui_disable_{$post_type['name']}_cpt", false, $post_type ) ) {
308 continue;
309 }
310
311 /**
312 * Filters whether or not to skip registration of the current iterated post type.
313 *
314 * @since 1.7.0
315 *
316 * @param bool $value Whether or not to skip the post type.
317 * @param array $post_type Current post type being registered.
318 */
319 if ( (bool) apply_filters( 'cptui_disable_cpt', false, $post_type ) ) {
320 continue;
321 }
322
323 cptui_register_single_post_type( $post_type );
324 }
325 }
326
327 /**
328 * Fires after the completion of the post type registrations.
329 *
330 * @since 1.3.0
331 *
332 * @param array $cpts Array of post types registered.
333 */
334 do_action( 'cptui_post_register_post_types', $cpts );
335 }
336 add_action( 'init', 'cptui_create_custom_post_types', 10 ); // Leave on standard init for legacy purposes.
337
338 /**
339 * Helper function to register the actual post_type.
340 *
341 * @since 1.0.0
342 *
343 * @internal
344 *
345 * @param array $post_type Post type array to register. Optional.
346 * @return null Result of register_post_type.
347 */
348 function cptui_register_single_post_type( $post_type = [] ) {
349
350 /**
351 * Filters the map_meta_cap value.
352 *
353 * @since 1.0.0
354 *
355 * @param bool $value True.
356 * @param string $name Post type name being registered.
357 * @param array $post_type All parameters for post type registration.
358 */
359 $post_type['map_meta_cap'] = apply_filters( 'cptui_map_meta_cap', true, $post_type['name'], $post_type );
360
361 if ( empty( $post_type['supports'] ) ) {
362 $post_type['supports'] = [];
363 }
364
365 /**
366 * Filters custom supports parameters for 3rd party plugins.
367 *
368 * @since 1.0.0
369 *
370 * @param array $value Empty array to add supports keys to.
371 * @param string $name Post type slug being registered.
372 * @param array $post_type Array of post type arguments to be registered.
373 */
374 $user_supports_params = apply_filters( 'cptui_user_supports_params', [], $post_type['name'], $post_type );
375
376 if ( is_array( $user_supports_params ) && ! empty( $user_supports_params ) ) {
377 if ( is_array( $post_type['supports'] ) ) {
378 $post_type['supports'] = array_merge( $post_type['supports'], $user_supports_params );
379 } else {
380 $post_type['supports'] = [ $user_supports_params ];
381 }
382 }
383
384 $yarpp = false; // Prevent notices.
385 if ( ! empty( $post_type['custom_supports'] ) ) {
386 $custom = explode( ',', $post_type['custom_supports'] );
387 foreach ( $custom as $part ) {
388 // We'll handle YARPP separately.
389 if ( in_array( $part, [ 'YARPP', 'yarpp' ], true ) ) {
390 $yarpp = true;
391 continue;
392 }
393 $post_type['supports'][] = trim( $part );
394 }
395 }
396
397 if ( isset( $post_type['supports'] ) && is_array( $post_type['supports'] ) && in_array( 'none', $post_type['supports'], true ) ) {
398 $post_type['supports'] = false;
399 }
400
401 $labels = [
402 'name' => $post_type['label'],
403 'singular_name' => $post_type['singular_label'],
404 ];
405
406 $preserved = cptui_get_preserved_keys( 'post_types' );
407 $preserved_labels = cptui_get_preserved_labels();
408 foreach ( $post_type['labels'] as $key => $label ) {
409
410 if ( ! empty( $label ) ) {
411 if ( 'parent' === $key ) {
412 $labels['parent_item_colon'] = $label;
413 } else {
414 $labels[ $key ] = $label;
415 }
416 } elseif ( empty( $label ) && in_array( $key, $preserved, true ) ) {
417 $singular_or_plural = ( in_array( $key, array_keys( $preserved_labels['post_types']['plural'] ) ) ) ? 'plural' : 'singular'; // phpcs:ignore.
418 $label_plurality = ( 'plural' === $singular_or_plural ) ? $post_type['label'] : $post_type['singular_label'];
419 $labels[ $key ] = sprintf( $preserved_labels['post_types'][ $singular_or_plural ][ $key ], $label_plurality );
420 }
421 }
422
423 $has_archive = isset( $post_type['has_archive'] ) ? get_disp_boolean( $post_type['has_archive'] ) : false;
424 if ( $has_archive && ! empty( $post_type['has_archive_string'] ) ) {
425 $has_archive = $post_type['has_archive_string'];
426 }
427
428 $show_in_menu = get_disp_boolean( $post_type['show_in_menu'] );
429 if ( ! empty( $post_type['show_in_menu_string'] ) ) {
430 $show_in_menu = $post_type['show_in_menu_string'];
431 }
432
433 $rewrite = get_disp_boolean( $post_type['rewrite'] );
434 if ( false !== $rewrite ) {
435 // Core converts to an empty array anyway, so safe to leave this instead of passing in boolean true.
436 $rewrite = [];
437 $rewrite['slug'] = ! empty( $post_type['rewrite_slug'] ) ? $post_type['rewrite_slug'] : $post_type['name'];
438
439 $rewrite['with_front'] = true; // Default value.
440 if ( isset( $post_type['rewrite_withfront'] ) ) {
441 $rewrite['with_front'] = 'false' === disp_boolean( $post_type['rewrite_withfront'] ) ? false : true;
442 }
443 }
444
445 $menu_icon = ! empty( $post_type['menu_icon'] ) ? $post_type['menu_icon'] : null;
446 $register_meta_box_cb = ! empty( $post_type['register_meta_box_cb'] ) ? $post_type['register_meta_box_cb'] : null;
447
448 if ( in_array( $post_type['query_var'], [ 'true', 'false', '0', '1' ], true ) ) {
449 $post_type['query_var'] = get_disp_boolean( $post_type['query_var'] );
450 }
451 if ( ! empty( $post_type['query_var_slug'] ) ) {
452 $post_type['query_var'] = $post_type['query_var_slug'];
453 }
454
455 $menu_position = null;
456 if ( ! empty( $post_type['menu_position'] ) ) {
457 $menu_position = (int) $post_type['menu_position'];
458 }
459
460 $delete_with_user = null;
461 if ( ! empty( $post_type['delete_with_user'] ) ) {
462 $delete_with_user = get_disp_boolean( $post_type['delete_with_user'] );
463 }
464
465 $capability_type = 'post';
466 if ( ! empty( $post_type['capability_type'] ) ) {
467 $capability_type = $post_type['capability_type'];
468 if ( false !== strpos( $post_type['capability_type'], ',' ) ) {
469 $caps = array_map( 'trim', explode( ',', $post_type['capability_type'] ) );
470 if ( count( $caps ) > 2 ) {
471 $caps = array_slice( $caps, 0, 2 );
472 }
473 $capability_type = $caps;
474 }
475 }
476
477 $public = get_disp_boolean( $post_type['public'] );
478 if ( ! empty( $post_type['exclude_from_search'] ) ) {
479 $exclude_from_search = get_disp_boolean( $post_type['exclude_from_search'] );
480 } else {
481 $exclude_from_search = false === $public;
482 }
483
484 $queryable = ( ! empty( $post_type['publicly_queryable'] ) && isset( $post_type['publicly_queryable'] ) ) ? get_disp_boolean( $post_type['publicly_queryable'] ) : $public;
485
486 if ( empty( $post_type['show_in_nav_menus'] ) ) {
487 // Defaults to value of public.
488 $post_type['show_in_nav_menus'] = $public;
489 }
490
491 if ( empty( $post_type['show_in_rest'] ) ) {
492 $post_type['show_in_rest'] = false;
493 }
494
495 $rest_base = null;
496 if ( ! empty( $post_type['rest_base'] ) ) {
497 $rest_base = $post_type['rest_base'];
498 }
499
500 $rest_controller_class = null;
501 if ( ! empty( $post_type['rest_controller_class'] ) ) {
502 $rest_controller_class = $post_type['rest_controller_class'];
503 }
504
505 $rest_namespace = null;
506 if ( ! empty( $post_type['rest_namespace'] ) ) {
507 $rest_namespace = $post_type['rest_namespace'];
508 }
509
510 $can_export = null;
511 if ( ! empty( $post_type['can_export'] ) ) {
512 $can_export = get_disp_boolean( $post_type['can_export'] );
513 }
514
515 $args = [
516 'labels' => $labels,
517 'description' => $post_type['description'],
518 'public' => get_disp_boolean( $post_type['public'] ),
519 'publicly_queryable' => $queryable,
520 'show_ui' => get_disp_boolean( $post_type['show_ui'] ),
521 'show_in_nav_menus' => get_disp_boolean( $post_type['show_in_nav_menus'] ),
522 'has_archive' => $has_archive,
523 'show_in_menu' => $show_in_menu,
524 'delete_with_user' => $delete_with_user,
525 'show_in_rest' => get_disp_boolean( $post_type['show_in_rest'] ),
526 'rest_base' => $rest_base,
527 'rest_controller_class' => $rest_controller_class,
528 'rest_namespace' => $rest_namespace,
529 'exclude_from_search' => $exclude_from_search,
530 'capability_type' => $capability_type,
531 'map_meta_cap' => $post_type['map_meta_cap'],
532 'hierarchical' => get_disp_boolean( $post_type['hierarchical'] ),
533 'can_export' => $can_export,
534 'rewrite' => $rewrite,
535 'menu_position' => $menu_position,
536 'menu_icon' => $menu_icon,
537 'register_meta_box_cb' => $register_meta_box_cb,
538 'query_var' => $post_type['query_var'],
539 'supports' => $post_type['supports'],
540 'taxonomies' => $post_type['taxonomies'],
541 ];
542
543 if ( true === $yarpp ) {
544 $args['yarpp_support'] = $yarpp;
545 }
546
547 /**
548 * Filters the arguments used for a post type right before registering.
549 *
550 * @since 1.0.0
551 * @since 1.3.0 Added original passed in values array
552 *
553 * @param array $args Array of arguments to use for registering post type.
554 * @param string $value Post type slug to be registered.
555 * @param array $post_type Original passed in values for post type.
556 */
557 $args = apply_filters( 'cptui_pre_register_post_type', $args, $post_type['name'], $post_type );
558
559 return register_post_type( $post_type['name'], $args );
560 }
561
562 /**
563 * Register our users' custom taxonomies.
564 *
565 * @since 0.5.0
566 *
567 * @internal
568 */
569 function cptui_create_custom_taxonomies() {
570 $taxes = get_option( 'cptui_taxonomies', [] );
571 /**
572 * Filters an override array of taxonomy data to be registered instead of our saved option.
573 *
574 * @since 1.10.0
575 *
576 * @param array $value Default override value.
577 */
578 $taxes_override = apply_filters( 'cptui_taxonomies_override', [] );
579
580 if ( empty( $taxes ) && empty( $taxes_override ) ) {
581 return;
582 }
583
584 // Assume good intent, and we're also not wrecking the option so things are always reversable.
585 if ( is_array( $taxes_override ) && ! empty( $taxes_override ) ) {
586 $taxes = $taxes_override;
587 }
588
589 /**
590 * Fires before the start of the taxonomy registrations.
591 *
592 * @since 1.3.0
593 *
594 * @param array $taxes Array of taxonomies to register.
595 */
596 do_action( 'cptui_pre_register_taxonomies', $taxes );
597
598 if ( is_array( $taxes ) ) {
599 foreach ( $taxes as $tax ) {
600
601 if ( ! is_string( $tax['name'] ) ) {
602 $tax['name'] = (string) $tax['name'];
603 }
604 /**
605 * Filters whether or not to skip registration of the current iterated taxonomy.
606 *
607 * Dynamic part of the filter name is the chosen taxonomy slug.
608 *
609 * @since 1.7.0
610 *
611 * @param bool $value Whether or not to skip the taxonomy.
612 * @param array $tax Current taxonomy being registered.
613 */
614 if ( (bool) apply_filters( "cptui_disable_{$tax['name']}_tax", false, $tax ) ) {
615 continue;
616 }
617
618 /**
619 * Filters whether or not to skip registration of the current iterated taxonomy.
620 *
621 * @since 1.7.0
622 *
623 * @param bool $value Whether or not to skip the taxonomy.
624 * @param array $tax Current taxonomy being registered.
625 */
626 if ( (bool) apply_filters( 'cptui_disable_tax', false, $tax ) ) {
627 continue;
628 }
629
630 cptui_register_single_taxonomy( $tax );
631 }
632 }
633
634 /**
635 * Fires after the completion of the taxonomy registrations.
636 *
637 * @since 1.3.0
638 *
639 * @param array $taxes Array of taxonomies registered.
640 */
641 do_action( 'cptui_post_register_taxonomies', $taxes );
642 }
643 add_action( 'init', 'cptui_create_custom_taxonomies', 9 ); // Leave on standard init for legacy purposes.
644
645 /**
646 * Helper function to register the actual taxonomy.
647 *
648 * @since 1.0.0
649 *
650 * @internal
651 *
652 * @param array $taxonomy Taxonomy array to register. Optional.
653 * @return null Result of register_taxonomy.
654 */
655 function cptui_register_single_taxonomy( $taxonomy = [] ) {
656
657 $labels = [
658 'name' => $taxonomy['label'],
659 'singular_name' => $taxonomy['singular_label'],
660 ];
661
662 $description = '';
663 if ( ! empty( $taxonomy['description'] ) ) {
664 $description = $taxonomy['description'];
665 }
666
667 $preserved = cptui_get_preserved_keys( 'taxonomies' );
668 $preserved_labels = cptui_get_preserved_labels();
669 foreach ( $taxonomy['labels'] as $key => $label ) {
670
671 if ( ! empty( $label ) ) {
672 $labels[ $key ] = $label;
673 } elseif ( empty( $label ) && in_array( $key, $preserved, true ) ) {
674 $singular_or_plural = ( in_array( $key, array_keys( $preserved_labels['taxonomies']['plural'] ) ) ) ? 'plural' : 'singular'; // phpcs:ignore.
675 $label_plurality = ( 'plural' === $singular_or_plural ) ? $taxonomy['label'] : $taxonomy['singular_label'];
676 $labels[ $key ] = sprintf( $preserved_labels['taxonomies'][ $singular_or_plural ][ $key ], $label_plurality );
677 }
678 }
679
680 $rewrite = get_disp_boolean( $taxonomy['rewrite'] );
681 if ( false !== get_disp_boolean( $taxonomy['rewrite'] ) ) {
682 $rewrite = [];
683 $rewrite['slug'] = ! empty( $taxonomy['rewrite_slug'] ) ? $taxonomy['rewrite_slug'] : $taxonomy['name'];
684 $rewrite['with_front'] = true;
685 if ( isset( $taxonomy['rewrite_withfront'] ) ) {
686 $rewrite['with_front'] = ( 'false' === disp_boolean( $taxonomy['rewrite_withfront'] ) ) ? false : true;
687 }
688 $rewrite['hierarchical'] = false;
689 if ( isset( $taxonomy['rewrite_hierarchical'] ) ) {
690 $rewrite['hierarchical'] = ( 'true' === disp_boolean( $taxonomy['rewrite_hierarchical'] ) ) ? true : false;
691 }
692 }
693
694 if ( in_array( $taxonomy['query_var'], [ 'true', 'false', '0', '1' ], true ) ) {
695 $taxonomy['query_var'] = get_disp_boolean( $taxonomy['query_var'] );
696 }
697 if ( true === $taxonomy['query_var'] && ! empty( $taxonomy['query_var_slug'] ) ) {
698 $taxonomy['query_var'] = $taxonomy['query_var_slug'];
699 }
700
701 $public = ( ! empty( $taxonomy['public'] ) && false === get_disp_boolean( $taxonomy['public'] ) ) ? false : true;
702 $publicly_queryable = ( ! empty( $taxonomy['publicly_queryable'] ) && false === get_disp_boolean( $taxonomy['publicly_queryable'] ) ) ? false : true;
703 if ( empty( $taxonomy['publicly_queryable'] ) ) {
704 $publicly_queryable = $public;
705 }
706
707 $show_admin_column = ( ! empty( $taxonomy['show_admin_column'] ) && false !== get_disp_boolean( $taxonomy['show_admin_column'] ) ) ? true : false;
708
709 $show_in_menu = ( ! empty( $taxonomy['show_in_menu'] ) && false !== get_disp_boolean( $taxonomy['show_in_menu'] ) ) ? true : false;
710
711 if ( empty( $taxonomy['show_in_menu'] ) ) {
712 $show_in_menu = get_disp_boolean( $taxonomy['show_ui'] );
713 }
714
715 $show_in_nav_menus = ( ! empty( $taxonomy['show_in_nav_menus'] ) && false !== get_disp_boolean( $taxonomy['show_in_nav_menus'] ) ) ? true : false;
716 if ( empty( $taxonomy['show_in_nav_menus'] ) ) {
717 $show_in_nav_menus = $public;
718 }
719
720 $show_tagcloud = ( ! empty( $taxonomy['show_tagcloud'] ) && false !== get_disp_boolean( $taxonomy['show_tagcloud'] ) ) ? true : false;
721 if ( empty( $taxonomy['show_tagcloud'] ) ) {
722 $show_tagcloud = get_disp_boolean( $taxonomy['show_ui'] );
723 }
724
725 $show_in_rest = ( ! empty( $taxonomy['show_in_rest'] ) && false !== get_disp_boolean( $taxonomy['show_in_rest'] ) ) ? true : false;
726
727 $show_in_quick_edit = ( ! empty( $taxonomy['show_in_quick_edit'] ) && false !== get_disp_boolean( $taxonomy['show_in_quick_edit'] ) ) ? true : false;
728
729 $sort = ( ! empty( $taxonomy['sort'] ) && false !== get_disp_boolean( $taxonomy['sort'] ) ) ? true : false;
730
731 $rest_base = null;
732 if ( ! empty( $taxonomy['rest_base'] ) ) {
733 $rest_base = $taxonomy['rest_base'];
734 }
735
736 $rest_controller_class = null;
737 if ( ! empty( $taxonomy['rest_controller_class'] ) ) {
738 $rest_controller_class = $taxonomy['rest_controller_class'];
739 }
740
741 $rest_namespace = null;
742 if ( ! empty( $taxonomy['rest_namespace'] ) ) {
743 $rest_namespace = $taxonomy['rest_namespace'];
744 }
745
746 $meta_box_cb = null;
747 if ( ! empty( $taxonomy['meta_box_cb'] ) ) {
748 $meta_box_cb = ( false !== get_disp_boolean( $taxonomy['meta_box_cb'] ) ) ? $taxonomy['meta_box_cb'] : false;
749 }
750 $default_term = null;
751 if ( ! empty( $taxonomy['default_term'] ) ) {
752 $term_parts = explode( ',', $taxonomy['default_term'] );
753 if ( ! empty( $term_parts[0] ) ) {
754 $default_term['name'] = trim( $term_parts[0] );
755 }
756 if ( ! empty( $term_parts[1] ) ) {
757 $default_term['slug'] = trim( $term_parts[1] );
758 }
759 if ( ! empty( $term_parts[2] ) ) {
760 $default_term['description'] = trim( $term_parts[2] );
761 }
762 }
763
764 $args = [
765 'labels' => $labels,
766 'label' => $taxonomy['label'],
767 'description' => $description,
768 'public' => $public,
769 'publicly_queryable' => $publicly_queryable,
770 'hierarchical' => get_disp_boolean( $taxonomy['hierarchical'] ),
771 'show_ui' => get_disp_boolean( $taxonomy['show_ui'] ),
772 'show_in_menu' => $show_in_menu,
773 'show_in_nav_menus' => $show_in_nav_menus,
774 'show_tagcloud' => $show_tagcloud,
775 'query_var' => $taxonomy['query_var'],
776 'rewrite' => $rewrite,
777 'show_admin_column' => $show_admin_column,
778 'show_in_rest' => $show_in_rest,
779 'rest_base' => $rest_base,
780 'rest_controller_class' => $rest_controller_class,
781 'rest_namespace' => $rest_namespace,
782 'show_in_quick_edit' => $show_in_quick_edit,
783 'sort' => $sort,
784 'meta_box_cb' => $meta_box_cb,
785 'default_term' => $default_term,
786 ];
787
788 $object_type = ! empty( $taxonomy['object_types'] ) ? $taxonomy['object_types'] : '';
789
790 /**
791 * Filters the arguments used for a taxonomy right before registering.
792 *
793 * @since 1.0.0
794 * @since 1.3.0 Added original passed in values array
795 * @since 1.6.0 Added $obect_type variable to passed parameters.
796 *
797 * @param array $args Array of arguments to use for registering taxonomy.
798 * @param string $value Taxonomy slug to be registered.
799 * @param array $taxonomy Original passed in values for taxonomy.
800 * @param array $object_type Array of chosen post types for the taxonomy.
801 */
802 $args = apply_filters( 'cptui_pre_register_taxonomy', $args, $taxonomy['name'], $taxonomy, $object_type );
803
804 return register_taxonomy( $taxonomy['name'], $object_type, $args );
805 }
806
807 /**
808 * Construct and output tab navigation.
809 *
810 * @since 1.0.0
811 *
812 * @param string $page Whether it's the CPT or Taxonomy page. Optional. Default "post_types".
813 * @return string
814 */
815 function cptui_settings_tab_menu( $page = 'post_types' ) {
816
817 /**
818 * Filters the tabs to render on a given page.
819 *
820 * @since 1.3.0
821 *
822 * @param array $value Array of tabs to render.
823 * @param string $page Current page being displayed.
824 */
825 $tabs = (array) apply_filters( 'cptui_get_tabs', [], $page );
826
827 if ( empty( $tabs['page_title'] ) ) {
828 return '';
829 }
830
831 $tmpl = '<h1>%s</h1><nav class="nav-tab-wrapper wp-clearfix" aria-label="%s">%s</nav>';
832
833 $tab_output = '';
834 foreach ( $tabs['tabs'] as $tab ) {
835 $tab_output .= sprintf(
836 '<a class="%s" href="%s" aria-selected="%s">%s</a>',
837 implode( ' ', $tab['classes'] ),
838 $tab['url'],
839 $tab['aria-selected'],
840 $tab['text']
841 );
842 }
843
844 printf(
845 $tmpl, // phpcs:ignore.
846 $tabs['page_title'], // phpcs:ignore.
847 esc_attr__( 'Secondary menu', 'custom-post-type-ui' ), // phpcs:ignore
848 $tab_output // phpcs:ignore.
849 );
850 }
851
852 /**
853 * Convert our old settings to the new options keys.
854 *
855 * These are left with standard get_option/update_option function calls for legacy and pending update purposes.
856 *
857 * @since 1.0.0
858 *
859 * @internal
860 *
861 * @return bool Whether or not options were successfully updated.
862 */
863 function cptui_convert_settings() {
864
865 if ( wp_doing_ajax() ) {
866 return;
867 }
868
869 $retval = '';
870
871 if ( false === get_option( 'cptui_post_types' ) && ( $post_types = get_option( 'cpt_custom_post_types' ) ) ) { // phpcs:ignore.
872
873 $new_post_types = [];
874 foreach ( $post_types as $type ) {
875 $new_post_types[ $type['name'] ] = $type; // This one assigns the # indexes. Named arrays are our friend.
876 $new_post_types[ $type['name'] ]['supports'] = ! empty( $type[0] ) ? $type[0] : []; // Especially for multidimensional arrays.
877 $new_post_types[ $type['name'] ]['taxonomies'] = ! empty( $type[1] ) ? $type[1] : [];
878 $new_post_types[ $type['name'] ]['labels'] = ! empty( $type[2] ) ? $type[2] : [];
879 unset(
880 $new_post_types[ $type['name'] ][0],
881 $new_post_types[ $type['name'] ][1],
882 $new_post_types[ $type['name'] ][2]
883 ); // Remove our previous indexed versions.
884 }
885
886 $retval = update_option( 'cptui_post_types', $new_post_types );
887 }
888
889 if ( false === get_option( 'cptui_taxonomies' ) && ( $taxonomies = get_option( 'cpt_custom_tax_types' ) ) ) { // phpcs:ignore.
890
891 $new_taxonomies = [];
892 foreach ( $taxonomies as $tax ) {
893 $new_taxonomies[ $tax['name'] ] = $tax; // Yep, still our friend.
894 $new_taxonomies[ $tax['name'] ]['labels'] = $tax[0]; // Taxonomies are the only thing with.
895 $new_taxonomies[ $tax['name'] ]['object_types'] = $tax[1]; // "tax" in the name that I like.
896 unset(
897 $new_taxonomies[ $tax['name'] ][0],
898 $new_taxonomies[ $tax['name'] ][1]
899 );
900 }
901
902 $retval = update_option( 'cptui_taxonomies', $new_taxonomies );
903 }
904
905 if ( ! empty( $retval ) ) {
906 flush_rewrite_rules();
907 }
908
909 return $retval;
910 }
911 add_action( 'admin_init', 'cptui_convert_settings' );
912
913 /**
914 * Return a notice based on conditions.
915 *
916 * @since 1.0.0
917 *
918 * @param string $action The type of action that occurred. Optional. Default empty string.
919 * @param string $object_type Whether it's from a post type or taxonomy. Optional. Default empty string.
920 * @param bool $success Whether the action succeeded or not. Optional. Default true.
921 * @param string $custom Custom message if necessary. Optional. Default empty string.
922 * @return bool|string false on no message, else HTML div with our notice message.
923 */
924 function cptui_admin_notices( $action = '', $object_type = '', $success = true, $custom = '' ) {
925
926 $class = [];
927 $class[] = $success ? 'updated' : 'error';
928 $class[] = 'notice is-dismissible';
929 $object_type = esc_attr( $object_type );
930
931 $messagewrapstart = '<div id="message" class="' . implode( ' ', $class ) . '"><p>';
932 $message = '';
933
934 $messagewrapend = '</p></div>';
935
936 if ( 'add' === $action ) {
937 if ( $success ) {
938 $message .= sprintf( esc_html__( '%s has been successfully added', 'custom-post-type-ui' ), $object_type );
939 } else {
940 $message .= sprintf( esc_html__( '%s has failed to be added', 'custom-post-type-ui' ), $object_type );
941 }
942 } elseif ( 'update' === $action ) {
943 if ( $success ) {
944 $message .= sprintf( esc_html__( '%s has been successfully updated', 'custom-post-type-ui' ), $object_type );
945 } else {
946 $message .= sprintf( esc_html__( '%s has failed to be updated', 'custom-post-type-ui' ), $object_type );
947 }
948 } elseif ( 'delete' === $action ) {
949 if ( $success ) {
950 $message .= sprintf( esc_html__( '%s has been successfully deleted', 'custom-post-type-ui' ), $object_type );
951 } else {
952 $message .= sprintf( esc_html__( '%s has failed to be deleted', 'custom-post-type-ui' ), $object_type );
953 }
954 } elseif ( 'import' === $action ) {
955 if ( $success ) {
956 $message .= sprintf( esc_html__( '%s has been successfully imported', 'custom-post-type-ui' ), $object_type );
957 } else {
958 $message .= sprintf( esc_html__( '%s has failed to be imported', 'custom-post-type-ui' ), $object_type );
959 }
960 } elseif ( 'error' === $action ) {
961 if ( ! empty( $custom ) ) {
962 $message = $custom;
963 }
964 }
965
966 if ( $message ) {
967
968 /**
969 * Filters the custom admin notice for CPTUI.
970 *
971 * @since 1.0.0
972 *
973 * @param string $value Complete HTML output for notice.
974 * @param string $action Action whose message is being generated.
975 * @param string $message The message to be displayed.
976 * @param string $messagewrapstart Beginning wrap HTML.
977 * @param string $messagewrapend Ending wrap HTML.
978 */
979 return apply_filters( 'cptui_admin_notice', $messagewrapstart . $message . $messagewrapend, $action, $message, $messagewrapstart, $messagewrapend );
980 }
981
982 return false;
983 }
984
985 /**
986 * Return array of keys needing preserved.
987 *
988 * @since 1.0.5
989 *
990 * @param string $type Type to return. Either 'post_types' or 'taxonomies'. Optional. Default empty string.
991 * @return array Array of keys needing preservered for the requested type.
992 */
993 function cptui_get_preserved_keys( $type = '' ) {
994
995 $preserved_labels = [
996 'post_types' => [
997 'add_new_item',
998 'edit_item',
999 'new_item',
1000 'view_item',
1001 'view_items',
1002 'all_items',
1003 'search_items',
1004 'not_found',
1005 'not_found_in_trash',
1006 ],
1007 'taxonomies' => [
1008 'search_items',
1009 'popular_items',
1010 'all_items',
1011 'parent_item',
1012 'parent_item_colon',
1013 'edit_item',
1014 'update_item',
1015 'add_new_item',
1016 'new_item_name',
1017 'separate_items_with_commas',
1018 'add_or_remove_items',
1019 'choose_from_most_used',
1020 ],
1021 ];
1022 return ! empty( $type ) ? $preserved_labels[ $type ] : [];
1023 }
1024
1025 /**
1026 * Return label for the requested type and label key.
1027 *
1028 * @since 1.0.5
1029 *
1030 * @deprecated
1031 *
1032 * @param string $type Type to return. Either 'post_types' or 'taxonomies'. Optional. Default empty string.
1033 * @param string $key Requested label key. Optional. Default empty string.
1034 * @param string $plural Plural verbiage for the requested label and type. Optional. Default empty string.
1035 * @param string $singular Singular verbiage for the requested label and type. Optional. Default empty string.
1036 * @return string Internationalized default label.
1037 */
1038 function cptui_get_preserved_label( $type = '', $key = '', $plural = '', $singular = '' ) {
1039
1040 $preserved_labels = [
1041 'post_types' => [
1042 'add_new_item' => sprintf( esc_html__( 'Add new %s', 'custom-post-type-ui' ), $singular ),
1043 'edit_item' => sprintf( esc_html__( 'Edit %s', 'custom-post-type-ui' ), $singular ),
1044 'new_item' => sprintf( esc_html__( 'New %s', 'custom-post-type-ui' ), $singular ),
1045 'view_item' => sprintf( esc_html__( 'View %s', 'custom-post-type-ui' ), $singular ),
1046 'view_items' => sprintf( esc_html__( 'View %s', 'custom-post-type-ui' ), $plural ),
1047 'all_items' => sprintf( esc_html__( 'All %s', 'custom-post-type-ui' ), $plural ),
1048 'search_items' => sprintf( esc_html__( 'Search %s', 'custom-post-type-ui' ), $plural ),
1049 'not_found' => sprintf( esc_html__( 'No %s found.', 'custom-post-type-ui' ), $plural ),
1050 'not_found_in_trash' => sprintf( esc_html__( 'No %s found in trash.', 'custom-post-type-ui' ), $plural ),
1051 ],
1052 'taxonomies' => [
1053 'search_items' => sprintf( esc_html__( 'Search %s', 'custom-post-type-ui' ), $plural ),
1054 'popular_items' => sprintf( esc_html__( 'Popular %s', 'custom-post-type-ui' ), $plural ),
1055 'all_items' => sprintf( esc_html__( 'All %s', 'custom-post-type-ui' ), $plural ),
1056 'parent_item' => sprintf( esc_html__( 'Parent %s', 'custom-post-type-ui' ), $singular ),
1057 'parent_item_colon' => sprintf( esc_html__( 'Parent %s:', 'custom-post-type-ui' ), $singular ),
1058 'edit_item' => sprintf( esc_html__( 'Edit %s', 'custom-post-type-ui' ), $singular ),
1059 'update_item' => sprintf( esc_html__( 'Update %s', 'custom-post-type-ui' ), $singular ),
1060 'add_new_item' => sprintf( esc_html__( 'Add new %s', 'custom-post-type-ui' ), $singular ),
1061 'new_item_name' => sprintf( esc_html__( 'New %s name', 'custom-post-type-ui' ), $singular ),
1062 'separate_items_with_commas' => sprintf( esc_html__( 'Separate %s with commas', 'custom-post-type-ui' ), $plural ),
1063 'add_or_remove_items' => sprintf( esc_html__( 'Add or remove %s', 'custom-post-type-ui' ), $plural ),
1064 'choose_from_most_used' => sprintf( esc_html__( 'Choose from the most used %s', 'custom-post-type-ui' ), $plural ),
1065 ],
1066 ];
1067
1068 return $preserved_labels[ $type ][ $key ];
1069 }
1070
1071 /**
1072 * Returns an array of translated labels, ready for use with sprintf().
1073 *
1074 * Replacement for cptui_get_preserved_label for the sake of performance.
1075 *
1076 * @since 1.6.0
1077 *
1078 * @return array
1079 */
1080 function cptui_get_preserved_labels() {
1081 return [
1082 'post_types' => [
1083 'singular' => [
1084 'add_new_item' => esc_html__( 'Add new %s', 'custom-post-type-ui' ),
1085 'edit_item' => esc_html__( 'Edit %s', 'custom-post-type-ui' ),
1086 'new_item' => esc_html__( 'New %s', 'custom-post-type-ui' ),
1087 'view_item' => esc_html__( 'View %s', 'custom-post-type-ui' ),
1088 ],
1089 'plural' => [
1090 'view_items' => esc_html__( 'View %s', 'custom-post-type-ui' ),
1091 'all_items' => esc_html__( 'All %s', 'custom-post-type-ui' ),
1092 'search_items' => esc_html__( 'Search %s', 'custom-post-type-ui' ),
1093 'not_found' => esc_html__( 'No %s found.', 'custom-post-type-ui' ),
1094 'not_found_in_trash' => esc_html__( 'No %s found in trash.', 'custom-post-type-ui' ),
1095 ],
1096 ],
1097 'taxonomies' => [
1098 'singular' => [
1099 'parent_item' => esc_html__( 'Parent %s', 'custom-post-type-ui' ),
1100 'parent_item_colon' => esc_html__( 'Parent %s:', 'custom-post-type-ui' ),
1101 'edit_item' => esc_html__( 'Edit %s', 'custom-post-type-ui' ),
1102 'update_item' => esc_html__( 'Update %s', 'custom-post-type-ui' ),
1103 'add_new_item' => esc_html__( 'Add new %s', 'custom-post-type-ui' ),
1104 'new_item_name' => esc_html__( 'New %s name', 'custom-post-type-ui' ),
1105 ],
1106 'plural' => [
1107 'search_items' => esc_html__( 'Search %s', 'custom-post-type-ui' ),
1108 'popular_items' => esc_html__( 'Popular %s', 'custom-post-type-ui' ),
1109 'all_items' => esc_html__( 'All %s', 'custom-post-type-ui' ),
1110 'separate_items_with_commas' => esc_html__( 'Separate %s with commas', 'custom-post-type-ui' ),
1111 'add_or_remove_items' => esc_html__( 'Add or remove %s', 'custom-post-type-ui' ),
1112 'choose_from_most_used' => esc_html__( 'Choose from the most used %s', 'custom-post-type-ui' ),
1113 ],
1114 ],
1115 ];
1116 }
1 <?php
2
3 namespace CPTUI;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 /**
10 * This class creates settings for Custom Post Type UI to show Custom Post Types in GraphQL
11 */
12 class CPTUI_GraphQL {
13
14 /**
15 * @var bool
16 */
17 protected $show_in_graphql = false;
18
19 /**
20 * @var string
21 */
22 protected $graphql_single_name = '';
23
24 /**
25 * @var string
26 */
27 protected $graphql_plural_name = '';
28
29 /**
30 * Initializes the plugin functionality
31 */
32 public function init() {
33
34 // Post Types.
35 add_action( 'cptui_post_type_after_fieldsets', [ $this, 'add_graphql_post_type_settings' ], 10, 1 );
36 add_filter( 'cptui_before_update_post_type', [ $this, 'before_update_post_type' ], 10, 2 );
37 add_filter( 'cptui_pre_register_post_type', [ $this, 'add_graphql_settings_to_registry' ], 10, 3 );
38 add_filter( 'cptui_pre_save_post_type', [ $this, 'save_graphql_settings' ], 10, 2 );
39
40 // Taxonomies.
41 add_action( 'cptui_taxonomy_after_fieldsets', [ $this, 'add_taxonomy_graphql_settings' ], 10, 1 );
42 add_filter( 'cptui_before_update_taxonomy', [ $this, 'before_update_taxonomy' ], 10, 2 );
43 add_filter( 'cptui_pre_register_taxonomy', [ $this, 'add_graphql_settings_to_registry' ], 10, 3 );
44 add_filter( 'cptui_pre_save_taxonomy', [ $this, 'save_graphql_settings' ], 10, 2 );
45 }
46
47 /**
48 * Adds the GraphQL Settings from CPT UI to the post_type and taxonomy registry args.
49 *
50 * @param array $args The args for the registry.
51 * @param string $name The name of the type.
52 * @param array $type The array that composes the Type.
53 *
54 * @return array
55 */
56 public function add_graphql_settings_to_registry( $args, $name, $type ) {
57
58 // If the type is not set to show_in_graphql, return the args as-is.
59 if ( ! isset( $type['show_in_graphql'] ) || true !== (bool) $type['show_in_graphql'] ) {
60 return $args;
61 }
62
63 // If the type has no graphql_plural_name, return the args as-is, but
64 // add a message to the debug log for why the Type is not in the Schema.
65 if ( ! isset( $type['graphql_plural_name'] ) || empty( $type['graphql_plural_name'] ) ) {
66 graphql_debug(
67 sprintf(
68 // phpcs:ignore.
69 esc_attr__( 'The graphql_plural_name is empty for the "%s" Post Type or Taxonomy registered by Custom Post Type UI.' ),
70 $type['name']
71 )
72 );
73
74 return $args;
75 }
76
77 // If the type has no graphql_single_name, return the args as-is, but
78 // add a message to the debug log for why the Type is not in the Schema.
79 if ( ! isset( $type['graphql_single_name'] ) || empty( $type['graphql_single_name'] ) ) {
80 graphql_debug(
81 sprintf(
82 // phpcs:ignore.
83 esc_attr__( 'The graphql_single_name is empty for the "%s" Post Type or Taxonomy registered by Custom Post Type UI.' ),
84 $type['name']
85 )
86 );
87
88 return $args;
89 }
90
91 $args['show_in_graphql'] = isset( $type['show_in_graphql'] ) ? (bool) $type['show_in_graphql'] : false;
92 $args['graphql_single_name'] = ! empty( $type['graphql_single_name'] ) ? $type['graphql_single_name'] : null;
93 $args['graphql_plural_name'] = ! empty( $type['graphql_plural_name'] ) ? $type['graphql_plural_name'] : null;
94
95 return $args;
96 }
97
98 /**
99 * Capture post type settings from form submission for saving
100 *
101 * @param array $data
102 */
103 public function before_update_post_type( $data ) {
104 $this->show_in_graphql = isset( $data['cpt_custom_post_type']['show_in_graphql'] ) ? $data['cpt_custom_post_type']['show_in_graphql'] : false;
105 $this->graphql_single_name = isset( $data['cpt_custom_post_type']['graphql_single_name'] ) ? \WPGraphQL\Utils\Utils::format_type_name( $data['cpt_custom_post_type']['graphql_single_name'] ) : '';
106 $this->graphql_plural_name = isset( $data['cpt_custom_post_type']['graphql_plural_name'] ) ? \WPGraphQL\Utils\Utils::format_type_name( $data['cpt_custom_post_type']['graphql_plural_name'] ) : '';
107 }
108
109 /**
110 * Capture taxonomy settings from form submission for saving
111 *
112 * @param array $data
113 */
114 public function before_update_taxonomy( $data ) {
115 $this->show_in_graphql = isset( $data['cpt_custom_tax']['show_in_graphql'] ) ? $data['cpt_custom_tax']['show_in_graphql'] : false;
116 $this->graphql_single_name = isset( $data['cpt_custom_tax']['graphql_single_name'] ) ? \WPGraphQL\Utils\Utils::format_type_name( $data['cpt_custom_tax']['graphql_single_name'] ) : '';
117 $this->graphql_plural_name = isset( $data['cpt_custom_tax']['graphql_plural_name'] ) ? \WPGraphQL\Utils\Utils::format_type_name( $data['cpt_custom_tax']['graphql_plural_name'] ) : '';
118 }
119
120 /**
121 * Save values from form submission
122 *
123 * @param array $type
124 * @param string $name
125 *
126 * @return array
127 */
128 public function save_graphql_settings( $type, $name ) {
129 $type[ $name ]['show_in_graphql'] = $this->show_in_graphql;
130 $type[ $name ]['graphql_single_name'] = \WPGraphQL\Utils\Utils::format_type_name( $this->graphql_single_name );
131 $type[ $name ]['graphql_plural_name'] = \WPGraphQL\Utils\Utils::format_type_name( $this->graphql_plural_name );
132
133 return $type;
134 }
135
136 /**
137 * Add settings fields to Custom Post Type UI form
138 *
139 * @param cptui_admin_ui $ui Admin UI instance.
140 */
141 public function add_graphql_post_type_settings( $ui ) {
142 $tab = ( ! empty( $_GET ) && ! empty( $_GET['action'] ) && 'edit' === $_GET['action'] ) ? 'edit' : 'new'; // phpcs:ignore WordPress.Security.NonceVerification
143 $current = [];
144 $name_array = 'cpt_custom_post_type';
145 if ( 'edit' === $tab ) {
146 $post_types = cptui_get_post_type_data();
147 $selected_post_type = cptui_get_current_post_type( false );
148 if ( $selected_post_type ) {
149 if ( array_key_exists( $selected_post_type, $post_types ) ) {
150 $current = $post_types[ $selected_post_type ];
151 }
152 }
153 }
154 echo $this->get_setting_fields( $ui, $current, $name_array ); // phpcs:ignore.
155 }
156
157 /**
158 * Add settings fields to Custom Post Type UI form
159 *
160 * @param cptui_admin_ui $ui Admin UI instance.
161 */
162 public function add_taxonomy_graphql_settings( $ui ) {
163 $tab = ( ! empty( $_GET ) && ! empty( $_GET['action'] ) && 'edit' === $_GET['action'] ) ? 'edit' : 'new'; // phpcs:ignore WordPress.Security.NonceVerification
164 $name_array = 'cpt_custom_tax';
165 $current = [];
166 if ( 'edit' === $tab ) {
167 $taxonomies = cptui_get_taxonomy_data();
168 $selected_taxonomy = cptui_get_current_taxonomy( false );
169 if ( $selected_taxonomy ) {
170 if ( array_key_exists( $selected_taxonomy, $taxonomies ) ) {
171 $current = $taxonomies[ $selected_taxonomy ];
172 }
173 }
174 }
175 echo $this->get_setting_fields( $ui, $current, $name_array ); // phpcs:ignore.
176 }
177
178 /**
179 * Get the settings fields to render for the form
180 *
181 * @param cptui_admin_ui $ui Admin UI instance.
182 * @param array $current
183 * @param string $name_array
184 */
185 public function get_setting_fields( $ui, $current, $name_array ) {
186 ?>
187 <div class="cptui-section postbox">
188 <div class="postbox-header">
189
190 <h2 class="hndle ui-sortable-handle">
191 <span><?php esc_html_e( 'WPGraphQL', 'wp-graphql-custom-post-type-ui' ); ?></span>
192 </h2>
193 <div class="handle-actions hide-if-no-js">
194 <button type="button" class="handlediv">
195 <span class="screen-reader-text"><?php esc_html_e( 'Toggle panel: GraphQL Settings', 'wp-graphql-custom-post-type-ui' ); ?></span>
196 <span class="toggle-indicator" aria-hidden="true"></span>
197 </button>
198 </div>
199 </div>
200 <div class="inside">
201 <div class="main">
202 <table class="form-table cptui-table">
203 <?php
204
205 $selections = [
206 'options' => [
207 [
208 'attr' => '0',
209 'text' => esc_attr__( 'False', 'wp-graphql-custom-post-type-ui' ),
210 ],
211 [
212 'attr' => '1',
213 'text' => esc_attr__( 'True', 'wp-graphql-custom-post-type-ui' ),
214 ],
215 ],
216 ];
217
218 $selected = ( isset( $current ) && ! empty( $current['show_in_graphql'] ) ) ? disp_boolean( $current['show_in_graphql'] ) : '';
219 $selections['selected'] = ( ! empty( $selected ) && ! empty( $current['show_in_graphql'] ) ) ? $current['show_in_graphql'] : '0';
220
221 echo $ui->get_select_input( // phpcs:ignore.
222 [
223 'namearray' => $name_array,
224 'name' => 'show_in_graphql',
225 'labeltext' => esc_html__( 'Show in GraphQL', 'wp-graphql-custom-post-type-ui' ),
226 'aftertext' => esc_html__( 'Whether or not to show data of this type in the WPGraphQL. Default: false', 'wp-graphql-custom-post-type-ui' ),
227 'selections' => $selections, // phpcs:ignore.
228 'default' => false,
229 'required' => true,
230 ]
231 );
232
233 echo $ui->get_text_input( // phpcs:ignore.
234 [
235 'namearray' => $name_array,
236 'name' => 'graphql_single_name',
237 'labeltext' => esc_html__( 'GraphQL Single Name', 'wp-graphql-custom-post-type-ui' ),
238 'aftertext' => esc_attr__( 'Singular name for reference in the GraphQL API.', 'wp-graphql-custom-post-type-ui' ),
239 'textvalue' => ( isset( $current['graphql_single_name'] ) ) ? esc_attr( $current['graphql_single_name'] ) : '', // phpcs:ignore.
240 'required' => true,
241 ]
242 );
243
244 echo $ui->get_text_input( // phpcs:ignore.
245 [
246 'namearray' => $name_array,
247 'name' => 'graphql_plural_name',
248 'labeltext' => esc_html__( 'GraphQL Plural Name', 'wp-graphql-custom-post-type-ui' ),
249 'aftertext' => esc_attr__( 'Plural name for reference in the GraphQL API.', 'wp-graphql-custom-post-type-ui' ),
250 'textvalue' => ( isset( $current['graphql_plural_name'] ) ) ? esc_attr( $current['graphql_plural_name'] ) : '', // phpcs:ignore.
251 'required' => true,
252 ]
253 );
254 ?>
255 </table>
256 </div>
257 </div>
258 </div>
259 <?php
260 $this->graphql_field_helpers();
261 }
262
263 /**
264 * JavaScript helpers to add conditional logic and support for the GraphQL setting fields
265 */
266 public function graphql_field_helpers() {
267 // This script provides helpers for the GraphQL fields in the CPT UI screen.
268 // If the Post Type or Taxonomy is not set to show_in_graphql the single/plural names
269 // should not be required.
270 ?>
271 <script type="application/javascript">
272 let singleName = document.getElementById('graphql_single_name');
273 let singleNameRow = singleName.closest('tr');
274 let pluralName = document.getElementById('graphql_plural_name');
275 let pluralNameRow = pluralName.closest('tr');
276 let showInGraphQL = document.getElementById('show_in_graphql');
277 let label = document.getElementById('label');
278 let singleLabel = document.getElementById('singular_label');
279
280 // Set the values of the GraphQL fields and their display state
281 function updateGraphQlFields() {
282
283 // Set default state for field values and display state
284 // If the show_in_graphql value is true (or '1') show the
285 // fields and set them as required
286 // Else hide the fields and leave them as not-required
287 if (showInGraphQL.value === '1') {
288 singleName.required = true;
289 pluralName.required = true;
290 pluralNameRow.style.display = "table-row";
291 singleNameRow.style.display = "table-row";
292 } else {
293 singleName.required = false;
294 pluralName.required = false;
295 pluralNameRow.style.display = "none";
296 singleNameRow.style.display = "none";
297 }
298
299 // If single_name has no value, but single_label does, use single_label as the value
300 if (!singleName.value.length) {
301 singleName.value = singleLabel.value;
302 }
303
304 // If single_name has no value, but single_label does, use single_label as the value
305 if (!pluralName.value.length) {
306 pluralName.value = label.value;
307 }
308 }
309
310 // Once the DOM is ready, listen for events
311 document.addEventListener("DOMContentLoaded", function () {
312 updateGraphQlFields();
313 // When the show in graphql field changes, re-apply GraphQL Field Values
314 showInGraphQL.addEventListener('input', function () {
315 updateGraphQlFields();
316 });
317 });
318 </script>
319 <?php
320 }
321 }
322
323 /**
324 * Load WPGraphQL for CPT UI
325 */
326 add_action( 'cptui_loaded', __NAMESPACE__ . '\cptui_graphql_init' );
327
328 function cptui_graphql_init() {
329 if ( class_exists( 'WPGraphQL_CPT_UI' ) ) {
330 add_action(
331 'admin_notices',
332 function () {
333 $link = trailingslashit( admin_url() ) . 'plugins.php';
334 ?>
335 <div class="notice notice-error">
336 <p>
337 <?php
338 echo sprintf(
339 // phpcs:ignore.
340 esc_html__( 'Custom Post Type UI has native support for WPGraphQL. Please <a href="%s">de-active</a> the "WPGraphQL for Custom Post Type UI" extension to proceed.', 'custom-post-type-ui' ),
341 $link // phpcs:ignore.
342 );
343 ?>
344 </p>
345 </div>
346 <?php
347 }
348 );
349
350 return;
351 }
352
353 $wpgraphql_cpt_ui = new CPTUI_GraphQL();
354 $wpgraphql_cpt_ui->init();
355 }
1 <?php
2 /**
3 * Custom Post Type UI About Page.
4 *
5 * @package CPTUI
6 * @subpackage About
7 * @author WebDevStudios
8 * @since 1.3.0
9 * @license GPL-2.0+
10 */
11
12 // phpcs:disable WebDevStudios.All.RequireAuthor
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Enqueue our Custom Post Type UI assets.
21 *
22 * @since 1.6.0
23 */
24 function cptui_about_assets() {
25 $current_screen = get_current_screen();
26
27 if ( ! is_object( $current_screen ) || 'toplevel_page_cptui_main_menu' !== $current_screen->base ) {
28 return;
29 }
30
31 if ( wp_doing_ajax() ) {
32 return;
33 }
34
35 wp_enqueue_style( 'cptui-css' );
36 }
37 add_action( 'admin_enqueue_scripts', 'cptui_about_assets' );
38
39 /**
40 * Display our primary menu page.
41 *
42 * @since 0.3.0
43 *
44 * @internal
45 */
46 function cptui_settings() {
47 ?>
48 <div class="wrap about-wrap">
49 <?php
50
51 /**
52 * Fires inside and at the top of the wrapper for the main plugin landing page.
53 *
54 * @since 1.0.0
55 */
56 do_action( 'cptui_main_page_start' );
57 ?>
58 <h1><?php esc_html_e( 'Custom Post Type UI', 'custom-post-type-ui' ); ?> <?php echo esc_html( CPTUI_VERSION ); ?></h1>
59
60 <?php
61
62 /**
63 * Fires after the main page `<h1>` heading tag.
64 *
65 * @since 1.3.0
66 */
67 do_action( 'cptui_main_page_after_header' );
68 ?>
69 <div class="cptui-intro-devblock">
70 <p class="about-text cptui-about-text">
71 <?php esc_html_e( 'Thank you for choosing Custom Post Type UI! We hope that your experience with our plugin makes creating post types and taxonomies and organizing your content quick and easy.', 'custom-post-type-ui' ); ?>
72 </p>
73 <div class="cptui-badge"></div>
74 </div>
75 <?php
76 /**
77 * Fires before the About Page changelog.
78 *
79 * @since 1.4.0
80 */
81 do_action( 'cptui_main_page_before_changelog' );
82 ?>
83
84 <h2>
85 <?php
86 printf(
87 // translators: Placeholder will hold the plugin version.
88 esc_html__( "What's new in version %s", 'custom-post-type-ui' ),
89 esc_html( CPTUI_VERSION )
90 );
91 ?>
92 </h2>
93 <div class="changelog about-integrations">
94 <div class="cptui-feature feature-section col three-col">
95 <div class="col">
96 <h2><?php esc_html_e( 'Post type descriptions', 'custom-post-type-ui' ); ?></h2>
97 <p><?php esc_html_e( 'We have updated a number of details around the post type description field. First we addressed issues with the Tools area when descriptions included quotes. Second we fixed an issue around stripping HTML from the field from previous security updates.', 'custom-post-type-ui' ); ?></p>
98 <h2><?php esc_html_e( 'Miscellaneous code cleanup and separation.', 'custom-post-type-ui' ); ?></h2>
99 <p><?php esc_html_e( 'Largely under the hood, but we have done some separation of our code and done more to help ensure code quality.', 'custom-post-type-ui' ); ?></p>
100 <h2><?php esc_html_e( 'Branding.', 'custom-post-type-ui' ); ?></h2>
101 <p><?php esc_html_e( 'We updated our branding for the plugin. Both within our UI but also on WordPress.org', 'custom-post-type-ui' ); ?></p>
102 <h2><?php esc_html_e( 'Miscellaneous.', 'custom-post-type-ui' ); ?></h2>
103 <p><?php esc_html_e( 'Added notes about some post type features also needing theme support declared for them to work. Fixed a pluralization issue with our UI and forms.', 'custom-post-type-ui' ); ?></p>
104 </div>
105 </div>
106 </div>
107
108 <div class="extranotes">
109 <?php
110
111 /**
112 * Fires inside a div for extra notes.
113 *
114 * @since 1.3.0
115 */
116 do_action( 'cptui_main_page_extra_notes' );
117 ?>
118 </div>
119 </div>
120 <?php
121 }
122
123 /**
124 * Display Pluginize-based content.
125 *
126 * @since 1.4.0
127 */
128 function cptui_pluginize_content() {
129 // translators: Placeholder will hold the name of the author of the plugin.
130 echo '<h1>' . sprintf( esc_html__( 'More from %s', 'custom-post-type-ui' ), 'WebDevStudios' ) . '</h1>';
131 echo '<div class="wdspromos-about">';
132 $ads = cptui_get_ads();
133 if ( ! empty( $ads ) ) {
134
135 foreach ( $ads as $ad ) {
136
137 $the_ad = sprintf(
138 '<img src="%s" alt="%s">',
139 esc_attr( $ad['image'] ),
140 esc_attr( $ad['text'] )
141 );
142
143 // Escaping $the_ad breaks the html.
144 printf(
145 '<p><a href="%s">%s</a></p>',
146 esc_url( $ad['url'] ),
147 $the_ad // phpcs:ignore
148 );
149 }
150 }
151 echo '</div>';
152 }
153 add_action( 'cptui_main_page_extra_notes', 'cptui_pluginize_content', 9 );
154
155 /**
156 * Render our newsletter form for the about page.
157 *
158 * @since 1.4.0
159 */
160 function cptui_about_page_newsletter() {
161
162 if ( cptui_is_new_install() ) {
163 return '';
164 }
165
166 ?>
167 <div class='wdsoctosignup'>
168 <?php
169 cptui_newsletter_form();
170 ?>
171 </div>
172
173 <?php
174
175 return '';
176 }
177 add_action( 'cptui_main_page_before_changelog', 'cptui_about_page_newsletter' );
178
179 /**
180 * Marks site as not new at the end of the about/main page.
181 *
182 * Can't be done on activation or else cptui_is_new_install() will immediately start
183 * returning false. So we'll do it at the end of the redirected landing page.
184 *
185 * @since 1.5.0
186 */
187 function cptui_mark_not_new() {
188 if ( cptui_is_new_install() ) {
189 cptui_set_not_new_install();
190 }
191 }
192 add_action( 'cptui_main_page_extra_notes', 'cptui_mark_not_new', 999 );
1 <?php
2 /**
3 * Custom Post Type UI Registered Content.
4 *
5 * @package CPTUI
6 * @subpackage Listings
7 * @author WebDevStudios
8 * @since 1.1.0
9 * @license GPL-2.0+
10 */
11
12 // phpcs:disable WebDevStudios.All.RequireAuthor
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Enqueue our Custom Post Type UI assets.
21 *
22 * @since 1.6.0
23 */
24 function cptui_listings_assets() {
25 $current_screen = get_current_screen();
26
27 if ( ! is_object( $current_screen ) || 'cpt-ui_page_cptui_listings' !== $current_screen->base ) {
28 return;
29 }
30
31 if ( wp_doing_ajax() ) {
32 return;
33 }
34
35 wp_enqueue_style( 'cptui-css' );
36 }
37 add_action( 'admin_enqueue_scripts', 'cptui_listings_assets' );
38
39 /**
40 * Output the content for the "Registered Types/Taxes" page.
41 *
42 * @since 1.1.0
43 *
44 * @internal
45 */
46 function cptui_listings() {
47 ?>
48 <div class="wrap cptui-listings">
49 <?php
50 /**
51 * Fires right inside the wrap div for the listings screen.
52 *
53 * @since 1.3.0
54 */
55 do_action( 'cptui_inside_listings_wrap' );
56 ?>
57
58 <h1 class="wp-heading-inline"><?php esc_html_e( 'Content types registered with Custom Post Type UI.', 'custom-post-type-ui' ); ?></h1>
59 <a href="<?php echo esc_url( cptui_get_add_new_link( 'post_types' ) ); ?>" class="page-title-action"><?php esc_html_e( 'Add New Post Type', 'custom-post-type-ui' ); ?></a>
60 <a href="<?php echo esc_url( cptui_get_add_new_link( 'taxonomies' ) ); ?>" class="page-title-action"><?php esc_html_e( 'Add New Taxonomy', 'custom-post-type-ui' ); ?></a>
61 <?php
62 $post_types = cptui_get_post_type_data();
63 echo '<h2 id="post-types">' . esc_html__( 'Post Types', 'custom-post-type-ui' ) . '</h2>';
64 if ( ! empty( $post_types ) ) {
65 ?>
66 <p>
67 <?php
68 printf(
69 /* translators: %s: Total count of registered CPTUI post types */
70 esc_html__( 'Custom Post Type UI registered post types count total: %d', 'custom-post-type-ui' ),
71 count( $post_types )
72 );
73 ?>
74 </p>
75
76 <?php
77
78 $post_type_table_heads = [
79 esc_html__( 'Post Type', 'custom-post-type-ui' ),
80 esc_html__( 'Settings', 'custom-post-type-ui' ),
81 esc_html__( 'Supports', 'custom-post-type-ui' ),
82 esc_html__( 'Taxonomies', 'custom-post-type-ui' ),
83 esc_html__( 'Labels', 'custom-post-type-ui' ),
84 esc_html__( 'Template Hierarchy', 'custom-post-type-ui' ),
85 ];
86
87 /**
88 * Fires before the listing of registered post type data.
89 *
90 * @since 1.1.0
91 */
92 do_action( 'cptui_before_post_type_listing' );
93 ?>
94 <table class="wp-list-table widefat post-type-listing">
95 <thead>
96 <tr>
97 <?php
98 foreach ( $post_type_table_heads as $head ) {
99 echo '<th>' . esc_html( $head ) . '</th>';
100 }
101 ?>
102 </tr>
103 </thead>
104 <tbody>
105 <?php
106 $counter = 1;
107 foreach ( $post_types as $post_type => $post_type_settings ) {
108
109 $rowclass = ( 0 === $counter % 2 ) ? '' : 'alternate';
110
111 $strings = [];
112 $supports = [];
113 $taxonomies = [];
114 $archive = '';
115 foreach ( $post_type_settings as $settings_key => $settings_value ) {
116 if ( 'labels' === $settings_key ) {
117 continue;
118 }
119
120 if ( is_string( $settings_value ) ) {
121 $strings[ $settings_key ] = $settings_value;
122 } else {
123 if ( 'supports' === $settings_key ) {
124 $supports[ $settings_key ] = $settings_value;
125 }
126
127 if ( 'taxonomies' === $settings_key ) {
128 $taxonomies[ $settings_key ] = $settings_value;
129
130 // In case they are not associated from the post type settings.
131 if ( empty( $taxonomies['taxonomies'] ) ) {
132 $taxonomies['taxonomies'] = get_object_taxonomies( $post_type );
133 }
134 }
135 }
136 $archive = get_post_type_archive_link( $post_type );
137 }
138 ?>
139 <tr class="<?php echo esc_attr( $rowclass ); ?>">
140 <?php
141 $edit_path = 'admin.php?page=cptui_manage_post_types&action=edit&cptui_post_type=' . $post_type;
142 $post_type_link_url = is_network_admin() ? network_admin_url( $edit_path ) : admin_url( $edit_path );
143 ?>
144 <td>
145 <?php
146 printf(
147 '<a href="%s">%s</a><br/>
148 <a href="%s">%s</a><br/>',
149 esc_attr( $post_type_link_url ),
150 sprintf(
151 /* translators: %s: Post type slug */
152 esc_html__( 'Edit %1$s (%2$s)', 'custom-post-type-ui' ),
153 esc_html( $post_type_settings['label'] ),
154 esc_html( $post_type )
155 ),
156 esc_attr( admin_url( 'admin.php?page=cptui_tools&action=get_code#' . $post_type ) ),
157 esc_html__( 'Get code', 'custom-post-type-ui' )
158 );
159
160 if ( $archive ) {
161 ?>
162 <a href="<?php echo esc_attr( get_post_type_archive_link( $post_type ) ); ?>"><?php esc_html_e( 'View frontend archive', 'custom-post-type-ui' ); ?></a>
163 <?php } ?>
164 </td>
165 <td>
166 <?php
167 foreach ( $strings as $key => $value ) {
168 printf( '<strong>%s:</strong> ', esc_html( $key ) );
169 if ( in_array( $value, [ '1', '0' ], true ) ) {
170 echo esc_html( disp_boolean( $value ) );
171 } else {
172 echo ! empty( $value ) ? esc_html( $value ) : '""';
173 }
174 echo '<br/>';
175 }
176 ?>
177 </td>
178 <td>
179 <?php
180 foreach ( $supports['supports'] as $support ) {
181 echo esc_html( $support ) . '<br/>';
182 }
183 ?>
184 </td>
185 <td>
186 <?php
187 if ( ! empty( $taxonomies['taxonomies'] ) ) {
188 foreach ( $taxonomies['taxonomies'] as $taxonomy ) {
189 echo esc_html( $taxonomy ) . '<br/>';
190 }
191 } else {
192 printf(
193 '<span aria-hidden="true">—</span><span class="screen-reader-text">%s</span>',
194 esc_html__( 'No associated taxonomies', 'custom-post-type-ui' )
195 );
196 }
197 ?>
198 </td>
199 <td>
200 <?php
201 $maybe_empty = array_filter( $post_type_settings['labels'] );
202 if ( ! empty( $maybe_empty ) ) {
203 foreach ( $post_type_settings['labels'] as $key => $value ) {
204 if ( 'parent' === $key && array_key_exists( 'parent_item_colon', $post_type_settings['labels'] ) ) {
205 continue;
206 }
207 printf(
208 '<strong>%s</strong>: %s<br/>',
209 esc_html( $key ),
210 esc_html( $value )
211 );
212 }
213 } else {
214 printf(
215 '<span aria-hidden="true">—</span><span class="screen-reader-text">%s</span>',
216 esc_html__( 'No custom labels to display', 'custom-post-type-ui' )
217 );
218 }
219 ?>
220 </td>
221 <td>
222 <p><strong><?php esc_html_e( 'Archives file name examples.', 'custom-post-type-ui' ); ?></strong><br/>
223 archive-<?php echo esc_html( $post_type ); ?>.php<br/>
224 archive.php<br/>
225 index.php
226 </p>
227
228 <p><strong><?php esc_html_e( 'Single Posts file name examples.', 'custom-post-type-ui' ); ?></strong><br/>
229 single-<?php echo esc_html( $post_type ); ?>-post_slug.php *<br/>
230 single-<?php echo esc_html( $post_type ); ?>.php<br/>
231 single.php<br/>
232 singular.php<br/>
233 index.php
234 </p>
235
236 <p>
237 <?php esc_html_e( '*Replace "post_slug" with the slug of the actual post.', 'custom-post-type-ui' ); ?>
238 </p>
239
240 <p>
241 <?php
242 printf(
243 '<a href="https://developer.wordpress.org/themes/basics/template-hierarchy/">%s</a>',
244 esc_html__( 'Template hierarchy Theme Handbook', 'custom-post-type-ui' )
245 );
246 ?>
247 </p>
248 </td>
249 </tr>
250
251 <?php
252 $counter++;
253 }
254 ?>
255 </tbody>
256 <tfoot>
257 <tr>
258 <?php
259 foreach ( $post_type_table_heads as $head ) {
260 echo '<th>' . esc_html( $head ) . '</th>';
261 }
262 ?>
263 </tr>
264 </tfoot>
265 </table>
266 <?php
267 /**
268 * Fires after the listing of registered post type data.
269 *
270 * @since 1.3.0
271 */
272 do_action( 'cptui_after_post_type_listing' );
273 } else {
274
275 /**
276 * Fires when there are no registered post types to list.
277 *
278 * @since 1.3.0
279 */
280 do_action( 'cptui_no_post_types_listing' );
281 }
282
283 $taxonomies = cptui_get_taxonomy_data();
284 echo '<h2 id="taxonomies">' . esc_html__( 'Taxonomies', 'custom-post-type-ui' ) . '</h2>';
285 if ( ! empty( $taxonomies ) ) {
286 ?>
287 <p>
288 <?php
289 printf(
290 /* translators: %s: Total count of CPTUI registered taxonomies */
291 esc_html__( 'Custom Post Type UI registered taxonomies count total: %d', 'custom-post-type-ui' ),
292 count( $taxonomies )
293 );
294 ?>
295 </p>
296
297 <?php
298
299 $taxonomy_table_heads = [
300 esc_html__( 'Taxonomy', 'custom-post-type-ui' ),
301 esc_html__( 'Settings', 'custom-post-type-ui' ),
302 esc_html__( 'Post Types', 'custom-post-type-ui' ),
303 esc_html__( 'Labels', 'custom-post-type-ui' ),
304 esc_html__( 'Template Hierarchy', 'custom-post-type-ui' ),
305 ];
306
307 /**
308 * Fires before the listing of registered taxonomy data.
309 *
310 * @since 1.1.0
311 */
312 do_action( 'cptui_before_taxonomy_listing' );
313 ?>
314 <table class="wp-list-table widefat taxonomy-listing">
315 <thead>
316 <tr>
317 <?php
318 foreach ( $taxonomy_table_heads as $head ) {
319 echo '<th>' . esc_html( $head ) . '</th>';
320 }
321 ?>
322 </tr>
323 </thead>
324 <tbody>
325 <?php
326 $counter = 1;
327 foreach ( $taxonomies as $taxonomy => $taxonomy_settings ) {
328
329 $rowclass = ( 0 === $counter % 2 ) ? '' : 'alternate';
330
331 $strings = [];
332 $object_types = [];
333 foreach ( $taxonomy_settings as $settings_key => $settings_value ) {
334 if ( 'labels' === $settings_key ) {
335 continue;
336 }
337
338 if ( is_string( $settings_value ) ) {
339 $strings[ $settings_key ] = $settings_value;
340 } else {
341 if ( 'object_types' === $settings_key ) {
342 $object_types[ $settings_key ] = $settings_value;
343
344 // In case they are not associated from the post type settings.
345 if ( empty( $object_types['object_types'] ) ) {
346 $types = get_taxonomy( $taxonomy );
347 $object_types['object_types'] = $types->object_type;
348 }
349 }
350 }
351 }
352 ?>
353 <tr class="<?php echo esc_attr( $rowclass ); ?>">
354 <?php
355 $edit_path = 'admin.php?page=cptui_manage_taxonomies&action=edit&cptui_taxonomy=' . $taxonomy;
356 $taxonomy_link_url = is_network_admin() ? network_admin_url( $edit_path ) : admin_url( $edit_path );
357 ?>
358 <td>
359 <?php
360 printf(
361 '<a href="%s">%s</a><br/>
362 <a href="%s">%s</a>',
363 esc_attr( $taxonomy_link_url ),
364 sprintf(
365 /* translators: %s: Taxonomy slug */
366 esc_html__( 'Edit %1$s (%2$s)', 'custom-post-type-ui' ),
367 esc_html( $taxonomy_settings['label'] ),
368 esc_html( $taxonomy )
369 ),
370 esc_attr( admin_url( 'admin.php?page=cptui_tools&action=get_code#' . $taxonomy ) ),
371 esc_html__( 'Get code', 'custom-post-type-ui' )
372 );
373 ?>
374 </td>
375 <td>
376 <?php
377 foreach ( $strings as $key => $value ) {
378 printf( '<strong>%s:</strong> ', esc_html( $key ) );
379 if ( in_array( $value, [ '1', '0' ], true ) ) {
380 echo esc_html( disp_boolean( $value ) );
381 } else {
382 echo ! empty( $value ) ? esc_html( $value ) : '""';
383 }
384 echo '<br/>';
385 }
386 ?>
387 </td>
388 <td>
389 <?php
390 if ( ! empty( $object_types['object_types'] ) ) {
391 foreach ( $object_types['object_types'] as $type ) {
392 echo esc_html( $type ) . '<br/>';
393 }
394 }
395 ?>
396 </td>
397 <td>
398 <?php
399 $maybe_empty = array_filter( $taxonomy_settings['labels'] );
400 if ( ! empty( $maybe_empty ) ) {
401 foreach ( $taxonomy_settings['labels'] as $key => $value ) {
402 printf(
403 '<strong>%s</strong>: %s<br/>',
404 esc_html( $key ),
405 esc_html( $value )
406 );
407 }
408 } else {
409 printf(
410 '<span aria-hidden="true">—</span><span class="screen-reader-text">%s</span>',
411 esc_html__( 'No custom labels to display', 'custom-post-type-ui' )
412 );
413 }
414 ?>
415 </td>
416 <td>
417 <p><strong><?php esc_html_e( 'Archives file name examples.', 'custom-post-type-ui' ); ?></strong><br />
418 taxonomy-<?php echo esc_html( $taxonomy ); ?>-term_slug.php *<br />
419 taxonomy-<?php echo esc_html( $taxonomy ); ?>.php<br />
420 taxonomy.php<br />
421 archive.php<br />
422 index.php
423 </p>
424
425 <p>
426 <?php esc_html_e( '*Replace "term_slug" with the slug of the actual taxonomy term.', 'custom-post-type-ui' ); ?>
427 </p>
428 <p>
429 <?php
430 printf(
431 '<a href="https://developer.wordpress.org/themes/basics/template-hierarchy/">%s</a>',
432 esc_html__( 'Template hierarchy Theme Handbook', 'custom-post-type-ui' )
433 );
434 ?>
435 </p>
436 </td>
437 </tr>
438
439 <?php
440 $counter++;
441 }
442 ?>
443 </tbody>
444 <tfoot>
445 <tr>
446 <?php
447 foreach ( $taxonomy_table_heads as $head ) {
448 echo '<th>' . esc_html( $head ) . '</th>';
449 }
450 ?>
451 </tr>
452 </tfoot>
453 </table>
454 <?php
455 /**
456 * Fires after the listing of registered taxonomy data.
457 *
458 * @since 1.3.0
459 */
460 do_action( 'cptui_after_taxonomy_listing' );
461
462 } else {
463
464 /**
465 * Fires when there are no registered taxonomies to list.
466 *
467 * @since 1.3.0
468 */
469 do_action( 'cptui_no_taxonomies_listing' );
470 }
471 ?>
472
473 </div>
474 <?php
475 }
476
477 /**
478 * Displays a message for when no post types are registered.
479 *
480 * Uses the `cptui_no_post_types_listing` hook.
481 *
482 * @since 1.3.0
483 *
484 * @internal
485 */
486 function cptui_no_post_types_to_list() {
487 echo '<p>' . sprintf(
488 /* translators: 1st %s: Link to manage post types section 2nd %s Link text */
489 esc_html__( 'No post types registered for display. Visit %s to get started.', 'custom-post-type-ui' ),
490 sprintf(
491 '<a href="%s">%s</a>',
492 esc_attr( admin_url( 'admin.php?page=cptui_manage_post_types' ) ),
493 esc_html__( 'Add/Edit Post Types', 'custom-post-type-ui' )
494 )
495 ) . '</p>';
496 }
497 add_action( 'cptui_no_post_types_listing', 'cptui_no_post_types_to_list' );
498
499 /**
500 * Displays a message for when no taxonomies are registered.
501 *
502 * Uses the `cptui_no_taxonomies_listing` hook.
503 *
504 * @since 1.3.0
505 *
506 * @internal
507 */
508 function cptui_no_taxonomies_to_list() {
509 echo '<p>' . sprintf(
510 /* translators: %s: Link to manage taxonomies section */
511 esc_html__( 'No taxonomies registered for display. Visit %s to get started.', 'custom-post-type-ui' ),
512 sprintf(
513 '<a href="%s">%s</a>',
514 esc_attr( admin_url( 'admin.php?page=cptui_manage_taxonomies' ) ),
515 esc_html__( 'Add/Edit Taxonomies', 'custom-post-type-ui' )
516 )
517 ) . '</p>';
518 }
519 add_action( 'cptui_no_taxonomies_listing', 'cptui_no_taxonomies_to_list' );
This diff could not be displayed because it is too large.
1 <?php
2 /**
3 * Custom Post Type UI Support Questions.
4 *
5 * @package CPTUI
6 * @subpackage Support
7 * @author WebDevStudios
8 * @since 1.0.0
9 * @license GPL-2.0+
10 */
11
12 // phpcs:disable WebDevStudios.All.RequireAuthor
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Add our cptui.js file, with dependencies on jQuery.
21 *
22 * @since 1.0.0
23 *
24 * @internal
25 */
26 function cptui_support_enqueue_scripts() {
27
28 $current_screen = get_current_screen();
29
30 if ( ! is_object( $current_screen ) || 'cpt-ui_page_cptui_support' !== $current_screen->base ) {
31 return;
32 }
33
34 if ( wp_doing_ajax() ) {
35 return;
36 }
37
38 wp_enqueue_script( 'cptui' );
39 wp_enqueue_style( 'cptui-css' );
40 }
41 add_action( 'admin_enqueue_scripts', 'cptui_support_enqueue_scripts' );
42
43 /**
44 * Create our settings page output.
45 *
46 * @since 1.0.0
47 *
48 * @internal
49 */
50 function cptui_support() {
51 echo '<div class="wrap cptui-support">';
52
53 /**
54 * Fires at the top of the FAQ/Support page.
55 *
56 * @since 1.0.0
57 */
58 do_action( 'cptui_main_page_before_faq' ); ?>
59
60 <h1><?php esc_html_e( 'Custom Post Type UI Support', 'custom-post-type-ui' ); ?></h1>
61
62 <p>
63 <?php
64 printf(
65 /* translators: Placeholders are just for HTML markup that doesn't need translated */
66 esc_html__( 'Please note that %1$s this plugin will not handle display %2$s of registered post types or taxonomies in your current theme. It simply registers them for you. To display your data, check out %3$s. %4$s to see some examples that are available with Custom Post Type UI Extended. If all else fails, visit us on the %5$s', 'custom-post-type-ui' ),
67 '<strong>',
68 '</strong>',
69 '<a href="https://pluginize.com/plugins/custom-post-type-ui-extended/?utm_source=faq&utm_medium=text&utm_campaign=cptui">' . esc_html__( 'CPTUI Extended', 'custom-post-type-ui' ) . '</a>',
70 '<a href="https://pluginize.com/cpt-ui-extended-features/?utm_source=faq-layouts&utm_medium=text&utm_campaign=cptui">' . esc_html__( 'View our Layouts page', 'custom-post-type-ui' ) . '</a>',
71 '<a href="https://www.wordpress.org/support/plugin/custom-post-type-ui/">' . esc_html__( 'Support Forums', 'custom-post-type-ui' ) . '</a>'
72 );
73 ?>
74 </p>
75
76 <table id="support" class="form-table cptui-table">
77 <tr>
78 <td class="outer">
79 <h2><?php esc_html_e( 'Pluginize', 'custom-post-type-ui' ); ?></h2>
80 <ol id="questions_pluginize">
81 <li>
82 <span tabindex="0" class="question" aria-controls="q1" aria-expanded="false"><?php esc_html_e( 'What is Pluginize?', 'custom-post-type-ui' ); ?></span>
83 <div class="answer" id="q1"><?php esc_html_e( 'Pluginize is a marketplace of plugins by WebDevStudios.', 'custom-post-type-ui' ); ?>
84 </div>
85 </li>
86 <li>
87 <span tabindex="0" class="question" aria-controls="q2" aria-expanded="false"><?php esc_html_e( 'What does Pluginize offer?', 'custom-post-type-ui' ); ?></span>
88 <div class="answer" id="q2"><?php esc_html_e( 'Pluginize offers both free and paid WordPress plugins.', 'custom-post-type-ui' ); ?>
89 </div>
90 </li>
91 <li>
92 <span tabindex="0" class="question" aria-controls="q3" aria-expanded="false"><?php esc_html_e( 'Will these ad spots ever show third-party data?', 'custom-post-type-ui' ); ?></span>
93 <div class="answer" id="q3"><?php esc_html_e( 'No. These spots are intended for and will only be used for other available WebDevStudios products and services.', 'custom-post-type-ui' ); ?>
94 </div>
95 </li>
96 <li>
97 <span tabindex="0" class="question" aria-controls="q4" aria-expanded="false"><?php esc_html_e( 'How can I remove the ads that suddenly started showing up?', 'custom-post-type-ui' ); ?></span>
98 <div class="answer" id="q4">
99 <?php
100 printf(
101 /* translators: Placeholders are just for HTML markup that doesn't need translated */
102 esc_html__( 'You can have them automatically removed from display via a purchased copy of %s.', 'custom-post-type-ui' ),
103 sprintf(
104 '<a href="%s">%s</a>',
105 'https://pluginize.com/plugins/custom-post-type-ui-extended/?utm_source=faq-remove&utm_medium=text&utm_campaign=cptui',
106 'Custom Post Type UI Extended'
107 )
108 );
109 ?>
110 </div>
111 </li>
112 <li>
113 <span tabindex="0" class="question" aria-controls="q5" aria-expanded="false"><?php esc_html_e( 'Are these ad spots tracking my personal information in any way?', 'custom-post-type-ui' ); ?></span>
114 <div class="answer" id="q5"><?php esc_html_e( 'No, there is no data being sent out from your site with these. The only way anything is tracked is via UTM parameters for WebDevStudios\'s analytics so we can get an idea of where traffic is coming from. Those are only tracked if you actually click on an ad spot.', 'custom-post-type-ui' ); ?>
115 </div>
116 </li>
117 <li>
118 <span tabindex="0" class="question" aria-controls="q6" aria-expanded="false"><?php esc_html_e( 'Do I still need Custom Post Type UI if I purchase and install Custom Post Type UI Extended?', 'custom-post-type-ui' ); ?></span>
119 <div class="answer" id="q6"><?php esc_html_e( 'Yes you will. The Custom Post Type UI Extended is not a replacement of the free version with added extra features. It acts based on the data made available through Custom Post Type UI', 'custom-post-type-ui' ); ?>
120 </div>
121 </li>
122 <li>
123 <span tabindex="0" class="question" aria-controls="q7" aria-expanded="false"><?php esc_html_e( 'Does Custom Post Type UI Extended require multisite?', 'custom-post-type-ui' ); ?></span>
124 <div class="answer" id="q7"><?php esc_html_e( 'No it does not. The Shortcode builder is not multisite dependent and will work with either setup.', 'custom-post-type-ui' ); ?>
125 </div>
126 </li>
127 </ol>
128 </td>
129 <td class="outer">
130 <h2><?php esc_html_e( 'General', 'custom-post-type-ui' ); ?></h2>
131 <ol id="questions_general">
132 <li>
133 <span tabindex="0" class="question" aria-controls="q8" aria-expanded="false"><?php esc_html_e( 'I have post types with spaces in their slug and can not successfully delete them. How can I fix that?', 'custom-post-type-ui' ); ?></span>
134 <div class="answer" id="q8"><?php esc_html_e( 'Visit the Import/Export page and copy the export code into the import side on the left. Replace the space with an underscore and then click "Import". You should be able to delete the individual post types afterwards.', 'custom-post-type-ui' ); ?>
135 </div>
136 </li>
137 <li>
138 <span tabindex="0" class="question" aria-controls="q9" aria-expanded="false"><?php esc_html_e( 'I changed my custom post type name and now I can not get to my posts. How do I get them back?', 'custom-post-type-ui' ); ?></span>
139 <div class="answer" id="q9"><?php esc_html_e( 'You can either change the custom post type name back to the original name or try the Post Type Switcher plugin', 'custom-post-type-ui' ); ?>
140 <a href="https://wordpress.org/plugins/post-type-switcher/" target="_blank" rel="noopener">https://wordpress.org/extend/plugins/post-type-switcher/</a>
141 </div>
142 </li>
143 <li>
144 <span tabindex="0" class="question" aria-controls="q10" aria-expanded="false"><?php esc_html_e( 'I changed my custom post type or taxonomy slug and now I have duplicates shown. How do I remove the duplicate?', 'custom-post-type-ui' ); ?></span>
145 <div class="answer" id="q10"><?php esc_html_e( 'Renaming the slug for a post type or taxonomy creates a new entry in our saved option which gets registered as its own post type or taxonomy. Since the settings will be mirrored from the previous slug, you will just need to delete the previous version\'s entry.', 'custom-post-type-ui' ); ?> <a href="https://wordpress.org/plugins/post-type-switcher/" target="_blank" rel="noopener">https://wordpress.org/extend/plugins/post-type-switcher/</a></div>
146 </li>
147 <li>
148 <span tabindex="0" class="question" aria-controls="q11" aria-expanded="false"><?php esc_html_e( 'I have added post thumbnail and/or post format support to my post type, but those do not appear when adding a post type post.', 'custom-post-type-ui' ); ?></span>
149 <div class="answer" id="q11"><?php esc_html_e( 'Make sure your theme has post "post-thumbnails" theme support enabled.', 'custom-post-type-ui' ); ?> <a href="https://codex.wordpress.org/Function_Reference/add_theme_support" target="_blank" rel="noopener">https://codex.wordpress.org/Function_Reference/add_theme_support</a></div>
150 </li>
151 <li>
152 <span tabindex="0" class="question" aria-controls="q12" aria-expanded="false"><?php esc_html_e( 'Do you have any recommendations for an alternative to Visual Composer?', 'custom-post-type-ui' ); ?></span>
153 <div class="answer" id="q12"><?php esc_html_e( 'We recommend using VelocityPage.', 'custom-post-type-ui' ); ?>
154 <a href="https://velocitypage.com" target="_blank" rel="noopener">https://velocitypage.com</a>
155 </div>
156 </li>
157 <li>
158 <span tabindex="0" class="question" aria-controls="q13" aria-expanded="false"><?php esc_html_e( 'Is there any way to get Custom Post Type UI-registered post types working with Visual Composer Media Grid?', 'custom-post-type-ui' ); ?></span>
159
160 <div class="answer" id="q13"><?php esc_html_e( 'Please see the solution from the following forum support thread.', 'custom-post-type-ui' ); ?>
161 <a href="https://wordpress.org/support/topic/custom-post-type-and-visual-composer-grid-block?replies=11#post-7111458" target="_blank" rel="noopener">https://wordpress.org/support/topic/custom-post-type-and-visual-composer-grid-block?replies=11#post-7111458</a>
162 </div>
163 </li>
164 </ol>
165 </td>
166 </tr>
167 <tr>
168 <td class="outer">
169 <h2><?php esc_html_e( 'Front-end Display', 'custom-post-type-ui' ); ?></h2>
170 <ol id="questions_front">
171 <li>
172 <span tabindex="0" class="question" aria-controls="q14" aria-expanded="false"><?php esc_html_e( 'What template files should I edit to alter my post type display?', 'custom-post-type-ui' ); ?></span>
173 <div class="answer" id="q14">
174 <?php
175 printf(
176 /* translators: Placeholders are just for HTML markup that doesn't need translated */
177 esc_html__( 'Please visit the %1$sTemplate Hierarchy%2$s page on the WordPress codex for details about available templates.', 'custom-post-type-ui' ),
178 '<a href="https://codex.wordpress.org/Template_Hierarchy" target="_blank" rel="noopener">',
179 '</a>'
180 );
181 ?>
182 </div>
183 </li>
184 <li>
185 <span tabindex="0" class="question" aria-controls="q15" aria-expanded="false"><?php esc_html_e( 'How do I display my custom post type on my site?', 'custom-post-type-ui' ); ?></span>
186 <div class="answer" id="q15">
187 <?php
188 printf(
189 /* translators: Placeholders are just for HTML markup that doesn't need translated */
190 esc_html__( 'We encourage checking out %1$s for easily displaying post type content wherever you can utilize a shortcode. If you prefer to handle on your own, you will need to utilize the %2$s class to handle display in custom locations. If you have set the post type to have archives, the archive url should be something like "http://www.mysite.com/post-type-slug"', 'custom-post-type-ui' ),
191 sprintf(
192 '<a href="%s">%s</a>',
193 'https://pluginize.com/plugins/custom-post-type-ui-extended/?utm_source=faq&utm_medium=text&utm_campaign=cptui',
194 'Custom Post Type UI Extended'
195 ),
196 '<a href="https://codex.wordpress.org/Class_Reference/WP_Query" target="_blank" rel="noopener">WP_Query</a>'
197 );
198 ?>
199 </div>
200 </li>
201 <li>
202 <span tabindex="0" class="question" aria-controls="q16" aria-expanded="false"><?php esc_html_e( 'I have added categories and tags to my custom post type, but they do not appear in the archives.', 'custom-post-type-ui' ); ?></span>
203 <div class="answer" id="q16">
204 <?php
205 printf(
206 /* translators: Placeholders are just for HTML markup that doesn't need translated */
207 esc_html__( 'You will need to add your newly created post type to the types that the category and tag archives query for. You can see a tutorial on how to do that at %s', 'custom-post-type-ui' ),
208 '<a href="http://docs.pluginize.com/article/17-post-types-in-category-tag-archives" target="_blank" rel="noopener">http://docs.pluginize.com/article/17-post-types-in-category-tag-archives</a>'
209 );
210 ?>
211 </div>
212 </li>
213 <li>
214 <span tabindex="0" class="question" aria-controls="q17" aria-expanded="false"><?php esc_html_e( 'How do I add custom post type support for custom templates selection like pages have?', 'custom-post-type-ui' ); ?></span>
215 <div class="answer" id="q17">
216 <?php
217 printf(
218 /* translators: Placeholders are just for HTML markup that doesn't need translated */
219 esc_html__( 'Please visit the %1$sPost Type Templates in 4.7%2$s post on the Make WordPress Core blog for details about setting templates for multiple post types.', 'custom-post-type-ui' ),
220 '<a href="https://make.wordpress.org/core/2016/11/03/post-type-templates-in-4-7/" target="_blank" rel="noopener">',
221 '</a>'
222 );
223 ?>
224 </div>
225 </li>
226 <li>
227 <span tabindex="0" class="question" aria-controls="q18" aria-expanded="false"><?php esc_html_e( 'Why are my post types not showing in taxonomy term archives?', 'custom-post-type-ui' ); ?></span>
228 <div class="answer" id="q18">
229 <?php
230 esc_html_e( 'If you have set "exclude from search" to True for the pot type, this would be why. If you need the post types in the archives, but still want to exclude them from search, it is recommended to use the "pre_get_posts" hook to unset the post type from considered types.', 'custom-post-type-ui' );
231 ?>
232 </div>
233 </li>
234 </ol>
235 </td>
236 <td class="outer">
237 <h2><?php esc_html_e( 'Advanced', 'custom-post-type-ui' ); ?></h2>
238 <ol id="questions_advanced">
239 <li>
240 <span tabindex="0" class="question" aria-controls="q19" aria-expanded="false"><?php esc_html_e( 'How do I add custom metaboxes to my post type?', 'custom-post-type-ui' ); ?></span>
241 <div class="answer" id="q19">
242 <?php
243 printf(
244 /* translators: Placeholders are just for HTML markup that doesn't need translated */
245 esc_html__( 'We recommend checking out %s, the latest iteration of "CMB2". Both are supported by WebDevStudios.', 'custom-post-type-ui' ),
246 '<a href="https://wordpress.org/plugins/cmb2/" target="_blank" rel="noopener">CMB2</a>'
247 );
248 ?>
249 </div>
250 </li>
251 <li>
252 <span tabindex="0" class="question" aria-controls="q20" aria-expanded="false"><?php esc_html_e( 'How do I add a newly registered taxonomy to a post type that already exists?', 'custom-post-type-ui' ); ?></span>
253 <div class="answer" id="q20">
254 <?php
255 printf(
256 /* translators: Placeholders are just for HTML markup that doesn't need translated */
257 esc_html__( 'Check out the %s function for documentation and usage examples.', 'custom-post-type-ui' ),
258 '<a href="https://codex.wordpress.org/Function_Reference/register_taxonomy_for_object_type" target="_blank" rel="noopener">register_taxonomy_for_object_type()</a>'
259 );
260 ?>
261 </div>
262 </li>
263 <li>
264 <span tabindex="0" class="question" aria-controls="q21" aria-expanded="false"><?php esc_html_e( 'Post relationships?', 'custom-post-type-ui' ); ?></span>
265 <div class="answer" id="q21">
266 <?php
267 printf(
268 /* translators: Placeholders are just for HTML markup that doesn't need translated */
269 esc_html__( '%1$s has an excellent %2$spost%3$s introducing users to the %4$sPosts 2 Posts%5$s plugin that should be a good start.', 'custom-post-type-ui' ),
270 'Pippin Williamson',
271 '<a href="https://pippinsplugins.com/introduction-posts-2-posts-plugin/" target="_blank" rel="noopener">',
272 '</a>',
273 '<a href="https://wordpress.org/plugins/posts-to-posts/" target="_blank" rel="noopener">',
274 '</a>'
275 );
276 ?>
277 </div>
278 </li>
279 <li>
280 <span tabindex="0" class="question" aria-controls="q22" aria-expanded="false"><?php esc_html_e( 'Is there any function reference list?', 'custom-post-type-ui' ); ?></span>
281 <div class="answer" id="q22">
282 <?php
283 printf(
284 /* translators: Placeholders are just for HTML markup that doesn't need translated */
285 esc_html__( '%s has compiled a nice list of functions used by our plugin. Note not all will be useful as they are attached to hooks.', 'custom-post-type-ui' ),
286 '<a href="http://hookr.io/plugins/custom-post-type-ui/" target="_blank" rel="noopener">Hookr.io</a>'
287 );
288 ?>
289 </div>
290 </li>
291 <li>
292 <span tabindex="0" class="question" aria-controls="q23" aria-expanded="false"><?php esc_html_e( 'How do I filter the "enter title here" text in the post editor screen?', 'custom-post-type-ui' ); ?></span>
293 <div class="answer" id="q23"><p><?php esc_html_e( 'Change text inside the post/page editor title field. Should be able to adapt as necessary.', 'custom-post-type-ui' ); ?></p>
294 <pre><code>function my_custom_title_text( $title ){
295 global $post;
296 if ( 'ENTER POST TYPE SLUG HERE' == $post->post_type )
297 return 'NEW CUSTOM TEXT HERE';
298 }
299 }
300 add_filter( 'enter_title_here', 'my_custom_title_text' );
301 </code></pre></div>
302 </li>
303 <li>
304 <span tabindex="0" class="question" aria-controls="q25" aria-expanded="false"><?php esc_html_e( 'Any help with customizing capabilities?', 'custom-post-type-ui' ); ?></span>
305 <div class="answer" id="q25">
306 <p>
307 <?php
308 printf(
309 /* translators: Placeholders are just for HTML markup that doesn't need translated */
310 esc_html__( 'We recommend %s for some extended customization and addition of extra fields regarding roles and capabilities.', 'custom-post-type-ui' ),
311 '<a href="https://github.com/tw2113/custom-post-type-ui-capabilities" target="_blank" rel="noopener">Custom Post Type UI Capabilities on GitHub</a>'
312 );
313 ?>
314 </p>
315 </div>
316 </li>
317 </ol>
318 </td>
319 <td class="outer">
320 &nbsp;
321 <?php
322
323 /**
324 * Fires in the last table cell of the FAQ list.
325 *
326 * @since 1.0.0
327 */
328 do_action( 'cptui_main_page_custom_questions' );
329 ?>
330 </td>
331 </tr>
332 </table>
333
334 <?php
335
336 /**
337 * Fires at the bottom of the FAQ/Support page.
338 *
339 * @since 1.0.0
340 */
341 do_action( 'cptui_main_page_after_faq' );
342
343 echo '</div>';
344 }
1 <?php
2 /**
3 * Custom Post Type UI Taxonomy Settings.
4 *
5 * @package CPTUI
6 * @subpackage Taxonomies
7 * @author WebDevStudios
8 * @since 1.0.0
9 * @license GPL-2.0+
10 */
11
12 // phpcs:disable WebDevStudios.All.RequireAuthor
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Add our cptui.js file, with dependencies on jQuery and jQuery UI.
21 *
22 * @since 1.0.0
23 *
24 * @internal
25 */
26 function cptui_taxonomies_enqueue_scripts() {
27
28 $current_screen = get_current_screen();
29
30 if ( ! is_object( $current_screen ) || 'cpt-ui_page_cptui_manage_taxonomies' !== $current_screen->base ) {
31 return;
32 }
33
34 if ( wp_doing_ajax() ) {
35 return;
36 }
37
38 wp_enqueue_script( 'cptui' );
39 wp_enqueue_style( 'cptui-css' );
40
41 $core = get_taxonomies(
42 [
43 '_builtin' => true,
44 ]
45 );
46 $public = get_taxonomies(
47 [
48 '_builtin' => false,
49 'public' => true,
50 ]
51 );
52 $private = get_taxonomies(
53 [
54 '_builtin' => false,
55 'public' => false,
56 ]
57 );
58
59 $registered_taxonomies = array_merge( $core, $public, $private );
60
61 wp_localize_script(
62 'cptui',
63 'cptui_tax_data',
64 [
65 'confirm' => esc_html__( 'Are you sure you want to delete this? Deleting will NOT remove created content.', 'custom-post-type-ui' ),
66 'no_associated_type' => esc_html__( 'Please select a post type to associate with.', 'custom-post-type-ui' ),
67 'existing_taxonomies' => $registered_taxonomies,
68 ]
69 );
70 }
71 add_action( 'admin_enqueue_scripts', 'cptui_taxonomies_enqueue_scripts' );
72
73 /**
74 * Register our tabs for the Taxonomy screen.
75 *
76 * @since 1.3.0
77 *
78 * @internal
79 *
80 * @param array $tabs Array of tabs to display. Optional.
81 * @param string $current_page Current page being shown. Optional. Default empty string.
82 * @return array Amended array of tabs to show.
83 */
84 function cptui_taxonomy_tabs( $tabs = [], $current_page = '' ) {
85
86 if ( 'taxonomies' === $current_page ) {
87 $taxonomies = cptui_get_taxonomy_data();
88 $classes = [ 'nav-tab' ];
89
90 $tabs['page_title'] = get_admin_page_title();
91 $tabs['tabs'] = [];
92 $tabs['tabs']['add'] = [ // Start out with our basic "Add new" tab.
93 'text' => esc_html__( 'Add New Taxonomy', 'custom-post-type-ui' ),
94 'classes' => $classes,
95 'url' => cptui_admin_url( 'admin.php?page=cptui_manage_' . $current_page ),
96 'aria-selected' => 'false',
97 ];
98
99 $action = cptui_get_current_action();
100 if ( empty( $action ) ) {
101 $tabs['tabs']['add']['classes'][] = 'nav-tab-active';
102 $tabs['tabs']['add']['aria-selected'] = 'true';
103 }
104
105 if ( ! empty( $taxonomies ) ) {
106
107 if ( ! empty( $action ) ) {
108 $classes[] = 'nav-tab-active';
109 }
110 $tabs['tabs']['edit'] = [
111 'text' => esc_html__( 'Edit Taxonomies', 'custom-post-type-ui' ),
112 'classes' => $classes,
113 'url' => esc_url( add_query_arg( [ 'action' => 'edit' ], cptui_admin_url( 'admin.php?page=cptui_manage_' . $current_page ) ) ),
114 'aria-selected' => ! empty( $action ) ? 'true' : 'false',
115 ];
116
117 $tabs['tabs']['view'] = [
118 'text' => esc_html__( 'View Taxonomies', 'custom-post-type-ui' ),
119 'classes' => [ 'nav-tab' ], // Prevent notices.
120 'url' => esc_url( cptui_admin_url( 'admin.php?page=cptui_listings#taxonomies' ) ),
121 'aria-selected' => 'false',
122 ];
123
124 $tabs['tabs']['export'] = [
125 'text' => esc_html__( 'Import/Export Taxonomies', 'custom-post-type-ui' ),
126 'classes' => [ 'nav-tab' ], // Prevent notices.
127 'url' => esc_url( cptui_admin_url( 'admin.php?page=cptui_tools&action=taxonomies' ) ),
128 'aria-selected' => 'false',
129 ];
130 }
131 }
132
133 return $tabs;
134 }
135
136 add_filter( 'cptui_get_tabs', 'cptui_taxonomy_tabs', 10, 2 );
137
138 /**
139 * Create our settings page output.
140 *
141 * @since 1.0.0
142 *
143 * @internal
144 */
145 function cptui_manage_taxonomies() {
146
147 $tab = ( ! empty( $_GET ) && ! empty( $_GET['action'] ) && 'edit' == $_GET['action'] ) ? 'edit' : 'new'; // phpcs:ignore.
148 $tab_class = 'cptui-' . $tab;
149 $current = null;
150 ?>
151
152 <div class="wrap <?php echo esc_attr( $tab_class ); ?>">
153
154 <?php
155 /**
156 * Fires right inside the wrap div for the taxonomy editor screen.
157 *
158 * @since 1.3.0
159 */
160 do_action( 'cptui_inside_taxonomy_wrap' );
161
162 /**
163 * Filters whether or not a taxonomy was deleted.
164 *
165 * @since 1.4.0
166 *
167 * @param bool $value Whether or not taxonomy deleted. Default false.
168 */
169 $taxonomy_deleted = apply_filters( 'cptui_taxonomy_deleted', false );
170
171 // Create our tabs.
172 cptui_settings_tab_menu( 'taxonomies' );
173
174 /**
175 * Fires below the output for the tab menu on the taxonomy add/edit screen.
176 *
177 * @since 1.3.0
178 */
179 do_action( 'cptui_below_taxonomy_tab_menu' );
180
181 if ( 'edit' === $tab ) {
182
183 $taxonomies = cptui_get_taxonomy_data();
184
185 $selected_taxonomy = cptui_get_current_taxonomy( $taxonomy_deleted );
186
187 if ( $selected_taxonomy && array_key_exists( $selected_taxonomy, $taxonomies ) ) {
188 $current = $taxonomies[ $selected_taxonomy ];
189 }
190 }
191
192 $ui = new cptui_admin_ui();
193
194 // Will only be set if we're already on the edit screen.
195 if ( ! empty( $taxonomies ) ) {
196 ?>
197 <form id="cptui_select_taxonomy" method="post" action="<?php echo esc_url( cptui_get_post_form_action( $ui ) ); ?>">
198 <label for="taxonomy"><?php esc_html_e( 'Select: ', 'custom-post-type-ui' ); ?></label>
199 <?php
200 cptui_taxonomies_dropdown( $taxonomies );
201
202 wp_nonce_field( 'cptui_select_taxonomy_nonce_action', 'cptui_select_taxonomy_nonce_field' );
203
204 /**
205 * Filters the text value to use on the select taxonomy button.
206 *
207 * @since 1.0.0
208 *
209 * @param string $value Text to use for the button.
210 */
211 ?>
212 <input type="submit" class="button-secondary" id="cptui_select_taxonomy_submit" name="cptui_select_taxonomy_submit" value="<?php echo esc_attr( apply_filters( 'cptui_taxonomy_submit_select', esc_attr__( 'Select', 'custom-post-type-ui' ) ) ); ?>" />
213 </form>
214 <?php
215
216 /**
217 * Fires below the taxonomy select input.
218 *
219 * @since 1.1.0
220 *
221 * @param string $value Current taxonomy selected.
222 */
223 do_action( 'cptui_below_taxonomy_select', $current['name'] );
224 }
225 ?>
226
227 <form class="taxonomiesui" method="post" action="<?php echo esc_url( cptui_get_post_form_action( $ui ) ); ?>">
228 <div class="postbox-container">
229 <div id="poststuff">
230 <div class="cptui-section postbox">
231 <div class="postbox-header">
232 <h2 class="hndle ui-sortable-handle">
233 <span><?php esc_html_e( 'Basic settings', 'custom-post-type-ui' ); ?></span>
234 </h2>
235 <div class="handle-actions hide-if-no-js">
236 <button type="button" class="handlediv" aria-expanded="true">
237 <span class="screen-reader-text"><?php esc_html_e( 'Toggle panel: Basic settings', 'custom-post-type-ui' ); ?></span>
238 <span class="toggle-indicator" aria-hidden="true"></span>
239 </button>
240 </div>
241 </div>
242 <div class="inside">
243 <div class="main">
244 <table class="form-table cptui-table">
245 <?php
246 echo $ui->get_tr_start() . $ui->get_th_start(); // phpcs:ignore.
247 echo $ui->get_label( 'name', esc_html__( 'Taxonomy Slug', 'custom-post-type-ui' ) ) . $ui->get_required_span(); // phpcs:ignore.
248
249 if ( 'edit' === $tab ) {
250 echo '<p id="slugchanged" class="hidemessage">' . esc_html__( 'Slug has changed', 'custom-post-type-ui' ) . '<span class="dashicons dashicons-warning"></span></p>';
251 }
252 echo '<p id="slugexists" class="hidemessage">' . esc_html__( 'Slug already exists', 'custom-post-type-ui' ) . '<span class="dashicons dashicons-warning"></span></p>';
253
254 echo $ui->get_th_end() . $ui->get_td_start(); // phpcs:ignore.
255
256 echo $ui->get_text_input( // phpcs:ignore.
257 [
258 'namearray' => 'cpt_custom_tax',
259 'name' => 'name',
260 'textvalue' => isset( $current['name'] ) ? esc_attr( $current['name'] ) : '', // phpcs:ignore.
261 'maxlength' => '32',
262 'helptext' => esc_attr__( 'The taxonomy name/slug. Used for various queries for taxonomy content.', 'custom-post-type-ui' ),
263 'required' => true,
264 'placeholder' => false,
265 'wrap' => false,
266 ]
267 );
268
269 echo '<p class="cptui-slug-details">';
270 esc_html_e( 'Slugs should only contain alphanumeric, latin characters. Underscores should be used in place of spaces. Set "Custom Rewrite Slug" field to make slug use dashes for URLs.', 'custom-post-type-ui' );
271 echo '</p>';
272
273 if ( 'edit' === $tab ) {
274 echo '<p>';
275 esc_html_e( 'DO NOT EDIT the taxonomy slug unless also planning to migrate terms. Changing the slug registers a new taxonomy entry.', 'custom-post-type-ui' );
276 echo '</p>';
277
278 echo '<div class="cptui-spacer">';
279 echo $ui->get_check_input( // phpcs:ignore.
280 [
281 'checkvalue' => 'update_taxonomy',
282 'checked' => 'false',
283 'name' => 'update_taxonomy',
284 'namearray' => 'update_taxonomy',
285 'labeltext' => esc_html__( 'Migrate terms to newly renamed taxonomy?', 'custom-post-type-ui' ),
286 'helptext' => '',
287 'default' => false,
288 'wrap' => false,
289 ]
290 );
291 echo '</div>';
292 }
293
294 echo $ui->get_text_input( // phpcs:ignore.
295 [
296 'namearray' => 'cpt_custom_tax',
297 'name' => 'label',
298 'textvalue' => isset( $current['label'] ) ? esc_attr( $current['label'] ) : '', // phpcs:ignore.
299 'aftertext' => esc_html__( '(e.g. Actors)', 'custom-post-type-ui' ),
300 'labeltext' => esc_html__( 'Plural Label', 'custom-post-type-ui' ),
301 'helptext' => esc_attr__( 'Used for the taxonomy admin menu item.', 'custom-post-type-ui' ),
302 'required' => true,
303 ]
304 );
305
306 echo $ui->get_text_input( // phpcs:ignore.
307 [
308 'namearray' => 'cpt_custom_tax',
309 'name' => 'singular_label',
310 'textvalue' => isset( $current['singular_label'] ) ? esc_attr( $current['singular_label'] ) : '', // phpcs:ignore.
311 'aftertext' => esc_html__( '(e.g. Actor)', 'custom-post-type-ui' ),
312 'labeltext' => esc_html__( 'Singular Label', 'custom-post-type-ui' ),
313 'helptext' => esc_attr__( 'Used when a singular label is needed.', 'custom-post-type-ui' ),
314 'required' => true,
315 ]
316 );
317 echo $ui->get_td_end() . $ui->get_tr_end(); // phpcs:ignore.
318
319 $link_text = ( 'new' === $tab ) ?
320 esc_html__( 'Populate additional labels based on chosen labels', 'custom-post-type-ui' ) :
321 esc_html__( 'Populate missing labels based on chosen labels', 'custom-post-type-ui' );
322 echo $ui->get_tr_end(); // phpcs:ignore.
323 echo $ui->get_th_start() . esc_html__( 'Auto-populate labels', 'custom-post-type-ui' ) . $ui->get_th_end(); // phpcs:ignore.
324 echo $ui->get_td_start(); // phpcs:ignore.
325
326 ?>
327 <a href="#" id="auto-populate"><?php echo esc_html( $link_text ); ?></a> |
328 <a href="#" id="auto-clear"><?php esc_html_e( 'Clear labels', 'custom-post-type-ui' ); ?></a>
329 <?php
330
331 echo $ui->get_td_end() . $ui->get_tr_end(); // phpcs:ignore.
332
333 echo $ui->get_tr_start() . $ui->get_th_start() . esc_html__( 'Attach to Post Type', 'custom-post-type-ui' ) . $ui->get_required_span(); // phpcs:ignore.
334 echo $ui->get_p( esc_html__( 'Add support for available registered post types. At least one is required. Only public post types listed by default.', 'custom-post-type-ui' ) ); // phpcs:ignore.
335 echo $ui->get_th_end() . $ui->get_td_start() . $ui->get_fieldset_start(); // phpcs:ignore.
336
337 echo $ui->get_legend_start() . esc_html__( 'Post type options', 'custom-post-type-ui' ) . $ui->get_legend_end(); // phpcs:ignore.
338
339 /**
340 * Filters the arguments for post types to list for taxonomy association.
341 *
342 * @since 1.0.0
343 *
344 * @param array $value Array of default arguments.
345 */
346 $args = apply_filters( 'cptui_attach_post_types_to_taxonomy', [ 'public' => true ] );
347
348 // If they don't return an array, fall back to the original default. Don't need to check for empty, because empty array is default for $args param in get_post_types anyway.
349 if ( ! is_array( $args ) ) {
350 $args = [ 'public' => true ];
351 }
352 $output = 'objects'; // Or objects.
353
354 /**
355 * Filters the results returned to display for available post types for taxonomy.
356 *
357 * @since 1.3.0
358 *
359 * @param array $value Array of post type objects.
360 * @param array $args Array of arguments for the post type query.
361 * @param string $output The output type we want for the results.
362 */
363 $post_types = apply_filters( 'cptui_get_post_types_for_taxonomies', get_post_types( $args, $output ), $args, $output );
364
365 foreach ( $post_types as $post_type ) {
366 $core_label = in_array(
367 $post_type->name,
368 [
369 'post',
370 'page',
371 'attachment',
372 ],
373 true
374 ) ? esc_html__( '(WP Core)', 'custom-post-type-ui' ) : '';
375 echo $ui->get_check_input( // phpcs:ignore.
376 [
377 'checkvalue' => $post_type->name,
378 'checked' => ( ! empty( $current['object_types'] ) && is_array( $current['object_types'] ) && in_array( $post_type->name, $current['object_types'], true ) ) ? 'true' : 'false', // phpcs:ignore.
379 'name' => esc_attr( $post_type->name ),
380 'namearray' => 'cpt_post_types',
381 'textvalue' => esc_attr( $post_type->name ),
382 'labeltext' => "{$post_type->label} {$core_label}", // phpcs:ignore.
383 'wrap' => false,
384 ]
385 );
386 }
387
388 echo $ui->get_fieldset_end() . $ui->get_td_end() . $ui->get_tr_end(); // phpcs:ignore.
389 ?>
390 </table>
391 <p class="submit">
392 <?php
393 wp_nonce_field( 'cptui_addedit_taxonomy_nonce_action', 'cptui_addedit_taxonomy_nonce_field' );
394 if ( ! empty( $_GET ) && ! empty( $_GET['action'] ) && 'edit' === $_GET['action'] ) { // phpcs:ignore.
395
396 /**
397 * Filters the text value to use on the button when editing.
398 *
399 * @since 1.0.0
400 *
401 * @param string $value Text to use for the button.
402 */
403 ?>
404 <input type="submit" class="button-primary cptui-taxonomy-submit" name="cpt_submit" value="<?php echo esc_attr( apply_filters( 'cptui_taxonomy_submit_edit', esc_attr__( 'Save Taxonomy', 'custom-post-type-ui' ) ) ); ?>" />
405 <?php
406
407 /**
408 * Filters the text value to use on the button when deleting.
409 *
410 * @since 1.0.0
411 *
412 * @param string $value Text to use for the button.
413 */
414 ?>
415 <input type="submit" class="button-secondary cptui-delete-top" name="cpt_delete" id="cpt_submit_delete" value="<?php echo esc_attr( apply_filters( 'cptui_taxonomy_submit_delete', esc_attr__( 'Delete Taxonomy', 'custom-post-type-ui' ) ) ); ?>" />
416 <?php } else { ?>
417 <?php
418
419 /**
420 * Filters the text value to use on the button when adding.
421 *
422 * @since 1.0.0
423 *
424 * @param string $value Text to use for the button.
425 */
426 ?>
427 <input type="submit" class="button-primary cptui-taxonomy-submit" name="cpt_submit" value="<?php echo esc_attr( apply_filters( 'cptui_taxonomy_submit_add', esc_attr__( 'Add Taxonomy', 'custom-post-type-ui' ) ) ); ?>" />
428 <?php } ?>
429
430 <?php if ( ! empty( $current ) ) { ?>
431 <input type="hidden" name="tax_original" id="tax_original" value="<?php echo esc_attr( $current['name'] ); ?>" />
432 <?php
433 }
434
435 // Used to check and see if we should prevent duplicate slugs.
436 ?>
437 <input type="hidden" name="cpt_tax_status" id="cpt_tax_status" value="<?php echo esc_attr( $tab ); ?>" />
438 </p>
439 </div>
440 </div>
441 </div>
442 <div class="cptui-section cptui-labels postbox">
443 <div class="postbox-header">
444 <h2 class="hndle ui-sortable-handle">
445 <span><?php esc_html_e( 'Additional labels', 'custom-post-type-ui' ); ?></span>
446 </h2>
447 <div class="handle-actions hide-if-no-js">
448 <button type="button" class="handlediv" aria-expanded="true">
449 <span class="screen-reader-text"><?php esc_html_e( 'Toggle panel: Additional labels', 'custom-post-type-ui' ); ?></span>
450 <span class="toggle-indicator" aria-hidden="true"></span>
451 </button>
452 </div>
453 </div>
454 <div class="inside">
455 <div class="main">
456 <table class="form-table cptui-table">
457
458 <?php
459 if ( isset( $current['description'] ) ) {
460 $current['description'] = stripslashes_deep( $current['description'] );
461 }
462 echo $ui->get_textarea_input( // phpcs:ignore.
463 [
464 'namearray' => 'cpt_custom_tax',
465 'name' => 'description',
466 'rows' => '4',
467 'cols' => '40',
468 'textvalue' => isset( $current['description'] ) ? esc_textarea( $current['description'] ) : '', // phpcs:ignore.
469 'labeltext' => esc_html__( 'Description', 'custom-post-type-ui' ),
470 'helptext' => esc_attr__( 'Describe what your taxonomy is used for.', 'custom-post-type-ui' ),
471 ]
472 );
473
474 echo $ui->get_text_input( // phpcs:ignore.
475 [
476 'namearray' => 'cpt_tax_labels',
477 'name' => 'menu_name',
478 'textvalue' => isset( $current['labels']['menu_name'] ) ? esc_attr( $current['labels']['menu_name'] ) : '', // phpcs:ignore.
479 'aftertext' => esc_attr__( '(e.g. Actors)', 'custom-post-type-ui' ),
480 'labeltext' => esc_html__( 'Menu Name', 'custom-post-type-ui' ),
481 'helptext' => esc_html__( 'Custom admin menu name for your taxonomy.', 'custom-post-type-ui' ),
482 'data' => [
483 'label' => 'item', // Not localizing because it's isolated.
484 'plurality' => 'plural',
485 ],
486 ]
487 );
488
489 echo $ui->get_text_input( // phpcs:ignore.
490 [
491 'namearray' => 'cpt_tax_labels',
492 'name' => 'all_items',
493 'textvalue' => isset( $current['labels']['all_items'] ) ? esc_attr( $current['labels']['all_items'] ) : '', // phpcs:ignore.
494 'aftertext' => esc_attr__( '(e.g. All Actors)', 'custom-post-type-ui' ),
495 'labeltext' => esc_html__( 'All Items', 'custom-post-type-ui' ),
496 'helptext' => esc_html__( 'Used as tab text when showing all terms for hierarchical taxonomy while editing post.', 'custom-post-type-ui' ),
497 'data' => [
498 /* translators: Used for autofill */
499 'label' => sprintf( esc_attr__( 'All %s', 'custom-post-type-ui' ), 'item' ),
500 'plurality' => 'plural',
501 ],
502 ]
503 );
504
505 echo $ui->get_text_input( // phpcs:ignore.
506 [
507 'namearray' => 'cpt_tax_labels',
508 'name' => 'edit_item',
509 'textvalue' => isset( $current['labels']['edit_item'] ) ? esc_attr( $current['labels']['edit_item'] ) : '', // phpcs:ignore.
510 'aftertext' => esc_attr__( '(e.g. Edit Actor)', 'custom-post-type-ui' ),
511 'labeltext' => esc_html__( 'Edit Item', 'custom-post-type-ui' ),
512 'helptext' => esc_html__( 'Used at the top of the term editor screen for an existing taxonomy term.', 'custom-post-type-ui' ),
513 'data' => [
514 /* translators: Used for autofill */
515 'label' => sprintf( esc_attr__( 'Edit %s', 'custom-post-type-ui' ), 'item' ),
516 'plurality' => 'singular',
517 ],
518 ]
519 );
520
521 echo $ui->get_text_input( // phpcs:ignore.
522 [
523 'namearray' => 'cpt_tax_labels',
524 'name' => 'view_item',
525 'textvalue' => isset( $current['labels']['view_item'] ) ? esc_attr( $current['labels']['view_item'] ) : '', // phpcs:ignore.
526 'aftertext' => esc_attr__( '(e.g. View Actor)', 'custom-post-type-ui' ),
527 'labeltext' => esc_html__( 'View Item', 'custom-post-type-ui' ),
528 'helptext' => esc_html__( 'Used in the admin bar when viewing editor screen for an existing taxonomy term.', 'custom-post-type-ui' ),
529 'data' => [
530 /* translators: Used for autofill */
531 'label' => sprintf( esc_attr__( 'View %s', 'custom-post-type-ui' ), 'item' ),
532 'plurality' => 'singular',
533 ],
534 ]
535 );
536
537 echo $ui->get_text_input( // phpcs:ignore.
538 [
539 'namearray' => 'cpt_tax_labels',
540 'name' => 'update_item',
541 'textvalue' => isset( $current['labels']['update_item'] ) ? esc_attr( $current['labels']['update_item'] ) : '', // phpcs:ignore.
542 'aftertext' => esc_attr__( '(e.g. Update Actor Name)', 'custom-post-type-ui' ),
543 'labeltext' => esc_html__( 'Update Item Name', 'custom-post-type-ui' ),
544 'helptext' => esc_html__( 'Custom taxonomy label. Used in the admin menu for displaying taxonomies.', 'custom-post-type-ui' ),
545 'data' => [
546 /* translators: Used for autofill */
547 'label' => sprintf( esc_attr__( 'Update %s name', 'custom-post-type-ui' ), 'item' ),
548 'plurality' => 'singular',
549 ],
550 ]
551 );
552
553 echo $ui->get_text_input( // phpcs:ignore.
554 [
555 'namearray' => 'cpt_tax_labels',
556 'name' => 'add_new_item',
557 'textvalue' => isset( $current['labels']['add_new_item'] ) ? esc_attr( $current['labels']['add_new_item'] ) : '', // phpcs:ignore.
558 'aftertext' => esc_attr__( '(e.g. Add New Actor)', 'custom-post-type-ui' ),
559 'labeltext' => esc_html__( 'Add New Item', 'custom-post-type-ui' ),
560 'helptext' => esc_html__( 'Used at the top of the term editor screen and button text for a new taxonomy term.', 'custom-post-type-ui' ),
561 'data' => [
562 /* translators: Used for autofill */
563 'label' => sprintf( esc_attr__( 'Add new %s', 'custom-post-type-ui' ), 'item' ),
564 'plurality' => 'singular',
565 ],
566 ]
567 );
568
569 echo $ui->get_text_input( // phpcs:ignore.
570 [
571 'namearray' => 'cpt_tax_labels',
572 'name' => 'new_item_name',
573 'textvalue' => isset( $current['labels']['new_item_name'] ) ? esc_attr( $current['labels']['new_item_name'] ) : '', // phpcs:ignore.
574 'aftertext' => esc_attr__( '(e.g. New Actor Name)', 'custom-post-type-ui' ),
575 'labeltext' => esc_html__( 'New Item Name', 'custom-post-type-ui' ),
576 'helptext' => esc_html__( 'Custom taxonomy label. Used in the admin menu for displaying taxonomies.', 'custom-post-type-ui' ),
577 'data' => [
578 /* translators: Used for autofill */
579 'label' => sprintf( esc_attr__( 'New %s name', 'custom-post-type-ui' ), 'item' ),
580 'plurality' => 'singular',
581 ],
582 ]
583 );
584
585 echo $ui->get_text_input( // phpcs:ignore.
586 [
587 'namearray' => 'cpt_tax_labels',
588 'name' => 'parent_item',
589 'textvalue' => isset( $current['labels']['parent_item'] ) ? esc_attr( $current['labels']['parent_item'] ) : '', // phpcs:ignore.
590 'aftertext' => esc_attr__( '(e.g. Parent Actor)', 'custom-post-type-ui' ),
591 'labeltext' => esc_html__( 'Parent Item', 'custom-post-type-ui' ),
592 'helptext' => esc_html__( 'Custom taxonomy label. Used in the admin menu for displaying taxonomies.', 'custom-post-type-ui' ),
593 'data' => [
594 /* translators: Used for autofill */
595 'label' => sprintf( esc_attr__( 'Parent %s', 'custom-post-type-ui' ), 'item' ),
596 'plurality' => 'singular',
597 ],
598 ]
599 );
600
601 echo $ui->get_text_input( // phpcs:ignore.
602 [
603 'namearray' => 'cpt_tax_labels',
604 'name' => 'parent_item_colon',
605 'textvalue' => isset( $current['labels']['parent_item_colon'] ) ? esc_attr( $current['labels']['parent_item_colon'] ) : '', // phpcs:ignore.
606 'aftertext' => esc_attr__( '(e.g. Parent Actor:)', 'custom-post-type-ui' ),
607 'labeltext' => esc_html__( 'Parent Item Colon', 'custom-post-type-ui' ),
608 'helptext' => esc_html__( 'Custom taxonomy label. Used in the admin menu for displaying taxonomies.', 'custom-post-type-ui' ),
609 'data' => [
610 /* translators: Used for autofill */
611 'label' => sprintf( esc_attr__( 'Parent %s:', 'custom-post-type-ui' ), 'item' ),
612 'plurality' => 'singular',
613 ],
614 ]
615 );
616
617 echo $ui->get_text_input( // phpcs:ignore.
618 [
619 'namearray' => 'cpt_tax_labels',
620 'name' => 'search_items',
621 'textvalue' => isset( $current['labels']['search_items'] ) ? esc_attr( $current['labels']['search_items'] ) : '', // phpcs:ignore.
622 'aftertext' => esc_attr__( '(e.g. Search Actors)', 'custom-post-type-ui' ),
623 'labeltext' => esc_html__( 'Search Items', 'custom-post-type-ui' ),
624 'helptext' => esc_html__( 'Custom taxonomy label. Used in the admin menu for displaying taxonomies.', 'custom-post-type-ui' ),
625 'data' => [
626 /* translators: Used for autofill */
627 'label' => sprintf( esc_attr__( 'Search %s', 'custom-post-type-ui' ), 'item' ),
628 'plurality' => 'plural',
629 ],
630 ]
631 );
632
633 echo $ui->get_text_input( // phpcs:ignore.
634 [
635 'namearray' => 'cpt_tax_labels',
636 'name' => 'popular_items',
637 'textvalue' => isset( $current['labels']['popular_items'] ) ? esc_attr( $current['labels']['popular_items'] ) : null, // phpcs:ignore.
638 'aftertext' => esc_attr__( '(e.g. Popular Actors)', 'custom-post-type-ui' ),
639 'labeltext' => esc_html__( 'Popular Items', 'custom-post-type-ui' ),
640 'helptext' => esc_html__( 'Custom taxonomy label. Used in the admin menu for displaying taxonomies.', 'custom-post-type-ui' ),
641 'data' => [
642 /* translators: Used for autofill */
643 'label' => sprintf( esc_attr__( 'Popular %s', 'custom-post-type-ui' ), 'item' ),
644 'plurality' => 'plural',
645 ],
646 ]
647 );
648
649 echo $ui->get_text_input( // phpcs:ignore.
650 [
651 'namearray' => 'cpt_tax_labels',
652 'name' => 'separate_items_with_commas',
653 'textvalue' => isset( $current['labels']['separate_items_with_commas'] ) ? esc_attr( $current['labels']['separate_items_with_commas'] ) : null, // phpcs:ignore.
654 'aftertext' => esc_attr__( '(e.g. Separate Actors with commas)', 'custom-post-type-ui' ),
655 'labeltext' => esc_html__( 'Separate Items with Commas', 'custom-post-type-ui' ),
656 'helptext' => esc_html__( 'Custom taxonomy label. Used in the admin menu for displaying taxonomies.', 'custom-post-type-ui' ),
657 'data' => [
658 /* translators: Used for autofill */
659 'label' => sprintf( esc_attr__( 'Separate %s with commas', 'custom-post-type-ui' ), 'item' ),
660 'plurality' => 'plural',
661 ],
662 ]
663 );
664
665 echo $ui->get_text_input( // phpcs:ignore.
666 [
667 'namearray' => 'cpt_tax_labels',
668 'name' => 'add_or_remove_items',
669 'textvalue' => isset( $current['labels']['add_or_remove_items'] ) ? esc_attr( $current['labels']['add_or_remove_items'] ) : null, // phpcs:ignore.
670 'aftertext' => esc_attr__( '(e.g. Add or remove Actors)', 'custom-post-type-ui' ),
671 'labeltext' => esc_html__( 'Add or Remove Items', 'custom-post-type-ui' ),
672 'helptext' => esc_html__( 'Custom taxonomy label. Used in the admin menu for displaying taxonomies.', 'custom-post-type-ui' ),
673 'data' => [
674 /* translators: Used for autofill */
675 'label' => sprintf( esc_attr__( 'Add or remove %s', 'custom-post-type-ui' ), 'item' ),
676 'plurality' => 'plural',
677 ],
678 ]
679 );
680
681 echo $ui->get_text_input( // phpcs:ignore.
682 [
683 'namearray' => 'cpt_tax_labels',
684 'name' => 'choose_from_most_used',
685 'textvalue' => isset( $current['labels']['choose_from_most_used'] ) ? esc_attr( $current['labels']['choose_from_most_used'] ) : null, // phpcs:ignore.
686 'aftertext' => esc_attr__( '(e.g. Choose from the most used Actors)', 'custom-post-type-ui' ),
687 'labeltext' => esc_html__( 'Choose From Most Used', 'custom-post-type-ui' ),
688 'helptext' => esc_attr__( 'The text displayed via clicking ‘Choose from the most used items’ in the taxonomy meta box when no items are available.', 'custom-post-type-ui' ),
689 'data' => [
690 /* translators: Used for autofill */
691 'label' => sprintf( esc_attr__( 'Choose from the most used %s', 'custom-post-type-ui' ), 'item' ),
692 'plurality' => 'plural',
693 ],
694 ]
695 );
696
697 echo $ui->get_text_input( // phpcs:ignore.
698 [
699 'namearray' => 'cpt_tax_labels',
700 'name' => 'not_found',
701 'textvalue' => isset( $current['labels']['not_found'] ) ? esc_attr( $current['labels']['not_found'] ) : null, // phpcs:ignore.
702 'aftertext' => esc_attr__( '(e.g. No Actors found)', 'custom-post-type-ui' ),
703 'labeltext' => esc_html__( 'Not found', 'custom-post-type-ui' ),
704 'helptext' => esc_html__( 'Used when indicating that there are no terms in the given taxonomy within the meta box and taxonomy list table.', 'custom-post-type-ui' ),
705 'data' => [
706 /* translators: Used for autofill */
707 'label' => sprintf( esc_attr__( 'No %s found', 'custom-post-type-ui' ), 'item' ),
708 'plurality' => 'plural',
709 ],
710 ]
711 );
712
713 echo $ui->get_text_input( // phpcs:ignore.
714 [
715 'namearray' => 'cpt_tax_labels',
716 'name' => 'no_terms',
717 'textvalue' => isset( $current['labels']['no_terms'] ) ? esc_attr( $current['labels']['no_terms'] ) : null, // phpcs:ignore.
718 'aftertext' => esc_html__( '(e.g. No actors)', 'custom-post-type-ui' ),
719 'labeltext' => esc_html__( 'No terms', 'custom-post-type-ui' ),
720 'helptext' => esc_attr__( 'Used when indicating that there are no terms in the given taxonomy associated with an object.', 'custom-post-type-ui' ),
721 'data' => [
722 /* translators: Used for autofill */
723 'label' => sprintf( esc_attr__( 'No %s', 'custom-post-type-ui' ), 'item' ),
724 'plurality' => 'plural',
725 ],
726 ]
727 );
728
729 echo $ui->get_text_input( // phpcs:ignore.
730 [
731 'namearray' => 'cpt_tax_labels',
732 'name' => 'items_list_navigation',
733 'textvalue' => isset( $current['labels']['items_list_navigation'] ) ? esc_attr( $current['labels']['items_list_navigation'] ) : null, // phpcs:ignore.
734 'aftertext' => esc_html__( '(e.g. Actors list navigation)', 'custom-post-type-ui' ),
735 'labeltext' => esc_html__( 'Items List Navigation', 'custom-post-type-ui' ),
736 'helptext' => esc_attr__( 'Screen reader text for the pagination heading on the term listing screen.', 'custom-post-type-ui' ),
737 'data' => [
738 /* translators: Used for autofill */
739 'label' => sprintf( esc_attr__( '%s list navigation', 'custom-post-type-ui' ), 'item' ),
740 'plurality' => 'plural',
741 ],
742 ]
743 );
744
745 echo $ui->get_text_input( // phpcs:ignore.
746 [
747 'namearray' => 'cpt_tax_labels',
748 'name' => 'items_list',
749 'textvalue' => isset( $current['labels']['items_list'] ) ? esc_attr( $current['labels']['items_list'] ) : null, // phpcs:ignore.
750 'aftertext' => esc_html__( '(e.g. Actors list)', 'custom-post-type-ui' ),
751 'labeltext' => esc_html__( 'Items List', 'custom-post-type-ui' ),
752 'helptext' => esc_attr__( 'Screen reader text for the items list heading on the term listing screen.', 'custom-post-type-ui' ),
753 'data' => [
754 /* translators: Used for autofill */
755 'label' => sprintf( esc_attr__( '%s list', 'custom-post-type-ui' ), 'item' ),
756 'plurality' => 'plural',
757 ],
758 ]
759 );
760
761 echo $ui->get_text_input( // phpcs:ignore.
762 [
763 'namearray' => 'cpt_tax_labels',
764 'name' => 'back_to_items',
765 'textvalue' => isset( $current['labels']['back_to_items'] ) ? esc_attr( $current['labels']['back_to_items'] ) : null, // phpcs:ignore.
766 'aftertext' => esc_html__( '(e.g. &larr; Back to actors', 'custom-post-type-ui' ),
767 'labeltext' => esc_html__( 'Back to Items', 'custom-post-type-ui' ),
768 'helptext' => esc_attr__( 'The text displayed after a term has been updated for a link back to main index.', 'custom-post-type-ui' ),
769 'data' => [
770 /* translators: Used for autofill */
771 'label' => sprintf( esc_attr__( 'Back to %s', 'custom-post-type-ui' ), 'item' ),
772 'plurality' => 'plural',
773 ],
774 ]
775 );
776
777 echo $ui->get_text_input( // phpcs:ignore.
778 [
779 'namearray' => 'cpt_tax_labels',
780 'name' => 'name_field_description',
781 'textvalue' => isset( $current['labels']['name_field_description'] ) ? esc_attr( $current['labels']['name_field_description'] ) : null, // phpcs:ignore.
782 'aftertext' => esc_html__( '(e.g. "The name is how it appears on your site."', 'custom-post-type-ui' ),
783 'labeltext' => esc_html__( 'Term Name Field Description', 'custom-post-type-ui' ),
784 'helptext' => esc_attr__( 'Description for the Name field on Edit Tags screen.', 'custom-post-type-ui' ),
785 'data' => [
786 /* translators: Used for autofill */
787 'label' => sprintf( esc_attr__( 'The name is how it appears on your site.', 'custom-post-type-ui' ), 'item' ),
788 'plurality' => 'singular',
789 ],
790 ]
791 );
792
793 echo $ui->get_text_input( // phpcs:ignore.
794 [
795 'namearray' => 'cpt_tax_labels',
796 'name' => 'parent_field_description',
797 'textvalue' => isset( $current['labels']['parent_field_description'] ) ? esc_attr( $current['labels']['parent_field_description'] ) : null, // phpcs:ignore.
798 'aftertext' => esc_html__( '(e.g. "Assign a parent term to create a hierarchy. The term Jazz, for example, would be the parent of Bebop and Big Band."', 'custom-post-type-ui' ),
799 'labeltext' => esc_html__( 'Term Parent Field Description', 'custom-post-type-ui' ),
800 'helptext' => esc_attr__( 'Description for the Parent field on Edit Tags screen.', 'custom-post-type-ui' ),
801 'data' => [
802 /* translators: Used for autofill */
803 'label' => sprintf( esc_attr__( 'Assign a parent term to create a hierarchy. The term Jazz, for example, would be the parent of Bebop and Big Band.', 'custom-post-type-ui' ), 'item' ),
804 'plurality' => 'singular',
805 ],
806 ]
807 );
808
809 echo $ui->get_text_input( // phpcs:ignore.
810 [
811 'namearray' => 'cpt_tax_labels',
812 'name' => 'slug_field_description',
813 'textvalue' => isset( $current['labels']['slug_field_description'] ) ? esc_attr( $current['labels']['slug_field_description'] ) : null, // phpcs:ignore.
814 'aftertext' => esc_html__( '(e.g. "The « slug » is the URL-friendly version of the name. It is usually all lowercase and contains only letters, numbers, and hyphens."', 'custom-post-type-ui' ),
815 'labeltext' => esc_html__( 'Term Slug Field Description', 'custom-post-type-ui' ),
816 'helptext' => esc_attr__( 'Description for the Slug field on Edit Tags screen. ', 'custom-post-type-ui' ),
817 'data' => [
818 /* translators: Used for autofill */
819 'label' => sprintf( esc_attr__( 'The "slug" is the URL-friendly version of the name. It is usually all lowercase and contains only letters, numbers, and hyphens.', 'custom-post-type-ui' ), 'item' ),
820 'plurality' => 'singular',
821 ],
822 ]
823 );
824
825 echo $ui->get_text_input( // phpcs:ignore.
826 [
827 'namearray' => 'cpt_tax_labels',
828 'name' => 'desc_field_description',
829 'textvalue' => isset( $current['labels']['desc_field_description'] ) ? esc_attr( $current['labels']['desc_field_description'] ) : null, // phpcs:ignore.
830 'aftertext' => esc_html__( '(e.g. "The description is not prominent by default; however, some themes may show it."', 'custom-post-type-ui' ),
831 'labeltext' => esc_html__( 'Term Description Field Description', 'custom-post-type-ui' ),
832 'helptext' => esc_attr__( 'Description for the Description field on Edit Tags screen.', 'custom-post-type-ui' ),
833 'data' => [
834 /* translators: Used for autofill */
835 'label' => sprintf( esc_attr__( 'The description is not prominent by default; however, some themes may show it.', 'custom-post-type-ui' ), 'item' ),
836 'plurality' => 'plural',
837 ],
838 ]
839 );
840 ?>
841 </table>
842 </div>
843 </div>
844 </div>
845 <div class="cptui-section cptui-settings postbox">
846 <div class="postbox-header">
847 <h2 class="hndle ui-sortable-handle">
848 <span><?php esc_html_e( 'Settings', 'custom-post-type-ui' ); ?></span>
849 </h2>
850 <div class="handle-actions hide-if-no-js">
851 <button type="button" class="handlediv" aria-expanded="true">
852 <span class="screen-reader-text"><?php esc_html_e( 'Toggle panel: Settings', 'custom-post-type-ui' ); ?></span>
853 <span class="toggle-indicator" aria-hidden="true"></span>
854 </button>
855 </div>
856 </div>
857 <div class="inside">
858 <div class="main">
859 <table class="form-table cptui-table">
860 <?php
861
862 $select = [
863 'options' => [
864 [
865 'attr' => '0',
866 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
867 ],
868 [
869 'attr' => '1',
870 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
871 'default' => 'true',
872 ],
873 ],
874 ];
875 $selected = isset( $current ) ? disp_boolean( $current['public'] ) : '';
876 $select['selected'] = ! empty( $selected ) ? $current['public'] : '';
877 echo $ui->get_select_input( // phpcs:ignore.
878 [
879 'namearray' => 'cpt_custom_tax',
880 'name' => 'public',
881 'labeltext' => esc_html__( 'Public', 'custom-post-type-ui' ),
882 'aftertext' => esc_html__( '(default: true) Whether a taxonomy is intended for use publicly either via the admin interface or by front-end users.', 'custom-post-type-ui' ),
883 'selections' => $select, // phpcs:ignore.
884 ]
885 );
886
887 $select = [
888 'options' => [
889 [
890 'attr' => '0',
891 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
892 ],
893 [
894 'attr' => '1',
895 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
896 'default' => 'true',
897 ],
898 ],
899 ];
900 $selected = isset( $current ) ? disp_boolean( $current['publicly_queryable'] ) : '';
901 $select['selected'] = ! empty( $selected ) ? $current['publicly_queryable'] : '';
902 echo $ui->get_select_input( // phpcs:ignore.
903 [
904 'namearray' => 'cpt_custom_tax',
905 'name' => 'publicly_queryable',
906 'labeltext' => esc_html__( 'Public Queryable', 'custom-post-type-ui' ),
907 'aftertext' => esc_html__( '(default: value of "public" setting) Whether or not the taxonomy should be publicly queryable.', 'custom-post-type-ui' ),
908 'selections' => $select, // phpcs:ignore.
909 ]
910 );
911
912 $select = [
913 'options' => [
914 [
915 'attr' => '0',
916 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
917 'default' => 'true',
918 ],
919 [
920 'attr' => '1',
921 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
922 ],
923 ],
924 ];
925 $selected = isset( $current ) ? disp_boolean( $current['hierarchical'] ) : '';
926 $select['selected'] = ! empty( $selected ) ? $current['hierarchical'] : '';
927 echo $ui->get_select_input( // phpcs:ignore.
928 [
929 'namearray' => 'cpt_custom_tax',
930 'name' => 'hierarchical',
931 'labeltext' => esc_html__( 'Hierarchical', 'custom-post-type-ui' ),
932 'aftertext' => esc_html__( '(default: false) Whether the taxonomy can have parent-child relationships. "True" gives checkboxes, "False" gives text input.', 'custom-post-type-ui' ),
933 'selections' => $select, // phpcs:ignore.
934 ]
935 );
936
937 $select = [
938 'options' => [
939 [
940 'attr' => '0',
941 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
942 ],
943 [
944 'attr' => '1',
945 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
946 'default' => 'true',
947 ],
948 ],
949 ];
950 $selected = isset( $current ) ? disp_boolean( $current['show_ui'] ) : '';
951 $select['selected'] = ! empty( $selected ) ? $current['show_ui'] : '';
952 echo $ui->get_select_input( // phpcs:ignore.
953 [
954 'namearray' => 'cpt_custom_tax',
955 'name' => 'show_ui',
956 'labeltext' => esc_html__( 'Show UI', 'custom-post-type-ui' ),
957 'aftertext' => esc_html__( '(default: true) Whether to generate a default UI for managing this custom taxonomy.', 'custom-post-type-ui' ),
958 'selections' => $select, // phpcs:ignore.
959 ]
960 );
961
962 $select = [
963 'options' => [
964 [
965 'attr' => '0',
966 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
967 ],
968 [
969 'attr' => '1',
970 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
971 'default' => 'true',
972 ],
973 ],
974 ];
975 $selected = isset( $current ) ? disp_boolean( $current['show_in_menu'] ) : '';
976 $select['selected'] = ! empty( $selected ) ? $current['show_in_menu'] : '';
977 echo $ui->get_select_input( // phpcs:ignore.
978 [
979 'namearray' => 'cpt_custom_tax',
980 'name' => 'show_in_menu',
981 'labeltext' => esc_html__( 'Show in menu', 'custom-post-type-ui' ),
982 'aftertext' => esc_html__( '(default: value of show_ui) Whether to show the taxonomy in the admin menu.', 'custom-post-type-ui' ),
983 'selections' => $select, // phpcs:ignore.
984 ]
985 );
986
987 $select = [
988 'options' => [
989 [
990 'attr' => '0',
991 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
992 ],
993 [
994 'attr' => '1',
995 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
996 'default' => 'true',
997 ],
998 ],
999 ];
1000 $selected = ( isset( $current ) && ! empty( $current['show_in_nav_menus'] ) ) ? disp_boolean( $current['show_in_nav_menus'] ) : '';
1001 $select['selected'] = ! empty( $selected ) ? $current['show_in_nav_menus'] : '';
1002 echo $ui->get_select_input( // phpcs:ignore.
1003 [
1004 'namearray' => 'cpt_custom_tax',
1005 'name' => 'show_in_nav_menus',
1006 'labeltext' => esc_html__( 'Show in nav menus', 'custom-post-type-ui' ),
1007 'aftertext' => esc_html__( '(default: value of public) Whether to make the taxonomy available for selection in navigation menus.', 'custom-post-type-ui' ),
1008 'selections' => $select, // phpcs:ignore.
1009 ]
1010 );
1011
1012 $select = [
1013 'options' => [
1014 [
1015 'attr' => '0',
1016 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1017 ],
1018 [
1019 'attr' => '1',
1020 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1021 'default' => 'true',
1022 ],
1023 ],
1024 ];
1025 $selected = isset( $current ) ? disp_boolean( $current['query_var'] ) : '';
1026 $select['selected'] = ! empty( $selected ) ? $current['query_var'] : '';
1027 echo $ui->get_select_input( // phpcs:ignore.
1028 [
1029 'namearray' => 'cpt_custom_tax',
1030 'name' => 'query_var',
1031 'labeltext' => esc_html__( 'Query Var', 'custom-post-type-ui' ),
1032 'aftertext' => esc_html__( '(default: true) Sets the query_var key for this taxonomy.', 'custom-post-type-ui' ),
1033 'selections' => $select, // phpcs:ignore.
1034 ]
1035 );
1036
1037 echo $ui->get_text_input( // phpcs:ignore.
1038 [
1039 'namearray' => 'cpt_custom_tax',
1040 'name' => 'query_var_slug',
1041 'textvalue' => isset( $current['query_var_slug'] ) ? esc_attr( $current['query_var_slug'] ) : '', // phpcs:ignore.
1042 'aftertext' => esc_attr__( '(default: taxonomy slug). Query var needs to be true to use.', 'custom-post-type-ui' ),
1043 'labeltext' => esc_html__( 'Custom Query Var String', 'custom-post-type-ui' ),
1044 'helptext' => esc_html__( 'Sets a custom query_var slug for this taxonomy.', 'custom-post-type-ui' ),
1045 ]
1046 );
1047
1048 $select = [
1049 'options' => [
1050 [
1051 'attr' => '0',
1052 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1053 ],
1054 [
1055 'attr' => '1',
1056 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1057 'default' => 'true',
1058 ],
1059 ],
1060 ];
1061 $selected = isset( $current ) ? disp_boolean( $current['rewrite'] ) : '';
1062 $select['selected'] = ! empty( $selected ) ? $current['rewrite'] : '';
1063 echo $ui->get_select_input( // phpcs:ignore.
1064 [
1065 'namearray' => 'cpt_custom_tax',
1066 'name' => 'rewrite',
1067 'labeltext' => esc_html__( 'Rewrite', 'custom-post-type-ui' ),
1068 'aftertext' => esc_html__( '(default: true) Whether or not WordPress should use rewrites for this taxonomy.', 'custom-post-type-ui' ),
1069 'selections' => $select, // phpcs:ignore.
1070 ]
1071 );
1072
1073 echo $ui->get_text_input( // phpcs:ignore.
1074 [
1075 'namearray' => 'cpt_custom_tax',
1076 'name' => 'rewrite_slug',
1077 'textvalue' => isset( $current['rewrite_slug'] ) ? esc_attr( $current['rewrite_slug'] ) : '', // phpcs:ignore.
1078 'aftertext' => esc_attr__( '(default: taxonomy name)', 'custom-post-type-ui' ),
1079 'labeltext' => esc_html__( 'Custom Rewrite Slug', 'custom-post-type-ui' ),
1080 'helptext' => esc_html__( 'Custom taxonomy rewrite slug.', 'custom-post-type-ui' ),
1081 ]
1082 );
1083
1084 $select = [
1085 'options' => [
1086 [
1087 'attr' => '0',
1088 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1089 ],
1090 [
1091 'attr' => '1',
1092 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1093 'default' => 'true',
1094 ],
1095 ],
1096 ];
1097 $selected = isset( $current ) ? disp_boolean( $current['rewrite_withfront'] ) : '';
1098 $select['selected'] = ! empty( $selected ) ? $current['rewrite_withfront'] : '';
1099 echo $ui->get_select_input( // phpcs:ignore.
1100 [
1101 'namearray' => 'cpt_custom_tax',
1102 'name' => 'rewrite_withfront',
1103 'labeltext' => esc_html__( 'Rewrite With Front', 'custom-post-type-ui' ),
1104 'aftertext' => esc_html__( '(default: true) Should the permastruct be prepended with the front base.', 'custom-post-type-ui' ),
1105 'selections' => $select, // phpcs:ignore.
1106 ]
1107 );
1108
1109 $select = [
1110 'options' => [
1111 [
1112 'attr' => '0',
1113 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1114 'default' => 'false',
1115 ],
1116 [
1117 'attr' => '1',
1118 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1119 ],
1120 ],
1121 ];
1122 $selected = isset( $current ) ? disp_boolean( $current['rewrite_hierarchical'] ) : '';
1123 $select['selected'] = ! empty( $selected ) ? $current['rewrite_hierarchical'] : '';
1124 echo $ui->get_select_input( // phpcs:ignore.
1125 [
1126 'namearray' => 'cpt_custom_tax',
1127 'name' => 'rewrite_hierarchical',
1128 'labeltext' => esc_html__( 'Rewrite Hierarchical', 'custom-post-type-ui' ),
1129 'aftertext' => esc_html__( '(default: false) Should the permastruct allow hierarchical urls.', 'custom-post-type-ui' ),
1130 'selections' => $select, // phpcs:ignore.
1131 ]
1132 );
1133
1134 $select = [
1135 'options' => [
1136 [
1137 'attr' => '0',
1138 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1139 'default' => 'true',
1140 ],
1141 [
1142 'attr' => '1',
1143 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1144 ],
1145 ],
1146 ];
1147 $selected = isset( $current ) ? disp_boolean( $current['show_admin_column'] ) : '';
1148 $select['selected'] = ! empty( $selected ) ? $current['show_admin_column'] : '';
1149 echo $ui->get_select_input( // phpcs:ignore.
1150 [
1151 'namearray' => 'cpt_custom_tax',
1152 'name' => 'show_admin_column',
1153 'labeltext' => esc_html__( 'Show Admin Column', 'custom-post-type-ui' ),
1154 'aftertext' => esc_html__( '(default: false) Whether to allow automatic creation of taxonomy columns on associated post-types.', 'custom-post-type-ui' ),
1155 'selections' => $select, // phpcs:ignore.
1156 ]
1157 );
1158
1159 $select = [
1160 'options' => [
1161 [
1162 'attr' => '0',
1163 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1164 ],
1165 [
1166 'attr' => '1',
1167 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1168 'default' => 'true',
1169 ],
1170 ],
1171 ];
1172 $selected = isset( $current ) ? disp_boolean( $current['show_in_rest'] ) : '';
1173 $select['selected'] = ! empty( $selected ) ? $current['show_in_rest'] : '';
1174 echo $ui->get_select_input( // phpcs:ignore.
1175 [
1176 'namearray' => 'cpt_custom_tax',
1177 'name' => 'show_in_rest',
1178 'labeltext' => esc_html__( 'Show in REST API', 'custom-post-type-ui' ),
1179 'aftertext' => esc_html__( '(Custom Post Type UI default: true) Whether to show this taxonomy data in the WP REST API.', 'custom-post-type-ui' ),
1180 'selections' => $select, // phpcs:ignore.
1181 ]
1182 );
1183
1184 echo $ui->get_text_input( // phpcs:ignore.
1185 [
1186 'namearray' => 'cpt_custom_tax',
1187 'name' => 'rest_base',
1188 'labeltext' => esc_html__( 'REST API base slug', 'custom-post-type-ui' ),
1189 'helptext' => esc_attr__( 'Slug to use in REST API URLs.', 'custom-post-type-ui' ),
1190 'textvalue' => isset( $current['rest_base'] ) ? esc_attr( $current['rest_base'] ) : '', // phpcs:ignore.
1191 ]
1192 );
1193
1194 echo $ui->get_text_input( // phpcs:ignore.
1195 [
1196 'namearray' => 'cpt_custom_tax',
1197 'name' => 'rest_controller_class',
1198 'labeltext' => esc_html__( 'REST API controller class', 'custom-post-type-ui' ),
1199 'aftertext' => esc_attr__( '(default: WP_REST_Terms_Controller) Custom controller to use instead of WP_REST_Terms_Controller.', 'custom-post-type-ui' ),
1200 'textvalue' => isset( $current['rest_controller_class'] ) ? esc_attr( $current['rest_controller_class'] ) : '', // phpcs:ignore.
1201 ]
1202 );
1203
1204 echo $ui->get_text_input( // phpcs:ignore.
1205 [
1206 'namearray' => 'cpt_custom_tax',
1207 'name' => 'rest_namespace',
1208 'labeltext' => esc_html__( 'REST API namespace', 'custom-post-type-ui' ),
1209 'aftertext' => esc_attr__( '(default: wp/v2) To change the namespace URL of REST API route.', 'custom-post-type-ui' ),
1210 'textvalue' => isset( $current['rest_namespace'] ) ? esc_attr( $current['rest_namespace'] ) : '', // phpcs:ignore.
1211 ]
1212 );
1213
1214 $select = [
1215 'options' => [
1216 [
1217 'attr' => '0',
1218 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1219 'default' => 'false',
1220 ],
1221 [
1222 'attr' => '1',
1223 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1224 ],
1225 ],
1226 ];
1227 $selected = ( isset( $current ) && ! empty( $current['show_tagcloud'] ) ) ? disp_boolean( $current['show_tagcloud'] ) : '';
1228 $select['selected'] = ! empty( $selected ) ? $current['show_tagcloud'] : '';
1229 echo $ui->get_select_input( // phpcs:ignore.
1230 [
1231 'namearray' => 'cpt_custom_tax',
1232 'name' => 'show_tagcloud',
1233 'labeltext' => esc_html__( 'Show in tag cloud.', 'custom-post-type-ui' ),
1234 'aftertext' => esc_html__( '(default: inherited from "show_ui") Whether to list the taxonomy in the Tag Cloud Widget controls.', 'custom-post-type-ui' ),
1235 'selections' => $select, // phpcs:ignore.
1236 ]
1237 );
1238
1239 $select = [
1240 'options' => [
1241 [
1242 'attr' => '0',
1243 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1244 'default' => 'false',
1245 ],
1246 [
1247 'attr' => '1',
1248 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1249 ],
1250 ],
1251 ];
1252 $selected = ( isset( $current ) && ! empty( $current['show_in_quick_edit'] ) ) ? disp_boolean( $current['show_in_quick_edit'] ) : '';
1253 $select['selected'] = ! empty( $selected ) ? $current['show_in_quick_edit'] : '';
1254 echo $ui->get_select_input( // phpcs:ignore.
1255 [
1256 'namearray' => 'cpt_custom_tax',
1257 'name' => 'show_in_quick_edit',
1258 'labeltext' => esc_html__( 'Show in quick/bulk edit panel.', 'custom-post-type-ui' ),
1259 'aftertext' => esc_html__( '(default: false) Whether to show the taxonomy in the quick/bulk edit panel.', 'custom-post-type-ui' ),
1260 'selections' => $select, // phpcs:ignore.
1261 ]
1262 );
1263
1264 $select = [
1265 'options' => [
1266 [
1267 'attr' => '0',
1268 'text' => esc_attr__( 'False', 'custom-post-type-ui' ),
1269 'default' => 'false',
1270 ],
1271 [
1272 'attr' => '1',
1273 'text' => esc_attr__( 'True', 'custom-post-type-ui' ),
1274 ],
1275 ],
1276 ];
1277 $selected = ( isset( $current ) && ! empty( $current['sort'] ) ) ? disp_boolean( $current['sort'] ) : '';
1278 $select['selected'] = ! empty( $selected ) ? $current['sort'] : '';
1279 echo $ui->get_select_input( // phpcs:ignore.
1280 [
1281 'namearray' => 'cpt_custom_tax',
1282 'name' => 'sort',
1283 'labeltext' => esc_html__( 'Sort', 'custom-post-type-ui' ),
1284 'aftertext' => esc_html__( 'Whether terms in this taxonomy should be sorted in the order they are provided to wp_set_object_terms()', 'custom-post-type-ui' ),
1285 'selections' => $select, // phpcs:ignore.
1286 ]
1287 );
1288
1289 echo $ui->get_text_input( // phpcs:ignore.
1290 [
1291 'namearray' => 'cpt_custom_tax',
1292 'name' => 'meta_box_cb',
1293 'textvalue' => isset( $current['meta_box_cb'] ) ? esc_attr( $current['meta_box_cb'] ) : '', // phpcs:ignore.
1294 'labeltext' => esc_html__( 'Metabox callback', 'custom-post-type-ui' ),
1295 'helptext' => esc_html__( 'Sets a callback function name for the meta box display. Hierarchical default: post_categories_meta_box, non-hierarchical default: post_tags_meta_box. To remove the metabox completely, use "false".', 'custom-post-type-ui' ),
1296 ]
1297 );
1298
1299 echo $ui->get_text_input( // phpcs:ignore.
1300 [
1301 'namearray' => 'cpt_custom_tax',
1302 'name' => 'default_term',
1303 'textvalue' => isset( $current['default_term'] ) ? esc_attr( $current['default_term'] ) : '', // phpcs:ignore.
1304 'labeltext' => esc_html__( 'Default Term', 'custom-post-type-ui' ),
1305 'helptext' => esc_html__( 'Set a default term for the taxonomy. Able to set a name, slug, and description. Only a name is required if setting a default, others are optional. Set values in the following order, separated by comma. Example: name, slug, description', 'custom-post-type-ui' ),
1306 ]
1307 );
1308 ?>
1309 </table>
1310 </div>
1311 </div>
1312 </div>
1313
1314 <?php
1315 /**
1316 * Fires after the default fieldsets on the taxonomy screen.
1317 *
1318 * @since 1.3.0
1319 *
1320 * @param cptui_admin_ui $ui Admin UI instance.
1321 */
1322 do_action( 'cptui_taxonomy_after_fieldsets', $ui );
1323 ?>
1324
1325 <p class="submit">
1326 <?php
1327 wp_nonce_field( 'cptui_addedit_taxonomy_nonce_action', 'cptui_addedit_taxonomy_nonce_field' );
1328 if ( ! empty( $_GET ) && ! empty( $_GET['action'] ) && 'edit' === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
1329 /**
1330 * Filters the text value to use on the button when editing.
1331 *
1332 * @since 1.0.0
1333 *
1334 * @param string $value Text to use for the button.
1335 */
1336 ?>
1337 <input type="submit" class="button-primary cptui-taxonomy-submit" name="cpt_submit" value="<?php echo esc_attr( apply_filters( 'cptui_taxonomy_submit_edit', esc_attr__( 'Save Taxonomy', 'custom-post-type-ui' ) ) ); ?>" />
1338 <?php
1339
1340 /**
1341 * Filters the text value to use on the button when deleting.
1342 *
1343 * @since 1.0.0
1344 *
1345 * @param string $value Text to use for the button.
1346 */
1347 ?>
1348 <input type="submit" class="button-secondary cptui-delete-bottom" name="cpt_delete" id="cpt_submit_delete" value="<?php echo esc_attr( apply_filters( 'cptui_taxonomy_submit_delete', esc_attr__( 'Delete Taxonomy', 'custom-post-type-ui' ) ) ); ?>" />
1349 <?php } else { ?>
1350 <?php
1351
1352 /**
1353 * Filters the text value to use on the button when adding.
1354 *
1355 * @since 1.0.0
1356 *
1357 * @param string $value Text to use for the button.
1358 */
1359 ?>
1360 <input type="submit" class="button-primary cptui-taxonomy-submit" name="cpt_submit" value="<?php echo esc_attr( apply_filters( 'cptui_taxonomy_submit_add', esc_attr__( 'Add Taxonomy', 'custom-post-type-ui' ) ) ); ?>" />
1361 <?php } ?>
1362
1363 <?php if ( ! empty( $current ) ) { ?>
1364 <input type="hidden" name="tax_original" id="tax_original" value="<?php echo esc_attr( $current['name'] ); ?>" />
1365 <?php
1366 }
1367
1368 // Used to check and see if we should prevent duplicate slugs.
1369 ?>
1370 <input type="hidden" name="cpt_tax_status" id="cpt_tax_status" value="<?php echo esc_attr( $tab ); ?>" />
1371 </p>
1372 </div>
1373 </div>
1374 </form>
1375 </div><!-- End .wrap -->
1376 <?php
1377 }
1378
1379 /**
1380 * Construct a dropdown of our taxonomies so users can select which to edit.
1381 *
1382 * @since 1.0.0
1383 *
1384 * @param array $taxonomies Array of taxonomies that are registered. Optional.
1385 */
1386 function cptui_taxonomies_dropdown( $taxonomies = [] ) {
1387
1388 $ui = new cptui_admin_ui();
1389
1390 if ( ! empty( $taxonomies ) ) {
1391 $select = [];
1392 $select['options'] = [];
1393
1394 foreach ( $taxonomies as $tax ) {
1395 $text = ! empty( $tax['label'] ) ? esc_html( $tax['label'] ) : esc_html( $tax['name'] );
1396 $select['options'][] = [
1397 'attr' => $tax['name'],
1398 'text' => $text,
1399 ];
1400 }
1401
1402 $current = cptui_get_current_taxonomy();
1403 $select['selected'] = $current;
1404
1405 /**
1406 * Filters the taxonomy dropdown options before rendering.
1407 *
1408 * @since 1.6.0
1409 *
1410 * @param array $select Array of options for the dropdown.
1411 * @param array $taxonomies Array of original passed in post types.
1412 */
1413 $select = apply_filters( 'cptui_taxonomies_dropdown_options', $select, $taxonomies );
1414
1415 echo $ui->get_select_input( // phpcs:ignore.
1416 [
1417 'namearray' => 'cptui_selected_taxonomy',
1418 'name' => 'taxonomy',
1419 'selections' => $select, // phpcs:ignore.
1420 'wrap' => false,
1421 ]
1422 );
1423 }
1424 }
1425
1426 /**
1427 * Get the selected taxonomy from the $_POST global.
1428 *
1429 * @since 1.0.0
1430 *
1431 * @internal
1432 *
1433 * @param bool $taxonomy_deleted Whether or not a taxonomy was recently deleted. Optional. Default false.
1434 * @return bool|string False on no result, sanitized taxonomy if set.
1435 */
1436 function cptui_get_current_taxonomy( $taxonomy_deleted = false ) {
1437
1438 $tax = false;
1439
1440 if ( ! empty( $_POST ) ) {
1441 if ( ! empty( $_POST['cptui_select_taxonomy_nonce_field'] ) ) {
1442 check_admin_referer( 'cptui_select_taxonomy_nonce_action', 'cptui_select_taxonomy_nonce_field' );
1443 }
1444 if ( isset( $_POST['cptui_selected_taxonomy']['taxonomy'] ) ) {
1445 $tax = sanitize_text_field( wp_unslash( $_POST['cptui_selected_taxonomy']['taxonomy'] ) );
1446 } elseif ( $taxonomy_deleted ) {
1447 $taxonomies = cptui_get_taxonomy_data();
1448 $tax = key( $taxonomies );
1449 } elseif ( isset( $_POST['cpt_custom_tax']['name'] ) ) {
1450 // Return the submitted value.
1451 if ( ! in_array( $_POST['cpt_custom_tax']['name'], cptui_reserved_taxonomies(), true ) ) {
1452 $tax = sanitize_text_field( wp_unslash( $_POST['cpt_custom_tax']['name'] ) );
1453 } else {
1454 // Return the original value since user tried to submit a reserved term.
1455 $tax = sanitize_text_field( wp_unslash( $_POST['tax_original'] ) ); // phpcs:ignore.
1456 }
1457 }
1458 } elseif ( ! empty( $_GET ) && isset( $_GET['cptui_taxonomy'] ) ) {
1459 $tax = sanitize_text_field( wp_unslash( $_GET['cptui_taxonomy'] ) );
1460 } else {
1461 $taxonomies = cptui_get_taxonomy_data();
1462 if ( ! empty( $taxonomies ) ) {
1463 // Will return the first array key.
1464 $tax = key( $taxonomies );
1465 }
1466 }
1467
1468 /**
1469 * Filters the current taxonomy to edit.
1470 *
1471 * @since 1.3.0
1472 *
1473 * @param string $tax Taxonomy slug.
1474 */
1475 return apply_filters( 'cptui_current_taxonomy', $tax );
1476 }
1477
1478 /**
1479 * Delete our custom taxonomy from the array of taxonomies.
1480 *
1481 * @since 1.0.0
1482 *
1483 * @internal
1484 *
1485 * @param array $data The $_POST values. Optional.
1486 * @return bool|string False on failure, string on success.
1487 */
1488 function cptui_delete_taxonomy( $data = [] ) {
1489
1490 if ( is_string( $data ) && taxonomy_exists( $data ) ) {
1491 $slug = $data;
1492 $data = [];
1493 $data['name'] = $slug;
1494 }
1495
1496 // Check if they selected one to delete.
1497 if ( empty( $data['name'] ) ) {
1498 return cptui_admin_notices( 'error', '', false, esc_html__( 'Please provide a taxonomy to delete', 'custom-post-type-ui' ) );
1499 }
1500
1501 /**
1502 * Fires before a taxonomy is deleted from our saved options.
1503 *
1504 * @since 1.0.0
1505 *
1506 * @param array $data Array of taxonomy data we are deleting.
1507 */
1508 do_action( 'cptui_before_delete_taxonomy', $data );
1509
1510 $taxonomies = cptui_get_taxonomy_data();
1511
1512 if ( array_key_exists( strtolower( $data['name'] ), $taxonomies ) ) {
1513
1514 unset( $taxonomies[ $data['name'] ] );
1515
1516 /**
1517 * Filters whether or not 3rd party options were saved successfully within taxonomy deletion.
1518 *
1519 * @since 1.3.0
1520 *
1521 * @param bool $value Whether or not someone else saved successfully. Default false.
1522 * @param array $taxonomies Array of our updated taxonomies data.
1523 * @param array $data Array of submitted taxonomy to update.
1524 */
1525 if ( false === ( $success = apply_filters( 'cptui_taxonomy_delete_tax', false, $taxonomies, $data ) ) ) { // phpcs:ignore.
1526 $success = update_option( 'cptui_taxonomies', $taxonomies );
1527 }
1528 }
1529 delete_option( "default_term_{$data['name']}" );
1530
1531 /**
1532 * Fires after a taxonomy is deleted from our saved options.
1533 *
1534 * @since 1.0.0
1535 *
1536 * @param array $data Array of taxonomy data that was deleted.
1537 */
1538 do_action( 'cptui_after_delete_taxonomy', $data );
1539
1540 // Used to help flush rewrite rules on init.
1541 set_transient( 'cptui_flush_rewrite_rules', 'true', 5 * 60 );
1542
1543 if ( isset( $success ) ) {
1544 return 'delete_success';
1545 }
1546 return 'delete_fail';
1547 }
1548
1549 /**
1550 * Add to or update our CPTUI option with new data.
1551 *
1552 * @since 1.0.0
1553 *
1554 * @internal
1555 *
1556 * @param array $data Array of taxonomy data to update. Optional.
1557 * @return bool|string False on failure, string on success.
1558 */
1559 function cptui_update_taxonomy( $data = [] ) {
1560
1561 /**
1562 * Fires before a taxonomy is updated to our saved options.
1563 *
1564 * @since 1.0.0
1565 *
1566 * @param array $data Array of taxonomy data we are updating.
1567 */
1568 do_action( 'cptui_before_update_taxonomy', $data );
1569
1570 // They need to provide a name.
1571 if ( empty( $data['cpt_custom_tax']['name'] ) ) {
1572 return cptui_admin_notices( 'error', '', false, esc_html__( 'Please provide a taxonomy name', 'custom-post-type-ui' ) );
1573 }
1574
1575 // Maybe a little harsh, but we shouldn't be saving THAT frequently.
1576 delete_option( "default_term_{$data['cpt_custom_tax']['name']}" );
1577
1578 if ( empty( $data['cpt_post_types'] ) ) {
1579 add_filter( 'cptui_custom_error_message', 'cptui_empty_cpt_on_taxonomy' );
1580 return 'error';
1581 }
1582
1583 if ( ! empty( $data['tax_original'] ) && $data['tax_original'] !== $data['cpt_custom_tax']['name'] ) {
1584 if ( ! empty( $data['update_taxonomy'] ) ) {
1585 add_filter( 'cptui_convert_taxonomy_terms', '__return_true' );
1586 }
1587 }
1588
1589 foreach ( $data as $key => $value ) {
1590 if ( is_string( $value ) ) {
1591 $data[ $key ] = sanitize_text_field( $value );
1592 } else {
1593 array_map( 'sanitize_text_field', $data[ $key ] );
1594 }
1595 }
1596
1597 if ( false !== strpos( $data['cpt_custom_tax']['name'], '\'' ) ||
1598 false !== strpos( $data['cpt_custom_tax']['name'], '\"' ) ||
1599 false !== strpos( $data['cpt_custom_tax']['rewrite_slug'], '\'' ) ||
1600 false !== strpos( $data['cpt_custom_tax']['rewrite_slug'], '\"' ) ) {
1601
1602 add_filter( 'cptui_custom_error_message', 'cptui_slug_has_quotes' );
1603 return 'error';
1604 }
1605
1606 $taxonomies = cptui_get_taxonomy_data();
1607
1608 /**
1609 * Check if we already have a post type of that name.
1610 *
1611 * @since 1.3.0
1612 *
1613 * @param bool $value Assume we have no conflict by default.
1614 * @param string $value Post type slug being saved.
1615 * @param array $post_types Array of existing post types from CPTUI.
1616 */
1617 $slug_exists = apply_filters( 'cptui_taxonomy_slug_exists', false, $data['cpt_custom_tax']['name'], $taxonomies );
1618 if ( true === $slug_exists ) {
1619 add_filter( 'cptui_custom_error_message', 'cptui_slug_matches_taxonomy' );
1620 return 'error';
1621 }
1622
1623 if ( empty( $data['cpt_tax_labels'] ) || ! is_array( $data['cpt_tax_labels'] ) ) {
1624 $data['cpt_tax_labels'] = [];
1625 }
1626
1627 foreach ( $data['cpt_tax_labels'] as $key => $label ) {
1628 if ( empty( $label ) ) {
1629 unset( $data['cpt_tax_labels'][ $key ] );
1630 }
1631 $label = str_replace( '"', '', htmlspecialchars_decode( $label ) );
1632 $label = htmlspecialchars( $label, ENT_QUOTES );
1633 $label = trim( $label );
1634 $data['cpt_tax_labels'][ $key ] = stripslashes_deep( $label );
1635 }
1636
1637 $label = ucwords( str_replace( '_', ' ', $data['cpt_custom_tax']['name'] ) );
1638 if ( ! empty( $data['cpt_custom_tax']['label'] ) ) {
1639 $label = str_replace( '"', '', htmlspecialchars_decode( $data['cpt_custom_tax']['label'] ) );
1640 $label = htmlspecialchars( stripslashes( $label ), ENT_QUOTES );
1641 }
1642
1643 $name = trim( $data['cpt_custom_tax']['name'] );
1644
1645 $singular_label = ucwords( str_replace( '_', ' ', $data['cpt_custom_tax']['name'] ) );
1646 if ( ! empty( $data['cpt_custom_tax']['singular_label'] ) ) {
1647 $singular_label = str_replace( '"', '', htmlspecialchars_decode( $data['cpt_custom_tax']['singular_label'] ) );
1648 $singular_label = htmlspecialchars( stripslashes( $singular_label ) );
1649 }
1650 $description = stripslashes_deep( $data['cpt_custom_tax']['description'] );
1651 $query_var_slug = trim( $data['cpt_custom_tax']['query_var_slug'] );
1652 $rewrite_slug = trim( $data['cpt_custom_tax']['rewrite_slug'] );
1653 $rest_base = trim( $data['cpt_custom_tax']['rest_base'] );
1654 $rest_controller_class = trim( $data['cpt_custom_tax']['rest_controller_class'] );
1655 $rest_namespace = trim( $data['cpt_custom_tax']['rest_namespace'] );
1656 $show_quickpanel_bulk = ! empty( $data['cpt_custom_tax']['show_in_quick_edit'] ) ? disp_boolean( $data['cpt_custom_tax']['show_in_quick_edit'] ) : '';
1657 $default_term = trim( $data['cpt_custom_tax']['default_term'] );
1658
1659 $meta_box_cb = trim( $data['cpt_custom_tax']['meta_box_cb'] );
1660 // We may or may not need to force a boolean false keyword.
1661 $maybe_false = strtolower( trim( $data['cpt_custom_tax']['meta_box_cb'] ) );
1662 if ( 'false' === $maybe_false ) {
1663 $meta_box_cb = $maybe_false;
1664 }
1665
1666 $taxonomies[ $data['cpt_custom_tax']['name'] ] = [
1667 'name' => $name,
1668 'label' => $label,
1669 'singular_label' => $singular_label,
1670 'description' => $description,
1671 'public' => disp_boolean( $data['cpt_custom_tax']['public'] ),
1672 'publicly_queryable' => disp_boolean( $data['cpt_custom_tax']['publicly_queryable'] ),
1673 'hierarchical' => disp_boolean( $data['cpt_custom_tax']['hierarchical'] ),
1674 'show_ui' => disp_boolean( $data['cpt_custom_tax']['show_ui'] ),
1675 'show_in_menu' => disp_boolean( $data['cpt_custom_tax']['show_in_menu'] ),
1676 'show_in_nav_menus' => disp_boolean( $data['cpt_custom_tax']['show_in_nav_menus'] ),
1677 'query_var' => disp_boolean( $data['cpt_custom_tax']['query_var'] ),
1678 'query_var_slug' => $query_var_slug,
1679 'rewrite' => disp_boolean( $data['cpt_custom_tax']['rewrite'] ),
1680 'rewrite_slug' => $rewrite_slug,
1681 'rewrite_withfront' => $data['cpt_custom_tax']['rewrite_withfront'],
1682 'rewrite_hierarchical' => $data['cpt_custom_tax']['rewrite_hierarchical'],
1683 'show_admin_column' => disp_boolean( $data['cpt_custom_tax']['show_admin_column'] ),
1684 'show_in_rest' => disp_boolean( $data['cpt_custom_tax']['show_in_rest'] ),
1685 'show_tagcloud' => disp_boolean( $data['cpt_custom_tax']['show_tagcloud'] ),
1686 'sort' => disp_boolean( $data['cpt_custom_tax']['sort'] ),
1687 'show_in_quick_edit' => $show_quickpanel_bulk,
1688 'rest_base' => $rest_base,
1689 'rest_controller_class' => $rest_controller_class,
1690 'rest_namespace' => $rest_namespace,
1691 'labels' => $data['cpt_tax_labels'],
1692 'meta_box_cb' => $meta_box_cb,
1693 'default_term' => $default_term,
1694 ];
1695
1696 $taxonomies[ $data['cpt_custom_tax']['name'] ]['object_types'] = $data['cpt_post_types'];
1697
1698 /**
1699 * Filters final data to be saved right before saving taxoomy data.
1700 *
1701 * @since 1.6.0
1702 *
1703 * @param array $taxonomies Array of final taxonomy data to save.
1704 * @param string $name Taxonomy slug for taxonomy being saved.
1705 */
1706 $taxonomies = apply_filters( 'cptui_pre_save_taxonomy', $taxonomies, $name );
1707
1708 /**
1709 * Filters whether or not 3rd party options were saved successfully within taxonomy add/update.
1710 *
1711 * @since 1.3.0
1712 *
1713 * @param bool $value Whether or not someone else saved successfully. Default false.
1714 * @param array $taxonomies Array of our updated taxonomies data.
1715 * @param array $data Array of submitted taxonomy to update.
1716 */
1717 if ( false === ( $success = apply_filters( 'cptui_taxonomy_update_save', false, $taxonomies, $data ) ) ) { // phpcs:ignore.
1718 $success = update_option( 'cptui_taxonomies', $taxonomies );
1719 }
1720
1721 /**
1722 * Fires after a taxonomy is updated to our saved options.
1723 *
1724 * @since 1.0.0
1725 *
1726 * @param array $data Array of taxonomy data that was updated.
1727 */
1728 do_action( 'cptui_after_update_taxonomy', $data );
1729
1730 // Used to help flush rewrite rules on init.
1731 set_transient( 'cptui_flush_rewrite_rules', 'true', 5 * 60 );
1732
1733 if ( isset( $success ) && 'new' === $data['cpt_tax_status'] ) {
1734 return 'add_success';
1735 }
1736
1737 return 'update_success';
1738 }
1739
1740 /**
1741 * Return an array of names that users should not or can not use for taxonomy names.
1742 *
1743 * @since 1.3.0
1744 *
1745 * @return array $value Array of names that are recommended against.
1746 */
1747 function cptui_reserved_taxonomies() {
1748
1749 $reserved = [
1750 'action',
1751 'attachment',
1752 'attachment_id',
1753 'author',
1754 'author_name',
1755 'calendar',
1756 'cat',
1757 'category',
1758 'category__and',
1759 'category__in',
1760 'category__not_in',
1761 'category_name',
1762 'comments_per_page',
1763 'comments_popup',
1764 'cpage',
1765 'custom',
1766 'customize_messenger_channel',
1767 'customized',
1768 'date',
1769 'day',
1770 'debug',
1771 'embed',
1772 'error',
1773 'exact',
1774 'feed',
1775 'fields',
1776 'hour',
1777 'include',
1778 'link_category',
1779 'm',
1780 'minute',
1781 'monthnum',
1782 'more',
1783 'name',
1784 'nav_menu',
1785 'nonce',
1786 'nopaging',
1787 'offset',
1788 'order',
1789 'orderby',
1790 'output',
1791 'p',
1792 'page',
1793 'page_id',
1794 'paged',
1795 'pagename',
1796 'pb',
1797 'perm',
1798 'post',
1799 'post__in',
1800 'post__not_in',
1801 'post_format',
1802 'post_mime_type',
1803 'post_status',
1804 'post_tag',
1805 'post_type',
1806 'posts',
1807 'posts_per_archive_page',
1808 'posts_per_page',
1809 'preview',
1810 'robots',
1811 's',
1812 'search',
1813 'second',
1814 'sentence',
1815 'showposts',
1816 'static',
1817 'status',
1818 'subpost',
1819 'subpost_id',
1820 'tag',
1821 'tag__and',
1822 'tag__in',
1823 'tag__not_in',
1824 'tag_id',
1825 'tag_slug__and',
1826 'tag_slug__in',
1827 'taxonomy',
1828 'tb',
1829 'term',
1830 'terms',
1831 'theme',
1832 'themes',
1833 'title',
1834 'type',
1835 'types',
1836 'w',
1837 'withcomments',
1838 'withoutcomments',
1839 'year',
1840 ];
1841
1842 /**
1843 * Filters the list of reserved post types to check against.
1844 * 3rd party plugin authors could use this to prevent duplicate post types.
1845 *
1846 * @since 1.0.0
1847 *
1848 * @param array $value Array of post type slugs to forbid.
1849 */
1850 $custom_reserved = apply_filters( 'cptui_reserved_taxonomies', [] );
1851
1852 if ( is_string( $custom_reserved ) && ! empty( $custom_reserved ) ) {
1853 $reserved[] = $custom_reserved;
1854 } elseif ( is_array( $custom_reserved ) && ! empty( $custom_reserved ) ) {
1855 foreach ( $custom_reserved as $slug ) {
1856 $reserved[] = $slug;
1857 }
1858 }
1859
1860 return $reserved;
1861 }
1862
1863 /**
1864 * Convert taxonomies.
1865 *
1866 * @since 1.3.0
1867 *
1868 * @internal
1869 *
1870 * @param string $original_slug Original taxonomy slug. Optional. Default empty string.
1871 * @param string $new_slug New taxonomy slug. Optional. Default empty string.
1872 */
1873 function cptui_convert_taxonomy_terms( $original_slug = '', $new_slug = '' ) {
1874 global $wpdb;
1875
1876 $args = [
1877 'taxonomy' => $original_slug,
1878 'hide_empty' => false,
1879 'fields' => 'ids',
1880 ];
1881
1882 $term_ids = get_terms( $args );
1883
1884 if ( is_int( $term_ids ) ) {
1885 $term_ids = (array) $term_ids;
1886 }
1887
1888 if ( is_array( $term_ids ) && ! empty( $term_ids ) ) {
1889 $term_ids = implode( ',', $term_ids );
1890
1891 $query = "UPDATE `{$wpdb->term_taxonomy}` SET `taxonomy` = %s WHERE `taxonomy` = %s AND `term_id` IN ( {$term_ids} )";
1892
1893 $wpdb->query( // phpcs:ignore.
1894 $wpdb->prepare( $query, $new_slug, $original_slug ) // phpcs:ignore.
1895 );
1896 }
1897 cptui_delete_taxonomy( $original_slug );
1898 }
1899
1900 /**
1901 * Checks if we are trying to register an already registered taxonomy slug.
1902 *
1903 * @since 1.3.0
1904 *
1905 * @param bool $slug_exists Whether or not the post type slug exists. Optional. Default false.
1906 * @param string $taxonomy_slug The post type slug being saved. Optional. Default empty string.
1907 * @param array $taxonomies Array of CPTUI-registered post types. Optional.
1908 *
1909 * @return bool
1910 */
1911 function cptui_check_existing_taxonomy_slugs( $slug_exists = false, $taxonomy_slug = '', $taxonomies = [] ) {
1912
1913 // If true, then we'll already have a conflict, let's not re-process.
1914 if ( true === $slug_exists ) {
1915 return $slug_exists;
1916 }
1917
1918 if ( ! is_array( $taxonomies ) ) {
1919 return $slug_exists;
1920 }
1921
1922 // Check if CPTUI has already registered this slug.
1923 if ( array_key_exists( strtolower( $taxonomy_slug ), $taxonomies ) ) { // phpcs:ignore.
1924 return true;
1925 }
1926
1927 // Check if we're registering a reserved post type slug.
1928 if ( in_array( $taxonomy_slug, cptui_reserved_taxonomies() ) ) { // phpcs:ignore.
1929 return true;
1930 }
1931
1932 // Check if other plugins have registered this same slug.
1933 $public = get_taxonomies(
1934 [
1935 '_builtin' => false,
1936 'public' => true,
1937 ]
1938 );
1939 $private = get_taxonomies(
1940 [
1941 '_builtin' => false,
1942 'public' => false,
1943 ]
1944 );
1945
1946 $registered_taxonomies = array_merge( $public, $private );
1947 if ( in_array( $taxonomy_slug, $registered_taxonomies, true ) ) {
1948 return true;
1949 }
1950
1951 // If we're this far, it's false.
1952 return $slug_exists;
1953 }
1954 add_filter( 'cptui_taxonomy_slug_exists', 'cptui_check_existing_taxonomy_slugs', 10, 3 );
1955
1956 /**
1957 * Handle the save and deletion of taxonomy data.
1958 *
1959 * @since 1.4.0
1960 */
1961 function cptui_process_taxonomy() {
1962
1963 if ( wp_doing_ajax() ) {
1964 return;
1965 }
1966
1967 if ( ! is_admin() ) {
1968 return;
1969 }
1970
1971 if ( ! empty( $_GET ) && isset( $_GET['page'] ) && 'cptui_manage_taxonomies' !== $_GET['page'] ) {
1972 return;
1973 }
1974
1975 if ( ! empty( $_POST ) ) {
1976 $result = '';
1977 if ( isset( $_POST['cpt_submit'] ) ) {
1978 check_admin_referer( 'cptui_addedit_taxonomy_nonce_action', 'cptui_addedit_taxonomy_nonce_field' );
1979 $data = cptui_filtered_taxonomy_post_global();
1980 $result = cptui_update_taxonomy( $data );
1981 } elseif ( isset( $_POST['cpt_delete'] ) ) {
1982 check_admin_referer( 'cptui_addedit_taxonomy_nonce_action', 'cptui_addedit_taxonomy_nonce_field' );
1983
1984 $filtered_data = filter_input( INPUT_POST, 'cpt_custom_tax', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
1985 $result = cptui_delete_taxonomy( $filtered_data );
1986 add_filter( 'cptui_taxonomy_deleted', '__return_true' );
1987 }
1988
1989 if ( $result && is_callable( "cptui_{$result}_admin_notice" ) ) {
1990 add_action( 'admin_notices', "cptui_{$result}_admin_notice" );
1991 }
1992
1993 if ( isset( $_POST['cpt_delete'] ) && empty( cptui_get_taxonomy_slugs() ) ) {
1994 wp_safe_redirect(
1995 add_query_arg(
1996 [ 'page' => 'cptui_manage_taxonomies' ],
1997 cptui_admin_url( 'admin.php?page=cptui_manage_taxonomies' )
1998 )
1999 );
2000 }
2001 }
2002 }
2003 add_action( 'init', 'cptui_process_taxonomy', 8 );
2004
2005 /**
2006 * Handle the conversion of taxonomy terms.
2007 *
2008 * This function came to be because we needed to convert AFTER registration.
2009 *
2010 * @since 1.4.3
2011 */
2012 function cptui_do_convert_taxonomy_terms() {
2013
2014 /**
2015 * Whether or not to convert taxonomy terms.
2016 *
2017 * @since 1.4.3
2018 *
2019 * @param bool $value Whether or not to convert.
2020 */
2021 if ( apply_filters( 'cptui_convert_taxonomy_terms', false ) ) {
2022 check_admin_referer( 'cptui_addedit_taxonomy_nonce_action', 'cptui_addedit_taxonomy_nonce_field' );
2023
2024 $original = filter_input( INPUT_POST, 'tax_original', FILTER_SANITIZE_SPECIAL_CHARS );
2025 $new = filter_input( INPUT_POST, 'cpt_custom_tax', FILTER_SANITIZE_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
2026
2027 // Return early if either fails to successfully validate.
2028 if ( ! $original || ! $new ) {
2029 return;
2030 }
2031
2032 cptui_convert_taxonomy_terms( sanitize_text_field( $original ), sanitize_text_field( $new['name'] ) );
2033 }
2034 }
2035 add_action( 'init', 'cptui_do_convert_taxonomy_terms' );
2036
2037 /**
2038 * Handles slug_exist checks for cases of editing an existing taxonomy.
2039 *
2040 * @since 1.5.3
2041 *
2042 * @param bool $slug_exists Current status for exist checks.
2043 * @param string $taxonomy_slug Taxonomy slug being processed.
2044 * @param array $taxonomies CPTUI taxonomies.
2045 * @return bool
2046 */
2047 function cptui_updated_taxonomy_slug_exists( $slug_exists, $taxonomy_slug = '', $taxonomies = [] ) {
2048 if (
2049 ( ! empty( $_POST['cpt_tax_status'] ) && 'edit' === $_POST['cpt_tax_status'] ) && // phpcs:ignore WordPress.Security.NonceVerification
2050 ! in_array( $taxonomy_slug, cptui_reserved_taxonomies(), true ) && // phpcs:ignore WordPress.Security.NonceVerification
2051 ( ! empty( $_POST['tax_original'] ) && $taxonomy_slug === $_POST['tax_original'] ) // phpcs:ignore WordPress.Security.NonceVerification
2052 ) {
2053 $slug_exists = false;
2054 }
2055 return $slug_exists;
2056 }
2057 add_filter( 'cptui_taxonomy_slug_exists', 'cptui_updated_taxonomy_slug_exists', 11, 3 );
2058
2059 /**
2060 * Sanitize and filter the $_POST global and return a reconstructed array of the parts we need.
2061 *
2062 * Used for when managing taxonomies.
2063 *
2064 * @since 1.10.0
2065 * @return array
2066 */
2067 function cptui_filtered_taxonomy_post_global() {
2068 $filtered_data = [];
2069
2070 $default_arrays = [
2071 'cpt_custom_tax',
2072 'cpt_tax_labels',
2073 'cpt_post_types',
2074 'update_taxonomy',
2075 ];
2076
2077 $third_party_items_arrays = apply_filters(
2078 'cptui_filtered_taxonomy_post_global_arrays',
2079 (array) [] // phpcs:ignore.
2080 );
2081
2082 $items_arrays = array_merge( $default_arrays, $third_party_items_arrays );
2083 foreach ( $items_arrays as $item ) {
2084 $first_result = filter_input( INPUT_POST, $item, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
2085
2086 if ( $first_result ) {
2087 $filtered_data[ $item ] = $first_result;
2088 }
2089 }
2090
2091 $default_strings = [
2092 'tax_original',
2093 'cpt_tax_status',
2094 ];
2095
2096 $third_party_items_strings = apply_filters(
2097 'cptui_filtered_taxonomy_post_global_strings',
2098 (array) [] // phpcs:ignore.
2099 );
2100
2101 $items_strings = array_merge( $default_strings, $third_party_items_strings );
2102 foreach ( $items_strings as $item ) {
2103 $second_result = filter_input( INPUT_POST, $item, FILTER_SANITIZE_SPECIAL_CHARS );
2104 if ( $second_result ) {
2105 $filtered_data[ $item ] = $second_result;
2106 }
2107 }
2108
2109 return $filtered_data;
2110 }
1 <?php
2
3 // Exit if accessed directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * Content for the Debug Info tab.
10 * @since 1.2.0
11 * @internal
12 */
13 function cptui_render_debuginfo_section() {
14
15 $debuginfo = new CPTUI_Debug_Info();
16
17 echo '<form id="cptui_debug_info" method="post">';
18 $debuginfo->tab_site_info();
19
20 wp_nonce_field( 'cptui_debuginfo_nonce_action', 'cptui_debuginfo_nonce_field' );
21
22 if ( ! empty( $_POST ) && isset( $_POST['cptui_debug_info_email'] ) && isset( $_POST['cptui_debuginfo_nonce_field'] ) ) {
23 if ( wp_verify_nonce( 'cptui_debuginfo_nonce_field', 'cptui_debuginfo_nonce_action' ) ) {
24 $email_args = [];
25 $email_args['email'] = sanitize_text_field( $_POST['cptui_debug_info_email'] );
26 $debuginfo->send_email( $email_args );
27 }
28 }
29
30 echo '<p><label for="cptui_debug_info_email">' . esc_html__( 'Please provide an email address to send debug information to: ', 'custom-post-type-ui' ) . '</label><input type="email" id="cptui_debug_info_email" name="cptui_debug_info_email" value="" /></p>';
31
32 /**
33 * Filters the text value to use on the button when sending debug information.
34 *
35 * @param string $value Text to use for the button.
36 *
37 * @since 1.2.0
38 */
39 echo '<p><input type="submit" class="button-primary" name="cptui_send_debug_email" value="' . esc_attr( apply_filters( 'cptui_debug_email_submit_button', __( 'Send debug info', 'custom-post-type-ui' ) ) ) . '" /></p>';
40 echo '</form>';
41
42 /**
43 * Fires after the display of the site information.
44 * @since 1.3.0
45 */
46 do_action( 'cptui_after_site_info' );
47 }
1 <?php
2
3 // Exit if accessed directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * Content for the Get Code tab.
10 * @since 1.2.0
11 * @internal
12 */
13 function cptui_render_getcode_section() {
14 ?>
15 <h1><?php esc_html_e( 'Get Post Type and Taxonomy Code', 'custom-post-type-ui' ); ?></h1>
16
17 <h2><?php esc_html_e( 'All Custom Post Type UI Post Types', 'custom-post-type-ui' ); ?></h2>
18
19 <p><?php esc_html_e( 'All of the selectable code snippets below are useful if you wish to migrate away from Custom Post Type UI and retain your existing registered post types or taxonomies.', 'custom-post-type-ui' ); ?></p>
20
21 <?php $cptui_post_types = cptui_get_post_type_data(); ?>
22 <p>
23 <label for="cptui_post_type_get_code"><?php esc_html_e( 'Copy/paste the code below into your functions.php file.', 'custom-post-type-ui' ); ?></label>
24 </p>
25 <textarea name="cptui_post_type_get_code" id="cptui_post_type_get_code" class="large-text cptui_post_type_get_code" onclick="this.focus();this.select()" onfocus="this.focus();this.select();" readonly="readonly" aria-readonly="true"><?php cptui_get_post_type_code( $cptui_post_types ); ?></textarea>
26
27 <?php
28 if ( ! empty( $cptui_post_types ) ) {
29 foreach ( $cptui_post_types as $post_type ) {
30 ?>
31 <h2 id="<?php echo esc_attr( $post_type['name'] ); ?>">
32 <?php
33 $type = ! empty( $post_type['label'] ) ? esc_html( $post_type['label'] ) : esc_html( $post_type['name'] );
34 printf( esc_html__( '%s Post Type', 'custom-post-type-ui' ), esc_html( $type ) ); ?></h2>
35 <p>
36 <label for="cptui_post_type_get_code_<?php echo esc_attr( $post_type['name'] ); ?>"><?php esc_html_e( 'Copy/paste the code below into your functions.php file.', 'custom-post-type-ui' ); ?></label>
37 </p>
38 <textarea name="cptui_post_type_get_code_<?php echo esc_attr( $post_type['name'] ); ?>" id="cptui_post_type_get_code_<?php echo esc_attr( $post_type['name'] ); ?>" class="large-text cptui_post_type_get_code" onclick="this.focus();this.select()" onfocus="this.focus();this.select();" readonly="readonly" aria-readonly="true"><?php cptui_get_post_type_code( [ $post_type ], true ); ?></textarea>
39 <?php
40 }
41 }
42 ?>
43
44 <h2><?php esc_html_e( 'All Custom Post Type UI Taxonomies', 'custom-post-type-ui' ); ?></h2>
45
46 <?php $cptui_taxonomies = cptui_get_taxonomy_data(); ?>
47 <p>
48 <label for="cptui_tax_get_code"><?php esc_html_e( 'Copy/paste the code below into your functions.php file.', 'custom-post-type-ui' ); ?></label>
49 </p>
50 <textarea name="cptui_tax_get_code" id="cptui_tax_get_code" class="large-text cptui_tax_get_code" onclick="this.focus();this.select()" onfocus="this.focus();this.select();" readonly="readonly" aria-readonly="true"><?php cptui_get_taxonomy_code( $cptui_taxonomies ); ?></textarea>
51
52 <?php
53 if ( ! empty( $cptui_taxonomies ) ) {
54 foreach ( $cptui_taxonomies as $taxonomy ) {
55 ?>
56 <h2 id="<?php echo esc_attr( $taxonomy['name'] ); ?>">
57 <?php
58 $tax = ! empty( $taxonomy['label'] ) ? esc_html( $taxonomy['label'] ) : esc_html( $taxonomy['name'] );
59 printf( esc_html__( '%s Taxonomy', 'custom-post-type-ui' ), esc_html( $tax ) );
60 ?>
61 </h2>
62 <p>
63 <label for="cptui_tax_get_code_<?php echo esc_attr( $taxonomy['name'] ); ?>"><?php esc_html_e( 'Copy/paste the code below into your functions.php file.', 'custom-post-type-ui' ); ?></label>
64 </p>
65 <textarea name="cptui_tax_get_code_<?php echo esc_attr( $taxonomy['name'] ); ?>" id="cptui_tax_get_code_<?php echo esc_attr( $taxonomy['name'] ); ?>" class="large-text cptui_tax_get_code" onclick="this.focus();this.select()" onfocus="this.focus();this.select();" readonly="readonly" aria-readonly="true"><?php cptui_get_taxonomy_code( [ $taxonomy ], true ); ?></textarea>
66 <?php
67 }
68 }
69 ?>
70 <?php
71 }
1 <?php
2
3 // Exit if accessed directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * Display our copy-able code for registered post types.
10 *
11 * @param array $cptui_post_types Array of post types to render. Optional.
12 * @param bool $single Whether or not we are rendering a single post type. Optional. Default false.
13 *
14 * @since 1.2.0 Added $single parameter.
15 * @since 1.0.0
16 * @since 1.2.0 Added $cptui_post_types parameter.
17 */
18 function cptui_get_post_type_code( $cptui_post_types = [], $single = false ) {
19 // Whitespace very much matters here, thus why it's all flush against the left side.
20 if ( ! empty( $cptui_post_types ) ) {
21 $callback = 'cptui_register_my_cpts';
22 if ( $single ) {
23 $key = key( $cptui_post_types );
24 $callback = 'cptui_register_my_cpts_' . str_replace( '-', '_', esc_html( $cptui_post_types[ $key ]['name'] ) );
25 }
26 ?>
27
28 function <?php echo esc_html( $callback ); ?>() {
29 <?php
30 // Space before this line reflects in textarea.
31 foreach ( $cptui_post_types as $type ) {
32 echo cptui_get_single_post_type_registery( $type );
33 }
34 ?>
35 }
36
37 add_action( 'init', '<?php echo esc_html( $callback ); ?>' );
38 <?php
39 } else {
40 esc_html_e( 'No post types to display at this time', 'custom-post-type-ui' );
41 }
42 }
43
44 /**
45 * Create output for single post type to be ready for copy/paste from Get Code.
46 *
47 * @param array $post_type Post type data to output. Optional.
48 *
49 * @since 1.0.0
50 */
51 function cptui_get_single_post_type_registery( $post_type = [] ) {
52
53 /* This filter is documented in custom-post-type-ui/custom-post-type-ui.php */
54 $post_type['map_meta_cap'] = apply_filters( 'cptui_map_meta_cap', 'true', $post_type['name'], $post_type );
55
56 /* This filter is documented in custom-post-type-ui/custom-post-type-ui.php */
57 $user_supports_params = apply_filters( 'cptui_user_supports_params', [], $post_type['name'], $post_type );
58 if ( is_array( $user_supports_params ) ) {
59 $post_type['supports'] = array_merge( $post_type['supports'], $user_supports_params );
60 }
61
62 $yarpp = false; // Prevent notices.
63 if ( ! empty( $post_type['custom_supports'] ) ) {
64 $custom = explode( ',', $post_type['custom_supports'] );
65 foreach ( $custom as $part ) {
66 // We'll handle YARPP separately.
67 if ( in_array( $part, [ 'YARPP', 'yarpp' ], true ) ) {
68 $yarpp = true;
69 continue;
70 }
71 $post_type['supports'][] = $part;
72 }
73 }
74
75
76 $show_graphql = isset( $post_type['show_in_graphql'] ) ? (bool) $post_type['show_in_graphql'] : false;
77
78 $rewrite_withfront = '';
79 $rewrite = get_disp_boolean( $post_type['rewrite'] );
80 if ( false !== $rewrite ) {
81 $rewrite = disp_boolean( $post_type['rewrite'] );
82
83 $rewrite_slug = ' "slug" => "' . $post_type['name'] . '",';
84 if ( ! empty( $post_type['rewrite_slug'] ) ) {
85 $rewrite_slug = ' "slug" => "' . $post_type['rewrite_slug'] . '",';
86 }
87
88 $withfront = disp_boolean( $post_type['rewrite_withfront'] );
89 if ( ! empty( $withfront ) ) {
90 $rewrite_withfront = ' "with_front" => ' . $withfront . ' ';
91 }
92
93 if ( ! empty( $post_type['rewrite_slug'] ) || ! empty( $post_type['rewrite_withfront'] ) ) {
94 $rewrite_start = '[';
95 $rewrite_end = ']';
96
97 $rewrite = $rewrite_start . $rewrite_slug . $rewrite_withfront . $rewrite_end;
98 }
99 } else {
100 $rewrite = disp_boolean( $post_type['rewrite'] );
101 }
102 $has_archive = get_disp_boolean( $post_type['has_archive'] );
103 if ( false !== $has_archive ) {
104 $has_archive = disp_boolean( $post_type['has_archive'] );
105 if ( ! empty( $post_type['has_archive_string'] ) ) {
106 $has_archive = '"' . $post_type['has_archive_string'] . '"';
107 }
108 } else {
109 $has_archive = disp_boolean( $post_type['has_archive'] );
110 }
111
112 $supports = '';
113 // Do a little bit of php work to get these into strings.
114 if ( ! empty( $post_type['supports'] ) && is_array( $post_type['supports'] ) ) {
115 $supports = '[ "' . implode( '", "', $post_type['supports'] ) . '" ]';
116 }
117
118 if ( in_array( 'none', $post_type['supports'], true ) ) {
119 $supports = 'false';
120 }
121
122 $taxonomies = '';
123 if ( ! empty( $post_type['taxonomies'] ) && is_array( $post_type['taxonomies'] ) ) {
124 $taxonomies = '[ "' . implode( '", "', $post_type['taxonomies'] ) . '" ]';
125 }
126
127 if ( in_array( $post_type['query_var'], [ 'true', 'false', '0', '1' ], true ) ) {
128 $post_type['query_var'] = disp_boolean( $post_type['query_var'] );
129 }
130 if ( ! empty( $post_type['query_var_slug'] ) ) {
131 $post_type['query_var'] = '"' . $post_type['query_var_slug'] . '"';
132 }
133
134 if ( empty( $post_type['show_in_rest'] ) ) {
135 $post_type['show_in_rest'] = 'false';
136 }
137 $rest_controller_class = ! empty( $post_type['rest_controller_class'] ) ? $post_type['rest_controller_class'] : 'WP_REST_Posts_Controller';
138 $rest_namespace = ! empty( $post_type['rest_namespace'] ) ? $post_type['rest_namespace'] : 'wp/v2';
139
140 $show_in_menu = get_disp_boolean( $post_type['show_in_menu'] );
141 if ( false !== $show_in_menu ) {
142 $show_in_menu = disp_boolean( $post_type['show_in_menu'] );
143 if ( ! empty( $post_type['show_in_menu_string'] ) ) {
144 $show_in_menu = '"' . $post_type['show_in_menu_string'] . '"';
145 }
146 } else {
147 $show_in_menu = disp_boolean( $post_type['show_in_menu'] );
148 }
149
150 $delete_with_user = 'false';
151 if ( isset( $post_type['delete_with_user'] ) ) {
152 $delete_with_user = disp_boolean( $post_type['delete_with_user'] );
153 }
154
155 $can_export = 'true';
156 if ( isset( $post_type['can_export'] ) ) {
157 $can_export = disp_boolean( $post_type['can_export'] );
158 }
159
160 $public = isset( $post_type['public'] ) ? disp_boolean( $post_type['public'] ) : 'true';
161 $show_in_nav_menus = ( ! empty( $post_type['show_in_nav_menus'] ) && false !== get_disp_boolean( $post_type['show_in_nav_menus'] ) ) ? 'true' : 'false';
162 if ( empty( $post_type['show_in_nav_menus'] ) ) {
163 $show_in_nav_menus = $public;
164 }
165
166 $capability_type = '"post"';
167 if ( ! empty( $post_type['capability_type'] ) ) {
168 $capability_type = '"' . $post_type['capability_type'] . '"';
169 if ( false !== strpos( $post_type['capability_type'], ',' ) ) {
170 $caps = array_map( 'trim', explode( ',', $post_type['capability_type'] ) );
171 if ( count( $caps ) > 2 ) {
172 $caps = array_slice( $caps, 0, 2 );
173 }
174 $capability_type = '[ "' . $caps[0] . '", "' . $caps[1] . '" ]';
175 }
176 }
177
178 $post_type['description'] = addslashes( $post_type['description'] );
179
180 $my_theme = wp_get_theme();
181 $textdomain = $my_theme->get( 'TextDomain' );
182 if ( empty( $textdomain ) ) {
183 $textdomain = 'custom-post-type-ui';
184 }
185 ?>
186
187 /**
188 * Post Type: <?php echo $post_type['label']; ?>.
189 */
190
191 $labels = [
192 "name" => esc_html__( "<?php echo $post_type['label']; ?>", "<?php echo $textdomain; ?>" ),
193 "singular_name" => esc_html__( "<?php echo $post_type['singular_label']; ?>", "<?php echo $textdomain; ?>" ),
194 <?php
195 foreach ( $post_type['labels'] as $key => $label ) {
196 if ( ! empty( $label ) ) {
197 if ( 'parent' === $key && ! array_key_exists( 'parent_item_colon', $post_type['labels'] ) ) {
198 // Fix for incorrect label key. See #439.
199 echo "\t\t" . '"' . 'parent_item_colon' . '" => esc_html__( "' . $label . '", "' . $textdomain . '" ),' . "\n";
200 } else {
201 echo "\t\t" . '"' . $key . '" => esc_html__( "' . $label . '", "' . $textdomain . '" ),' . "\n";
202 }
203 }
204 }
205 ?>
206 ];
207
208 $args = [
209 "label" => esc_html__( "<?php echo $post_type['label']; ?>", "<?php echo $textdomain; ?>" ),
210 "labels" => $labels,
211 "description" => "<?php echo $post_type['description']; ?>",
212 "public" => <?php echo disp_boolean( $post_type['public'] ); ?>,
213 "publicly_queryable" => <?php echo disp_boolean( $post_type['publicly_queryable'] ); ?>,
214 "show_ui" => <?php echo disp_boolean( $post_type['show_ui'] ); ?>,
215 "show_in_rest" => <?php echo disp_boolean( $post_type['show_in_rest'] ); ?>,
216 "rest_base" => "<?php echo $post_type['rest_base']; ?>",
217 "rest_controller_class" => "<?php echo $rest_controller_class; ?>",
218 "rest_namespace" => "<?php echo $rest_namespace; ?>",
219 "has_archive" => <?php echo $has_archive; ?>,
220 "show_in_menu" => <?php echo $show_in_menu; ?>,
221 "show_in_nav_menus" => <?php echo $show_in_nav_menus; ?>,
222 "delete_with_user" => <?php echo $delete_with_user; ?>,
223 "exclude_from_search" => <?php echo disp_boolean( $post_type['exclude_from_search'] ); ?>,
224 "capability_type" => <?php echo $capability_type; ?>,
225 "map_meta_cap" => <?php echo disp_boolean( $post_type['map_meta_cap'] ); ?>,
226 "hierarchical" => <?php echo disp_boolean( $post_type['hierarchical'] ); ?>,
227 "can_export" => <?php echo $can_export; ?>,
228 "rewrite" => <?php echo $rewrite; ?>,
229 "query_var" => <?php echo $post_type['query_var']; ?>,
230 <?php if ( ! empty( $post_type['menu_position'] ) ) { ?>
231 "menu_position" => <?php echo $post_type['menu_position']; ?>,
232 <?php } ?>
233 <?php if ( ! empty( $post_type['menu_icon'] ) ) { ?>
234 "menu_icon" => "<?php echo $post_type['menu_icon']; ?>",
235 <?php } ?>
236 <?php if ( ! empty( $post_type['register_meta_box_cb'] ) ) { ?>
237 "register_meta_box_cb" => "<?php echo $post_type['register_meta_box_cb']; ?>",
238 <?php } ?>
239 <?php if ( ! empty( $supports ) ) { ?>
240 "supports" => <?php echo $supports; ?>,
241 <?php } ?>
242 <?php if ( ! empty( $taxonomies ) ) { ?>
243 "taxonomies" => <?php echo $taxonomies; ?>,
244 <?php } ?>
245 <?php if ( true === $yarpp ) { ?>
246 "yarpp_support" => <?php echo disp_boolean( $yarpp ); ?>,
247 <?php } ?>
248 <?php if ( $show_graphql ) : ?>
249 "show_in_graphql" => <?php echo disp_boolean( $post_type['show_in_graphql'] ); ?>,
250 "graphql_single_name" => "<?php echo esc_html( $post_type['graphql_single_name'] ); ?>",
251 "graphql_plural_name" => "<?php echo esc_html( $post_type['graphql_plural_name'] ); ?>",
252 <?php else: ?>
253 "show_in_graphql" => <?php echo disp_boolean( false ); ?>,
254 <?php endif; ?>
255 ];
256
257 register_post_type( "<?php echo esc_html( $post_type['name'] ); ?>", $args );
258 <?php
259 }
1 <?php
2
3 // Exit if accessed directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * Display our copy-able code for registered taxonomies.
10 *
11 * @param array $cptui_taxonomies Array of taxonomies to render. Optional.
12 * @param bool $single Whether or not we are rendering a single taxonomy. Optional. Default false.
13 *
14 * @since 1.2.0 Added $single parameter.
15 * @since 1.0.0
16 * @since 1.2.0 Added $cptui_taxonomies parameter.
17 */
18 function cptui_get_taxonomy_code( $cptui_taxonomies = [], $single = false ) {
19 if ( ! empty( $cptui_taxonomies ) ) {
20 $callback = 'cptui_register_my_taxes';
21 if ( $single ) {
22 $key = key( $cptui_taxonomies );
23 $callback = 'cptui_register_my_taxes_' . str_replace( '-', '_', esc_html( $cptui_taxonomies[ $key ]['name'] ) );
24 }
25 ob_start();
26 ?>
27 function <?php echo esc_html( $callback ); ?>() {
28 <?php
29 foreach ( $cptui_taxonomies as $tax ) {
30 echo cptui_get_single_taxonomy_registery( $tax );
31 }
32 ?>
33 }
34 add_action( 'init', '<?php echo esc_html( $callback ); ?>' );
35 <?php
36 } else {
37 esc_html_e( 'No taxonomies to display at this time', 'custom-post-type-ui' );
38 }
39 echo trim( ob_get_clean() );
40 }
41
42 /**
43 * Create output for single taxonomy to be ready for copy/paste from Get Code.
44 *
45 * @param array $taxonomy Taxonomy data to output. Optional.
46 *
47 * @since 1.0.0
48 */
49 function cptui_get_single_taxonomy_registery( $taxonomy = [] ) {
50
51 $post_types = "''";
52 if ( is_array( $taxonomy['object_types'] ) ) {
53 $post_types = '[ "' . implode( '", "', $taxonomy['object_types'] ) . '" ]';
54 }
55
56 if ( false !== get_disp_boolean( $taxonomy['rewrite'] ) ) {
57 $rewrite = disp_boolean( $taxonomy['rewrite'] );
58
59 $rewrite_slug = ' \'slug\' => \'' . $taxonomy['name'] . '\',';
60 if ( ! empty( $taxonomy['rewrite_slug'] ) ) {
61 $rewrite_slug = ' \'slug\' => \'' . $taxonomy['rewrite_slug'] . '\',';
62 }
63
64 $rewrite_withfront = '';
65 $withfront = disp_boolean( $taxonomy['rewrite_withfront'] );
66 if ( ! empty( $withfront ) ) {
67 $rewrite_withfront = ' \'with_front\' => ' . $withfront . ', ';
68 }
69
70 $hierarchical = ! empty( $taxonomy['rewrite_hierarchical'] ) ? disp_boolean( $taxonomy['rewrite_hierarchical'] ) : '';
71 $rewrite_hierarchcial = '';
72 if ( ! empty( $hierarchical ) ) {
73 $rewrite_hierarchcial = ' \'hierarchical\' => ' . $hierarchical . ', ';
74 }
75
76 if ( ! empty( $taxonomy['rewrite_slug'] ) || false !== disp_boolean( $taxonomy['rewrite_withfront'] ) ) {
77 $rewrite_start = '[';
78 $rewrite_end = ']';
79
80 $rewrite = $rewrite_start . $rewrite_slug . $rewrite_withfront . $rewrite_hierarchcial . $rewrite_end;
81 }
82 } else {
83 $rewrite = disp_boolean( $taxonomy['rewrite'] );
84 }
85 $public = isset( $taxonomy['public'] ) ? disp_boolean( $taxonomy['public'] ) : 'true';
86 $publicly_queryable = isset( $taxonomy['publicly_queryable'] ) ? disp_boolean( $taxonomy['publicly_queryable'] ) : disp_boolean( $taxonomy['public'] );
87 $show_in_quick_edit = isset( $taxonomy['show_in_quick_edit'] ) ? disp_boolean( $taxonomy['show_in_quick_edit'] ) : disp_boolean( $taxonomy['show_ui'] );
88 $show_tagcloud = isset( $taxonomy['show_tagcloud'] ) ? disp_boolean( $taxonomy['show_tagcloud'] ) : disp_boolean( $taxonomy['show_ui'] );
89
90 $show_in_menu = ( ! empty( $taxonomy['show_in_menu'] ) && false !== get_disp_boolean( $taxonomy['show_in_menu'] ) ) ? 'true' : 'false';
91 if ( empty( $taxonomy['show_in_menu'] ) ) {
92 $show_in_menu = disp_boolean( $taxonomy['show_ui'] );
93 }
94
95 $show_in_nav_menus = ( ! empty( $taxonomy['show_in_nav_menus'] ) && false !== get_disp_boolean( $taxonomy['show_in_nav_menus'] ) ) ? 'true' : 'false';
96 if ( empty( $taxonomy['show_in_nav_menus'] ) ) {
97 $show_in_nav_menus = $public;
98 }
99
100 $show_in_rest = ( ! empty( $taxonomy['show_in_rest'] ) && false !== get_disp_boolean( $taxonomy['show_in_rest'] ) ) ? 'true' : 'false';
101 $rest_base = ! empty( $taxonomy['rest_base'] ) ? $taxonomy['rest_base'] : $taxonomy['name'];
102 $rest_controller_class = ! empty( $taxonomy['rest_controller_class'] ) ? $taxonomy['rest_controller_class'] : 'WP_REST_Terms_Controller';
103 $rest_namespace = ! empty( $taxonomy['rest_namespace'] ) ? $taxonomy['rest_namespace'] : 'wp/v2';
104 $sort = ( ! empty( $taxonomy['sort'] ) && false !== get_disp_boolean( $taxonomy['sort'] ) ) ? 'true' : 'false';
105
106 if ( ! empty( $taxonomy['meta_box_cb'] ) ) {
107 $meta_box_cb = ( false !== get_disp_boolean( $taxonomy['meta_box_cb'] ) ) ? '"' . $taxonomy['meta_box_cb'] . '"' : 'false';
108 }
109
110 $default_term = '';
111 if ( ! empty( $taxonomy['default_term'] ) ) {
112 $term_parts = explode( ',', $taxonomy['default_term'] );
113 $default_term_start = '[';
114 $default_term_end = ']';
115 if ( ! empty( $term_parts[0] ) ) {
116 $default_term .= "'name' => '" . trim( $term_parts[0] ) . "'";
117 }
118 if ( ! empty( $term_parts[1] ) ) {
119 $default_term .= ", 'slug' => '" . trim( $term_parts[1] ) . "'";
120 }
121 if ( ! empty( $term_parts[2] ) ) {
122 $default_term .= ", 'description' => '" . trim( $term_parts[2] ) . "'";
123 }
124
125 $default_term = $default_term_start . $default_term . $default_term_end;
126 }
127
128 $my_theme = wp_get_theme();
129 $textdomain = $my_theme->get( 'TextDomain' );
130 if ( empty( $textdomain ) ) {
131 $textdomain = 'custom-post-type-ui';
132 }
133 ?>
134
135 /**
136 * Taxonomy: <?php echo esc_html( $taxonomy['label'] ); ?>.
137 */
138
139 $labels = [
140 "name" => esc_html__( "<?php echo esc_html( $taxonomy['label'] ); ?>", "<?php echo esc_html( $textdomain ); ?>" ),
141 "singular_name" => esc_html__( "<?php echo esc_html( $taxonomy['singular_label'] ); ?>", "<?php echo esc_html( $textdomain ); ?>" ),
142 <?php
143 foreach ( $taxonomy['labels'] as $key => $label ) {
144 if ( ! empty( $label ) ) {
145 echo "\t\t" . '"' . esc_html( $key ) . '" => esc_html__( "' . esc_html( $label ) . '", "' . esc_html( $textdomain ) . '" ),' . "\n";
146 }
147 }
148 ?>
149 ];
150
151 <?php
152 $show_graphql = isset( $taxonomy['show_in_graphql'] ) ? (bool) $taxonomy['show_in_graphql'] : false;
153 ?>
154
155 $args = [
156 "label" => esc_html__( "<?php echo $taxonomy['label']; ?>", "<?php echo $textdomain; ?>" ),
157 "labels" => $labels,
158 "public" => <?php echo $public; ?>,
159 "publicly_queryable" => <?php echo $publicly_queryable; ?>,
160 "hierarchical" => <?php echo $taxonomy['hierarchical']; ?>,
161 "show_ui" => <?php echo disp_boolean( $taxonomy['show_ui'] ); ?>,
162 "show_in_menu" => <?php echo $show_in_menu; ?>,
163 "show_in_nav_menus" => <?php echo $show_in_nav_menus; ?>,
164 "query_var" => <?php echo disp_boolean( $taxonomy['query_var'] ); ?>,
165 "rewrite" => <?php echo $rewrite; ?>,
166 "show_admin_column" => <?php echo $taxonomy['show_admin_column']; ?>,
167 "show_in_rest" => <?php echo $show_in_rest; ?>,
168 "show_tagcloud" => <?php echo $show_tagcloud; ?>,
169 "rest_base" => "<?php echo $rest_base; ?>",
170 "rest_controller_class" => "<?php echo $rest_controller_class; ?>",
171 "rest_namespace" => "<?php echo $rest_namespace; ?>",
172 "show_in_quick_edit" => <?php echo $show_in_quick_edit; ?>,
173 "sort" => <?php echo $sort; ?>,
174 <?php if ( $show_graphql ) : ?>
175 "show_in_graphql" => <?php echo disp_boolean( $taxonomy['show_in_graphql'] ); ?>,
176 "graphql_single_name" => "<?php echo esc_html( $taxonomy['graphql_single_name'] ); ?>",
177 "graphql_plural_name" => "<?php echo esc_html( $taxonomy['graphql_plural_name'] ); ?>",
178 <?php else: ?>
179 "show_in_graphql" => <?php echo disp_boolean( false ); ?>,
180 <?php endif; ?>
181 <?php if ( ! empty( $meta_box_cb ) ) { ?>
182 "meta_box_cb" => <?php echo $meta_box_cb; ?>,
183 <?php } ?>
184 <?php if ( ! empty( $default_term ) ) { ?>
185 "default_term" => <?php echo $default_term; ?>,
186 <?php } ?>
187 ];
188 register_taxonomy( "<?php echo esc_html( $taxonomy['name'] ); ?>", <?php echo $post_types; ?>, $args );
189 <?php
190 }
1 <?php
2 /**
3 * Custom Post Type UI Tools.
4 *
5 * @package CPTUI
6 * @subpackage Tools
7 * @author WebDevStudios
8 * @since 1.0.0
9 * @license GPL-2.0+
10 */
11
12 // phpcs:disable WebDevStudios.All.RequireAuthor
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Enqueue our Custom Post Type UI assets.
21 *
22 * @since 1.6.0
23 *
24 * @return void
25 */
26 function cptui_tools_assets() {
27 $current_screen = get_current_screen();
28
29 if ( ! is_object( $current_screen ) || 'cpt-ui_page_cptui_tools' !== $current_screen->base ) {
30 return;
31 }
32
33 if ( wp_doing_ajax() ) {
34 return;
35 }
36
37 wp_enqueue_style( 'cptui-css' );
38 }
39 add_action( 'admin_enqueue_scripts', 'cptui_tools_assets' );
40
41 /**
42 * Register our tabs for the Tools screen.
43 *
44 * @since 1.3.0
45 * @since 1.5.0 Renamed to "Tools"
46 *
47 * @internal
48 *
49 * @param array $tabs Array of tabs to display. Optional.
50 * @param string $current_page Current page being shown. Optional. Default empty string.
51 * @return array Amended array of tabs to show.
52 */
53 function cptui_tools_tabs( $tabs = [], $current_page = '' ) {
54
55 if ( 'tools' === $current_page ) {
56 $classes = [ 'nav-tab' ];
57
58 $tabs['page_title'] = get_admin_page_title();
59 $tabs['tabs'] = [];
60 $tabs['tabs']['post_types'] = [
61 'text' => esc_html__( 'Post Types', 'custom-post-type-ui' ),
62 'classes' => $classes,
63 'url' => cptui_admin_url( 'admin.php?page=cptui_' . $current_page ),
64 'aria-selected' => 'false',
65 ];
66
67 $tabs['tabs']['taxonomies'] = [
68 'text' => esc_html__( 'Taxonomies', 'custom-post-type-ui' ),
69 'classes' => $classes,
70 'url' => esc_url( add_query_arg( [ 'action' => 'taxonomies' ], cptui_admin_url( 'admin.php?page=cptui_' . $current_page ) ) ),
71 'aria-selected' => 'false',
72 ];
73
74 $tabs['tabs']['get_code'] = [
75 'text' => esc_html__( 'Get Code', 'custom-post-type-ui' ),
76 'classes' => $classes,
77 'url' => esc_url( add_query_arg( [ 'action' => 'get_code' ], cptui_admin_url( 'admin.php?page=cptui_' . $current_page ) ) ),
78 'aria-selected' => 'false',
79 ];
80
81 $tabs['tabs']['debuginfo'] = [
82 'text' => esc_html__( 'Debug Info', 'custom-post-type-ui' ),
83 'classes' => $classes,
84 'url' => esc_url( add_query_arg( [ 'action' => 'debuginfo' ], cptui_admin_url( 'admin.php?page=cptui_' . $current_page ) ) ),
85 'aria-selected' => 'false',
86 ];
87
88 $active_class = 'nav-tab-active';
89 $action = cptui_get_current_action();
90 if ( ! empty( $action ) ) {
91 if ( 'taxonomies' === $action ) {
92 $tabs['tabs']['taxonomies']['classes'][] = $active_class;
93 $tabs['tabs']['taxonomies']['aria-selected'] = 'true';
94 } elseif ( 'get_code' === $action ) {
95 $tabs['tabs']['get_code']['classes'][] = $active_class;
96 $tabs['tabs']['get_code']['aria-selected'] = 'true';
97 } elseif ( 'debuginfo' === $action ) {
98 $tabs['tabs']['debuginfo']['classes'][] = $active_class;
99 $tabs['tabs']['debuginfo']['aria-selected'] = 'true';
100 }
101 } else {
102 $tabs['tabs']['post_types']['classes'][] = $active_class;
103 $tabs['tabs']['post_types']['aria-selected'] = 'true';
104 }
105
106 /**
107 * Filters the tabs being added for the tools area.
108 *
109 * @since 1.5.0
110 *
111 * @param array $tabs Array of tabs to show.
112 * @param string $action Current tab being shown.
113 * @param string $active_class Class to use to mark the tab active.
114 */
115 $tabs = apply_filters( 'cptui_tools_tabs', $tabs, $action, $active_class );
116 }
117
118 return $tabs;
119 }
120 add_filter( 'cptui_get_tabs', 'cptui_tools_tabs', 10, 2 );
121
122 /**
123 * Create our settings page output.
124 *
125 * @since 1.0.0
126 *
127 * @internal
128 */
129 function cptui_tools() {
130
131 $tab = 'post_types';
132 if ( ! empty( $_GET ) ) { // phpcs:ignore WordPress.Security.NonceVerification
133 if ( ! empty( $_GET['action'] ) && 'taxonomies' === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
134 $tab = 'taxonomies';
135 } elseif ( ! empty( $_GET['action'] ) && 'get_code' === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
136 $tab = 'get_code';
137 } elseif ( ! empty( $_GET['action'] ) && 'debuginfo' === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
138 $tab = 'debuginfo';
139 }
140 }
141
142 echo '<div class="wrap">';
143
144 /**
145 * Fires right inside the wrap div for the import/export pages.
146 *
147 * @since 1.3.0
148 *
149 * @deprecated 1.5.0
150 */
151 do_action_deprecated( 'cptui_inside_importexport_wrap', [], '1.5.0', 'cptui_inside_tools_wrap' );
152
153 /**
154 * Fires right inside the wrap div for the tools pages.
155 *
156 * @since 1.5.0
157 */
158 do_action( 'cptui_inside_tools_wrap' );
159
160 // Create our tabs.
161 cptui_settings_tab_menu( 'tools' );
162
163 /**
164 * Fires inside the markup for the import/export section.
165 *
166 * Allows for more modular control and adding more sections more easily.
167 *
168 * @since 1.2.0
169 *
170 * @deprecated 1.5.0
171 *
172 * @param string $tab Current tab being displayed.
173 */
174 do_action_deprecated( 'cptui_import_export_sections', [ $tab ], '1.5.0', 'cptui_tools_sections' );
175
176 /**
177 * Fires inside the markup for the tools section.
178 *
179 * Allows for more modular control and adding more sections more easily.
180 *
181 * @since 1.5.0
182 *
183 * @param string $tab Current tab being displayed.
184 */
185 do_action( 'cptui_tools_sections', $tab );
186
187 echo '</div><!-- End .wrap -->';
188 }
189
190 /**
191 * Import the posted JSON data from a separate export.
192 *
193 * @since 1.0.0
194 *
195 * @internal
196 *
197 * @param array $postdata $_POST data as json. Optional.
198 * @return mixed false on nothing to do, otherwise void.
199 */
200 function cptui_import_types_taxes_settings( $postdata = [] ) {
201 if ( ! isset( $postdata['cptui_post_import'] ) && ! isset( $postdata['cptui_tax_import'] ) && ! array_key_exists( 'delete', $postdata ) ) {
202 return false;
203 }
204
205 $doing_wp_cli = ( defined( 'WP_CLI' ) && WP_CLI );
206 if ( ! $doing_wp_cli && ! check_admin_referer( 'cptui_typetaximport_nonce_action', 'cptui_typetaximport_nonce_field' ) ) {
207 return 'nonce_fail';
208 }
209
210 $status = 'import_fail';
211 $success = false;
212
213 /**
214 * Filters the post type data to import.
215 *
216 * Allows third parties to provide their own data dump and import instead of going through our UI.
217 *
218 * @since 1.2.0
219 *
220 * @param bool $value Default to no data.
221 */
222 $third_party_post_type_data = apply_filters( 'cptui_third_party_post_type_import', false );
223
224 /**
225 * Filters the taxonomy data to import.
226 *
227 * Allows third parties to provide their own data dump and import instead of going through our UI.
228 *
229 * @since 1.2.0
230 *
231 * @param bool $value Default to no data.
232 */
233 $third_party_taxonomy_data = apply_filters( 'cptui_third_party_taxonomy_import', false );
234
235 if ( false !== $third_party_post_type_data ) {
236 $postdata['cptui_post_import'] = $third_party_post_type_data;
237 }
238
239 if ( false !== $third_party_taxonomy_data ) {
240 $postdata['cptui_tax_import'] = $third_party_taxonomy_data;
241 }
242
243 if ( ! empty( $postdata['cptui_post_import'] ) || ( isset( $postdata['delete'] ) && 'type_true' === $postdata['delete'] ) ) {
244 $settings = null;
245 if ( ! empty( $postdata['cptui_post_import'] ) ) {
246 $settings = $postdata['cptui_post_import'];
247 }
248
249 // Add support to delete settings outright, without accessing database.
250 // Doing double check to protect.
251 if ( null === $settings && ( isset( $postdata['delete'] ) && 'type_true' === $postdata['delete'] ) ) {
252
253 /**
254 * Filters whether or not 3rd party options were deleted successfully within post type import.
255 *
256 * @since 1.3.0
257 *
258 * @param bool $value Whether or not someone else deleted successfully. Default false.
259 * @param array $postdata Post type data.
260 */
261 if ( false === ( $success = apply_filters( 'cptui_post_type_import_delete_save', false, $postdata ) ) ) { // phpcs:ignore.
262 $success = delete_option( 'cptui_post_types' );
263 }
264 }
265
266 if ( $settings ) {
267 if ( false !== cptui_get_post_type_data() ) {
268 /** This filter is documented in /inc/import-export.php */
269 if ( false === ( $success = apply_filters( 'cptui_post_type_import_delete_save', false, $postdata ) ) ) { // phpcs:ignore.
270 delete_option( 'cptui_post_types' );
271 }
272 }
273
274 /**
275 * Filters whether or not 3rd party options were updated successfully within the post type import.
276 *
277 * @since 1.3.0
278 *
279 * @param bool $value Whether or not someone else updated successfully. Default false.
280 * @param array $postdata Post type data.
281 */
282 if ( false === ( $success = apply_filters( 'cptui_post_type_import_update_save', false, $postdata ) ) ) { // phpcs:ignore.
283 $success = update_option( 'cptui_post_types', $settings );
284 }
285 }
286 // Used to help flush rewrite rules on init.
287 set_transient( 'cptui_flush_rewrite_rules', 'true', 5 * 60 );
288
289 if ( $success ) {
290 $status = 'import_success';
291 }
292 } elseif ( ! empty( $postdata['cptui_tax_import'] ) || ( isset( $postdata['delete'] ) && 'tax_true' === $postdata['delete'] ) ) {
293 $settings = null;
294
295 if ( ! empty( $postdata['cptui_tax_import'] ) ) {
296 $settings = $postdata['cptui_tax_import'];
297 }
298 // Add support to delete settings outright, without accessing database.
299 // Doing double check to protect.
300 if ( null === $settings && ( isset( $postdata['delete'] ) && 'tax_true' === $postdata['delete'] ) ) {
301
302 /**
303 * Filters whether or not 3rd party options were deleted successfully within taxonomy import.
304 *
305 * @since 1.3.0
306 *
307 * @param bool $value Whether or not someone else deleted successfully. Default false.
308 * @param array $postdata Taxonomy data
309 */
310 if ( false === ( $success = apply_filters( 'cptui_taxonomy_import_delete_save', false, $postdata ) ) ) { // phpcs:ignore.
311 $success = delete_option( 'cptui_taxonomies' );
312 }
313 }
314
315 if ( $settings ) {
316 if ( false !== cptui_get_taxonomy_data() ) {
317 /** This filter is documented in /inc/import-export.php */
318 if ( false === ( $success = apply_filters( 'cptui_taxonomy_import_delete_save', false, $postdata ) ) ) { // phpcs:ignore.
319 delete_option( 'cptui_taxonomies' );
320 }
321 }
322 /**
323 * Filters whether or not 3rd party options were updated successfully within the taxonomy import.
324 *
325 * @since 1.3.0
326 *
327 * @param bool $value Whether or not someone else updated successfully. Default false.
328 * @param array $postdata Taxonomy data.
329 */
330 if ( false === ( $success = apply_filters( 'cptui_taxonomy_import_update_save', false, $postdata ) ) ) { // phpcs:ignore.
331 $success = update_option( 'cptui_taxonomies', $settings );
332 }
333 }
334 // Used to help flush rewrite rules on init.
335 set_transient( 'cptui_flush_rewrite_rules', 'true', 5 * 60 );
336 if ( $success ) {
337 $status = 'import_success';
338 }
339 }
340
341 return $status;
342 }
343
344 /**
345 * Content for the Post Types/Taxonomies Tools tab.
346 *
347 * @since 1.2.0
348 *
349 * @internal
350 */
351 function cptui_render_posttypes_taxonomies_section() {
352 ?>
353
354 <p><?php esc_html_e( 'If you are wanting to migrate registered post types or taxonomies from this site to another, that will also use Custom Post Type UI, use the import and export functionality. If you are moving away from Custom Post Type UI, use the information in the "Get Code" tab.', 'custom-post-type-ui' ); ?></p>
355
356 <p>
357 <?php
358 printf(
359 '<strong>%s</strong>: %s',
360 esc_html__( 'NOTE', 'custom-post-type-ui' ),
361 esc_html__( 'This will not export the associated posts or taxonomy terms, just the settings.', 'custom-post-type-ui' )
362 );
363 ?>
364 </p>
365 <table class="form-table cptui-table">
366 <?php if ( ! empty( $_GET ) && empty( $_GET['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification ?>
367 <tr>
368 <td class="outer">
369 <h2><label for="cptui_post_import"><?php esc_html_e( 'Import Post Types', 'custom-post-type-ui' ); ?></label></h2>
370
371 <form method="post">
372 <textarea class="cptui_post_import" placeholder="<?php esc_attr_e( 'Paste content here.', 'custom-post-type-ui' ); ?>" id="cptui_post_import" name="cptui_post_import"></textarea>
373
374 <p class="wp-ui-highlight">
375 <strong><?php esc_html_e( 'Note:', 'custom-post-type-ui' ); ?></strong> <?php esc_html_e( 'Importing will overwrite previous registered settings.', 'custom-post-type-ui' ); ?>
376 </p>
377
378 <p>
379 <strong><?php esc_html_e( 'To import post types from a different WordPress site, paste the exported content from that site and click the "Import" button.', 'custom-post-type-ui' ); ?></strong>
380 </p>
381
382 <p>
383 <input class="button button-primary" type="submit" value="<?php esc_attr_e( 'Import', 'custom-post-type-ui' ); ?>" />
384 </p>
385 <?php wp_nonce_field( 'cptui_typetaximport_nonce_action', 'cptui_typetaximport_nonce_field' ); ?>
386 </form>
387 </td>
388 <td class="outer">
389 <h2><label for="cptui_post_export"><?php esc_html_e( 'Export Post Types settings', 'custom-post-type-ui' ); ?></label></h2>
390 <?php
391 $cptui_post_types = cptui_get_post_type_data();
392 if ( ! empty( $cptui_post_types ) ) {
393 foreach ( $cptui_post_types as $type => $values ) {
394 $cptui_post_types[ $type ]['description'] = wp_slash( html_entity_decode( $values['description'] ) );
395 }
396 $content = wp_json_encode( $cptui_post_types );
397 } else {
398 $content = esc_html__( 'No post types registered yet.', 'custom-post-type-ui' );
399 }
400 ?>
401 <textarea title="<?php esc_attr_e( 'To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac).', 'custom-post-type-ui' ); ?>" onclick="this.focus();this.select();" onfocus="this.focus();this.select();" readonly="readonly" aria-readonly="true" class="cptui_post_import" id="cptui_post_export" name="cptui_post_export"><?php echo $content; // phpcs:ignore. ?></textarea>
402
403 <p>
404 <strong><?php esc_html_e( 'Use the content above to import current post types into a different WordPress site. You can also use this to simply back up your post type settings.', 'custom-post-type-ui' ); ?></strong>
405 </p>
406 </td>
407 </tr>
408 <?php } elseif ( ! empty( $_GET ) && 'taxonomies' === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification ?>
409 <tr>
410 <td class="outer">
411 <h2><label for="cptui_tax_import"><?php esc_html_e( 'Import Taxonomies', 'custom-post-type-ui' ); ?></label></h2>
412
413 <form method="post">
414 <textarea class="cptui_tax_import" placeholder="<?php esc_attr_e( 'Paste content here.', 'custom-post-type-ui' ); ?>" id="cptui_tax_import" name="cptui_tax_import"></textarea>
415
416 <p class="wp-ui-highlight">
417 <strong><?php esc_html_e( 'Note:', 'custom-post-type-ui' ); ?></strong> <?php esc_html_e( 'Importing will overwrite previous registered settings.', 'custom-post-type-ui' ); ?>
418 </p>
419
420 <p>
421 <strong><?php esc_html_e( 'To import taxonomies from a different WordPress site, paste the exported content from that site and click the "Import" button.', 'custom-post-type-ui' ); ?></strong>
422 </p>
423
424 <p>
425 <input class="button button-primary" type="submit" value="<?php esc_attr_e( 'Import', 'custom-post-type-ui' ); ?>" />
426 </p>
427 <?php wp_nonce_field( 'cptui_typetaximport_nonce_action', 'cptui_typetaximport_nonce_field' ); ?>
428 </form>
429 </td>
430 <td class="outer">
431 <h2><label for="cptui_tax_export"><?php esc_html_e( 'Export Taxonomies settings', 'custom-post-type-ui' ); ?></label></h2>
432 <?php
433 $cptui_taxonomies = cptui_get_taxonomy_data();
434 if ( ! empty( $cptui_taxonomies ) ) {
435 foreach ( $cptui_taxonomies as $tax => $values ) {
436 $cptui_taxonomies[ $tax ]['description'] = wp_slash( html_entity_decode( $values['description'] ) );
437 }
438 $content = wp_json_encode( $cptui_taxonomies );
439 } else {
440 $content = esc_html__( 'No taxonomies registered yet.', 'custom-post-type-ui' );
441 }
442 ?>
443 <textarea title="<?php esc_attr_e( 'To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac).', 'custom-post-type-ui' ); ?>" onclick="this.focus();this.select()" onfocus="this.focus();this.select();" readonly="readonly" aria-readonly="true" class="cptui_tax_import" id="cptui_tax_export" name="cptui_tax_export"><?php echo $content; // phpcs:ignore WordPress.Security.EscapeOutput ?></textarea>
444
445 <p>
446 <strong><?php esc_html_e( 'Use the content above to import current taxonomies into a different WordPress site. You can also use this to simply back up your taxonomy settings.', 'custom-post-type-ui' ); ?></strong>
447 </p>
448 </td>
449 </tr>
450 <?php } ?>
451 </table>
452 <?php
453 }
454
455 /**
456 * Renders various tab sections for the Tools page, based on current tab.
457 *
458 * @since 1.2.0
459 *
460 * @internal
461 *
462 * @param string $tab Current tab to display.
463 */
464 function cptui_render_tools( $tab ) {
465 if ( 'post_types' === $tab || 'taxonomies' === $tab ) {
466 cptui_render_posttypes_taxonomies_section();
467 }
468
469 if ( 'get_code' === $tab ) {
470 cptui_render_getcode_section();
471 }
472
473 if ( 'debuginfo' === $tab ) {
474 cptui_render_debuginfo_section();
475 }
476 }
477 add_action( 'cptui_tools_sections', 'cptui_render_tools' );
478
479 /**
480 * Handle the import of transferred post types and taxonomies.
481 *
482 * @since 1.5.0
483 */
484 function cptui_do_import_types_taxes() {
485 // phpcs:ignore.
486 if ( ! empty( $_POST ) && // phpcs:ignore WordPress.Security.NonceVerification
487 ( ! empty( $_POST['cptui_post_import'] ) && isset( $_POST['cptui_post_import'] ) ) || // phpcs:ignore WordPress.Security.NonceVerification
488 ( ! empty( $_POST['cptui_tax_import'] ) && isset( $_POST['cptui_tax_import'] ) ) // phpcs:ignore WordPress.Security.NonceVerification
489 ) {
490 $data = [];
491 $decoded_post_data = null;
492 $decoded_tax_data = null;
493 if ( ! empty( $_POST['cptui_post_import'] ) ) { // phpcs:ignore.
494 $decoded_post_data = json_decode( stripslashes_deep( trim( $_POST['cptui_post_import'] ) ), true ); // phpcs:ignore.
495 }
496
497 if ( ! empty( $_POST['cptui_tax_import'] ) ) { // phpcs:ignore.
498 $decoded_tax_data = json_decode( stripslashes_deep( trim( $_POST['cptui_tax_import'] ) ), true ); // phpcs:ignore.
499 }
500
501 if (
502 empty( $decoded_post_data ) &&
503 empty( $decoded_tax_data ) &&
504 (
505 ! empty( $_POST['cptui_post_import'] ) && '{""}' !== stripslashes_deep( trim( $_POST['cptui_post_import'] ) ) // phpcs:ignore.
506 ) &&
507 (
508 ! empty( $_POST['cptui_tax_import'] ) && '{""}' !== stripslashes_deep( trim( $_POST['cptui_tax_import'] ) ) // phpcs:ignore.
509 )
510 ) {
511 return;
512 }
513 if ( null !== $decoded_post_data ) {
514 $data['cptui_post_import'] = $decoded_post_data;
515 }
516 if ( null !== $decoded_tax_data ) {
517 $data['cptui_tax_import'] = $decoded_tax_data;
518 }
519 if ( ! empty( $_POST['cptui_post_import'] ) && '{""}' === stripslashes_deep( trim( $_POST['cptui_post_import'] ) ) ) { // phpcs:ignore.
520 $data['delete'] = 'type_true';
521 }
522 if ( ! empty( $_POST['cptui_tax_import'] ) && '{""}' === stripslashes_deep( trim( $_POST['cptui_tax_import'] ) ) ) { // phpcs:ignore.
523 $data['delete'] = 'tax_true';
524 }
525 $success = cptui_import_types_taxes_settings( $data );
526 add_action( 'admin_notices', "cptui_{$success}_admin_notice" );
527 }
528 }
529 add_action( 'init', 'cptui_do_import_types_taxes', 8 );
1 <?php
2 /**
3 * Custom Post Type UI Utility Code.
4 *
5 * @package CPTUI
6 * @subpackage Utility
7 * @author WebDevStudios
8 * @since 1.3.0
9 * @license GPL-2.0+
10 */
11
12 // phpcs:disable WebDevStudios.All.RequireAuthor
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Edit links that appear on installed plugins list page, for our plugin.
21 *
22 * @since 1.0.0
23 *
24 * @internal
25 *
26 * @param array $links Array of links to display below our plugin listing.
27 * @return array Amended array of links.
28 */
29 function cptui_edit_plugin_list_links( $links ) {
30
31 if ( is_array( $links ) && isset( $links['edit'] ) ) {
32 // We shouldn't encourage editing our plugin directly.
33 unset( $links['edit'] );
34 }
35
36 // Add our custom links to the returned array value.
37 return array_merge(
38 array(
39 '<a href="' . admin_url( 'admin.php?page=cptui_main_menu' ) . '">' . esc_html__( 'About', 'custom-post-type-ui' ) . '</a>',
40 '<a href="' . admin_url( 'admin.php?page=cptui_support' ) . '">' . esc_html__( 'Help', 'custom-post-type-ui' ) . '</a>',
41 ),
42 $links
43 );
44 }
45 add_filter( 'plugin_action_links_' . plugin_basename( dirname( __DIR__ ) ) . '/custom-post-type-ui.php', 'cptui_edit_plugin_list_links' );
46
47 /**
48 * Returns SVG icon for custom menu icon
49 *
50 * @since 1.2.0
51 *
52 * @return string
53 */
54 function cptui_menu_icon() {
55 return 'dashicons-forms';
56 }
57
58 /**
59 * Return boolean status depending on passed in value.
60 *
61 * @since 0.5.0
62 *
63 * @param mixed $bool_text text to compare to typical boolean values.
64 * @return bool Which bool value the passed in value was.
65 */
66 function get_disp_boolean( $bool_text ) {
67 $bool_text = (string) $bool_text;
68 if ( empty( $bool_text ) || '0' === $bool_text || 'false' === $bool_text ) {
69 return false;
70 }
71
72 return true;
73 }
74
75 /**
76 * Return string versions of boolean values.
77 *
78 * @since 0.1.0
79 *
80 * @param string $bool_text String boolean value.
81 * @return string standardized boolean text.
82 */
83 function disp_boolean( $bool_text ) {
84 $bool_text = (string) $bool_text;
85 if ( empty( $bool_text ) || '0' === $bool_text || 'false' === $bool_text ) {
86 return 'false';
87 }
88
89 return 'true';
90 }
91
92 /**
93 * Display footer links and plugin credits.
94 *
95 * @since 0.3.0
96 *
97 * @internal
98 *
99 * @param string $original Original footer content. Optional. Default empty string.
100 * @return string $value HTML for footer.
101 */
102 function cptui_footer( $original = '' ) {
103
104 $screen = get_current_screen();
105
106 if ( ! is_object( $screen ) || 'cptui_main_menu' !== $screen->parent_base ) {
107 return $original;
108 }
109
110 return sprintf(
111 // translators: Placeholder will hold the name of the plugin, version of the plugin and a link to WebdevStudios.
112 esc_attr__( '%1$s version %2$s by %3$s', 'custom-post-type-ui' ),
113 esc_attr__( 'Custom Post Type UI', 'custom-post-type-ui' ),
114 CPTUI_VERSION,
115 '<a href="https://webdevstudios.com" target="_blank" rel="noopener">WebDevStudios</a>'
116 ) . ' - ' .
117 sprintf(
118 // translators: Placeholders are just for HTML markup that doesn't need translated.
119 '<a href="http://wordpress.org/support/plugin/custom-post-type-ui" target="_blank" rel="noopener">%s</a>',
120 esc_attr__( 'Support forums', 'custom-post-type-ui' )
121 ) . ' - ' .
122 sprintf(
123 // translators: Placeholders are just for HTML markup that doesn't need translated.
124 '<a href="https://wordpress.org/plugins/custom-post-type-ui/reviews/" target="_blank" rel="noopener">%s</a>',
125 sprintf(
126 // translators: Placeholder will hold `<abbr>` tag for CPTUI.
127 esc_attr__( 'Review %s', 'custom-post-type-ui' ),
128 sprintf(
129 // translators: Placeholders are just for HTML markup that doesn't need translated.
130 '<abbr title="%s">%s</abbr>',
131 esc_attr__( 'Custom Post Type UI', 'custom-post-type-ui' ),
132 'CPTUI'
133 )
134 )
135 ) . ' - ' .
136 esc_attr__( 'Follow on Twitter:', 'custom-post-type-ui' ) .
137 sprintf(
138 // translators: Placeholders are just for HTML markup that doesn't need translated.
139 ' %s',
140 '<a href="https://twitter.com/webdevstudios" target="_blank" rel="noopener">WebDevStudios</a>'
141 );
142 }
143 add_filter( 'admin_footer_text', 'cptui_footer' );
144
145 /**
146 * Conditionally flushes rewrite rules if we have reason to.
147 *
148 * @since 1.3.0
149 */
150 function cptui_flush_rewrite_rules() {
151
152 if ( wp_doing_ajax() ) {
153 return;
154 }
155
156 /*
157 * Wise men say that you should not do flush_rewrite_rules on init or admin_init. Due to the nature of our plugin
158 * and how new post types or taxonomies can suddenly be introduced, we need to...potentially. For this,
159 * we rely on a short lived transient. Only 5 minutes life span. If it exists, we do a soft flush before
160 * deleting the transient to prevent subsequent flushes. The only times the transient gets created, is if
161 * post types or taxonomies are created, updated, deleted, or imported. Any other time and this condition
162 * should not be met.
163 */
164 $flush_it = get_transient( 'cptui_flush_rewrite_rules' );
165 if ( 'true' === $flush_it ) {
166 flush_rewrite_rules( false );
167 // So we only run this once.
168 delete_transient( 'cptui_flush_rewrite_rules' );
169 }
170 }
171 add_action( 'admin_init', 'cptui_flush_rewrite_rules' );
172
173 /**
174 * Return the current action being done within CPTUI context.
175 *
176 * @since 1.3.0
177 *
178 * @return string Current action being done by CPTUI
179 */
180 function cptui_get_current_action() {
181 $current_action = '';
182 if ( ! empty( $_GET ) && isset( $_GET['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
183 $current_action .= esc_textarea( wp_unslash( $_GET['action'] ) ); // phpcs:ignore
184 }
185
186 return $current_action;
187 }
188
189 /**
190 * Return an array of all post type slugs from Custom Post Type UI.
191 *
192 * @since 1.3.0
193 *
194 * @return array CPTUI post type slugs.
195 */
196 function cptui_get_post_type_slugs() {
197 $post_types = get_option( 'cptui_post_types' );
198 if ( ! empty( $post_types ) ) {
199 return array_keys( $post_types );
200 }
201 return [];
202 }
203
204 /**
205 * Return an array of all taxonomy slugs from Custom Post Type UI.
206 *
207 * @since 1.3.0
208 *
209 * @return array CPTUI taxonomy slugs.
210 */
211 function cptui_get_taxonomy_slugs() {
212 $taxonomies = get_option( 'cptui_taxonomies' );
213 if ( ! empty( $taxonomies ) ) {
214 return array_keys( $taxonomies );
215 }
216 return [];
217 }
218
219 /**
220 * Return the appropriate admin URL depending on our context.
221 *
222 * @since 1.3.0
223 *
224 * @param string $path URL path.
225 * @return string
226 */
227 function cptui_admin_url( $path ) {
228 if ( is_multisite() && is_network_admin() ) {
229 return network_admin_url( $path );
230 }
231
232 return admin_url( $path );
233 }
234
235 /**
236 * Construct action tag for `<form>` tag.
237 *
238 * @since 1.3.0
239 *
240 * @param object|string $ui CPTUI Admin UI instance. Optional. Default empty string.
241 * @return string
242 */
243 function cptui_get_post_form_action( $ui = '' ) {
244 /**
245 * Filters the string to be used in an `action=""` attribute.
246 *
247 * @since 1.3.0
248 */
249 return apply_filters( 'cptui_post_form_action', '', $ui );
250 }
251
252 /**
253 * Display action tag for `<form>` tag.
254 *
255 * @since 1.3.0
256 *
257 * @param object $ui CPTUI Admin UI instance.
258 */
259 function cptui_post_form_action( $ui ) {
260 echo esc_attr( cptui_get_post_form_action( $ui ) );
261 }
262
263 /**
264 * Fetch our CPTUI post types option.
265 *
266 * @since 1.3.0
267 *
268 * @return mixed
269 */
270 function cptui_get_post_type_data() {
271 return apply_filters( 'cptui_get_post_type_data', get_option( 'cptui_post_types', [] ), get_current_blog_id() );
272 }
273
274 /**
275 * Fetch our CPTUI taxonomies option.
276 *
277 * @since 1.3.0
278 *
279 * @return mixed
280 */
281 function cptui_get_taxonomy_data() {
282 return apply_filters( 'cptui_get_taxonomy_data', get_option( 'cptui_taxonomies', [] ), get_current_blog_id() );
283 }
284
285 /**
286 * Checks if a post type is already registered.
287 *
288 * @since 1.3.0
289 *
290 * @param string $slug Post type slug to check. Optional. Default empty string.
291 * @param array|string $data Post type data being utilized. Optional.
292 * @return mixed
293 */
294 function cptui_get_post_type_exists( $slug = '', $data = [] ) {
295
296 /**
297 * Filters the boolean value for if a post type exists for 3rd parties.
298 *
299 * @since 1.3.0
300 *
301 * @param string $slug Post type slug to check.
302 * @param array|string $data Post type data being utilized.
303 */
304 return apply_filters( 'cptui_get_post_type_exists', post_type_exists( $slug ), $data );
305 }
306
307 /**
308 * Checks if a taxonomy is already registered.
309 *
310 * @since 1.6.0
311 *
312 * @param string $slug Taxonomy slug to check. Optional. Default empty string.
313 * @param array|string $data Taxonomy data being utilized. Optional.
314 *
315 * @return mixed
316 */
317 function cptui_get_taxonomy_exists( $slug = '', $data = [] ) {
318
319 /**
320 * Filters the boolean value for if a taxonomy exists for 3rd parties.
321 *
322 * @since 1.6.0
323 *
324 * @param string $slug Taxonomy slug to check.
325 * @param array|string $data Taxonomy data being utilized.
326 */
327 return apply_filters( 'cptui_get_taxonomy_exists', taxonomy_exists( $slug ), $data );
328 }
329
330 /**
331 * Displays WebDevStudios products in a sidebar on the add/edit screens for post types and taxonomies.
332 *
333 * We hope you don't mind.
334 *
335 * @since 1.3.0
336 *
337 * @internal
338 */
339 function cptui_products_sidebar() {
340
341 echo '<div class="wdspromos">';
342
343 cptui_newsletter_form();
344
345 $ads = cptui_get_ads();
346 if ( ! empty( $ads ) ) {
347 foreach ( $ads as $ad ) {
348 $the_ad = sprintf(
349 '<img src="%s" alt="%s">',
350 esc_attr( $ad['image'] ),
351 esc_attr( $ad['text'] )
352 );
353
354 // Escaping $the_ad breaks the html.
355 printf(
356 '<p><a href="%s">%s</a></p>',
357 esc_url( $ad['url'] ),
358 $the_ad // phpcs:ignore WordPress.Security.EscapeOutput
359 );
360 }
361 printf(
362 '<p><a href="%s">%s</a></p>',
363 'https://pluginize.com/plugins/custom-post-type-ui-extended/ref/pluginizeaff/?campaign=cptui-sidebar-remove',
364 esc_html__( 'Remove these ads?', 'custom-post-type-ui' )
365 );
366 }
367 echo '</div>';
368
369 }
370 add_action( 'cptui_below_post_type_tab_menu', 'cptui_products_sidebar' );
371 add_action( 'cptui_below_taxonomy_tab_menu', 'cptui_products_sidebar' );
372
373 /**
374 * Outputs our newsletter signup form.
375 *
376 * @since 1.3.4
377 * @internal
378 */
379 function cptui_newsletter_form() {
380 ?>
381
382 <div class="email-octopus-form-wrapper">
383 <?php
384 echo sprintf(
385 /* translators: Placeholders are just for HTML markup that doesn't need translated */
386 '<p><strong>%s</strong></p>',
387 esc_html__( 'Get email updates from pluginize.com about Custom Post Type UI', 'custom-post-type-ui' )
388 );
389 ?>
390 <p class="email-octopus-success-message"></p>
391 <p class="email-octopus-error-message"></p>
392
393 <form method="post" action="https://emailoctopus.com/lists/2039e001-4775-11ea-be00-06b4694bee2a/members/embedded/1.3/add" class="email-octopus-form" data-sitekey="6LdYsmsUAAAAAPXVTt-ovRsPIJ_IVhvYBBhGvRV6">
394 <div class="email-octopus-form-row">
395
396 <?php
397 echo sprintf(
398 /* translators: Placeholders are just for HTML markup that doesn't need translated */
399 '<label for="field_0">%s</label>',
400 esc_html__( 'Email address', 'custom-post-type-ui' )
401 );
402 ?>
403 <input id="field_0" name="field_0" type="email" placeholder="email@domain.com" style="max-width:100%;">
404 </div>
405
406 <div class="email-octopus-form-row-hp" aria-hidden="true">
407 <!-- Do not remove this field, otherwise you risk bot sign-ups -->
408 <input type="text" name="hp2039e001-4775-11ea-be00-06b4694bee2a" tabindex="-1" autocomplete="nope">
409 </div>
410
411 <div class="email-octopus-form-row-subscribe">
412 <input type="hidden" name="successRedirectUrl" value="">
413 <?php
414 echo sprintf(
415 /* translators: Placeholders are just for HTML markup that doesn't need translated */
416 '<button type="submit" class="button button-secondary">%s</button>',
417 esc_html__( 'Subscribe', 'custom-post-type-ui' )
418 );
419 ?>
420
421 </div>
422 </form>
423 </div>
424
425 <?php
426 }
427
428 /**
429 * Add our Email Octopus scripts and stylesheet.
430 *
431 * @author Scott Anderson <scott.anderson@webdevstudios.com>
432 * @since NEXT
433 */
434 function enqueue_email_octopus_assets() {
435
436 $current_screen = get_current_screen();
437
438 if ( ! is_object( $current_screen ) ) {
439 return;
440 }
441
442 $screens = [
443 'toplevel_page_cptui_main_menu',
444 'cpt-ui_page_cptui_manage_post_types',
445 'cpt-ui_page_cptui_manage_taxonomies',
446 ];
447
448 if ( ! in_array( $current_screen->base, $screens, true ) ) {
449 return;
450 }
451
452 if ( ! has_action( 'cptui_below_post_type_tab_menu' ) || ! has_action( 'cptui_below_taxonomy_tab_menu' ) ) {
453 return;
454 }
455
456 wp_enqueue_style( 'cptui-emailoctopus', 'https://emailoctopus.com/bundles/emailoctopuslist/css/formEmbed.css' ); // phpcs:ignore
457
458 wp_enqueue_script( 'cptui-emailoctopus-js', 'https://emailoctopus.com/bundles/emailoctopuslist/js/1.4/formEmbed.js', [ 'jquery' ], '', true ); // phpcs:ignore
459
460 }
461 add_action( 'admin_enqueue_scripts', 'enqueue_email_octopus_assets' );
462
463 /**
464 * Fetch all set ads to be displayed.
465 *
466 * @since 1.3.4
467 *
468 * @return array
469 */
470 function cptui_get_ads() {
471
472 /**
473 * Filters the array of ads to iterate over.
474 *
475 * Each index in the ads array should have a url index with the url to link to,
476 * an image index specifying an image location to load from, and a text index used
477 * for alt attribute text.
478 *
479 * @since 1.3.4
480 *
481 * @param array $value Array of ads to iterate over. Default empty.
482 */
483 return (array) apply_filters( 'cptui_ads', [] );
484 }
485
486 /**
487 * Add our default ads to the ads filter.
488 *
489 * @since 1.3.4
490 *
491 * @internal
492 *
493 * @param array $ads Array of ads set so far. Optional.
494 * @return array $ads Array of newly constructed ads.
495 */
496 function cptui_default_ads( $ads = [] ) {
497 $ads[] = [
498 'url' => 'https://pluginize.com/plugins/custom-post-type-ui-extended/?utm_source=cptui-sidebar&utm_medium=text&utm_campaign=cptui',
499 'image' => plugin_dir_url( __DIR__ ) . 'images/wds_ads/cptui-extended.png',
500 'text' => 'Custom Post Type UI Extended product ad',
501 ];
502
503 $ads[] = [
504 'url' => 'https://pluginize.com/plugins/instago/?utm_source=cptui-sidebar&utm_medium=text&utm_campaign=instago',
505 'image' => plugin_dir_url( __DIR__ ) . 'images/wds_ads/instago.png',
506 'text' => 'InstaGo product ad',
507 ];
508
509 $ads[] = [
510 'url' => 'https://pluginize.com/plugins/buddypages/?utm_source=cptui-sidebar&utm_medium=text&utm_campaign=buddypages',
511 'image' => plugin_dir_url( __DIR__ ) . 'images/wds_ads/buddypages.png',
512 'text' => 'BuddyPages product ad',
513 ];
514
515 $ads[] = [
516 'url' => 'https://pluginize.com/plugins/wp-search-with-algolia-pro/?utm_source=cptui-sidebar&utm_medium=text&utm_campaign=wp-search-with-algolia-pro',
517 'image' => plugin_dir_url( __DIR__ ) . 'images/wds_ads/wp-search-with-algolia-pro.png',
518 'text' => 'WP Search with Algolia Pro product ad',
519 ];
520
521 return $ads;
522 }
523 add_filter( 'cptui_ads', 'cptui_default_ads' );
524
525 /**
526 * Randomize our array order.
527 * Preserves CPTUI-Extended as the first index. Self promotion, yo.
528 *
529 * @since 1.3.0
530 *
531 * @param array $ads Array of ads to show.
532 * @return array
533 */
534 function cptui_randomize_ads( $ads = [] ) {
535 $new_order = [];
536 foreach ( $ads as $key => $ad ) {
537 if ( false !== strpos( $ad['url'], 'custom-post-type-ui-extended' ) ) {
538 $new_order[] = $ad;
539 unset( $ads[ $key ] );
540 }
541 }
542 shuffle( $ads );
543
544 return array_merge( $new_order, $ads );
545 }
546 add_filter( 'cptui_ads', 'cptui_randomize_ads', 11 );
547
548 /**
549 * Secondary admin notices function for use with admin_notices hook.
550 *
551 * Constructs admin notice HTML.
552 *
553 * @since 1.4.0
554 *
555 * @param string $message Message to use in admin notice. Optional. Default empty string.
556 * @param bool $success Whether or not a success. Optional. Default true.
557 * @return mixed
558 */
559 function cptui_admin_notices_helper( $message = '', $success = true ) {
560
561 $class = [];
562 $class[] = $success ? 'updated' : 'error';
563 $class[] = 'notice is-dismissible';
564
565 $messagewrapstart = '<div id="message" class="' . implode( ' ', $class ) . '"><p>';
566
567 $messagewrapend = '</p></div>';
568
569 $action = '';
570
571 /**
572 * Filters the custom admin notice for CPTUI.
573 *
574 * @since 1.0.0
575 *
576 * @param string $value Complete HTML output for notice.
577 * @param string $action Action whose message is being generated.
578 * @param string $message The message to be displayed.
579 * @param string $messagewrapstart Beginning wrap HTML.
580 * @param string $messagewrapend Ending wrap HTML.
581 */
582 return apply_filters( 'cptui_admin_notice', $messagewrapstart . $message . $messagewrapend, $action, $message, $messagewrapstart, $messagewrapend );
583 }
584
585 /**
586 * Grab post type or taxonomy slug from $_POST global, if available.
587 *
588 * @since 1.4.0
589 *
590 * @internal
591 *
592 * @return string
593 */
594 function cptui_get_object_from_post_global() {
595 if ( isset( $_POST['cpt_custom_post_type']['name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
596 $type_item = filter_input( INPUT_POST, 'cpt_custom_post_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
597 if ( $type_item ) {
598 return sanitize_text_field( $type_item['name'] );
599 }
600 }
601
602 if ( isset( $_POST['cpt_custom_tax']['name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
603 $tax_item = filter_input( INPUT_POST, 'cpt_custom_tax', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
604 if ( $tax_item ) {
605 return sanitize_text_field( $tax_item['name'] );
606 }
607 }
608
609 return esc_html__( 'Object', 'custom-post-type-ui' );
610 }
611
612 /**
613 * Successful add callback.
614 *
615 * @since 1.4.0
616 */
617 function cptui_add_success_admin_notice() {
618 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
619 sprintf(
620 /* translators: Placeholders are just for HTML markup that doesn't need translated */
621 esc_html__( '%s has been successfully added', 'custom-post-type-ui' ),
622 cptui_get_object_from_post_global()
623 )
624 );
625 }
626
627 /**
628 * Fail to add callback.
629 *
630 * @since 1.4.0
631 */
632 function cptui_add_fail_admin_notice() {
633 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
634 sprintf(
635 /* translators: Placeholders are just for HTML markup that doesn't need translated */
636 esc_html__( '%s has failed to be added', 'custom-post-type-ui' ),
637 cptui_get_object_from_post_global()
638 ),
639 false
640 );
641 }
642
643 /**
644 * Successful update callback.
645 *
646 * @since 1.4.0
647 */
648 function cptui_update_success_admin_notice() {
649 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
650 sprintf(
651 /* translators: Placeholders are just for HTML markup that doesn't need translated */
652 esc_html__( '%s has been successfully updated', 'custom-post-type-ui' ),
653 cptui_get_object_from_post_global()
654 )
655 );
656 }
657
658 /**
659 * Fail to update callback.
660 *
661 * @since 1.4.0
662 */
663 function cptui_update_fail_admin_notice() {
664 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
665 sprintf(
666 /* translators: Placeholders are just for HTML markup that doesn't need translated */
667 esc_html__( '%s has failed to be updated', 'custom-post-type-ui' ),
668 cptui_get_object_from_post_global()
669 ),
670 false
671 );
672 }
673
674 /**
675 * Successful delete callback.
676 *
677 * @since 1.4.0
678 */
679 function cptui_delete_success_admin_notice() {
680 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
681 sprintf(
682 /* translators: Placeholders are just for HTML markup that doesn't need translated */
683 esc_html__( '%s has been successfully deleted', 'custom-post-type-ui' ),
684 cptui_get_object_from_post_global()
685 )
686 );
687 }
688
689 /**
690 * Fail to delete callback.
691 *
692 * @since 1.4.0
693 */
694 function cptui_delete_fail_admin_notice() {
695 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
696 sprintf(
697 /* translators: Placeholders are just for HTML markup that doesn't need translated */
698 esc_html__( '%s has failed to be deleted', 'custom-post-type-ui' ),
699 cptui_get_object_from_post_global()
700 ),
701 false
702 );
703 }
704
705 /**
706 * Success to import callback.
707 *
708 * @since 1.5.0
709 */
710 function cptui_import_success_admin_notice() {
711 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
712 esc_html__( 'Successfully imported data.', 'custom-post-type-ui' )
713 );
714 }
715
716 /**
717 * Failure to import callback.
718 *
719 * @since 1.5.0
720 */
721 function cptui_import_fail_admin_notice() {
722 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
723 esc_html__( 'Invalid data provided', 'custom-post-type-ui' ),
724 false
725 );
726 }
727
728 /**
729 * Failure to verify nonce, callback
730 *
731 * @since 1.7.4
732 */
733 function cptui_nonce_fail_admin_notice() {
734 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
735 esc_html__( 'Nonce failed verification', 'custom-post-type-ui' ),
736 false
737 );
738 }
739
740 /**
741 * Returns error message for if trying to register existing post type.
742 *
743 * @since 1.4.0
744 *
745 * @return string
746 */
747 function cptui_slug_matches_post_type() {
748 return sprintf(
749 /* translators: Placeholders are just for HTML markup that doesn't need translated */
750 esc_html__( 'Please choose a different post type name. %s is already registered.', 'custom-post-type-ui' ),
751 cptui_get_object_from_post_global()
752 );
753 }
754
755 /**
756 * Returns error message for if trying to register existing taxonomy.
757 *
758 * @since 1.4.0
759 *
760 * @return string
761 */
762 function cptui_slug_matches_taxonomy() {
763 return sprintf(
764 /* translators: Placeholders are just for HTML markup that doesn't need translated */
765 esc_html__( 'Please choose a different taxonomy name. %s is already registered.', 'custom-post-type-ui' ),
766 cptui_get_object_from_post_global()
767 );
768 }
769
770 /**
771 * Returns error message for if not providing a post type to associate taxonomy to.
772 *
773 * @since 1.6.0
774 *
775 * @return string
776 */
777 function cptui_empty_cpt_on_taxonomy() {
778 return esc_html__( 'Please provide a post type to attach to.', 'custom-post-type-ui' );
779 }
780
781 /**
782 * Returns error message for if trying to register post type with matching page slug.
783 *
784 * @since 1.4.0
785 *
786 * @return string
787 */
788 function cptui_slug_matches_page() {
789 $slug = cptui_get_object_from_post_global();
790 $matched_slug = get_page_by_path(
791 cptui_get_object_from_post_global()
792 );
793 if ( $matched_slug instanceof WP_Post ) {
794 $slug = sprintf(
795 /* translators: Placeholders are just for HTML markup that doesn't need translated */
796 '<a href="%s">%s</a>',
797 get_edit_post_link( $matched_slug->ID ),
798 cptui_get_object_from_post_global()
799 );
800 }
801
802 return sprintf(
803 /* translators: Placeholders are just for HTML markup that doesn't need translated */
804 esc_html__( 'Please choose a different post type name. %s matches an existing page slug, which can cause conflicts.', 'custom-post-type-ui' ),
805 $slug
806 );
807 }
808
809 /**
810 * Returns error message for if trying to use quotes in slugs or rewrite slugs.
811 *
812 * @since 1.4.0
813 *
814 * @return string
815 */
816 function cptui_slug_has_quotes() {
817 return sprintf(
818 esc_html__( 'Please do not use quotes in post type/taxonomy names or rewrite slugs', 'custom-post-type-ui' ),
819 cptui_get_object_from_post_global()
820 );
821 }
822
823 /**
824 * Error admin notice.
825 *
826 * @since 1.4.0
827 */
828 function cptui_error_admin_notice() {
829 echo cptui_admin_notices_helper( // phpcs:ignore WordPress.Security.EscapeOutput
830 apply_filters( 'cptui_custom_error_message', '' ),
831 false
832 );
833 }
834
835 /**
836 * Mark site as not a new CPTUI install upon update to 1.5.0
837 *
838 * @since 1.5.0
839 *
840 * @param object $wp_upgrader WP_Upgrader instance.
841 * @param array $extras Extra information about performed upgrade.
842 */
843 function cptui_not_new_install( $wp_upgrader, $extras ) {
844
845 if ( $wp_upgrader instanceof \Plugin_Upgrader ) {
846 return;
847 }
848
849 if ( ! array_key_exists( 'plugins', $extras ) || ! is_array( $extras['plugins'] ) ) {
850 return;
851 }
852
853 // Was CPTUI updated?
854 if ( ! in_array( 'custom-post-type-ui/custom-post-type-ui.php', $extras['plugins'], true ) ) {
855 return;
856 }
857
858 // If we are already known as not new, return.
859 if ( cptui_is_new_install() ) {
860 return;
861 }
862
863 // We need to mark ourselves as not new.
864 cptui_set_not_new_install();
865 }
866 add_action( 'upgrader_process_complete', 'cptui_not_new_install', 10, 2 );
867
868 /**
869 * Check whether or not we're on a new install.
870 *
871 * @since 1.5.0
872 *
873 * @return bool
874 */
875 function cptui_is_new_install() {
876 $new_or_not = true;
877 $saved = get_option( 'cptui_new_install', '' );
878
879 if ( 'false' === $saved ) {
880 $new_or_not = false;
881 }
882
883 /**
884 * Filters the new install status.
885 *
886 * Offers third parties the ability to override if they choose to.
887 *
888 * @since 1.5.0
889 *
890 * @param bool $new_or_not Whether or not site is a new install.
891 */
892 return (bool) apply_filters( 'cptui_is_new_install', $new_or_not );
893 }
894
895 /**
896 * Set our activation status to not new.
897 *
898 * @since 1.5.0
899 */
900 function cptui_set_not_new_install() {
901 update_option( 'cptui_new_install', 'false' );
902 }
903
904 /**
905 * Returns saved values for single post type from CPTUI settings.
906 *
907 * @since 1.5.0
908 *
909 * @param string $post_type Post type to retrieve CPTUI object for.
910 * @return string
911 */
912 function cptui_get_cptui_post_type_object( $post_type = '' ) {
913 $post_types = get_option( 'cptui_post_types', [] );
914
915 if ( is_array( $post_types ) && array_key_exists( $post_type, $post_types ) ) {
916 return $post_types[ $post_type ];
917 }
918 return [];
919 }
920
921 /**
922 * Returns saved values for single taxonomy from CPTUI settings.
923 *
924 * @since 1.5.0
925 *
926 * @param string $taxonomy Taxonomy to retrieve CPTUI object for.
927 * @return string
928 */
929 function cptui_get_cptui_taxonomy_object( $taxonomy = '' ) {
930 $taxonomies = get_option( 'cptui_taxonomies', [] );
931
932 if ( is_array( $taxonomies ) && array_key_exists( $taxonomy, $taxonomies ) ) {
933 return $taxonomies[ $taxonomy ];
934 }
935 return [];
936 }
937
938 /**
939 * Checks if a requested post type has a custom CPTUI feature supported.
940 *
941 * @since 1.5.0
942 *
943 * @param string $post_type Post type slug.
944 * @param string $feature Feature to check for.
945 * @return bool
946 */
947 function cptui_post_type_supports( $post_type, $feature ) {
948
949 $object = cptui_get_cptui_post_type_object( $post_type );
950
951 if ( ! empty( $object ) ) {
952 if ( array_key_exists( $feature, $object ) && ! empty( $object[ $feature ] ) ) {
953 return true;
954 }
955
956 return false;
957 }
958
959 return false;
960 }
961
962 /**
963 * Add missing post_format taxonomy support for CPTUI post types.
964 *
965 * Addresses bug wih previewing changes for published posts with post types that
966 * have post-formats support.
967 *
968 * @since 1.5.8
969 *
970 * @param array $post_types Array of CPTUI post types.
971 */
972 function cptui_published_post_format_fix( $post_types ) {
973 if ( empty( $post_types ) || ! is_array( $post_types ) ) {
974 return;
975 }
976
977 foreach ( $post_types as $type ) {
978 if ( ! is_array( $type['supports'] ) ) {
979 continue;
980 }
981
982 if ( in_array( 'post-formats', $type['supports'], true ) ) {
983 add_post_type_support( $type['name'], 'post-formats' );
984 register_taxonomy_for_object_type( 'post_format', $type['name'] );
985 }
986 }
987 }
988 add_action( 'cptui_post_register_post_types', 'cptui_published_post_format_fix' );
989
990 /**
991 * Return a ready-to-use admin url for adding a new content type.
992 *
993 * @since 1.7.0
994 *
995 * @param string $content_type Content type to link to.
996 * @return string
997 */
998 function cptui_get_add_new_link( $content_type = '' ) {
999 if ( ! in_array( $content_type, [ 'post_types', 'taxonomies' ], true ) ) {
1000 return cptui_admin_url( 'admin.php?page=cptui_manage_post_types' );
1001 }
1002
1003 return cptui_admin_url( 'admin.php?page=cptui_manage_' . $content_type );
1004 }
1 <?php
2 /**
3 * Custom Post Type UI WP-CLI.
4 *
5 * @package CPTUI
6 * @subpackage WP-CLI
7 * @author WebDevStudios
8 * @since 1.6.0
9 * @license GPL-2.0+
10 */
11
12 // phpcs:disable WebDevStudios.All.RequireAuthor
13
14 /**
15 * Imports and exports Custom Post Type UI setting data.
16 */
17 class CPTUI_Import_JSON extends WP_CLI_Command {
18
19 public $args;
20
21 public $assoc_args;
22
23 public $type;
24
25 public $data = [];
26
27 /**
28 * Imports and parses JSON into CPTUI settings.
29 *
30 * ## Options
31 *
32 * [--type=<type>]
33 * : What type of import this is. Available options are `post_type` and `taxonomy`.
34 *
35 * [--data-path=<path>]
36 * : The server path to the file holding JSON data to import. Relative to PWD.
37 */
38 public function import( $args, $assoc_args ) {
39 $this->args = $args;
40 $this->assoc_args = $assoc_args;
41
42 if ( ! isset( $this->assoc_args['type'] ) ) {
43 WP_CLI::error( esc_html__( 'Please provide whether you are importing post types or taxonomies', 'custom-post-type-ui' ) );
44 }
45
46 if ( ! isset( $this->assoc_args['data-path'] ) ) {
47 WP_CLI::error( esc_html__( 'Please provide a path to the file holding your CPTUI JSON data.', 'custom-post-type-ui' ) );
48 }
49
50 $this->type = $assoc_args['type'];
51
52 $json = file_get_contents( $this->assoc_args['data-path'] );
53
54 if ( empty( $json ) ) {
55 WP_CLI::error( esc_html__( 'No JSON data found', 'custom-post-type-ui' ) );
56 }
57
58 if ( 'post_type' === $this->type ) {
59 $this->data['cptui_post_import'] = json_decode( stripslashes_deep( trim( $json ) ), true );
60 }
61
62 if ( 'taxonomy' === $this->type ) {
63 $this->data['cptui_tax_import'] = json_decode( stripslashes_deep( trim( $json ) ), true );
64 }
65
66 $result = cptui_import_types_taxes_settings( $this->data );
67
68 if ( false === $result || 'import_fail' === $result ) {
69 WP_CLI::error( sprintf( esc_html__( 'An error on import occurred', 'custom-post-type-ui' ) ) );
70 } else {
71 WP_CLI::success(
72 sprintf(
73 /* translators: Placeholders are just for HTML markup that doesn't need translated */
74 esc_html__( 'Imported %s successfully', 'custom-post-type-ui' ),
75 $this->type
76 )
77 );
78 }
79 }
80
81 /**
82 * Export CPTUI settings to file.
83 *
84 * ## Options
85 *
86 * [--type=<type>]
87 * : Which settings to export. Available options are `post_type` and `taxonomy`.
88 *
89 * [--dest-path=<path>]
90 * : The path and file to export to. Relative to PWD.
91 */
92 public function export( $args, $assoc_args ) {
93 $this->args = $args;
94 $this->assoc_args = $assoc_args;
95
96 if ( ! isset( $this->assoc_args['type'] ) ) {
97 WP_CLI::error( esc_html__( 'Please provide whether you are exporting your post types or taxonomies', 'custom-post-type-ui' ) );
98 }
99
100 if ( ! isset( $this->assoc_args['dest-path'] ) ) {
101 WP_CLI::error( esc_html__( 'Please provide a path to export your data to.', 'custom-post-type-ui' ) );
102 }
103
104 $this->type = $assoc_args['type'];
105
106 if ( 'post_type' === $this->type ) {
107 $content = cptui_get_post_type_data();
108 }
109
110 if ( 'taxonomy' === $this->type ) {
111 $content = cptui_get_taxonomy_data();
112 }
113
114 $content = wp_json_encode( $content );
115 $result = file_put_contents( $this->assoc_args['dest-path'], $content );
116
117 if ( false === $result ) {
118 WP_CLI::error( esc_html__( 'Error saving data.', 'custom-post-type-ui' ) );
119 }
120
121 WP_CLI::success( esc_html__( 'Successfully saved data to file.', 'custom-post-type-ui' ) );
122 }
123 }
124 WP_CLI::add_command( 'cptui', 'CPTUI_Import_JSON' );
1 === Custom Post Type UI ===
2 Contributors: webdevstudios, pluginize, tw2113, williamsba1
3 Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3084056
4 Tags: custom post types, post type, taxonomy, content types, CPT, CMS, post, types, custom
5 Requires at least: 5.9
6 Tested up to: 6.2.2
7 Stable tag: 1.13.7
8 License: GPL-2.0+
9 Requires PHP: 5.6
10
11 Admin UI for creating custom content types like post types and taxonomies
12
13 == Description ==
14
15 Custom Post Type UI provides an easy to use interface for registering and managing custom post types and taxonomies for your website.
16
17 = Custom Post Type UI Extended =
18
19 CPTUI helps create custom content types, but displaying that content can be a whole new challenge. We created [Custom Post Type UI Extended](https://pluginize.com/product/custom-post-type-ui-extended/?utm_source=cptui-desription&utm_medium=text&utm_campaign=wporg) to help with displaying your crafted content. [View our Layouts page](https://pluginize.com/cpt-ui-extended-features/?utm_source=cptui-description-examples&utm_medium=text&utm_campaign=wporg) to see available layout examples with Custom Post Type UI Extended.
20
21 Beginning with version 1.7.0, Custom Post Type UI Extended has properly moved in to the Block editor experience and is working to get all the layouts available in the new "Custom Post Type UI Block". It's now even easier to start showing your content with the existing and future layouts available with Custom Post Type UI Extended.
22
23 [Pluginize](https://pluginize.com/?utm_source=cptui&utm_medium=text&utm_campaign=wporg) was launched in 2016 by [WebDevStudios](https://webdevstudios.com/) to promote, support, and house all of their [WordPress products](https://pluginize.com/shop/?utm_source=cptui-&utm_medium=text&utm_campaign=wporg). Pluginize is not only [creating new products for WordPress, like CPTUI Extended](https://pluginize.com/product/custom-post-type-ui-extended/?utm_source=cptui&utm_medium=text&utm_campaign=wporg), but also provides ongoing support and development for WordPress community favorites like [CMB2](https://wordpress.org/plugins/cmb2/) and more.
24
25 = Plugin development =
26
27 Custom Post Type UI development is managed on GitHub, with official releases published on WordPress.org. The GitHub repo can be found at [https://github.com/WebDevStudios/custom-post-type-ui](https://github.com/WebDevStudios/custom-post-type-ui). Please use the WordPress.org support tab for potential bugs, issues, or enhancement ideas.
28
29 == Screenshots ==
30
31 1. Add new post type screen and tab.
32 2. Add new taxonomy screen and tab.
33 3. Registered post types and taxonomies from CPTUI
34 4. Tools screen.
35 5. Help/support screen.
36
37 == Changelog ==
38
39 = 1.13.7 - 2023-07-11 =
40 * Fixed: "themes" marked as reserved taxonomy slug. Causes issues with featured image metabox.
41 * Fixed: PHP notice around `sort` parameter.
42
43 = 1.13.6 - 2023-05-30 =
44 * Fixed: Prevent PHP errors for dynamic WordPress hooks.
45 * Fixed: Prevent PHP errors from array_key_exist() checks on non arrays.
46 * Updated: Removed Maintainn graphic and added WP Search with Algolia Pro graphic.
47 * Updated: Fixed a lot of text escaping for translation-ready content.
48
49 = 1.13.5 - 2023-03-27 =
50 * Fixed: Security issue in CPTUI Debug Info screen.
51 * Fixed: Added `empty()` check for `can_export` parameters.
52 * Updated: Changed textdomain loading from `plugins_loaded` to `init`.
53
54 = 1.13.4 - 2022-12-16 =
55 * Fixed: Character encoding issue on CPTUI setting save in conjunction with PHP8 compatibility.
56
57 = 1.13.3 - 2022-12-15 =
58 * Fixed: Multiple PHP8 compatibility notices and warnings.
59 * Fixed: "Invalid argument for foreach" based notices around labels.
60 * Updated: Added taxonomy PHP global sanitization for 3rd party parameters.
61
62 = 1.13.2 - 2022-11-29 =
63 * Fixed: Removed forcing of underscores in place of dashes for taxonomy slugs. Yay!
64 * Updated: tested up to WP 6.1.1
65 * Updated: Documentation links in wordpress.org FAQ section.
66
67 = 1.13.1 - 2022-09-08 =
68 * Fixed: Various issues caused by a misplaced output for `ob_get_clean()` outside of function.
69
70 = 1.13.0 - 2022-09-07 =
71 * Added: Notes regarding featured image and post format support also needing `add_theme_support` to work.
72 * Fixed: Issues around double quotes and JSON export with the post type description field
73 * Fixed: Issues around HTML markup being removed from post type description field stemming from 1.10.x release
74 * Fixed: Pluralization issue with our UI for some field labels
75 * Updated: Code separation and quality cleanup.
76 * Updated: Plugin branding.
77
78 = 1.12.1 - 2022-05-16 =
79 * Fixed: JSON decoding issues around WP-CLI import.
80
81 = 1.12.0 - 2022-05-09 =
82 * Added: Tested on WordPress 6.0.
83 * Added: Auto-check, but not force, "page-attributes" when setting a post type as hierarchical.
84 * Added: "rest_namespace" parameters for both post types and taxonomies.
85 * Added: "register_meta_box_cb" parameter for post types.
86 * Fixed: undefined index notices for "can_export".
87 * Updated: list of reserved taxonomy names with more that are considered reserved.
88 * Updated: readme descriptions and screenshots.
89
90 = 1.11.2 - 2022-03-21 =
91 * Fixed: Unintended reuse of `$delete_with_user` variable and `can_export` option. Props @bogutskyy
92 * Fixed: PHP notices around `sort` array index.
93
94 = 1.11.1 - 2022-03-18 =
95 * Fixed: Errors and warnings around array_key_exists() and bool values
96
97 = 1.11.0 - 2022-03-17 =
98 * Added: "sort" argument for taxonomies.
99 * Added: "can export" argument for post types
100 * Added: New taxonomy labels from WordPress 5.9
101 * Added: Custom option to set "Enter title here" value for post types.
102 * Added: Notes around "exclude from search" argument for post types and taxonomy term archives.
103 * Added: Notes around taxonomy "hierarchical" option regarding category vs tag behavior.
104 * Updated: Reserved post type slugs from recent WordPress releases.
105 * Fixed: PHP warnings around foreach loops in cptui_published_post_format_fix()
106
107 == Upgrade Notice ==
108
109 = 1.13.7 - 2023-07-11 =
110 * Fixed: "themes" marked as reserved taxonomy slug. Causes issues with featured image metabox.
111 * Fixed: PHP notice around `sort` parameter.
112
113 = 1.13.6 - 2023-05-30 =
114 * Fixed: Prevent PHP errors for dynamic WordPress hooks.
115 * Fixed: Prevent PHP errors from array_key_exist() checks on non arrays.
116 * Updated: Removed Maintainn graphic and added WP Search with Algolia Pro graphic.
117 * Updated: Fixed a lot of text escaping for translation-ready content.
118
119 = 1.13.5 - 2023-03-27 =
120 * Fixed: Security issue in CPTUI Debug Info screen.
121 * Fixed: Added `empty()` check for `can_export` parameters.
122 * Updated: Changed textdomain loading from `plugins_loaded` to `init`.
123
124 = 1.13.4 - 2022-12-16 =
125 * Fixed: Character encoding issue on CPTUI setting save in conjunction with PHP8 compatibility.
126
127 = 1.13.3 - 2022-12-15 =
128 * Fixed: Multiple PHP8 compatibility notices and warnings.
129 * Fixed: "Invalid argument for foreach" based notices around labels.
130 * Updated: Added taxonomy PHP global sanitization for 3rd party parameters.
131
132 = 1.13.2 - 2022-11-29 =
133 * Fixed: Removed forcing of underscores in place of dashes for taxonomy slugs. Yay!
134 * Updated: tested up to WP 6.1.1
135 * Updated: Documentation links in wordpress.org FAQ section.
136
137 = 1.13.1 - 2022-09-08 =
138 * Fixed: Various issues caused by a misplaced output for `ob_get_clean()` outside of function.
139
140 = 1.13.0 - 2022-09-07 =
141 * Added: Notes regarding featured image and post format support also needing `add_theme_support` to work.
142 * Fixed: Issues around double quotes and JSON export with the post type description field
143 * Fixed: Issues around HTML markup being removed from post type description field stemming from 1.10.x release
144 * Fixed: Pluralization issue with our UI for some field labels
145 * Updated: Code separation and quality cleanup.
146 * Updated: Plugin branding.
147
148 = 1.12.1 - 2022-05-16 =
149 * Fixed: JSON decoding issues around WP-CLI import.
150
151 = 1.12.0 - 2022-05-09 =
152 * Added: Tested on WordPress 6.0.
153 * Added: Auto-check, but not force, "page-attributes" when setting a post type as hierarchical.
154 * Added: "rest_namespace" parameters for both post types and taxonomies.
155 * Added: "register_meta_box_cb" parameter for post types.
156 * Fixed: undefined index notices for "can_export".
157 * Updated: list of reserved taxonomy names with more that are considered reserved.
158 * Updated: readme descriptions and screenshots.
159
160 = 1.11.2 - 2022-03-21 =
161 * Fixed: Unintended reuse of `$delete_with_user` variable and `can_export` option. Props @bogutskyy
162 * Fixed: PHP notices around `sort` array index.
163
164 = 1.11.1 - 2022-03-18 =
165 * Fixed: Errors and warnings around array_key_exists() and bool values
166
167 = 1.11.0 - 2022-03-17 =
168 * Added: "sort" argument for taxonomies.
169 * Added: "can export" argument for post types
170 * Added: New taxonomy labels from WordPress 5.9
171 * Added: Custom option to set "Enter title here" value for post types.
172 * Added: Notes around "exclude from search" argument for post types and taxonomy term archives.
173 * Added: Notes around taxonomy "hierarchical" option regarding category vs tag behavior.
174 * Updated: Reserved post type slugs from recent WordPress releases.
175 * Fixed: PHP warnings around foreach loops in cptui_published_post_format_fix()
176
177 == Installation ==
178
179 = Admin Installer via search =
180 1. Visit the Add New plugin screen and search for "custom post type ui".
181 2. Click the "Install Now" button.
182 3. Activate the plugin.
183 4. Navigate to the "CPTUI" Menu.
184
185 = Admin Installer via zip =
186 1. Visit the Add New plugin screen and click the "Upload Plugin" button.
187 2. Click the "Browse..." button and select zip file from your computer.
188 3. Click "Install Now" button.
189 4. Once done uploading, activate Custom Post Type UI.
190
191 = Manual =
192 1. Upload the Custom Post Type UI folder to the plugins directory in your WordPress installation.
193 2. Activate the plugin.
194 3. Navigate to the "CPTUI" Menu.
195
196 That's it! Now you can easily start creating custom post types and taxonomies in WordPress.
197
198 == Frequently Asked Questions ==
199
200 #### User documentation
201 Please see https://docs.pluginize.com/tutorials/custom-post-type-ui/