Version Description
(Released: August 05, 2021) = * Bug Fixed: Deprecated - Required parameter $atts follows optional parameter * Compatibility check up to version 5.8
Download this release
Release Info
Developer | catchthemes |
Plugin | Essential Content Types |
Version | 1.8.6 |
Comparing to | |
See all releases |
Code changes from version 1.8.5 to 1.8.6
- README.txt +297 -293
- admin/class-essential-content-types-admin.php +259 -259
- admin/class-featured-content.php +784 -784
- admin/class-food-menu.php +1537 -1537
- admin/class-portfolio.php +881 -881
- admin/class-service.php +735 -735
- admin/class-testimonial.php +1075 -1075
- admin/css/food-menu-shortcode.css +159 -159
- ect-templates/content-menu.php +36 -36
- ect-templates/ect-menu.php +108 -108
- essential-content-types.php +273 -273
- includes/CatchThemesThemePlugin.php +484 -484
- languages/essential-content-types-fr_FR.mo +0 -0
- languages/essential-content-types-fr_FR.po +4 -4
- languages/essential-content-types.pot +3 -3
README.txt
CHANGED
@@ -1,293 +1,297 @@
|
|
1 |
-
=== Essential Content Types ===
|
2 |
-
Contributors: catchplugins, catchthemes, sakinshrestha, pratikshrestha, maheshmaharjan, dreamsapana
|
3 |
-
Donate link: https://catchplugins.com/plugins/essential-content-types-pro/
|
4 |
-
Tags: custom post types, CPT, CMS, post, types, post type, taxonomy, tax, custom, content types, post types, custom content types, testimonial, portfolio, featured content, service
|
5 |
-
Requires at least: 4.8
|
6 |
-
Tested up to: 5.
|
7 |
-
Stable tag: trunk
|
8 |
-
License: GPLv3 or later
|
9 |
-
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
-
|
11 |
-
Essential Content Types allows you to feature the impressive content through different content/post types on your website just the way you want it. These content/post types are missed by the themes in WordPress Theme Directory as the feature falls more towards the plugins’ territory.
|
12 |
-
|
13 |
-
== Description ==
|
14 |
-
|
15 |
-
**Essential Content Types** allows you to feature the impressive content through different content/post types on your website just the way you want it. These content/post types are missed by the themes in WordPress Theme Directory as the feature falls more towards the plugins' territory.
|
16 |
-
|
17 |
-
Content is at the forefront of any website. Changing the layout of your important content changes the way your website looks, which may not be a plus point if your current website layout is loved by your users.
|
18 |
-
|
19 |
-
Additionally, switching themes changes your website layout completely. Therefore, to keep things looking spic-and- span in your website, we bring you Essential Content.
|
20 |
-
|
21 |
-
Essential Content allows you to add up to three content/post types:
|
22 |
-
* Portfolio – Create and display your portfolio on your website
|
23 |
-
* Testimonials – Add customer testimonials to your website
|
24 |
-
* Featured Content – Display the content you want as featured content on your website to attract visitors' attention
|
25 |
-
* Services – Add your services on your website
|
26 |
-
|
27 |
-
Features of Essential Content:
|
28 |
-
* Enable/Disable any content/post type as needed
|
29 |
-
* Light-weight
|
30 |
-
* Supports all themes on WordPress
|
31 |
-
|
32 |
-
Essential Content is inspired by *Jetpack's Custom Content Types feature*.
|
33 |
-
|
34 |
-
However, not everyone wants to have a plugin that “does-it- all”. Some may want plugins to be niche focused and concentrate on smaller areas.
|
35 |
-
|
36 |
-
That is precisely what we have done with Essential Content. Essential content, true to its name, has only the essential elements. We have added the features that WordPressers use most. We have ruled out all other elements to make it non-bloated and clean. It takes up lesser space and does the job well.
|
37 |
-
|
38 |
-
If you think we have missed any essential content/post types, please let us know. We’ll review the frequency of usage and add your suggestions.
|
39 |
-
|
40 |
-
***Portfolio Shortcode***
|
41 |
-
|
42 |
-
You can use shortcodes to embed portfolio projects on posts and pages.
|
43 |
-
|
44 |
-
**Embedding Portfolio Projects**
|
45 |
-
|
46 |
-
To embed portfolio projects on posts and pages, first activate the Portfolio custom content type on your site and add some projects to your portfolio.
|
47 |
-
|
48 |
-
Next, add the `[portfolio]` shortcode to a post or page. The shortcode will display projects in different ways, depending on how you use the optional attributes to customize the portfolio layout.
|
49 |
-
|
50 |
-
**Attributes**
|
51 |
-
* display_types: display Project Types. (true/false)
|
52 |
-
* display_tags: display Project Tags. (true/false)
|
53 |
-
* display_content: display project content. (true/false)
|
54 |
-
* include_type: display specific Project Types. Defaults to all. (comma-separated list of Project Type slugs)
|
55 |
-
* include_tag: display specific Project Tags. Defaults to all. (comma-separated list of Project Tag slugs)
|
56 |
-
* columns: number of columns in shortcode. Defaults to 2. (number, 1-6)
|
57 |
-
* showposts: number of projects to display. Defaults to all. (number)
|
58 |
-
* order: display projects in ascending or descending order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display projects in descending order instead. (ASC/DESC)
|
59 |
-
* orderby: sort projects by different criteria, including author name, project title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
|
60 |
-
|
61 |
-
**Example**
|
62 |
-
`
|
63 |
-
[portfolio display_types="true" display_tags="false" include_type="grooming-tips,best-kitties" columns="2" showposts="10" orderby="title"]
|
64 |
-
`
|
65 |
-
The example will display up to ten portfolio projects in two columns, in ascending alphabetical order by project title. It will display Project Types, hide Project Tags, and only display projects that are assigned the “Grooming Tips” or “Best Kitties” Project Types.
|
66 |
-
|
67 |
-
|
68 |
-
***Featured Content Shortcode***
|
69 |
-
|
70 |
-
You can use shortcodes to embed featured content on posts and pages.
|
71 |
-
|
72 |
-
**Embedding Featured Content Projects**
|
73 |
-
|
74 |
-
To embed featured content on posts and pages, first activate the Featured Content content type on your site and add some projects to your featured content.
|
75 |
-
|
76 |
-
Next, add the `[featured_content]` shortcode to a post or page. The shortcode will display projects in different ways, depending on how you use the optional attributes to customize the featured content layout.
|
77 |
-
|
78 |
-
**Attributes**
|
79 |
-
* display_types: display Content Types. (true/false)
|
80 |
-
* display_tags: display Content Tags. (true/false)
|
81 |
-
* display_content: display project content. (true/false)
|
82 |
-
* include_type: display specific Content Types. Defaults to all. (comma-separated list of Content Type slugs)
|
83 |
-
* include_tag: display specific Content Tags. Defaults to all. (comma-separated list of Content Tag slugs)
|
84 |
-
* columns: number of columns in shortcode. Defaults to 2. (number, 1-6)
|
85 |
-
* showposts: number of projects to display. Defaults to all. (number)
|
86 |
-
* order: display projects in ascending or descending order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display projects in descending order instead. (ASC/DESC)
|
87 |
-
* orderby: sort projects by different criteria, including author name, project title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
|
88 |
-
|
89 |
-
**Example**
|
90 |
-
`
|
91 |
-
[featured_content display_types="true" display_tags="false" include_type="grooming-tips,best-kitties" columns="2" showposts="10" orderby="title"]
|
92 |
-
`
|
93 |
-
The example will display up to ten featured content in two columns, in ascending alphabetical order by project title. It will display Content Types, hide Content Tags, and only display projects that are assigned the “Grooming Tips” or “Best Kitties” Content Types.
|
94 |
-
|
95 |
-
***Testimonials Shortcode***
|
96 |
-
|
97 |
-
You can use shortcodes to embed testimonials on posts and pages.
|
98 |
-
Embedding Testimonials
|
99 |
-
|
100 |
-
To embed testimonials on posts and pages, first activate the Testimonial custom content type on your site and add some testimonials.
|
101 |
-
|
102 |
-
Next, add the `[testimonials]` shortcode to a post or page. The shortcode will display testimonials in different ways, depending on how you use the optional attributes to customize the testimonials layout.
|
103 |
-
|
104 |
-
**Attributes**
|
105 |
-
* display_content: display testimonial content. (full/true/false)
|
106 |
-
* image: display the featured image. (true/false) Defaults to true.
|
107 |
-
* columns: number of columns in shortcode. Defaults to 1. (number, 1-6)
|
108 |
-
* showposts: number of testimonials to display. Defaults to all. (number)
|
109 |
-
* order: display testimonials in ascending or descending chronological order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display testimonials in descending order instead. (ASC/DESC)
|
110 |
-
* orderby: sort testimonials by different criteria, including author name, testimonial title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
|
111 |
-
|
112 |
-
**Example**
|
113 |
-
`
|
114 |
-
[testimonials columns="2" showposts="10" orderby="title"]
|
115 |
-
`
|
116 |
-
The example will display up to ten testimonials in two columns, in ascending alphabetical order by testimonial title.
|
117 |
-
|
118 |
-
***Service Shortcode***
|
119 |
-
|
120 |
-
You can use shortcodes to embed service on posts and pages.
|
121 |
-
|
122 |
-
**Embedding Service Projects**
|
123 |
-
|
124 |
-
To embed service on posts and pages, first activate the Service content type on your site and add some projects to your Service.
|
125 |
-
|
126 |
-
Next, add the `[services]` shortcode to a post or page. The shortcode will display projects in different ways, depending on how you use the optional attributes to customize the featured content layout.
|
127 |
-
|
128 |
-
**Attributes**
|
129 |
-
* display_types: display Content Types. (true/false)
|
130 |
-
* display_tags: display Content Tags. (true/false)
|
131 |
-
* display_content: display project content. (true/false)
|
132 |
-
* include_type: display specific Content Types. Defaults to all. (comma-separated list of Content Type slugs)
|
133 |
-
* include_tag: display specific Content Tags. Defaults to all. (comma-separated list of Content Tag slugs)
|
134 |
-
* columns: number of columns in shortcode. Defaults to 2. (number, 1-6)
|
135 |
-
* showposts: number of projects to display. Defaults to all. (number)
|
136 |
-
* order: display projects in ascending or descending order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display projects in descending order instead. (ASC/DESC)
|
137 |
-
* orderby: sort projects by different criteria, including author name, project title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
|
138 |
-
|
139 |
-
**Example**
|
140 |
-
`
|
141 |
-
[services display_types="true" display_tags="false" include_type="grooming-tips,best-kitties" columns="2" showposts="10" orderby="title"]
|
142 |
-
`
|
143 |
-
The example will display up to ten featured content in two columns, in ascending alphabetical order by project title. It will display Content Types, hide Content Tags, and only display projects that are assigned the “Grooming Tips” or “Best Kitties” Content Types.
|
144 |
-
|
145 |
-
***Food Menu Shortcode***
|
146 |
-
|
147 |
-
You can use shortcodes to embed Food Menu on posts and pages.
|
148 |
-
Embedding Food Menu
|
149 |
-
|
150 |
-
**Embedding Food Menu**
|
151 |
-
|
152 |
-
To embed food menus on posts and pages, first activate the Food Menu custom content type on your site and add some food menus.
|
153 |
-
|
154 |
-
Next, add the `[food_menu]` shortcode to a post or page. The shortcode will display food menu in the selected post or page.
|
155 |
-
|
156 |
-
**Attributes**
|
157 |
-
* showposts: number of menu items to display. Defaults to all. (number)
|
158 |
-
* include_type: display specific Content Types. Defaults to all. (comma-separated list of Content Type slugs)
|
159 |
-
* include_tag: display specific Content Tags. Defaults to all. (comma-separated list of Content Tag slugs)
|
160 |
-
|
161 |
-
**Example**
|
162 |
-
|
163 |
-
`[food_menu showposts="10" include_type="pizza,burger,breakfast"]`
|
164 |
-
The example will display up to ten menu items. It will only display menu items in “Pizza”, “Burger” or “Breakfast” sections.
|
165 |
-
|
166 |
-
== Translations ==
|
167 |
-
|
168 |
-
To translate the plugin, use translate.wordpress.org (GlotPress). You only need your WordPress.org account to join the collaborative translation project.
|
169 |
-
|
170 |
-
You can translate Essential Widgets on [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/essential-content-types/).
|
171 |
-
|
172 |
-
== Installation ==
|
173 |
-
|
174 |
-
The easy way (via Dashboard) :
|
175 |
-
|
176 |
-
* Go to Plugins > Add New
|
177 |
-
* Type in the **Essential Content Types** in Search Plugins box
|
178 |
-
* Click Install Now to install the plugin
|
179 |
-
* After Installation click activate to start using the **Essential Content Types**
|
180 |
-
* Go to **Essential Content Types** from Dashboard menu
|
181 |
-
* Use Shortcodes in your posts/pages/templates
|
182 |
-
|
183 |
-
Not so easy way (via FTP) :
|
184 |
-
|
185 |
-
* Download the **Essential Content Types**
|
186 |
-
* Unarchive **Essential Content Types** plugin
|
187 |
-
* Copy folder with `essential-content-types.zip`
|
188 |
-
* Open the ftp `\wp-content\plugins\`
|
189 |
-
* Paste the plug-ins folder in the folder
|
190 |
-
* Go to admin panel => open item "Plugins" => activate **Essential Content Types**
|
191 |
-
* Go to **Essential Content Types** from Dashboard menu
|
192 |
-
* Use Shortcodes in your posts/pages/templates
|
193 |
-
|
194 |
-
== Screenshots ==
|
195 |
-
|
196 |
-
1. Main Dashboard
|
197 |
-
2. Customizer: Portfolio Archive Options
|
198 |
-
3. Customizer: Testimonial Archive Options
|
199 |
-
4. Customizer: Featured Content Archive Options
|
200 |
-
5. Customizer: Services Archive Options
|
201 |
-
|
202 |
-
== Changelog ==
|
203 |
-
|
204 |
-
= 1.8.
|
205 |
-
* Bug Fixed:
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
*
|
210 |
-
|
211 |
-
= 1.8.
|
212 |
-
* Bug Fixed:
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
* Compatibility check up to version 5.
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
*
|
234 |
-
|
235 |
-
|
236 |
-
= 1.5 (Released:
|
237 |
-
*
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
*
|
242 |
-
|
243 |
-
|
244 |
-
*
|
245 |
-
|
246 |
-
|
247 |
-
*
|
248 |
-
*
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
*
|
254 |
-
*
|
255 |
-
|
256 |
-
= 1.
|
257 |
-
*
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
*
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
* Compatibility check up to version 4.9
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
*
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
* Added:
|
274 |
-
*
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
*
|
279 |
-
*
|
280 |
-
|
281 |
-
= 1.0.
|
282 |
-
*
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
*
|
287 |
-
|
288 |
-
= 1.0.
|
289 |
-
*
|
290 |
-
*
|
291 |
-
|
292 |
-
= 1.0.
|
293 |
-
*
|
|
|
|
|
|
|
|
1 |
+
=== Essential Content Types ===
|
2 |
+
Contributors: catchplugins, catchthemes, sakinshrestha, pratikshrestha, maheshmaharjan, dreamsapana
|
3 |
+
Donate link: https://catchplugins.com/plugins/essential-content-types-pro/
|
4 |
+
Tags: custom post types, CPT, CMS, post, types, post type, taxonomy, tax, custom, content types, post types, custom content types, testimonial, portfolio, featured content, service
|
5 |
+
Requires at least: 4.8
|
6 |
+
Tested up to: 5.8
|
7 |
+
Stable tag: trunk
|
8 |
+
License: GPLv3 or later
|
9 |
+
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
+
|
11 |
+
Essential Content Types allows you to feature the impressive content through different content/post types on your website just the way you want it. These content/post types are missed by the themes in WordPress Theme Directory as the feature falls more towards the plugins’ territory.
|
12 |
+
|
13 |
+
== Description ==
|
14 |
+
|
15 |
+
**Essential Content Types** allows you to feature the impressive content through different content/post types on your website just the way you want it. These content/post types are missed by the themes in WordPress Theme Directory as the feature falls more towards the plugins' territory.
|
16 |
+
|
17 |
+
Content is at the forefront of any website. Changing the layout of your important content changes the way your website looks, which may not be a plus point if your current website layout is loved by your users.
|
18 |
+
|
19 |
+
Additionally, switching themes changes your website layout completely. Therefore, to keep things looking spic-and- span in your website, we bring you Essential Content.
|
20 |
+
|
21 |
+
Essential Content allows you to add up to three content/post types:
|
22 |
+
* Portfolio – Create and display your portfolio on your website
|
23 |
+
* Testimonials – Add customer testimonials to your website
|
24 |
+
* Featured Content – Display the content you want as featured content on your website to attract visitors' attention
|
25 |
+
* Services – Add your services on your website
|
26 |
+
|
27 |
+
Features of Essential Content:
|
28 |
+
* Enable/Disable any content/post type as needed
|
29 |
+
* Light-weight
|
30 |
+
* Supports all themes on WordPress
|
31 |
+
|
32 |
+
Essential Content is inspired by *Jetpack's Custom Content Types feature*.
|
33 |
+
|
34 |
+
However, not everyone wants to have a plugin that “does-it- all”. Some may want plugins to be niche focused and concentrate on smaller areas.
|
35 |
+
|
36 |
+
That is precisely what we have done with Essential Content. Essential content, true to its name, has only the essential elements. We have added the features that WordPressers use most. We have ruled out all other elements to make it non-bloated and clean. It takes up lesser space and does the job well.
|
37 |
+
|
38 |
+
If you think we have missed any essential content/post types, please let us know. We’ll review the frequency of usage and add your suggestions.
|
39 |
+
|
40 |
+
***Portfolio Shortcode***
|
41 |
+
|
42 |
+
You can use shortcodes to embed portfolio projects on posts and pages.
|
43 |
+
|
44 |
+
**Embedding Portfolio Projects**
|
45 |
+
|
46 |
+
To embed portfolio projects on posts and pages, first activate the Portfolio custom content type on your site and add some projects to your portfolio.
|
47 |
+
|
48 |
+
Next, add the `[portfolio]` shortcode to a post or page. The shortcode will display projects in different ways, depending on how you use the optional attributes to customize the portfolio layout.
|
49 |
+
|
50 |
+
**Attributes**
|
51 |
+
* display_types: display Project Types. (true/false)
|
52 |
+
* display_tags: display Project Tags. (true/false)
|
53 |
+
* display_content: display project content. (true/false)
|
54 |
+
* include_type: display specific Project Types. Defaults to all. (comma-separated list of Project Type slugs)
|
55 |
+
* include_tag: display specific Project Tags. Defaults to all. (comma-separated list of Project Tag slugs)
|
56 |
+
* columns: number of columns in shortcode. Defaults to 2. (number, 1-6)
|
57 |
+
* showposts: number of projects to display. Defaults to all. (number)
|
58 |
+
* order: display projects in ascending or descending order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display projects in descending order instead. (ASC/DESC)
|
59 |
+
* orderby: sort projects by different criteria, including author name, project title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
|
60 |
+
|
61 |
+
**Example**
|
62 |
+
`
|
63 |
+
[portfolio display_types="true" display_tags="false" include_type="grooming-tips,best-kitties" columns="2" showposts="10" orderby="title"]
|
64 |
+
`
|
65 |
+
The example will display up to ten portfolio projects in two columns, in ascending alphabetical order by project title. It will display Project Types, hide Project Tags, and only display projects that are assigned the “Grooming Tips” or “Best Kitties” Project Types.
|
66 |
+
|
67 |
+
|
68 |
+
***Featured Content Shortcode***
|
69 |
+
|
70 |
+
You can use shortcodes to embed featured content on posts and pages.
|
71 |
+
|
72 |
+
**Embedding Featured Content Projects**
|
73 |
+
|
74 |
+
To embed featured content on posts and pages, first activate the Featured Content content type on your site and add some projects to your featured content.
|
75 |
+
|
76 |
+
Next, add the `[featured_content]` shortcode to a post or page. The shortcode will display projects in different ways, depending on how you use the optional attributes to customize the featured content layout.
|
77 |
+
|
78 |
+
**Attributes**
|
79 |
+
* display_types: display Content Types. (true/false)
|
80 |
+
* display_tags: display Content Tags. (true/false)
|
81 |
+
* display_content: display project content. (true/false)
|
82 |
+
* include_type: display specific Content Types. Defaults to all. (comma-separated list of Content Type slugs)
|
83 |
+
* include_tag: display specific Content Tags. Defaults to all. (comma-separated list of Content Tag slugs)
|
84 |
+
* columns: number of columns in shortcode. Defaults to 2. (number, 1-6)
|
85 |
+
* showposts: number of projects to display. Defaults to all. (number)
|
86 |
+
* order: display projects in ascending or descending order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display projects in descending order instead. (ASC/DESC)
|
87 |
+
* orderby: sort projects by different criteria, including author name, project title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
|
88 |
+
|
89 |
+
**Example**
|
90 |
+
`
|
91 |
+
[featured_content display_types="true" display_tags="false" include_type="grooming-tips,best-kitties" columns="2" showposts="10" orderby="title"]
|
92 |
+
`
|
93 |
+
The example will display up to ten featured content in two columns, in ascending alphabetical order by project title. It will display Content Types, hide Content Tags, and only display projects that are assigned the “Grooming Tips” or “Best Kitties” Content Types.
|
94 |
+
|
95 |
+
***Testimonials Shortcode***
|
96 |
+
|
97 |
+
You can use shortcodes to embed testimonials on posts and pages.
|
98 |
+
Embedding Testimonials
|
99 |
+
|
100 |
+
To embed testimonials on posts and pages, first activate the Testimonial custom content type on your site and add some testimonials.
|
101 |
+
|
102 |
+
Next, add the `[testimonials]` shortcode to a post or page. The shortcode will display testimonials in different ways, depending on how you use the optional attributes to customize the testimonials layout.
|
103 |
+
|
104 |
+
**Attributes**
|
105 |
+
* display_content: display testimonial content. (full/true/false)
|
106 |
+
* image: display the featured image. (true/false) Defaults to true.
|
107 |
+
* columns: number of columns in shortcode. Defaults to 1. (number, 1-6)
|
108 |
+
* showposts: number of testimonials to display. Defaults to all. (number)
|
109 |
+
* order: display testimonials in ascending or descending chronological order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display testimonials in descending order instead. (ASC/DESC)
|
110 |
+
* orderby: sort testimonials by different criteria, including author name, testimonial title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
|
111 |
+
|
112 |
+
**Example**
|
113 |
+
`
|
114 |
+
[testimonials columns="2" showposts="10" orderby="title"]
|
115 |
+
`
|
116 |
+
The example will display up to ten testimonials in two columns, in ascending alphabetical order by testimonial title.
|
117 |
+
|
118 |
+
***Service Shortcode***
|
119 |
+
|
120 |
+
You can use shortcodes to embed service on posts and pages.
|
121 |
+
|
122 |
+
**Embedding Service Projects**
|
123 |
+
|
124 |
+
To embed service on posts and pages, first activate the Service content type on your site and add some projects to your Service.
|
125 |
+
|
126 |
+
Next, add the `[services]` shortcode to a post or page. The shortcode will display projects in different ways, depending on how you use the optional attributes to customize the featured content layout.
|
127 |
+
|
128 |
+
**Attributes**
|
129 |
+
* display_types: display Content Types. (true/false)
|
130 |
+
* display_tags: display Content Tags. (true/false)
|
131 |
+
* display_content: display project content. (true/false)
|
132 |
+
* include_type: display specific Content Types. Defaults to all. (comma-separated list of Content Type slugs)
|
133 |
+
* include_tag: display specific Content Tags. Defaults to all. (comma-separated list of Content Tag slugs)
|
134 |
+
* columns: number of columns in shortcode. Defaults to 2. (number, 1-6)
|
135 |
+
* showposts: number of projects to display. Defaults to all. (number)
|
136 |
+
* order: display projects in ascending or descending order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display projects in descending order instead. (ASC/DESC)
|
137 |
+
* orderby: sort projects by different criteria, including author name, project title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
|
138 |
+
|
139 |
+
**Example**
|
140 |
+
`
|
141 |
+
[services display_types="true" display_tags="false" include_type="grooming-tips,best-kitties" columns="2" showposts="10" orderby="title"]
|
142 |
+
`
|
143 |
+
The example will display up to ten featured content in two columns, in ascending alphabetical order by project title. It will display Content Types, hide Content Tags, and only display projects that are assigned the “Grooming Tips” or “Best Kitties” Content Types.
|
144 |
+
|
145 |
+
***Food Menu Shortcode***
|
146 |
+
|
147 |
+
You can use shortcodes to embed Food Menu on posts and pages.
|
148 |
+
Embedding Food Menu
|
149 |
+
|
150 |
+
**Embedding Food Menu**
|
151 |
+
|
152 |
+
To embed food menus on posts and pages, first activate the Food Menu custom content type on your site and add some food menus.
|
153 |
+
|
154 |
+
Next, add the `[food_menu]` shortcode to a post or page. The shortcode will display food menu in the selected post or page.
|
155 |
+
|
156 |
+
**Attributes**
|
157 |
+
* showposts: number of menu items to display. Defaults to all. (number)
|
158 |
+
* include_type: display specific Content Types. Defaults to all. (comma-separated list of Content Type slugs)
|
159 |
+
* include_tag: display specific Content Tags. Defaults to all. (comma-separated list of Content Tag slugs)
|
160 |
+
|
161 |
+
**Example**
|
162 |
+
|
163 |
+
`[food_menu showposts="10" include_type="pizza,burger,breakfast"]`
|
164 |
+
The example will display up to ten menu items. It will only display menu items in “Pizza”, “Burger” or “Breakfast” sections.
|
165 |
+
|
166 |
+
== Translations ==
|
167 |
+
|
168 |
+
To translate the plugin, use translate.wordpress.org (GlotPress). You only need your WordPress.org account to join the collaborative translation project.
|
169 |
+
|
170 |
+
You can translate Essential Widgets on [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/essential-content-types/).
|
171 |
+
|
172 |
+
== Installation ==
|
173 |
+
|
174 |
+
The easy way (via Dashboard) :
|
175 |
+
|
176 |
+
* Go to Plugins > Add New
|
177 |
+
* Type in the **Essential Content Types** in Search Plugins box
|
178 |
+
* Click Install Now to install the plugin
|
179 |
+
* After Installation click activate to start using the **Essential Content Types**
|
180 |
+
* Go to **Essential Content Types** from Dashboard menu
|
181 |
+
* Use Shortcodes in your posts/pages/templates
|
182 |
+
|
183 |
+
Not so easy way (via FTP) :
|
184 |
+
|
185 |
+
* Download the **Essential Content Types**
|
186 |
+
* Unarchive **Essential Content Types** plugin
|
187 |
+
* Copy folder with `essential-content-types.zip`
|
188 |
+
* Open the ftp `\wp-content\plugins\`
|
189 |
+
* Paste the plug-ins folder in the folder
|
190 |
+
* Go to admin panel => open item "Plugins" => activate **Essential Content Types**
|
191 |
+
* Go to **Essential Content Types** from Dashboard menu
|
192 |
+
* Use Shortcodes in your posts/pages/templates
|
193 |
+
|
194 |
+
== Screenshots ==
|
195 |
+
|
196 |
+
1. Main Dashboard
|
197 |
+
2. Customizer: Portfolio Archive Options
|
198 |
+
3. Customizer: Testimonial Archive Options
|
199 |
+
4. Customizer: Featured Content Archive Options
|
200 |
+
5. Customizer: Services Archive Options
|
201 |
+
|
202 |
+
== Changelog ==
|
203 |
+
|
204 |
+
= 1.8.6 (Released: August 05, 2021) =
|
205 |
+
* Bug Fixed: Deprecated - Required parameter $atts follows optional parameter
|
206 |
+
* Compatibility check up to version 5.8
|
207 |
+
|
208 |
+
= 1.8.5 (Released: December 14, 2020) =
|
209 |
+
* Bug Fixed: ECT archive title messing with other NON-ECT archive title
|
210 |
+
|
211 |
+
= 1.8.4 (Released: December 07, 2020) =
|
212 |
+
* Bug Fixed: ECT archive title and description via customizer
|
213 |
+
* Compatibility check up to version 5.6
|
214 |
+
|
215 |
+
= 1.8.3 (Released: September 21, 2020) =
|
216 |
+
* Bug Fixed: Check if thumbnail exists on templates
|
217 |
+
|
218 |
+
= 1.8.2 (Released: Aug 19, 2020) =
|
219 |
+
* Bug Fixed: Issue in add new theme page
|
220 |
+
|
221 |
+
= 1.8.1 (Released: May 07, 2020) =
|
222 |
+
* Added: French translation by Charles GIRARDIN
|
223 |
+
|
224 |
+
= 1.8 (Released: March 17, 2020) =
|
225 |
+
* Compatibility check up to version 5.4
|
226 |
+
|
227 |
+
= 1.7 (Released: November 12, 2019) =
|
228 |
+
* Compatibility check up to version 5.3
|
229 |
+
|
230 |
+
= 1.6 (Released: August 20, 2019) =
|
231 |
+
* Added: Option to turn off Catch Themes and Catch Plugins tabs
|
232 |
+
* Compatibility check up to version 5.2
|
233 |
+
* Updated: Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
234 |
+
|
235 |
+
|
236 |
+
= 1.5.1 (Released: April 09, 2019) =
|
237 |
+
* Added: Excerpt support for CPT
|
238 |
+
* Updated: Catch Themes and Catch Plugins tabs displaying code
|
239 |
+
|
240 |
+
= 1.5 (Released: February 21, 2019) =
|
241 |
+
* Compatibility check up to version 5.1
|
242 |
+
|
243 |
+
= 1.4 (Released: December 12, 2018) =
|
244 |
+
* Added: Catch Themes and Catch Plugins tabs in Add themes and Add plugins page respectively
|
245 |
+
* Added: Themes by Catch Themes section under Themes panel in customizer
|
246 |
+
* Bug Fixed: Undefined index when no section is selected for food items
|
247 |
+
* Compatibility check up to version 5.0
|
248 |
+
* Updated: How to use link
|
249 |
+
|
250 |
+
= 1.3 (Released: July 05, 2018) =
|
251 |
+
* Added: Default featured-image-size
|
252 |
+
* Bug fixed: settings_page function found
|
253 |
+
* Changed: function name changed to settings_page
|
254 |
+
* Updated: Html structure
|
255 |
+
|
256 |
+
= 1.2 (Released: May 07, 2018) =
|
257 |
+
* Updated: Moved domain from catchthemes.com to catchplugins.com
|
258 |
+
* Compatibility check up to version 4.9.5
|
259 |
+
|
260 |
+
= 1.1 =
|
261 |
+
* Removed: Unnecessary code hiding menu price in Food Menu CPT
|
262 |
+
|
263 |
+
= 1.0.9 =
|
264 |
+
* Added: CPT-Food Menu Items
|
265 |
+
* Compatibility check up to version 4.9.4
|
266 |
+
* Update: Moved all plugin customizer options to new panel Essential Content Types Plugin Options
|
267 |
+
|
268 |
+
= 1.0.8 =
|
269 |
+
* Compatibility check up to version 4.9
|
270 |
+
|
271 |
+
= 1.0.7 =
|
272 |
+
* Added: Action links in plugin page
|
273 |
+
* Added: Restrict activation if Pro version is active
|
274 |
+
* Updated: Plugin page and reivew links
|
275 |
+
|
276 |
+
= 1.0.6 =
|
277 |
+
* Added: Screenshots: Services Archive Option
|
278 |
+
* Bug Fixed: Services Archive option in Customizer
|
279 |
+
* Bug Fixed: Link to Services Archive option in Dashboard
|
280 |
+
|
281 |
+
= 1.0.5 =
|
282 |
+
* Added: Custom Post Type: Service
|
283 |
+
* Added: Position in Testimonials
|
284 |
+
|
285 |
+
= 1.0.3 & 1.0.4 =
|
286 |
+
* Shortcode instruction link added
|
287 |
+
|
288 |
+
= 1.0.2 =
|
289 |
+
* Checked: Version compatibility WordPress 4.8
|
290 |
+
* Renamed Featured Content to ECT: Featured Content
|
291 |
+
|
292 |
+
= 1.0.1 =
|
293 |
+
* Bug Fixed: Featured Content compatibility with themes with Jetpack: Featured Content Support
|
294 |
+
* Bug Fixed: Admin CSS
|
295 |
+
|
296 |
+
= 1.0.0 =
|
297 |
+
* Initial Release
|
admin/class-essential-content-types-admin.php
CHANGED
@@ -1,259 +1,259 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* The admin-specific functionality of the plugin.
|
5 |
-
*
|
6 |
-
* @link https://catchplugins.com
|
7 |
-
* @since 1.0.0
|
8 |
-
*
|
9 |
-
* @package Essential_Content_Types
|
10 |
-
* @subpackage Essential_Content_Types/admin
|
11 |
-
*/
|
12 |
-
|
13 |
-
/**
|
14 |
-
* The admin-specific functionality of the plugin.
|
15 |
-
*
|
16 |
-
* Defines the plugin name, version, and two examples hooks for how to
|
17 |
-
* enqueue the admin-specific stylesheet and JavaScript.
|
18 |
-
*
|
19 |
-
* @package Essential_Content_Types
|
20 |
-
* @subpackage Essential_Content_Types/admin
|
21 |
-
* @author Catch Plugins <info@catchplugins.com>
|
22 |
-
*/
|
23 |
-
class Essential_Content_Types_Admin {
|
24 |
-
|
25 |
-
/**
|
26 |
-
* The ID of this plugin.
|
27 |
-
*
|
28 |
-
* @since 1.0.0
|
29 |
-
* @access private
|
30 |
-
* @var string $plugin_name The ID of this plugin.
|
31 |
-
*/
|
32 |
-
private $plugin_name;
|
33 |
-
|
34 |
-
/**
|
35 |
-
* The version of this plugin.
|
36 |
-
*
|
37 |
-
* @since 1.0.0
|
38 |
-
* @access private
|
39 |
-
* @var string $version The current version of this plugin.
|
40 |
-
*/
|
41 |
-
private $version;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Initialize the class and set its properties.
|
45 |
-
*
|
46 |
-
* @since 1.0.0
|
47 |
-
* @param string $plugin_name The name of this plugin.
|
48 |
-
* @param string $version The version of this plugin.
|
49 |
-
*/
|
50 |
-
public function __construct( $plugin_name, $version ) {
|
51 |
-
|
52 |
-
$this->plugin_name = $plugin_name;
|
53 |
-
$this->version = $version;
|
54 |
-
|
55 |
-
$this->load_dependencies();
|
56 |
-
|
57 |
-
}
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Load the required dependencies for this plugin.
|
61 |
-
*
|
62 |
-
* Include the following files that make up the plugin:
|
63 |
-
*
|
64 |
-
* - Essential_Content_Types_Loader. Orchestrates the hooks of the plugin.
|
65 |
-
* - Essential_Content_Types_i18n. Defines internationalization functionality.
|
66 |
-
* - Essential_Content_Types_Admin. Defines all hooks for the admin area.
|
67 |
-
* - Essential_Content_Types_Public. Defines all hooks for the public side of the site.
|
68 |
-
*
|
69 |
-
* Create an instance of the loader which will be used to register the hooks
|
70 |
-
* with WordPress.
|
71 |
-
*
|
72 |
-
* @since 1.0.0
|
73 |
-
* @access private
|
74 |
-
*/
|
75 |
-
private function load_dependencies() {
|
76 |
-
|
77 |
-
$portfolio_options = get_option( 'ect_portfolio' );
|
78 |
-
if ( isset($portfolio_options['status']) && $portfolio_options['status'] ) {
|
79 |
-
/**
|
80 |
-
* Load Portfolio Content Type
|
81 |
-
*/
|
82 |
-
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-portfolio.php';
|
83 |
-
}
|
84 |
-
|
85 |
-
$testimonial_options = get_option( 'ect_testimonial' );
|
86 |
-
if ( isset($testimonial_options['status']) && $testimonial_options['status'] ) {
|
87 |
-
/**
|
88 |
-
* Load Testimonial Content Type
|
89 |
-
*/
|
90 |
-
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-testimonial.php';
|
91 |
-
}
|
92 |
-
|
93 |
-
$featured_content_options = get_option( 'ect_featured_content' );
|
94 |
-
if ( isset($featured_content_options['status']) && $featured_content_options['status'] ) {
|
95 |
-
/**
|
96 |
-
* Load Featured Content Type
|
97 |
-
*/
|
98 |
-
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-featured-content.php';
|
99 |
-
}
|
100 |
-
|
101 |
-
$service_options = get_option( 'ect_service' );
|
102 |
-
if ( isset($service_options['status']) && $service_options['status'] ) {
|
103 |
-
/**
|
104 |
-
* Load Service Type
|
105 |
-
*/
|
106 |
-
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-service.php';
|
107 |
-
}
|
108 |
-
|
109 |
-
$food_menu_options = get_option( 'ect_food_menu' );
|
110 |
-
if ( isset($food_menu_options['status']) && $food_menu_options['status'] ) {
|
111 |
-
/**
|
112 |
-
* Load Food Menu Type
|
113 |
-
*/
|
114 |
-
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-food-menu.php';
|
115 |
-
}
|
116 |
-
|
117 |
-
}
|
118 |
-
|
119 |
-
|
120 |
-
/**
|
121 |
-
* Register the stylesheets for the admin area.
|
122 |
-
*
|
123 |
-
* @since 1.0.0
|
124 |
-
*/
|
125 |
-
public function enqueue_styles( $hook_suffix ) {
|
126 |
-
$allowed_pages = array(
|
127 |
-
'toplevel_page_essential-content-types' => 1,
|
128 |
-
'essential-content-types_page_ect-portfolio' => 1,
|
129 |
-
'essential-content-types_page_ect-testimonial' => 1,
|
130 |
-
'essential-content-types_page_ect-featured-content' => 1,
|
131 |
-
'essential-content-types_page_ect-service' => 1,
|
132 |
-
'essential-content-types_page_ect-food-menu' => 1,
|
133 |
-
);
|
134 |
-
|
135 |
-
if ( ! isset( $allowed_pages[ $hook_suffix ] ) ){
|
136 |
-
return;
|
137 |
-
}
|
138 |
-
|
139 |
-
wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/essential-content-types-admin.css', array(), $this->version, 'all' );
|
140 |
-
|
141 |
-
wp_enqueue_style( $this->plugin_name.'-tabs', plugin_dir_url( __FILE__ ) . 'css/admin-dashboard.css', array(), $this->version, 'all' );
|
142 |
-
|
143 |
-
}
|
144 |
-
|
145 |
-
/**
|
146 |
-
* Register the JavaScript for the admin area.
|
147 |
-
*
|
148 |
-
* @since 1.0.0
|
149 |
-
*/
|
150 |
-
public function enqueue_scripts( $hook_suffix ) {
|
151 |
-
$allowed_pages = array(
|
152 |
-
'toplevel_page_essential-content-types' => 1,
|
153 |
-
'essential-content-types_page_ect-portfolio' => 1,
|
154 |
-
'essential-content-types_page_ect-testimonial' => 1,
|
155 |
-
'essential-content-types_page_ect-featured-content' => 1,
|
156 |
-
'essential-content-types_page_ect-service' => 1,
|
157 |
-
'essential-content-types_page_ect-food-menu' => 1,
|
158 |
-
);
|
159 |
-
|
160 |
-
if ( ! isset( $allowed_pages[ $hook_suffix ] ) ){
|
161 |
-
return;
|
162 |
-
}
|
163 |
-
|
164 |
-
wp_enqueue_script( 'minHeight', plugin_dir_url( __FILE__ ) . 'js/jquery.matchHeight.min.js', array( 'jquery' ), $this->version, false );
|
165 |
-
wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/essential-content-types-admin.js', array( 'minHeight', 'jquery' ), $this->version, false );
|
166 |
-
|
167 |
-
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* Essential Content Types: action_links
|
172 |
-
* Essential Content Types Settings Link function callback
|
173 |
-
*
|
174 |
-
* @param arrray $links Link url.
|
175 |
-
*
|
176 |
-
* @param arrray $file File name.
|
177 |
-
*/
|
178 |
-
public function action_links( $links, $file ) {
|
179 |
-
if ( $file === $this->plugin_name . '/' . $this->plugin_name . '.php' ) {
|
180 |
-
$settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=essential-content-types' ) ) . '">' . esc_html__( 'Settings', 'essential-content-types' ) . '</a>';
|
181 |
-
|
182 |
-
array_unshift( $links, $settings_link );
|
183 |
-
}
|
184 |
-
return $links;
|
185 |
-
}
|
186 |
-
|
187 |
-
/**
|
188 |
-
* Add settings menu
|
189 |
-
*/
|
190 |
-
function settings_menu() {
|
191 |
-
// Add Main Menu
|
192 |
-
add_menu_page(
|
193 |
-
esc_html__( 'Essential Content Types', 'essential-content-types' ), //$page_title
|
194 |
-
esc_html__( 'Essential Content Types', 'essential-content-types' ), //$menu_title
|
195 |
-
'manage_options', //$capability
|
196 |
-
'essential-content-types', //$menu_slug
|
197 |
-
array( $this, 'settings_page' ), //$function
|
198 |
-
'dashicons-layout', //$icon_url
|
199 |
-
'99.01564' //$position
|
200 |
-
);
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* Dashboard Page include
|
205 |
-
*/
|
206 |
-
function settings_page() {
|
207 |
-
if ( !current_user_can( 'manage_options' ) ) {
|
208 |
-
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
209 |
-
}
|
210 |
-
|
211 |
-
//require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/dashboard-display.php';
|
212 |
-
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/essential-content-types-admin-display.php';
|
213 |
-
}
|
214 |
-
|
215 |
-
function dashboard_switch() {
|
216 |
-
$value = ( 'true' == $_POST['value'] ) ? 1 : 0;
|
217 |
-
|
218 |
-
$option_name = $_POST['option_name'];
|
219 |
-
|
220 |
-
$option_value = get_option( $option_name );
|
221 |
-
|
222 |
-
$option_value['status'] = $value;
|
223 |
-
|
224 |
-
if( update_option( $option_name, $option_value ) ) {
|
225 |
-
echo $value;
|
226 |
-
} else {
|
227 |
-
esc_html_e( 'Connection Error. Please try again.', 'essential-content-types' );
|
228 |
-
}
|
229 |
-
|
230 |
-
wp_die(); // this is required to terminate immediately and return a proper response
|
231 |
-
}
|
232 |
-
function add_plugin_meta_links( $meta_fields, $file ){
|
233 |
-
|
234 |
-
if( ESSENTIAL_CONTENT_TYPES_BASENAME == $file ) {
|
235 |
-
|
236 |
-
$meta_fields[] = "<a href='https://catchplugins.com/support-forum/forum/essential-content-type/' target='_blank'>Support Forum</a>";
|
237 |
-
$meta_fields[] = "<a href='https://wordpress.org/support/plugin/essential-content-types/#reviews' target='_blank' title='Rate'>
|
238 |
-
<i class='ct-rate-stars'>"
|
239 |
-
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
240 |
-
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
241 |
-
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
242 |
-
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
243 |
-
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
244 |
-
. "</i></a>";
|
245 |
-
|
246 |
-
$stars_color = "#ffb900";
|
247 |
-
|
248 |
-
echo "<style>"
|
249 |
-
. ".ct-rate-stars{display:inline-block;color:" . $stars_color . ";position:relative;top:3px;}"
|
250 |
-
. ".ct-rate-stars svg{fill:" . $stars_color . ";}"
|
251 |
-
. ".ct-rate-stars svg:hover{fill:" . $stars_color . "}"
|
252 |
-
. ".ct-rate-stars svg:hover ~ svg{fill:none;}"
|
253 |
-
. "</style>";
|
254 |
-
}
|
255 |
-
|
256 |
-
return $meta_fields;
|
257 |
-
}
|
258 |
-
|
259 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* The admin-specific functionality of the plugin.
|
5 |
+
*
|
6 |
+
* @link https://catchplugins.com
|
7 |
+
* @since 1.0.0
|
8 |
+
*
|
9 |
+
* @package Essential_Content_Types
|
10 |
+
* @subpackage Essential_Content_Types/admin
|
11 |
+
*/
|
12 |
+
|
13 |
+
/**
|
14 |
+
* The admin-specific functionality of the plugin.
|
15 |
+
*
|
16 |
+
* Defines the plugin name, version, and two examples hooks for how to
|
17 |
+
* enqueue the admin-specific stylesheet and JavaScript.
|
18 |
+
*
|
19 |
+
* @package Essential_Content_Types
|
20 |
+
* @subpackage Essential_Content_Types/admin
|
21 |
+
* @author Catch Plugins <info@catchplugins.com>
|
22 |
+
*/
|
23 |
+
class Essential_Content_Types_Admin {
|
24 |
+
|
25 |
+
/**
|
26 |
+
* The ID of this plugin.
|
27 |
+
*
|
28 |
+
* @since 1.0.0
|
29 |
+
* @access private
|
30 |
+
* @var string $plugin_name The ID of this plugin.
|
31 |
+
*/
|
32 |
+
private $plugin_name;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* The version of this plugin.
|
36 |
+
*
|
37 |
+
* @since 1.0.0
|
38 |
+
* @access private
|
39 |
+
* @var string $version The current version of this plugin.
|
40 |
+
*/
|
41 |
+
private $version;
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Initialize the class and set its properties.
|
45 |
+
*
|
46 |
+
* @since 1.0.0
|
47 |
+
* @param string $plugin_name The name of this plugin.
|
48 |
+
* @param string $version The version of this plugin.
|
49 |
+
*/
|
50 |
+
public function __construct( $plugin_name, $version ) {
|
51 |
+
|
52 |
+
$this->plugin_name = $plugin_name;
|
53 |
+
$this->version = $version;
|
54 |
+
|
55 |
+
$this->load_dependencies();
|
56 |
+
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Load the required dependencies for this plugin.
|
61 |
+
*
|
62 |
+
* Include the following files that make up the plugin:
|
63 |
+
*
|
64 |
+
* - Essential_Content_Types_Loader. Orchestrates the hooks of the plugin.
|
65 |
+
* - Essential_Content_Types_i18n. Defines internationalization functionality.
|
66 |
+
* - Essential_Content_Types_Admin. Defines all hooks for the admin area.
|
67 |
+
* - Essential_Content_Types_Public. Defines all hooks for the public side of the site.
|
68 |
+
*
|
69 |
+
* Create an instance of the loader which will be used to register the hooks
|
70 |
+
* with WordPress.
|
71 |
+
*
|
72 |
+
* @since 1.0.0
|
73 |
+
* @access private
|
74 |
+
*/
|
75 |
+
private function load_dependencies() {
|
76 |
+
|
77 |
+
$portfolio_options = get_option( 'ect_portfolio' );
|
78 |
+
if ( isset($portfolio_options['status']) && $portfolio_options['status'] ) {
|
79 |
+
/**
|
80 |
+
* Load Portfolio Content Type
|
81 |
+
*/
|
82 |
+
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-portfolio.php';
|
83 |
+
}
|
84 |
+
|
85 |
+
$testimonial_options = get_option( 'ect_testimonial' );
|
86 |
+
if ( isset($testimonial_options['status']) && $testimonial_options['status'] ) {
|
87 |
+
/**
|
88 |
+
* Load Testimonial Content Type
|
89 |
+
*/
|
90 |
+
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-testimonial.php';
|
91 |
+
}
|
92 |
+
|
93 |
+
$featured_content_options = get_option( 'ect_featured_content' );
|
94 |
+
if ( isset($featured_content_options['status']) && $featured_content_options['status'] ) {
|
95 |
+
/**
|
96 |
+
* Load Featured Content Type
|
97 |
+
*/
|
98 |
+
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-featured-content.php';
|
99 |
+
}
|
100 |
+
|
101 |
+
$service_options = get_option( 'ect_service' );
|
102 |
+
if ( isset($service_options['status']) && $service_options['status'] ) {
|
103 |
+
/**
|
104 |
+
* Load Service Type
|
105 |
+
*/
|
106 |
+
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-service.php';
|
107 |
+
}
|
108 |
+
|
109 |
+
$food_menu_options = get_option( 'ect_food_menu' );
|
110 |
+
if ( isset($food_menu_options['status']) && $food_menu_options['status'] ) {
|
111 |
+
/**
|
112 |
+
* Load Food Menu Type
|
113 |
+
*/
|
114 |
+
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-food-menu.php';
|
115 |
+
}
|
116 |
+
|
117 |
+
}
|
118 |
+
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Register the stylesheets for the admin area.
|
122 |
+
*
|
123 |
+
* @since 1.0.0
|
124 |
+
*/
|
125 |
+
public function enqueue_styles( $hook_suffix ) {
|
126 |
+
$allowed_pages = array(
|
127 |
+
'toplevel_page_essential-content-types' => 1,
|
128 |
+
'essential-content-types_page_ect-portfolio' => 1,
|
129 |
+
'essential-content-types_page_ect-testimonial' => 1,
|
130 |
+
'essential-content-types_page_ect-featured-content' => 1,
|
131 |
+
'essential-content-types_page_ect-service' => 1,
|
132 |
+
'essential-content-types_page_ect-food-menu' => 1,
|
133 |
+
);
|
134 |
+
|
135 |
+
if ( ! isset( $allowed_pages[ $hook_suffix ] ) ){
|
136 |
+
return;
|
137 |
+
}
|
138 |
+
|
139 |
+
wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/essential-content-types-admin.css', array(), $this->version, 'all' );
|
140 |
+
|
141 |
+
wp_enqueue_style( $this->plugin_name.'-tabs', plugin_dir_url( __FILE__ ) . 'css/admin-dashboard.css', array(), $this->version, 'all' );
|
142 |
+
|
143 |
+
}
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Register the JavaScript for the admin area.
|
147 |
+
*
|
148 |
+
* @since 1.0.0
|
149 |
+
*/
|
150 |
+
public function enqueue_scripts( $hook_suffix ) {
|
151 |
+
$allowed_pages = array(
|
152 |
+
'toplevel_page_essential-content-types' => 1,
|
153 |
+
'essential-content-types_page_ect-portfolio' => 1,
|
154 |
+
'essential-content-types_page_ect-testimonial' => 1,
|
155 |
+
'essential-content-types_page_ect-featured-content' => 1,
|
156 |
+
'essential-content-types_page_ect-service' => 1,
|
157 |
+
'essential-content-types_page_ect-food-menu' => 1,
|
158 |
+
);
|
159 |
+
|
160 |
+
if ( ! isset( $allowed_pages[ $hook_suffix ] ) ){
|
161 |
+
return;
|
162 |
+
}
|
163 |
+
|
164 |
+
wp_enqueue_script( 'minHeight', plugin_dir_url( __FILE__ ) . 'js/jquery.matchHeight.min.js', array( 'jquery' ), $this->version, false );
|
165 |
+
wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/essential-content-types-admin.js', array( 'minHeight', 'jquery' ), $this->version, false );
|
166 |
+
|
167 |
+
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Essential Content Types: action_links
|
172 |
+
* Essential Content Types Settings Link function callback
|
173 |
+
*
|
174 |
+
* @param arrray $links Link url.
|
175 |
+
*
|
176 |
+
* @param arrray $file File name.
|
177 |
+
*/
|
178 |
+
public function action_links( $links, $file ) {
|
179 |
+
if ( $file === $this->plugin_name . '/' . $this->plugin_name . '.php' ) {
|
180 |
+
$settings_link = '<a href="' . esc_url( admin_url( 'admin.php?page=essential-content-types' ) ) . '">' . esc_html__( 'Settings', 'essential-content-types' ) . '</a>';
|
181 |
+
|
182 |
+
array_unshift( $links, $settings_link );
|
183 |
+
}
|
184 |
+
return $links;
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Add settings menu
|
189 |
+
*/
|
190 |
+
function settings_menu() {
|
191 |
+
// Add Main Menu
|
192 |
+
add_menu_page(
|
193 |
+
esc_html__( 'Essential Content Types', 'essential-content-types' ), //$page_title
|
194 |
+
esc_html__( 'Essential Content Types', 'essential-content-types' ), //$menu_title
|
195 |
+
'manage_options', //$capability
|
196 |
+
'essential-content-types', //$menu_slug
|
197 |
+
array( $this, 'settings_page' ), //$function
|
198 |
+
'dashicons-layout', //$icon_url
|
199 |
+
'99.01564' //$position
|
200 |
+
);
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Dashboard Page include
|
205 |
+
*/
|
206 |
+
function settings_page() {
|
207 |
+
if ( !current_user_can( 'manage_options' ) ) {
|
208 |
+
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
|
209 |
+
}
|
210 |
+
|
211 |
+
//require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/dashboard-display.php';
|
212 |
+
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/essential-content-types-admin-display.php';
|
213 |
+
}
|
214 |
+
|
215 |
+
function dashboard_switch() {
|
216 |
+
$value = ( 'true' == $_POST['value'] ) ? 1 : 0;
|
217 |
+
|
218 |
+
$option_name = $_POST['option_name'];
|
219 |
+
|
220 |
+
$option_value = get_option( $option_name );
|
221 |
+
|
222 |
+
$option_value['status'] = $value;
|
223 |
+
|
224 |
+
if( update_option( $option_name, $option_value ) ) {
|
225 |
+
echo $value;
|
226 |
+
} else {
|
227 |
+
esc_html_e( 'Connection Error. Please try again.', 'essential-content-types' );
|
228 |
+
}
|
229 |
+
|
230 |
+
wp_die(); // this is required to terminate immediately and return a proper response
|
231 |
+
}
|
232 |
+
function add_plugin_meta_links( $meta_fields, $file ){
|
233 |
+
|
234 |
+
if( ESSENTIAL_CONTENT_TYPES_BASENAME == $file ) {
|
235 |
+
|
236 |
+
$meta_fields[] = "<a href='https://catchplugins.com/support-forum/forum/essential-content-type/' target='_blank'>Support Forum</a>";
|
237 |
+
$meta_fields[] = "<a href='https://wordpress.org/support/plugin/essential-content-types/#reviews' target='_blank' title='Rate'>
|
238 |
+
<i class='ct-rate-stars'>"
|
239 |
+
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
240 |
+
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
241 |
+
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
242 |
+
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
243 |
+
. "<svg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-star'><polygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2'/></svg>"
|
244 |
+
. "</i></a>";
|
245 |
+
|
246 |
+
$stars_color = "#ffb900";
|
247 |
+
|
248 |
+
echo "<style>"
|
249 |
+
. ".ct-rate-stars{display:inline-block;color:" . $stars_color . ";position:relative;top:3px;}"
|
250 |
+
. ".ct-rate-stars svg{fill:" . $stars_color . ";}"
|
251 |
+
. ".ct-rate-stars svg:hover{fill:" . $stars_color . "}"
|
252 |
+
. ".ct-rate-stars svg:hover ~ svg{fill:none;}"
|
253 |
+
. "</style>";
|
254 |
+
}
|
255 |
+
|
256 |
+
return $meta_fields;
|
257 |
+
}
|
258 |
+
|
259 |
+
}
|
admin/class-featured-content.php
CHANGED
@@ -1,784 +1,784 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Support JetPack Featured Content
|
5 |
-
*/
|
6 |
-
class Essential_Content_Featured_Content {
|
7 |
-
const CUSTOM_POST_TYPE = 'featured-content';
|
8 |
-
const CUSTOM_TAXONOMY_TYPE = 'featured-content-type';
|
9 |
-
const CUSTOM_TAXONOMY_TAG = 'featured-content-tag';
|
10 |
-
const OPTION_NAME = 'featured_content';
|
11 |
-
const OPTION_READING_SETTING = 'featured_content_posts_per_page';
|
12 |
-
|
13 |
-
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
14 |
-
|
15 |
-
static function init() {
|
16 |
-
static $instance = false;
|
17 |
-
|
18 |
-
if ( ! $instance ) {
|
19 |
-
$instance = new Essential_Content_Featured_Content;
|
20 |
-
}
|
21 |
-
|
22 |
-
return $instance;
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Conditionally hook into WordPress.
|
27 |
-
*
|
28 |
-
* Setup user option for enabling CPT
|
29 |
-
* If user has CPT enabled, show in admin
|
30 |
-
*/
|
31 |
-
function __construct() {
|
32 |
-
// Make sure the post types are loaded for imports
|
33 |
-
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
34 |
-
|
35 |
-
// Add to REST API post type whitelist
|
36 |
-
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_featured_content_rest_api_type' ) );
|
37 |
-
|
38 |
-
// CPT magic
|
39 |
-
$this->register_post_types();
|
40 |
-
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
41 |
-
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
42 |
-
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE ), array( $this, 'flush_rules_on_first_content' ) );
|
43 |
-
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
44 |
-
|
45 |
-
// Admin Customization
|
46 |
-
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
47 |
-
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE ), array( $this, 'edit_admin_columns' ) );
|
48 |
-
add_filter( sprintf( 'manage_%s_posts_custom_column', self::CUSTOM_POST_TYPE ), array( $this, 'image_column' ), 10, 2 );
|
49 |
-
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
50 |
-
|
51 |
-
add_image_size( 'featured-content-admin-thumb', 50, 50, true );
|
52 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
|
53 |
-
|
54 |
-
// register featured_content shortcode and featured_content shortcode (legacy)
|
55 |
-
add_shortcode( 'featured_content', array( $this, 'featured_content_shortcode' ) );
|
56 |
-
add_shortcode( 'ect_featured_content', array( $this, 'featured_content_shortcode' ) );
|
57 |
-
|
58 |
-
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
59 |
-
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ) );
|
60 |
-
}
|
61 |
-
|
62 |
-
/*
|
63 |
-
* Flush permalinks when CPT option is turned on/off
|
64 |
-
*/
|
65 |
-
function flush_rules_on_enable() {
|
66 |
-
flush_rewrite_rules();
|
67 |
-
}
|
68 |
-
|
69 |
-
/*
|
70 |
-
* Count published contents and flush permalinks when first contents is published
|
71 |
-
*/
|
72 |
-
function flush_rules_on_first_content() {
|
73 |
-
$contents = get_transient( 'featured-content-count-cache' );
|
74 |
-
|
75 |
-
if ( false === $contents ) {
|
76 |
-
flush_rewrite_rules();
|
77 |
-
$contents = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
78 |
-
|
79 |
-
if ( ! empty( $contents ) ) {
|
80 |
-
set_transient( 'featured-content-count-cache', $contents, HOUR_IN_SECONDS * 12 );
|
81 |
-
}
|
82 |
-
}
|
83 |
-
}
|
84 |
-
|
85 |
-
/*
|
86 |
-
* Flush permalinks when CPT supported theme is activated
|
87 |
-
*/
|
88 |
-
function flush_rules_on_switch() {
|
89 |
-
flush_rewrite_rules();
|
90 |
-
}
|
91 |
-
|
92 |
-
/**
|
93 |
-
* Register Post Type
|
94 |
-
*/
|
95 |
-
function register_post_types() {
|
96 |
-
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
97 |
-
return;
|
98 |
-
}
|
99 |
-
|
100 |
-
$args = array(
|
101 |
-
'description' => esc_html__( 'Featured Content Items', 'essential-content-types' ),
|
102 |
-
'labels' => array(
|
103 |
-
'name' => esc_html__( 'Featured Contents', 'essential-content-types' ),
|
104 |
-
'singular_name' => esc_html__( 'Featured Content', 'essential-content-types' ),
|
105 |
-
'menu_name' => esc_html__( 'Featured Content', 'essential-content-types' ),
|
106 |
-
'all_items' => esc_html__( 'All Contents', 'essential-content-types' ),
|
107 |
-
'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
|
108 |
-
'add_new_item' => esc_html__( 'Add New Content', 'essential-content-types' ),
|
109 |
-
'edit_item' => esc_html__( 'Edit Content', 'essential-content-types' ),
|
110 |
-
'new_item' => esc_html__( 'New Content', 'essential-content-types' ),
|
111 |
-
'view_item' => esc_html__( 'View Content', 'essential-content-types' ),
|
112 |
-
'search_items' => esc_html__( 'Search Contents', 'essential-content-types' ),
|
113 |
-
'not_found' => esc_html__( 'No Contents found', 'essential-content-types' ),
|
114 |
-
'not_found_in_trash' => esc_html__( 'No Contents found in Trash', 'essential-content-types' ),
|
115 |
-
'filter_items_list' => esc_html__( 'Filter contents list', 'essential-content-types' ),
|
116 |
-
'items_list_navigation' => esc_html__( 'Content list navigation', 'essential-content-types' ),
|
117 |
-
'items_list' => esc_html__( 'Contents list', 'essential-content-types' ),
|
118 |
-
),
|
119 |
-
'supports' => array(
|
120 |
-
'title',
|
121 |
-
'editor',
|
122 |
-
'excerpt',
|
123 |
-
'thumbnail',
|
124 |
-
'author',
|
125 |
-
'comments',
|
126 |
-
),
|
127 |
-
'rewrite' => array(
|
128 |
-
'slug' => 'featured-content',
|
129 |
-
'with_front' => false,
|
130 |
-
'feeds' => true,
|
131 |
-
'pages' => true,
|
132 |
-
),
|
133 |
-
'public' => true,
|
134 |
-
'show_ui' => true,
|
135 |
-
'menu_position' => 20, // below Pages
|
136 |
-
'menu_icon' => 'dashicons-grid-view', // 3.8+ dashicon option
|
137 |
-
'capability_type' => 'page',
|
138 |
-
'map_meta_cap' => true,
|
139 |
-
'taxonomies' => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
|
140 |
-
'has_archive' => true,
|
141 |
-
'query_var' => 'featured_content',
|
142 |
-
'show_in_rest' => true,
|
143 |
-
);
|
144 |
-
|
145 |
-
$description = get_option( 'featured_content_content' );
|
146 |
-
if ( '' !== $description ) {
|
147 |
-
$args['description'] = $description;
|
148 |
-
}
|
149 |
-
|
150 |
-
register_post_type(
|
151 |
-
self::CUSTOM_POST_TYPE,
|
152 |
-
$args
|
153 |
-
);
|
154 |
-
|
155 |
-
register_taxonomy(
|
156 |
-
self::CUSTOM_TAXONOMY_TYPE,
|
157 |
-
self::CUSTOM_POST_TYPE,
|
158 |
-
array(
|
159 |
-
'hierarchical' => true,
|
160 |
-
'labels' => array(
|
161 |
-
'name' => esc_html__( 'Content Types', 'essential-content-types' ),
|
162 |
-
'singular_name' => esc_html__( 'Content Type', 'essential-content-types' ),
|
163 |
-
'menu_name' => esc_html__( 'Content Types', 'essential-content-types' ),
|
164 |
-
'all_items' => esc_html__( 'All Content Types', 'essential-content-types' ),
|
165 |
-
'edit_item' => esc_html__( 'Edit Content Type', 'essential-content-types' ),
|
166 |
-
'view_item' => esc_html__( 'View Content Type', 'essential-content-types' ),
|
167 |
-
'update_item' => esc_html__( 'Update Content Type', 'essential-content-types' ),
|
168 |
-
'add_new_item' => esc_html__( 'Add New Content Type', 'essential-content-types' ),
|
169 |
-
'new_item_name' => esc_html__( 'New Content Type Name', 'essential-content-types' ),
|
170 |
-
'parent_item' => esc_html__( 'Parent Content Type', 'essential-content-types' ),
|
171 |
-
'parent_item_colon' => esc_html__( 'Parent Content Type:', 'essential-content-types' ),
|
172 |
-
'search_items' => esc_html__( 'Search Content Types', 'essential-content-types' ),
|
173 |
-
'items_list_navigation' => esc_html__( 'Content type list navigation', 'essential-content-types' ),
|
174 |
-
'items_list' => esc_html__( 'Content type list', 'essential-content-types' ),
|
175 |
-
),
|
176 |
-
'public' => true,
|
177 |
-
'show_ui' => true,
|
178 |
-
'show_in_nav_menus' => true,
|
179 |
-
'show_in_rest' => true,
|
180 |
-
'show_admin_column' => true,
|
181 |
-
'query_var' => true,
|
182 |
-
'rewrite' => array( 'slug' => 'content-type' ),
|
183 |
-
)
|
184 |
-
);
|
185 |
-
|
186 |
-
register_taxonomy(
|
187 |
-
self::CUSTOM_TAXONOMY_TAG,
|
188 |
-
self::CUSTOM_POST_TYPE,
|
189 |
-
array(
|
190 |
-
'hierarchical' => false,
|
191 |
-
'labels' => array(
|
192 |
-
'name' => esc_html__( 'Content Tags', 'essential-content-types' ),
|
193 |
-
'singular_name' => esc_html__( 'Content Tag', 'essential-content-types' ),
|
194 |
-
'menu_name' => esc_html__( 'Content Tags', 'essential-content-types' ),
|
195 |
-
'all_items' => esc_html__( 'All Content Tags', 'essential-content-types' ),
|
196 |
-
'edit_item' => esc_html__( 'Edit Content Tag', 'essential-content-types' ),
|
197 |
-
'view_item' => esc_html__( 'View Content Tag', 'essential-content-types' ),
|
198 |
-
'update_item' => esc_html__( 'Update Content Tag', 'essential-content-types' ),
|
199 |
-
'add_new_item' => esc_html__( 'Add New Content Tag', 'essential-content-types' ),
|
200 |
-
'new_item_name' => esc_html__( 'New Content Tag Name', 'essential-content-types' ),
|
201 |
-
'search_items' => esc_html__( 'Search Content Tags', 'essential-content-types' ),
|
202 |
-
'popular_items' => esc_html__( 'Popular Content Tags', 'essential-content-types' ),
|
203 |
-
'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
|
204 |
-
'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
|
205 |
-
'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
|
206 |
-
'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
|
207 |
-
'items_list_navigation' => esc_html__( 'Content tag list navigation', 'essential-content-types' ),
|
208 |
-
'items_list' => esc_html__( 'Content tag list', 'essential-content-types' ),
|
209 |
-
),
|
210 |
-
'public' => true,
|
211 |
-
'show_ui' => true,
|
212 |
-
'show_in_nav_menus' => true,
|
213 |
-
'show_in_rest' => true,
|
214 |
-
'show_admin_column' => true,
|
215 |
-
'query_var' => true,
|
216 |
-
'rewrite' => array( 'slug' => 'content-tag' ),
|
217 |
-
)
|
218 |
-
);
|
219 |
-
}
|
220 |
-
|
221 |
-
/**
|
222 |
-
* Update messages for the Featured Content admin.
|
223 |
-
*/
|
224 |
-
function updated_messages( $messages ) {
|
225 |
-
global $post;
|
226 |
-
|
227 |
-
$messages[ self::CUSTOM_POST_TYPE ] = array(
|
228 |
-
0 => '', // Unused. Messages start at index 1.
|
229 |
-
1 => sprintf( __( 'Content updated. <a href="%s">View item</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
230 |
-
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
231 |
-
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
232 |
-
4 => esc_html__( 'Content updated.', 'essential-content-types' ),
|
233 |
-
/* translators: %s: date and time of the revision */
|
234 |
-
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Content restored to revision from %s', 'essential-content-types' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
235 |
-
6 => sprintf( __( 'Content published. <a href="%s">View content</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
236 |
-
7 => esc_html__( 'Content saved.', 'essential-content-types' ),
|
237 |
-
8 => sprintf( __( 'Content submitted. <a target="_blank" href="%s">Preview content</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
238 |
-
9 => sprintf(
|
239 |
-
__( 'Content scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview content</a>', 'essential-content-types' ),
|
240 |
-
// translators: Publish box date format, see http://php.net/date
|
241 |
-
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ),
|
242 |
-
esc_url( get_permalink( $post->ID ) )
|
243 |
-
),
|
244 |
-
10 => sprintf( __( 'Content item draft updated. <a target="_blank" href="%s">Preview content</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
245 |
-
);
|
246 |
-
|
247 |
-
return $messages;
|
248 |
-
}
|
249 |
-
|
250 |
-
/**
|
251 |
-
* Change ‘Title’ column label
|
252 |
-
* Add Featured Image column
|
253 |
-
*/
|
254 |
-
function edit_admin_columns( $columns ) {
|
255 |
-
// change 'Title' to 'Content'
|
256 |
-
$columns['title'] = __( 'Content', 'essential-content-types' );
|
257 |
-
if ( current_theme_supports( 'post-thumbnails' ) ) {
|
258 |
-
// add featured image before 'Content'
|
259 |
-
$columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, null, true );
|
260 |
-
}
|
261 |
-
|
262 |
-
return $columns;
|
263 |
-
}
|
264 |
-
|
265 |
-
/**
|
266 |
-
* Add featured image to column
|
267 |
-
*/
|
268 |
-
function image_column( $column, $post_id ) {
|
269 |
-
global $post;
|
270 |
-
switch ( $column ) {
|
271 |
-
case 'thumbnail':
|
272 |
-
echo get_the_post_thumbnail( $post_id, 'featured-content-admin-thumb' );
|
273 |
-
break;
|
274 |
-
}
|
275 |
-
}
|
276 |
-
|
277 |
-
/**
|
278 |
-
* Adjust image column width
|
279 |
-
*/
|
280 |
-
function enqueue_admin_styles( $hook ) {
|
281 |
-
$screen = get_current_screen();
|
282 |
-
|
283 |
-
if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
|
284 |
-
wp_add_inline_style( 'wp-admin', '.column-thumbnail img:nth-of-type(2) { display: none; } .manage-column.column-thumbnail { width: 50px; } @media screen and (max-width: 360px) { .column-thumbnail{ display:none; } }' );
|
285 |
-
}
|
286 |
-
}
|
287 |
-
|
288 |
-
/**
|
289 |
-
* Adds featured_content section to the Customizer.
|
290 |
-
*/
|
291 |
-
function customize_register( $wp_customize ) {
|
292 |
-
$wp_customize->add_panel(
|
293 |
-
'ect_plugin_options',
|
294 |
-
array(
|
295 |
-
'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
|
296 |
-
'priority' => 1,
|
297 |
-
)
|
298 |
-
);
|
299 |
-
|
300 |
-
$wp_customize->add_section(
|
301 |
-
'ect_featured_content',
|
302 |
-
array(
|
303 |
-
'title' => esc_html__( 'Featured Content', 'essential-content-types' ),
|
304 |
-
'panel' => 'ect_plugin_options',
|
305 |
-
)
|
306 |
-
);
|
307 |
-
|
308 |
-
$wp_customize->add_setting(
|
309 |
-
'featured_content_title',
|
310 |
-
array(
|
311 |
-
'default' => esc_html__( 'Contents', 'essential-content-types' ),
|
312 |
-
'type' => 'option',
|
313 |
-
'sanitize_callback' => 'sanitize_text_field',
|
314 |
-
'sanitize_js_callback' => 'sanitize_text_field',
|
315 |
-
)
|
316 |
-
);
|
317 |
-
|
318 |
-
$wp_customize->add_control(
|
319 |
-
'featured_content_title',
|
320 |
-
array(
|
321 |
-
'section' => 'ect_featured_content',
|
322 |
-
'label' => esc_html__( 'Featured Content Archive Title', 'essential-content-types' ),
|
323 |
-
'type' => 'text',
|
324 |
-
)
|
325 |
-
);
|
326 |
-
|
327 |
-
$wp_customize->add_setting(
|
328 |
-
'featured_content_content',
|
329 |
-
array(
|
330 |
-
'default' => '',
|
331 |
-
'type' => 'option',
|
332 |
-
'sanitize_callback' => 'wp_kses_post',
|
333 |
-
'sanitize_js_callback' => 'wp_kses_post',
|
334 |
-
)
|
335 |
-
);
|
336 |
-
|
337 |
-
$wp_customize->add_control(
|
338 |
-
'featured_content_content',
|
339 |
-
array(
|
340 |
-
'section' => 'ect_featured_content',
|
341 |
-
'label' => esc_html__( 'Featured Content Archive Content', 'essential-content-types' ),
|
342 |
-
'type' => 'textarea',
|
343 |
-
)
|
344 |
-
);
|
345 |
-
|
346 |
-
$wp_customize->add_setting(
|
347 |
-
'featured_content_featured_image',
|
348 |
-
array(
|
349 |
-
'default' => '',
|
350 |
-
'type' => 'option',
|
351 |
-
'sanitize_callback' => 'attachment_url_to_postid',
|
352 |
-
'sanitize_js_callback' => 'attachment_url_to_postid',
|
353 |
-
'theme_supports' => 'post-thumbnails',
|
354 |
-
)
|
355 |
-
);
|
356 |
-
|
357 |
-
$wp_customize->add_control(
|
358 |
-
new WP_Customize_Image_Control(
|
359 |
-
$wp_customize,
|
360 |
-
'featured_content_featured_image',
|
361 |
-
array(
|
362 |
-
'section' => 'ect_featured_content',
|
363 |
-
'label' => esc_html__( 'Featured Content Archive Featured Image', 'essential-content-types' ),
|
364 |
-
)
|
365 |
-
)
|
366 |
-
);
|
367 |
-
}
|
368 |
-
|
369 |
-
/**
|
370 |
-
* Follow CPT reading setting on CPT archive and taxonomy pages
|
371 |
-
*/
|
372 |
-
function query_reading_setting( $query ) {
|
373 |
-
if ( ! is_admin() &&
|
374 |
-
$query->is_main_query() &&
|
375 |
-
( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
|
376 |
-
) {
|
377 |
-
$post_per_page = ( null != get_option( 'posts_per_page' ) ) ? get_option( 'posts_per_page' ) : '10';
|
378 |
-
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
|
379 |
-
}
|
380 |
-
}
|
381 |
-
|
382 |
-
/**
|
383 |
-
* Add to REST API post type whitelist
|
384 |
-
*/
|
385 |
-
function allow_featured_content_rest_api_type( $post_types ) {
|
386 |
-
$post_types[] = self::CUSTOM_POST_TYPE;
|
387 |
-
|
388 |
-
return $post_types;
|
389 |
-
}
|
390 |
-
|
391 |
-
/**
|
392 |
-
* Our [featured_content] shortcode.
|
393 |
-
* Prints Featured Content data styled to look good on *any* theme.
|
394 |
-
*
|
395 |
-
* @return featured_content_shortcode_html
|
396 |
-
*/
|
397 |
-
static function featured_content_shortcode( $atts ) {
|
398 |
-
// Default attributes
|
399 |
-
$atts = shortcode_atts(
|
400 |
-
array(
|
401 |
-
'image' => true,
|
402 |
-
'display_types' => true,
|
403 |
-
'display_tags' => true,
|
404 |
-
'display_content' => true,
|
405 |
-
'display_author' => false,
|
406 |
-
'show_filter' => false,
|
407 |
-
'include_type' => false,
|
408 |
-
'include_tag' => false,
|
409 |
-
'columns' => 2,
|
410 |
-
'showposts' => -1,
|
411 |
-
'order' => 'asc',
|
412 |
-
'orderby' => 'date',
|
413 |
-
),
|
414 |
-
$atts,
|
415 |
-
'featured_content'
|
416 |
-
);
|
417 |
-
|
418 |
-
// A little sanitization
|
419 |
-
if ( $atts['image'] && 'true' != $atts['image'] ) {
|
420 |
-
$atts['image'] = false;
|
421 |
-
}
|
422 |
-
|
423 |
-
if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
|
424 |
-
$atts['display_types'] = false;
|
425 |
-
}
|
426 |
-
|
427 |
-
if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
|
428 |
-
$atts['display_tags'] = false;
|
429 |
-
}
|
430 |
-
|
431 |
-
if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
|
432 |
-
$atts['display_author'] = false;
|
433 |
-
}
|
434 |
-
|
435 |
-
if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
|
436 |
-
$atts['display_content'] = false;
|
437 |
-
}
|
438 |
-
|
439 |
-
if ( $atts['include_type'] ) {
|
440 |
-
$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
|
441 |
-
}
|
442 |
-
|
443 |
-
if ( $atts['include_tag'] ) {
|
444 |
-
$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
|
445 |
-
}
|
446 |
-
|
447 |
-
// Check if column value is set to valid numbers or else set default value as 2
|
448 |
-
if ( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
|
449 |
-
$atts['columns'] = absint( $atts['columns'] );
|
450 |
-
} else {
|
451 |
-
$atts['columns'] = 2;
|
452 |
-
}
|
453 |
-
|
454 |
-
$atts['showposts'] = intval( $atts['showposts'] );
|
455 |
-
|
456 |
-
if ( $atts['order'] ) {
|
457 |
-
$atts['order'] = urldecode( $atts['order'] );
|
458 |
-
$atts['order'] = strtoupper( $atts['order'] );
|
459 |
-
if ( 'DESC' != $atts['order'] ) {
|
460 |
-
$atts['order'] = 'ASC';
|
461 |
-
}
|
462 |
-
}
|
463 |
-
|
464 |
-
if ( $atts['orderby'] ) {
|
465 |
-
$atts['orderby'] = urldecode( $atts['orderby'] );
|
466 |
-
$atts['orderby'] = strtolower( $atts['orderby'] );
|
467 |
-
$allowed_keys = array( 'author', 'date', 'title', 'rand' );
|
468 |
-
|
469 |
-
$parsed = array();
|
470 |
-
foreach ( explode( ',', $atts['orderby'] ) as $featured_content_index_number => $orderby ) {
|
471 |
-
if ( ! in_array( $orderby, $allowed_keys ) ) {
|
472 |
-
continue;
|
473 |
-
}
|
474 |
-
$parsed[] = $orderby;
|
475 |
-
}
|
476 |
-
|
477 |
-
if ( empty( $parsed ) ) {
|
478 |
-
unset( $atts['orderby'] );
|
479 |
-
} else {
|
480 |
-
$atts['orderby'] = implode( ' ', $parsed );
|
481 |
-
}
|
482 |
-
}
|
483 |
-
|
484 |
-
// enqueue shortcode styles when shortcode is used
|
485 |
-
wp_enqueue_style( 'featured-content-style', plugins_url( 'css/featured-content-shortcode.css', __FILE__ ), array(), '20140326' );
|
486 |
-
|
487 |
-
return self::featured_content_shortcode_html( $atts );
|
488 |
-
}
|
489 |
-
|
490 |
-
/**
|
491 |
-
* Query to retrieve entries from the Featured Content post_type.
|
492 |
-
*
|
493 |
-
* @return object
|
494 |
-
*/
|
495 |
-
static function featured_content_query( $atts ) {
|
496 |
-
// Default query arguments
|
497 |
-
$default = array(
|
498 |
-
'order' => $atts['order'],
|
499 |
-
'orderby' => $atts['orderby'],
|
500 |
-
'posts_per_page' => $atts['showposts'],
|
501 |
-
);
|
502 |
-
|
503 |
-
$args = wp_parse_args( $atts, $default );
|
504 |
-
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
505 |
-
|
506 |
-
if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
|
507 |
-
$args['tax_query'] = array();
|
508 |
-
}
|
509 |
-
|
510 |
-
// If 'include_type' has been set use it on the main query
|
511 |
-
if ( false != $atts['include_type'] ) {
|
512 |
-
array_push(
|
513 |
-
$args['tax_query'],
|
514 |
-
array(
|
515 |
-
'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
|
516 |
-
'field' => 'slug',
|
517 |
-
'terms' => $atts['include_type'],
|
518 |
-
)
|
519 |
-
);
|
520 |
-
}
|
521 |
-
|
522 |
-
// If 'include_tag' has been set use it on the main query
|
523 |
-
if ( false != $atts['include_tag'] ) {
|
524 |
-
array_push(
|
525 |
-
$args['tax_query'],
|
526 |
-
array(
|
527 |
-
'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
|
528 |
-
'field' => 'slug',
|
529 |
-
'terms' => $atts['include_tag'],
|
530 |
-
)
|
531 |
-
);
|
532 |
-
}
|
533 |
-
|
534 |
-
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
535 |
-
$args['tax_query']['relation'] = 'AND';
|
536 |
-
}
|
537 |
-
|
538 |
-
// Run the query and return
|
539 |
-
$query = new WP_Query( $args );
|
540 |
-
return $query;
|
541 |
-
}
|
542 |
-
|
543 |
-
/**
|
544 |
-
* The Featured Content shortcode loop.
|
545 |
-
*
|
546 |
-
* @todo add theme color styles
|
547 |
-
* @return html
|
548 |
-
*/
|
549 |
-
static function featured_content_shortcode_html( $atts ) {
|
550 |
-
|
551 |
-
$query = self::featured_content_query( $atts );
|
552 |
-
|
553 |
-
ob_start();
|
554 |
-
|
555 |
-
// If we have posts, create the html
|
556 |
-
// with featured-content markup
|
557 |
-
if ( $query->have_posts() ) {
|
558 |
-
|
559 |
-
/**
|
560 |
-
* Hook: ect_before_featured_content_loop.
|
561 |
-
*
|
562 |
-
* @hooked ect_featured_content_section_open
|
563 |
-
*/
|
564 |
-
$layout = ect_get_layout();
|
565 |
-
do_action( 'ect_before_featured_content_loop', $layout[ $atts['columns'] ] );
|
566 |
-
|
567 |
-
?>
|
568 |
-
<?php
|
569 |
-
while ( $query->have_posts() ) {
|
570 |
-
$query->the_post();
|
571 |
-
ect_get_template_part( 'content', 'featured-content', $atts );
|
572 |
-
}
|
573 |
-
wp_reset_postdata();
|
574 |
-
?>
|
575 |
-
|
576 |
-
<?php
|
577 |
-
|
578 |
-
/**
|
579 |
-
* Hook: ect_after_featured_content_loop.
|
580 |
-
*
|
581 |
-
* @hooked essential_content_pro_featured_content_section_close
|
582 |
-
*/
|
583 |
-
do_action( 'ect_after_featured_content_loop' );
|
584 |
-
|
585 |
-
} else {
|
586 |
-
/**
|
587 |
-
* Hook: ect_no_articles_found.
|
588 |
-
*
|
589 |
-
* @hooked ect_no_articles_found
|
590 |
-
*/
|
591 |
-
do_action( 'ect_no_featured_content_found' );
|
592 |
-
}
|
593 |
-
|
594 |
-
$html = ob_get_clean();
|
595 |
-
|
596 |
-
// If there is a [featured-content] within a [featured-content], remove the shortcode
|
597 |
-
if ( has_shortcode( $html, 'featured-content' ) ) {
|
598 |
-
remove_shortcode( 'featured-content' );
|
599 |
-
}
|
600 |
-
|
601 |
-
// Return the HTML block
|
602 |
-
return $html;
|
603 |
-
}
|
604 |
-
|
605 |
-
/**
|
606 |
-
* Displays the content type that a content belongs to.
|
607 |
-
*
|
608 |
-
* @return html
|
609 |
-
*/
|
610 |
-
static function get_content_type( $post_id ) {
|
611 |
-
$content_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
|
612 |
-
|
613 |
-
// If no types, return empty string
|
614 |
-
if ( empty( $content_types ) || is_wp_error( $content_types ) ) {
|
615 |
-
return;
|
616 |
-
}
|
617 |
-
|
618 |
-
$html = '<div class="content-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
|
619 |
-
$types = array();
|
620 |
-
// Loop thorugh all the types
|
621 |
-
foreach ( $content_types as $content_type ) {
|
622 |
-
$content_type_link = get_term_link( $content_type, self::CUSTOM_TAXONOMY_TYPE );
|
623 |
-
|
624 |
-
if ( is_wp_error( $content_type_link ) ) {
|
625 |
-
return $content_type_link;
|
626 |
-
}
|
627 |
-
|
628 |
-
$types[] = '<a href="' . esc_url( $content_type_link ) . '" rel="tag">' . esc_html( $content_type->name ) . '</a>';
|
629 |
-
}
|
630 |
-
$html .= ' ' . implode( ', ', $types );
|
631 |
-
$html .= '</div>';
|
632 |
-
|
633 |
-
return $html;
|
634 |
-
}
|
635 |
-
|
636 |
-
/**
|
637 |
-
* Displays the content tags that a content belongs to.
|
638 |
-
*
|
639 |
-
* @return html
|
640 |
-
*/
|
641 |
-
static function get_content_tags( $post_id ) {
|
642 |
-
$content_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
|
643 |
-
|
644 |
-
// If no tags, return empty string
|
645 |
-
if ( empty( $content_tags ) || is_wp_error( $content_tags ) ) {
|
646 |
-
return false;
|
647 |
-
}
|
648 |
-
|
649 |
-
$html = '<div class="content-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
|
650 |
-
$tags = array();
|
651 |
-
// Loop thorugh all the tags
|
652 |
-
foreach ( $content_tags as $content_tag ) {
|
653 |
-
$content_tag_link = get_term_link( $content_tag, self::CUSTOM_TAXONOMY_TYPE );
|
654 |
-
|
655 |
-
if ( is_wp_error( $content_tag_link ) ) {
|
656 |
-
return $content_tag_link;
|
657 |
-
}
|
658 |
-
|
659 |
-
$tags[] = '<a href="' . esc_url( $content_tag_link ) . '" rel="tag">' . esc_html( $content_tag->name ) . '</a>';
|
660 |
-
}
|
661 |
-
$html .= ' ' . implode( ', ', $tags );
|
662 |
-
$html .= '</div>';
|
663 |
-
|
664 |
-
return $html;
|
665 |
-
}
|
666 |
-
|
667 |
-
/**
|
668 |
-
* Displays the author of the current featured_content content.
|
669 |
-
*
|
670 |
-
* @return html
|
671 |
-
*/
|
672 |
-
static function get_content_author() {
|
673 |
-
$html = '<div class="content-author">';
|
674 |
-
/* translators: %1$s is link to author posts, %2$s is author display name */
|
675 |
-
$html .= sprintf(
|
676 |
-
__( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
|
677 |
-
esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
|
678 |
-
esc_html( get_the_author() )
|
679 |
-
);
|
680 |
-
$html .= '</div>';
|
681 |
-
|
682 |
-
return $html;
|
683 |
-
}
|
684 |
-
}
|
685 |
-
add_action( 'init', array( 'Essential_Content_Featured_Content', 'init' ) );
|
686 |
-
|
687 |
-
/**
|
688 |
-
* Add Featured Content support
|
689 |
-
*/
|
690 |
-
function essential_content_featured_content_support() {
|
691 |
-
/*
|
692 |
-
* Adding theme support for Jetpack Featured Content CPT.
|
693 |
-
*/
|
694 |
-
add_image_size( 'ect-featured-content', 640, 640, true );
|
695 |
-
}
|
696 |
-
add_action( 'after_setup_theme', 'essential_content_featured_content_support' );
|
697 |
-
|
698 |
-
|
699 |
-
if ( ! function_exists( 'essential_content_get_featured_content_thumbnail_link' ) ) :
|
700 |
-
/**
|
701 |
-
* Display the featured image if it's available
|
702 |
-
*
|
703 |
-
* @return html
|
704 |
-
*/
|
705 |
-
function essential_content_get_featured_content_thumbnail_link( $post_id, $size ) {
|
706 |
-
if ( has_post_thumbnail( $post_id ) ) {
|
707 |
-
/**
|
708 |
-
* Change the Featured Content thumbnail size.
|
709 |
-
*
|
710 |
-
* @module custom-content-types
|
711 |
-
*
|
712 |
-
* @since 3.4.0
|
713 |
-
*
|
714 |
-
* @param string|array $var Either a registered size keyword or size array.
|
715 |
-
*/
|
716 |
-
return '<a class="featured-content-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'featured_content_thumbnail_size', $size ) ) . '</a>';
|
717 |
-
}
|
718 |
-
}
|
719 |
-
endif;
|
720 |
-
|
721 |
-
|
722 |
-
if ( ! function_exists( 'essential_content_no_featured_content_found' ) ) :
|
723 |
-
/**
|
724 |
-
* No items found text
|
725 |
-
*
|
726 |
-
* @return html
|
727 |
-
*/
|
728 |
-
function essential_content_no_featured_content_found() {
|
729 |
-
echo '<p><em>' . esc_html__( 'Your Featured Content Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . '</em></p>';
|
730 |
-
}
|
731 |
-
add_action( 'ect_no_featured_content_found', 'essential_content_no_featured_content_found', 10 );
|
732 |
-
endif;
|
733 |
-
|
734 |
-
|
735 |
-
if ( ! function_exists( 'essential_content_featured_content_section_open' ) ) :
|
736 |
-
/**
|
737 |
-
* Open section
|
738 |
-
*
|
739 |
-
* @return html
|
740 |
-
*/
|
741 |
-
function essential_content_featured_content_section_open( $layout ) {
|
742 |
-
echo '<div class="ect-featured-content ect-section ' . $layout . '">';
|
743 |
-
echo '<div class="ect-wrapper">';
|
744 |
-
}
|
745 |
-
endif;
|
746 |
-
add_action( 'ect_before_featured_content_loop', 'essential_content_featured_content_section_open', 10, 1 );
|
747 |
-
|
748 |
-
|
749 |
-
if ( ! function_exists( 'essential_content_featured_content_loop_start' ) ) :
|
750 |
-
/**
|
751 |
-
* open wrapper before loop
|
752 |
-
*
|
753 |
-
*/
|
754 |
-
function essential_content_featured_content_loop_start( $layout = null ) {
|
755 |
-
echo '<div class="section-content-wrapper featured-content-wrapper ' . $layout . '">';
|
756 |
-
}
|
757 |
-
endif;
|
758 |
-
add_action( 'ect_before_featured_content_loop', 'essential_content_featured_content_loop_start', 30 );
|
759 |
-
|
760 |
-
|
761 |
-
if ( ! function_exists( 'ect_featured_content_loop_end' ) ) :
|
762 |
-
/**
|
763 |
-
* close wrapper after loop
|
764 |
-
*
|
765 |
-
*/
|
766 |
-
function essential_content_featured_content_loop_end() {
|
767 |
-
echo '</div><!-- .featured-content-wrapper -->';
|
768 |
-
}
|
769 |
-
endif;
|
770 |
-
add_action( 'ect_after_featured_content_loop', 'essential_content_featured_content_loop_end', 10 );
|
771 |
-
|
772 |
-
|
773 |
-
if ( ! function_exists( 'ect_featured_content_section_close' ) ) :
|
774 |
-
/**
|
775 |
-
* Close section
|
776 |
-
*
|
777 |
-
* @return html
|
778 |
-
*/
|
779 |
-
function essential_content_featured_content_section_close() {
|
780 |
-
echo '</div><!-- .ect-wrapper -->';
|
781 |
-
echo '</div><!-- .ect-section -->';
|
782 |
-
}
|
783 |
-
endif;
|
784 |
-
add_action( 'ect_after_featured_content_loop', 'essential_content_featured_content_section_close', 20 );
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Support JetPack Featured Content
|
5 |
+
*/
|
6 |
+
class Essential_Content_Featured_Content {
|
7 |
+
const CUSTOM_POST_TYPE = 'featured-content';
|
8 |
+
const CUSTOM_TAXONOMY_TYPE = 'featured-content-type';
|
9 |
+
const CUSTOM_TAXONOMY_TAG = 'featured-content-tag';
|
10 |
+
const OPTION_NAME = 'featured_content';
|
11 |
+
const OPTION_READING_SETTING = 'featured_content_posts_per_page';
|
12 |
+
|
13 |
+
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
14 |
+
|
15 |
+
static function init() {
|
16 |
+
static $instance = false;
|
17 |
+
|
18 |
+
if ( ! $instance ) {
|
19 |
+
$instance = new Essential_Content_Featured_Content;
|
20 |
+
}
|
21 |
+
|
22 |
+
return $instance;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Conditionally hook into WordPress.
|
27 |
+
*
|
28 |
+
* Setup user option for enabling CPT
|
29 |
+
* If user has CPT enabled, show in admin
|
30 |
+
*/
|
31 |
+
function __construct() {
|
32 |
+
// Make sure the post types are loaded for imports
|
33 |
+
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
34 |
+
|
35 |
+
// Add to REST API post type whitelist
|
36 |
+
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_featured_content_rest_api_type' ) );
|
37 |
+
|
38 |
+
// CPT magic
|
39 |
+
$this->register_post_types();
|
40 |
+
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
41 |
+
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
42 |
+
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE ), array( $this, 'flush_rules_on_first_content' ) );
|
43 |
+
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
44 |
+
|
45 |
+
// Admin Customization
|
46 |
+
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
47 |
+
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE ), array( $this, 'edit_admin_columns' ) );
|
48 |
+
add_filter( sprintf( 'manage_%s_posts_custom_column', self::CUSTOM_POST_TYPE ), array( $this, 'image_column' ), 10, 2 );
|
49 |
+
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
50 |
+
|
51 |
+
add_image_size( 'featured-content-admin-thumb', 50, 50, true );
|
52 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
|
53 |
+
|
54 |
+
// register featured_content shortcode and featured_content shortcode (legacy)
|
55 |
+
add_shortcode( 'featured_content', array( $this, 'featured_content_shortcode' ) );
|
56 |
+
add_shortcode( 'ect_featured_content', array( $this, 'featured_content_shortcode' ) );
|
57 |
+
|
58 |
+
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
59 |
+
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ) );
|
60 |
+
}
|
61 |
+
|
62 |
+
/*
|
63 |
+
* Flush permalinks when CPT option is turned on/off
|
64 |
+
*/
|
65 |
+
function flush_rules_on_enable() {
|
66 |
+
flush_rewrite_rules();
|
67 |
+
}
|
68 |
+
|
69 |
+
/*
|
70 |
+
* Count published contents and flush permalinks when first contents is published
|
71 |
+
*/
|
72 |
+
function flush_rules_on_first_content() {
|
73 |
+
$contents = get_transient( 'featured-content-count-cache' );
|
74 |
+
|
75 |
+
if ( false === $contents ) {
|
76 |
+
flush_rewrite_rules();
|
77 |
+
$contents = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
78 |
+
|
79 |
+
if ( ! empty( $contents ) ) {
|
80 |
+
set_transient( 'featured-content-count-cache', $contents, HOUR_IN_SECONDS * 12 );
|
81 |
+
}
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
/*
|
86 |
+
* Flush permalinks when CPT supported theme is activated
|
87 |
+
*/
|
88 |
+
function flush_rules_on_switch() {
|
89 |
+
flush_rewrite_rules();
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Register Post Type
|
94 |
+
*/
|
95 |
+
function register_post_types() {
|
96 |
+
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
97 |
+
return;
|
98 |
+
}
|
99 |
+
|
100 |
+
$args = array(
|
101 |
+
'description' => esc_html__( 'Featured Content Items', 'essential-content-types' ),
|
102 |
+
'labels' => array(
|
103 |
+
'name' => esc_html__( 'Featured Contents', 'essential-content-types' ),
|
104 |
+
'singular_name' => esc_html__( 'Featured Content', 'essential-content-types' ),
|
105 |
+
'menu_name' => esc_html__( 'Featured Content', 'essential-content-types' ),
|
106 |
+
'all_items' => esc_html__( 'All Contents', 'essential-content-types' ),
|
107 |
+
'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
|
108 |
+
'add_new_item' => esc_html__( 'Add New Content', 'essential-content-types' ),
|
109 |
+
'edit_item' => esc_html__( 'Edit Content', 'essential-content-types' ),
|
110 |
+
'new_item' => esc_html__( 'New Content', 'essential-content-types' ),
|
111 |
+
'view_item' => esc_html__( 'View Content', 'essential-content-types' ),
|
112 |
+
'search_items' => esc_html__( 'Search Contents', 'essential-content-types' ),
|
113 |
+
'not_found' => esc_html__( 'No Contents found', 'essential-content-types' ),
|
114 |
+
'not_found_in_trash' => esc_html__( 'No Contents found in Trash', 'essential-content-types' ),
|
115 |
+
'filter_items_list' => esc_html__( 'Filter contents list', 'essential-content-types' ),
|
116 |
+
'items_list_navigation' => esc_html__( 'Content list navigation', 'essential-content-types' ),
|
117 |
+
'items_list' => esc_html__( 'Contents list', 'essential-content-types' ),
|
118 |
+
),
|
119 |
+
'supports' => array(
|
120 |
+
'title',
|
121 |
+
'editor',
|
122 |
+
'excerpt',
|
123 |
+
'thumbnail',
|
124 |
+
'author',
|
125 |
+
'comments',
|
126 |
+
),
|
127 |
+
'rewrite' => array(
|
128 |
+
'slug' => 'featured-content',
|
129 |
+
'with_front' => false,
|
130 |
+
'feeds' => true,
|
131 |
+
'pages' => true,
|
132 |
+
),
|
133 |
+
'public' => true,
|
134 |
+
'show_ui' => true,
|
135 |
+
'menu_position' => 20, // below Pages
|
136 |
+
'menu_icon' => 'dashicons-grid-view', // 3.8+ dashicon option
|
137 |
+
'capability_type' => 'page',
|
138 |
+
'map_meta_cap' => true,
|
139 |
+
'taxonomies' => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
|
140 |
+
'has_archive' => true,
|
141 |
+
'query_var' => 'featured_content',
|
142 |
+
'show_in_rest' => true,
|
143 |
+
);
|
144 |
+
|
145 |
+
$description = get_option( 'featured_content_content' );
|
146 |
+
if ( '' !== $description ) {
|
147 |
+
$args['description'] = $description;
|
148 |
+
}
|
149 |
+
|
150 |
+
register_post_type(
|
151 |
+
self::CUSTOM_POST_TYPE,
|
152 |
+
$args
|
153 |
+
);
|
154 |
+
|
155 |
+
register_taxonomy(
|
156 |
+
self::CUSTOM_TAXONOMY_TYPE,
|
157 |
+
self::CUSTOM_POST_TYPE,
|
158 |
+
array(
|
159 |
+
'hierarchical' => true,
|
160 |
+
'labels' => array(
|
161 |
+
'name' => esc_html__( 'Content Types', 'essential-content-types' ),
|
162 |
+
'singular_name' => esc_html__( 'Content Type', 'essential-content-types' ),
|
163 |
+
'menu_name' => esc_html__( 'Content Types', 'essential-content-types' ),
|
164 |
+
'all_items' => esc_html__( 'All Content Types', 'essential-content-types' ),
|
165 |
+
'edit_item' => esc_html__( 'Edit Content Type', 'essential-content-types' ),
|
166 |
+
'view_item' => esc_html__( 'View Content Type', 'essential-content-types' ),
|
167 |
+
'update_item' => esc_html__( 'Update Content Type', 'essential-content-types' ),
|
168 |
+
'add_new_item' => esc_html__( 'Add New Content Type', 'essential-content-types' ),
|
169 |
+
'new_item_name' => esc_html__( 'New Content Type Name', 'essential-content-types' ),
|
170 |
+
'parent_item' => esc_html__( 'Parent Content Type', 'essential-content-types' ),
|
171 |
+
'parent_item_colon' => esc_html__( 'Parent Content Type:', 'essential-content-types' ),
|
172 |
+
'search_items' => esc_html__( 'Search Content Types', 'essential-content-types' ),
|
173 |
+
'items_list_navigation' => esc_html__( 'Content type list navigation', 'essential-content-types' ),
|
174 |
+
'items_list' => esc_html__( 'Content type list', 'essential-content-types' ),
|
175 |
+
),
|
176 |
+
'public' => true,
|
177 |
+
'show_ui' => true,
|
178 |
+
'show_in_nav_menus' => true,
|
179 |
+
'show_in_rest' => true,
|
180 |
+
'show_admin_column' => true,
|
181 |
+
'query_var' => true,
|
182 |
+
'rewrite' => array( 'slug' => 'content-type' ),
|
183 |
+
)
|
184 |
+
);
|
185 |
+
|
186 |
+
register_taxonomy(
|
187 |
+
self::CUSTOM_TAXONOMY_TAG,
|
188 |
+
self::CUSTOM_POST_TYPE,
|
189 |
+
array(
|
190 |
+
'hierarchical' => false,
|
191 |
+
'labels' => array(
|
192 |
+
'name' => esc_html__( 'Content Tags', 'essential-content-types' ),
|
193 |
+
'singular_name' => esc_html__( 'Content Tag', 'essential-content-types' ),
|
194 |
+
'menu_name' => esc_html__( 'Content Tags', 'essential-content-types' ),
|
195 |
+
'all_items' => esc_html__( 'All Content Tags', 'essential-content-types' ),
|
196 |
+
'edit_item' => esc_html__( 'Edit Content Tag', 'essential-content-types' ),
|
197 |
+
'view_item' => esc_html__( 'View Content Tag', 'essential-content-types' ),
|
198 |
+
'update_item' => esc_html__( 'Update Content Tag', 'essential-content-types' ),
|
199 |
+
'add_new_item' => esc_html__( 'Add New Content Tag', 'essential-content-types' ),
|
200 |
+
'new_item_name' => esc_html__( 'New Content Tag Name', 'essential-content-types' ),
|
201 |
+
'search_items' => esc_html__( 'Search Content Tags', 'essential-content-types' ),
|
202 |
+
'popular_items' => esc_html__( 'Popular Content Tags', 'essential-content-types' ),
|
203 |
+
'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
|
204 |
+
'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
|
205 |
+
'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
|
206 |
+
'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
|
207 |
+
'items_list_navigation' => esc_html__( 'Content tag list navigation', 'essential-content-types' ),
|
208 |
+
'items_list' => esc_html__( 'Content tag list', 'essential-content-types' ),
|
209 |
+
),
|
210 |
+
'public' => true,
|
211 |
+
'show_ui' => true,
|
212 |
+
'show_in_nav_menus' => true,
|
213 |
+
'show_in_rest' => true,
|
214 |
+
'show_admin_column' => true,
|
215 |
+
'query_var' => true,
|
216 |
+
'rewrite' => array( 'slug' => 'content-tag' ),
|
217 |
+
)
|
218 |
+
);
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Update messages for the Featured Content admin.
|
223 |
+
*/
|
224 |
+
function updated_messages( $messages ) {
|
225 |
+
global $post;
|
226 |
+
|
227 |
+
$messages[ self::CUSTOM_POST_TYPE ] = array(
|
228 |
+
0 => '', // Unused. Messages start at index 1.
|
229 |
+
1 => sprintf( __( 'Content updated. <a href="%s">View item</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
230 |
+
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
231 |
+
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
232 |
+
4 => esc_html__( 'Content updated.', 'essential-content-types' ),
|
233 |
+
/* translators: %s: date and time of the revision */
|
234 |
+
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Content restored to revision from %s', 'essential-content-types' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
235 |
+
6 => sprintf( __( 'Content published. <a href="%s">View content</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
236 |
+
7 => esc_html__( 'Content saved.', 'essential-content-types' ),
|
237 |
+
8 => sprintf( __( 'Content submitted. <a target="_blank" href="%s">Preview content</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
238 |
+
9 => sprintf(
|
239 |
+
__( 'Content scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview content</a>', 'essential-content-types' ),
|
240 |
+
// translators: Publish box date format, see http://php.net/date
|
241 |
+
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ),
|
242 |
+
esc_url( get_permalink( $post->ID ) )
|
243 |
+
),
|
244 |
+
10 => sprintf( __( 'Content item draft updated. <a target="_blank" href="%s">Preview content</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
245 |
+
);
|
246 |
+
|
247 |
+
return $messages;
|
248 |
+
}
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Change ‘Title’ column label
|
252 |
+
* Add Featured Image column
|
253 |
+
*/
|
254 |
+
function edit_admin_columns( $columns ) {
|
255 |
+
// change 'Title' to 'Content'
|
256 |
+
$columns['title'] = __( 'Content', 'essential-content-types' );
|
257 |
+
if ( current_theme_supports( 'post-thumbnails' ) ) {
|
258 |
+
// add featured image before 'Content'
|
259 |
+
$columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, null, true );
|
260 |
+
}
|
261 |
+
|
262 |
+
return $columns;
|
263 |
+
}
|
264 |
+
|
265 |
+
/**
|
266 |
+
* Add featured image to column
|
267 |
+
*/
|
268 |
+
function image_column( $column, $post_id ) {
|
269 |
+
global $post;
|
270 |
+
switch ( $column ) {
|
271 |
+
case 'thumbnail':
|
272 |
+
echo get_the_post_thumbnail( $post_id, 'featured-content-admin-thumb' );
|
273 |
+
break;
|
274 |
+
}
|
275 |
+
}
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Adjust image column width
|
279 |
+
*/
|
280 |
+
function enqueue_admin_styles( $hook ) {
|
281 |
+
$screen = get_current_screen();
|
282 |
+
|
283 |
+
if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
|
284 |
+
wp_add_inline_style( 'wp-admin', '.column-thumbnail img:nth-of-type(2) { display: none; } .manage-column.column-thumbnail { width: 50px; } @media screen and (max-width: 360px) { .column-thumbnail{ display:none; } }' );
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Adds featured_content section to the Customizer.
|
290 |
+
*/
|
291 |
+
function customize_register( $wp_customize ) {
|
292 |
+
$wp_customize->add_panel(
|
293 |
+
'ect_plugin_options',
|
294 |
+
array(
|
295 |
+
'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
|
296 |
+
'priority' => 1,
|
297 |
+
)
|
298 |
+
);
|
299 |
+
|
300 |
+
$wp_customize->add_section(
|
301 |
+
'ect_featured_content',
|
302 |
+
array(
|
303 |
+
'title' => esc_html__( 'Featured Content', 'essential-content-types' ),
|
304 |
+
'panel' => 'ect_plugin_options',
|
305 |
+
)
|
306 |
+
);
|
307 |
+
|
308 |
+
$wp_customize->add_setting(
|
309 |
+
'featured_content_title',
|
310 |
+
array(
|
311 |
+
'default' => esc_html__( 'Contents', 'essential-content-types' ),
|
312 |
+
'type' => 'option',
|
313 |
+
'sanitize_callback' => 'sanitize_text_field',
|
314 |
+
'sanitize_js_callback' => 'sanitize_text_field',
|
315 |
+
)
|
316 |
+
);
|
317 |
+
|
318 |
+
$wp_customize->add_control(
|
319 |
+
'featured_content_title',
|
320 |
+
array(
|
321 |
+
'section' => 'ect_featured_content',
|
322 |
+
'label' => esc_html__( 'Featured Content Archive Title', 'essential-content-types' ),
|
323 |
+
'type' => 'text',
|
324 |
+
)
|
325 |
+
);
|
326 |
+
|
327 |
+
$wp_customize->add_setting(
|
328 |
+
'featured_content_content',
|
329 |
+
array(
|
330 |
+
'default' => '',
|
331 |
+
'type' => 'option',
|
332 |
+
'sanitize_callback' => 'wp_kses_post',
|
333 |
+
'sanitize_js_callback' => 'wp_kses_post',
|
334 |
+
)
|
335 |
+
);
|
336 |
+
|
337 |
+
$wp_customize->add_control(
|
338 |
+
'featured_content_content',
|
339 |
+
array(
|
340 |
+
'section' => 'ect_featured_content',
|
341 |
+
'label' => esc_html__( 'Featured Content Archive Content', 'essential-content-types' ),
|
342 |
+
'type' => 'textarea',
|
343 |
+
)
|
344 |
+
);
|
345 |
+
|
346 |
+
$wp_customize->add_setting(
|
347 |
+
'featured_content_featured_image',
|
348 |
+
array(
|
349 |
+
'default' => '',
|
350 |
+
'type' => 'option',
|
351 |
+
'sanitize_callback' => 'attachment_url_to_postid',
|
352 |
+
'sanitize_js_callback' => 'attachment_url_to_postid',
|
353 |
+
'theme_supports' => 'post-thumbnails',
|
354 |
+
)
|
355 |
+
);
|
356 |
+
|
357 |
+
$wp_customize->add_control(
|
358 |
+
new WP_Customize_Image_Control(
|
359 |
+
$wp_customize,
|
360 |
+
'featured_content_featured_image',
|
361 |
+
array(
|
362 |
+
'section' => 'ect_featured_content',
|
363 |
+
'label' => esc_html__( 'Featured Content Archive Featured Image', 'essential-content-types' ),
|
364 |
+
)
|
365 |
+
)
|
366 |
+
);
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* Follow CPT reading setting on CPT archive and taxonomy pages
|
371 |
+
*/
|
372 |
+
function query_reading_setting( $query ) {
|
373 |
+
if ( ! is_admin() &&
|
374 |
+
$query->is_main_query() &&
|
375 |
+
( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
|
376 |
+
) {
|
377 |
+
$post_per_page = ( null != get_option( 'posts_per_page' ) ) ? get_option( 'posts_per_page' ) : '10';
|
378 |
+
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
/**
|
383 |
+
* Add to REST API post type whitelist
|
384 |
+
*/
|
385 |
+
function allow_featured_content_rest_api_type( $post_types ) {
|
386 |
+
$post_types[] = self::CUSTOM_POST_TYPE;
|
387 |
+
|
388 |
+
return $post_types;
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* Our [featured_content] shortcode.
|
393 |
+
* Prints Featured Content data styled to look good on *any* theme.
|
394 |
+
*
|
395 |
+
* @return featured_content_shortcode_html
|
396 |
+
*/
|
397 |
+
static function featured_content_shortcode( $atts ) {
|
398 |
+
// Default attributes
|
399 |
+
$atts = shortcode_atts(
|
400 |
+
array(
|
401 |
+
'image' => true,
|
402 |
+
'display_types' => true,
|
403 |
+
'display_tags' => true,
|
404 |
+
'display_content' => true,
|
405 |
+
'display_author' => false,
|
406 |
+
'show_filter' => false,
|
407 |
+
'include_type' => false,
|
408 |
+
'include_tag' => false,
|
409 |
+
'columns' => 2,
|
410 |
+
'showposts' => -1,
|
411 |
+
'order' => 'asc',
|
412 |
+
'orderby' => 'date',
|
413 |
+
),
|
414 |
+
$atts,
|
415 |
+
'featured_content'
|
416 |
+
);
|
417 |
+
|
418 |
+
// A little sanitization
|
419 |
+
if ( $atts['image'] && 'true' != $atts['image'] ) {
|
420 |
+
$atts['image'] = false;
|
421 |
+
}
|
422 |
+
|
423 |
+
if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
|
424 |
+
$atts['display_types'] = false;
|
425 |
+
}
|
426 |
+
|
427 |
+
if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
|
428 |
+
$atts['display_tags'] = false;
|
429 |
+
}
|
430 |
+
|
431 |
+
if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
|
432 |
+
$atts['display_author'] = false;
|
433 |
+
}
|
434 |
+
|
435 |
+
if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
|
436 |
+
$atts['display_content'] = false;
|
437 |
+
}
|
438 |
+
|
439 |
+
if ( $atts['include_type'] ) {
|
440 |
+
$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
|
441 |
+
}
|
442 |
+
|
443 |
+
if ( $atts['include_tag'] ) {
|
444 |
+
$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
|
445 |
+
}
|
446 |
+
|
447 |
+
// Check if column value is set to valid numbers or else set default value as 2
|
448 |
+
if ( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
|
449 |
+
$atts['columns'] = absint( $atts['columns'] );
|
450 |
+
} else {
|
451 |
+
$atts['columns'] = 2;
|
452 |
+
}
|
453 |
+
|
454 |
+
$atts['showposts'] = intval( $atts['showposts'] );
|
455 |
+
|
456 |
+
if ( $atts['order'] ) {
|
457 |
+
$atts['order'] = urldecode( $atts['order'] );
|
458 |
+
$atts['order'] = strtoupper( $atts['order'] );
|
459 |
+
if ( 'DESC' != $atts['order'] ) {
|
460 |
+
$atts['order'] = 'ASC';
|
461 |
+
}
|
462 |
+
}
|
463 |
+
|
464 |
+
if ( $atts['orderby'] ) {
|
465 |
+
$atts['orderby'] = urldecode( $atts['orderby'] );
|
466 |
+
$atts['orderby'] = strtolower( $atts['orderby'] );
|
467 |
+
$allowed_keys = array( 'author', 'date', 'title', 'rand' );
|
468 |
+
|
469 |
+
$parsed = array();
|
470 |
+
foreach ( explode( ',', $atts['orderby'] ) as $featured_content_index_number => $orderby ) {
|
471 |
+
if ( ! in_array( $orderby, $allowed_keys ) ) {
|
472 |
+
continue;
|
473 |
+
}
|
474 |
+
$parsed[] = $orderby;
|
475 |
+
}
|
476 |
+
|
477 |
+
if ( empty( $parsed ) ) {
|
478 |
+
unset( $atts['orderby'] );
|
479 |
+
} else {
|
480 |
+
$atts['orderby'] = implode( ' ', $parsed );
|
481 |
+
}
|
482 |
+
}
|
483 |
+
|
484 |
+
// enqueue shortcode styles when shortcode is used
|
485 |
+
wp_enqueue_style( 'featured-content-style', plugins_url( 'css/featured-content-shortcode.css', __FILE__ ), array(), '20140326' );
|
486 |
+
|
487 |
+
return self::featured_content_shortcode_html( $atts );
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* Query to retrieve entries from the Featured Content post_type.
|
492 |
+
*
|
493 |
+
* @return object
|
494 |
+
*/
|
495 |
+
static function featured_content_query( $atts ) {
|
496 |
+
// Default query arguments
|
497 |
+
$default = array(
|
498 |
+
'order' => $atts['order'],
|
499 |
+
'orderby' => $atts['orderby'],
|
500 |
+
'posts_per_page' => $atts['showposts'],
|
501 |
+
);
|
502 |
+
|
503 |
+
$args = wp_parse_args( $atts, $default );
|
504 |
+
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
505 |
+
|
506 |
+
if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
|
507 |
+
$args['tax_query'] = array();
|
508 |
+
}
|
509 |
+
|
510 |
+
// If 'include_type' has been set use it on the main query
|
511 |
+
if ( false != $atts['include_type'] ) {
|
512 |
+
array_push(
|
513 |
+
$args['tax_query'],
|
514 |
+
array(
|
515 |
+
'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
|
516 |
+
'field' => 'slug',
|
517 |
+
'terms' => $atts['include_type'],
|
518 |
+
)
|
519 |
+
);
|
520 |
+
}
|
521 |
+
|
522 |
+
// If 'include_tag' has been set use it on the main query
|
523 |
+
if ( false != $atts['include_tag'] ) {
|
524 |
+
array_push(
|
525 |
+
$args['tax_query'],
|
526 |
+
array(
|
527 |
+
'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
|
528 |
+
'field' => 'slug',
|
529 |
+
'terms' => $atts['include_tag'],
|
530 |
+
)
|
531 |
+
);
|
532 |
+
}
|
533 |
+
|
534 |
+
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
535 |
+
$args['tax_query']['relation'] = 'AND';
|
536 |
+
}
|
537 |
+
|
538 |
+
// Run the query and return
|
539 |
+
$query = new WP_Query( $args );
|
540 |
+
return $query;
|
541 |
+
}
|
542 |
+
|
543 |
+
/**
|
544 |
+
* The Featured Content shortcode loop.
|
545 |
+
*
|
546 |
+
* @todo add theme color styles
|
547 |
+
* @return html
|
548 |
+
*/
|
549 |
+
static function featured_content_shortcode_html( $atts ) {
|
550 |
+
|
551 |
+
$query = self::featured_content_query( $atts );
|
552 |
+
|
553 |
+
ob_start();
|
554 |
+
|
555 |
+
// If we have posts, create the html
|
556 |
+
// with featured-content markup
|
557 |
+
if ( $query->have_posts() ) {
|
558 |
+
|
559 |
+
/**
|
560 |
+
* Hook: ect_before_featured_content_loop.
|
561 |
+
*
|
562 |
+
* @hooked ect_featured_content_section_open
|
563 |
+
*/
|
564 |
+
$layout = ect_get_layout();
|
565 |
+
do_action( 'ect_before_featured_content_loop', $layout[ $atts['columns'] ] );
|
566 |
+
|
567 |
+
?>
|
568 |
+
<?php
|
569 |
+
while ( $query->have_posts() ) {
|
570 |
+
$query->the_post();
|
571 |
+
ect_get_template_part( 'content', 'featured-content', $atts );
|
572 |
+
}
|
573 |
+
wp_reset_postdata();
|
574 |
+
?>
|
575 |
+
|
576 |
+
<?php
|
577 |
+
|
578 |
+
/**
|
579 |
+
* Hook: ect_after_featured_content_loop.
|
580 |
+
*
|
581 |
+
* @hooked essential_content_pro_featured_content_section_close
|
582 |
+
*/
|
583 |
+
do_action( 'ect_after_featured_content_loop' );
|
584 |
+
|
585 |
+
} else {
|
586 |
+
/**
|
587 |
+
* Hook: ect_no_articles_found.
|
588 |
+
*
|
589 |
+
* @hooked ect_no_articles_found
|
590 |
+
*/
|
591 |
+
do_action( 'ect_no_featured_content_found' );
|
592 |
+
}
|
593 |
+
|
594 |
+
$html = ob_get_clean();
|
595 |
+
|
596 |
+
// If there is a [featured-content] within a [featured-content], remove the shortcode
|
597 |
+
if ( has_shortcode( $html, 'featured-content' ) ) {
|
598 |
+
remove_shortcode( 'featured-content' );
|
599 |
+
}
|
600 |
+
|
601 |
+
// Return the HTML block
|
602 |
+
return $html;
|
603 |
+
}
|
604 |
+
|
605 |
+
/**
|
606 |
+
* Displays the content type that a content belongs to.
|
607 |
+
*
|
608 |
+
* @return html
|
609 |
+
*/
|
610 |
+
static function get_content_type( $post_id ) {
|
611 |
+
$content_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
|
612 |
+
|
613 |
+
// If no types, return empty string
|
614 |
+
if ( empty( $content_types ) || is_wp_error( $content_types ) ) {
|
615 |
+
return;
|
616 |
+
}
|
617 |
+
|
618 |
+
$html = '<div class="content-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
|
619 |
+
$types = array();
|
620 |
+
// Loop thorugh all the types
|
621 |
+
foreach ( $content_types as $content_type ) {
|
622 |
+
$content_type_link = get_term_link( $content_type, self::CUSTOM_TAXONOMY_TYPE );
|
623 |
+
|
624 |
+
if ( is_wp_error( $content_type_link ) ) {
|
625 |
+
return $content_type_link;
|
626 |
+
}
|
627 |
+
|
628 |
+
$types[] = '<a href="' . esc_url( $content_type_link ) . '" rel="tag">' . esc_html( $content_type->name ) . '</a>';
|
629 |
+
}
|
630 |
+
$html .= ' ' . implode( ', ', $types );
|
631 |
+
$html .= '</div>';
|
632 |
+
|
633 |
+
return $html;
|
634 |
+
}
|
635 |
+
|
636 |
+
/**
|
637 |
+
* Displays the content tags that a content belongs to.
|
638 |
+
*
|
639 |
+
* @return html
|
640 |
+
*/
|
641 |
+
static function get_content_tags( $post_id ) {
|
642 |
+
$content_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
|
643 |
+
|
644 |
+
// If no tags, return empty string
|
645 |
+
if ( empty( $content_tags ) || is_wp_error( $content_tags ) ) {
|
646 |
+
return false;
|
647 |
+
}
|
648 |
+
|
649 |
+
$html = '<div class="content-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
|
650 |
+
$tags = array();
|
651 |
+
// Loop thorugh all the tags
|
652 |
+
foreach ( $content_tags as $content_tag ) {
|
653 |
+
$content_tag_link = get_term_link( $content_tag, self::CUSTOM_TAXONOMY_TYPE );
|
654 |
+
|
655 |
+
if ( is_wp_error( $content_tag_link ) ) {
|
656 |
+
return $content_tag_link;
|
657 |
+
}
|
658 |
+
|
659 |
+
$tags[] = '<a href="' . esc_url( $content_tag_link ) . '" rel="tag">' . esc_html( $content_tag->name ) . '</a>';
|
660 |
+
}
|
661 |
+
$html .= ' ' . implode( ', ', $tags );
|
662 |
+
$html .= '</div>';
|
663 |
+
|
664 |
+
return $html;
|
665 |
+
}
|
666 |
+
|
667 |
+
/**
|
668 |
+
* Displays the author of the current featured_content content.
|
669 |
+
*
|
670 |
+
* @return html
|
671 |
+
*/
|
672 |
+
static function get_content_author() {
|
673 |
+
$html = '<div class="content-author">';
|
674 |
+
/* translators: %1$s is link to author posts, %2$s is author display name */
|
675 |
+
$html .= sprintf(
|
676 |
+
__( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
|
677 |
+
esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
|
678 |
+
esc_html( get_the_author() )
|
679 |
+
);
|
680 |
+
$html .= '</div>';
|
681 |
+
|
682 |
+
return $html;
|
683 |
+
}
|
684 |
+
}
|
685 |
+
add_action( 'init', array( 'Essential_Content_Featured_Content', 'init' ) );
|
686 |
+
|
687 |
+
/**
|
688 |
+
* Add Featured Content support
|
689 |
+
*/
|
690 |
+
function essential_content_featured_content_support() {
|
691 |
+
/*
|
692 |
+
* Adding theme support for Jetpack Featured Content CPT.
|
693 |
+
*/
|
694 |
+
add_image_size( 'ect-featured-content', 640, 640, true );
|
695 |
+
}
|
696 |
+
add_action( 'after_setup_theme', 'essential_content_featured_content_support' );
|
697 |
+
|
698 |
+
|
699 |
+
if ( ! function_exists( 'essential_content_get_featured_content_thumbnail_link' ) ) :
|
700 |
+
/**
|
701 |
+
* Display the featured image if it's available
|
702 |
+
*
|
703 |
+
* @return html
|
704 |
+
*/
|
705 |
+
function essential_content_get_featured_content_thumbnail_link( $post_id, $size ) {
|
706 |
+
if ( has_post_thumbnail( $post_id ) ) {
|
707 |
+
/**
|
708 |
+
* Change the Featured Content thumbnail size.
|
709 |
+
*
|
710 |
+
* @module custom-content-types
|
711 |
+
*
|
712 |
+
* @since 3.4.0
|
713 |
+
*
|
714 |
+
* @param string|array $var Either a registered size keyword or size array.
|
715 |
+
*/
|
716 |
+
return '<a class="featured-content-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'featured_content_thumbnail_size', $size ) ) . '</a>';
|
717 |
+
}
|
718 |
+
}
|
719 |
+
endif;
|
720 |
+
|
721 |
+
|
722 |
+
if ( ! function_exists( 'essential_content_no_featured_content_found' ) ) :
|
723 |
+
/**
|
724 |
+
* No items found text
|
725 |
+
*
|
726 |
+
* @return html
|
727 |
+
*/
|
728 |
+
function essential_content_no_featured_content_found() {
|
729 |
+
echo '<p><em>' . esc_html__( 'Your Featured Content Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . '</em></p>';
|
730 |
+
}
|
731 |
+
add_action( 'ect_no_featured_content_found', 'essential_content_no_featured_content_found', 10 );
|
732 |
+
endif;
|
733 |
+
|
734 |
+
|
735 |
+
if ( ! function_exists( 'essential_content_featured_content_section_open' ) ) :
|
736 |
+
/**
|
737 |
+
* Open section
|
738 |
+
*
|
739 |
+
* @return html
|
740 |
+
*/
|
741 |
+
function essential_content_featured_content_section_open( $layout ) {
|
742 |
+
echo '<div class="ect-featured-content ect-section ' . $layout . '">';
|
743 |
+
echo '<div class="ect-wrapper">';
|
744 |
+
}
|
745 |
+
endif;
|
746 |
+
add_action( 'ect_before_featured_content_loop', 'essential_content_featured_content_section_open', 10, 1 );
|
747 |
+
|
748 |
+
|
749 |
+
if ( ! function_exists( 'essential_content_featured_content_loop_start' ) ) :
|
750 |
+
/**
|
751 |
+
* open wrapper before loop
|
752 |
+
*
|
753 |
+
*/
|
754 |
+
function essential_content_featured_content_loop_start( $layout = null ) {
|
755 |
+
echo '<div class="section-content-wrapper featured-content-wrapper ' . $layout . '">';
|
756 |
+
}
|
757 |
+
endif;
|
758 |
+
add_action( 'ect_before_featured_content_loop', 'essential_content_featured_content_loop_start', 30 );
|
759 |
+
|
760 |
+
|
761 |
+
if ( ! function_exists( 'ect_featured_content_loop_end' ) ) :
|
762 |
+
/**
|
763 |
+
* close wrapper after loop
|
764 |
+
*
|
765 |
+
*/
|
766 |
+
function essential_content_featured_content_loop_end() {
|
767 |
+
echo '</div><!-- .featured-content-wrapper -->';
|
768 |
+
}
|
769 |
+
endif;
|
770 |
+
add_action( 'ect_after_featured_content_loop', 'essential_content_featured_content_loop_end', 10 );
|
771 |
+
|
772 |
+
|
773 |
+
if ( ! function_exists( 'ect_featured_content_section_close' ) ) :
|
774 |
+
/**
|
775 |
+
* Close section
|
776 |
+
*
|
777 |
+
* @return html
|
778 |
+
*/
|
779 |
+
function essential_content_featured_content_section_close() {
|
780 |
+
echo '</div><!-- .ect-wrapper -->';
|
781 |
+
echo '</div><!-- .ect-section -->';
|
782 |
+
}
|
783 |
+
endif;
|
784 |
+
add_action( 'ect_after_featured_content_loop', 'essential_content_featured_content_section_close', 20 );
|
admin/class-food-menu.php
CHANGED
@@ -1,1538 +1,1538 @@
|
|
1 |
-
<?php
|
2 |
-
/*
|
3 |
-
* Put the following code in your theme's Food Menu Page Template to customize the markup of the menu.
|
4 |
-
|
5 |
-
if ( class_exists( 'Essential_Content_Food_Menu' ) ) {
|
6 |
-
Essential_Content_Food_Menu::init( array(
|
7 |
-
'menu_tag' => 'section',
|
8 |
-
'menu_class' => 'menu-items',
|
9 |
-
'menu_header_tag' => 'header',
|
10 |
-
'menu_header_class' => 'menu-group-header',
|
11 |
-
'menu_title_tag' => 'h1',
|
12 |
-
'menu_title_class' => 'menu-group-title',
|
13 |
-
'menu_description_tag' => 'div',
|
14 |
-
'menu_description_class' => 'menu-group-description',
|
15 |
-
) );
|
16 |
-
}
|
17 |
-
|
18 |
-
*/
|
19 |
-
|
20 |
-
/* @todo
|
21 |
-
|
22 |
-
Bulk/Quick edit response of Menu Item rows is broken.
|
23 |
-
|
24 |
-
Drag and Drop reordering.
|
25 |
-
*/
|
26 |
-
|
27 |
-
class Essential_Content_Food_Menu {
|
28 |
-
const MENU_ITEM_POST_TYPE = 'ect_food_menu_item';
|
29 |
-
const MENU_ITEM_LABEL_TAX = 'ect_food_menu_item_label';
|
30 |
-
const MENU_TAX = 'ect_food_menu';
|
31 |
-
|
32 |
-
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
33 |
-
|
34 |
-
protected $default_menu_item_loop_markup = array(
|
35 |
-
'menu_tag' => 'section',
|
36 |
-
'menu_class' => 'menu-items',
|
37 |
-
'menu_header_tag' => 'header',
|
38 |
-
'menu_header_class' => 'menu-group-header',
|
39 |
-
'menu_title_tag' => 'h1',
|
40 |
-
'menu_title_class' => 'menu-group-title',
|
41 |
-
'menu_description_tag' => 'div',
|
42 |
-
'menu_description_class' => 'menu-group-description',
|
43 |
-
);
|
44 |
-
|
45 |
-
protected $menu_item_loop_markup = array();
|
46 |
-
protected $menu_item_loop_last_term_id = false;
|
47 |
-
protected $menu_item_loop_current_term = false;
|
48 |
-
|
49 |
-
static function init( $menu_item_loop_markup = array() ) {
|
50 |
-
static $instance = false;
|
51 |
-
|
52 |
-
if ( !$instance ) {
|
53 |
-
$instance = new Essential_Content_Food_Menu;
|
54 |
-
}
|
55 |
-
|
56 |
-
if ( $menu_item_loop_markup ) {
|
57 |
-
$instance->menu_item_loop_markup = wp_parse_args( $menu_item_loop_markup, $instance->default_menu_item_loop_markup );
|
58 |
-
}
|
59 |
-
|
60 |
-
return $instance;
|
61 |
-
}
|
62 |
-
|
63 |
-
function __construct() {
|
64 |
-
if ( ! $this->site_supports_food_menu() )
|
65 |
-
return;
|
66 |
-
|
67 |
-
$this->register_taxonomies();
|
68 |
-
$this->register_post_types();
|
69 |
-
add_action( 'admin_menu', array( $this, 'add_admin_menus' ) );
|
70 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_ect_food_styles' ) );
|
71 |
-
add_action( 'admin_head', array( $this, 'set_custom_font_icon' ) );
|
72 |
-
|
73 |
-
// Enable Omnisearch for Menu Items.
|
74 |
-
if ( class_exists( 'Jetpack_Omnisearch_Posts' ) )
|
75 |
-
new Jetpack_Omnisearch_Posts( self::MENU_ITEM_POST_TYPE );
|
76 |
-
|
77 |
-
// Always sort menu items correctly
|
78 |
-
add_action( 'parse_query', array( $this, 'sort_menu_item_queries_by_menu_order' ) );
|
79 |
-
add_filter( 'posts_results', array( $this, 'sort_menu_item_queries_by_menu_taxonomy' ), 10, 2 );
|
80 |
-
|
81 |
-
add_action( 'wp_insert_post', array( $this, 'add_post_meta' ) );
|
82 |
-
|
83 |
-
$this->menu_item_loop_markup = $this->default_menu_item_loop_markup;
|
84 |
-
|
85 |
-
// Only output our Menu Item Loop Markup on a real blog view. Not feeds, XML-RPC, admin, etc.
|
86 |
-
add_filter( 'template_include', array( $this, 'setup_menu_item_loop_markup__in_filter' ) );
|
87 |
-
|
88 |
-
add_filter( 'enter_title_here', array( $this, 'change_default_title' ) );
|
89 |
-
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
90 |
-
add_filter( 'dashboard_glance_items', array( $this, 'add_to_dashboard' ) );
|
91 |
-
|
92 |
-
add_filter( 'body_class', array( $this, 'custom_class' ) );
|
93 |
-
|
94 |
-
// register food_menu shortcode (legacy)
|
95 |
-
add_shortcode( 'food_menu', array( $this, 'ect_food_shortcode' ) );
|
96 |
-
}
|
97 |
-
|
98 |
-
public function custom_class( $classes ) {
|
99 |
-
global $post;
|
100 |
-
if( isset( $post->post_content ) && has_shortcode( $post->post_content, 'food_menu' ) ) {
|
101 |
-
$classes[] = 'page-template-menu-page';
|
102 |
-
}
|
103 |
-
return $classes;
|
104 |
-
}
|
105 |
-
|
106 |
-
/**
|
107 |
-
* Should this Custom Post Type be made available?
|
108 |
-
*/
|
109 |
-
function site_supports_food_menu() {
|
110 |
-
// If we're on WordPress.com, and it has the menu site vertical.
|
111 |
-
if ( function_exists( 'site_vertical' ) && 'ect_food_menu' == site_vertical() )
|
112 |
-
return true;
|
113 |
-
|
114 |
-
// Else, if the current theme requests it.
|
115 |
-
if ( current_theme_supports( self::MENU_ITEM_POST_TYPE ) )
|
116 |
-
return true;
|
117 |
-
}
|
118 |
-
|
119 |
-
/* Setup */
|
120 |
-
|
121 |
-
/**
|
122 |
-
* Register Taxonomies and Post Type
|
123 |
-
*/
|
124 |
-
function register_taxonomies() {
|
125 |
-
if ( ! taxonomy_exists( self::MENU_ITEM_LABEL_TAX ) ) {
|
126 |
-
register_taxonomy( self::MENU_ITEM_LABEL_TAX, self::MENU_ITEM_POST_TYPE, array(
|
127 |
-
'labels' => array(
|
128 |
-
/* translators: this is about a food menu */
|
129 |
-
'name' => __( 'Menu Item Labels', 'essential-content-types' ),
|
130 |
-
/* translators: this is about a food menu */
|
131 |
-
'singular_name' => __( 'Menu Item Label', 'essential-content-types' ),
|
132 |
-
/* translators: this is about a food menu */
|
133 |
-
'search_items' => __( 'Search Menu Item Labels', 'essential-content-types' ),
|
134 |
-
'popular_items' => __( 'Popular Labels', 'essential-content-types' ),
|
135 |
-
/* translators: this is about a food menu */
|
136 |
-
'all_items' => __( 'All Menu Item Labels', 'essential-content-types' ),
|
137 |
-
/* translators: this is about a food menu */
|
138 |
-
'edit_item' => __( 'Edit Menu Item Label', 'essential-content-types' ),
|
139 |
-
/* translators: this is about a food menu */
|
140 |
-
'view_item' => __( 'View Menu Item Label', 'essential-content-types' ),
|
141 |
-
/* translators: this is about a food menu */
|
142 |
-
'update_item' => __( 'Update Menu Item Label', 'essential-content-types' ),
|
143 |
-
/* translators: this is about a food menu */
|
144 |
-
'add_new_item' => __( 'Add New Menu Item Label', 'essential-content-types' ),
|
145 |
-
/* translators: this is about a food menu */
|
146 |
-
'new_item_name' => __( 'New Menu Item Label Name', 'essential-content-types' ),
|
147 |
-
'separate_items_with_commas' => __( 'For example, spicy, favorite, etc. <br /> Separate Labels with commas', 'essential-content-types' ),
|
148 |
-
'add_or_remove_items' => __( 'Add or remove Labels', 'essential-content-types' ),
|
149 |
-
'choose_from_most_used' => __( 'Choose from the most used Labels', 'essential-content-types' ),
|
150 |
-
'items_list_navigation' => __( 'Menu item label list navigation', 'essential-content-types' ),
|
151 |
-
'items_list' => __( 'Menu item labels list', 'essential-content-types' ),
|
152 |
-
),
|
153 |
-
'no_tagcloud' => __( 'No Labels found', 'essential-content-types' ),
|
154 |
-
'hierarchical' => false,
|
155 |
-
) );
|
156 |
-
}
|
157 |
-
|
158 |
-
if ( ! taxonomy_exists( self::MENU_TAX ) ) {
|
159 |
-
register_taxonomy( self::MENU_TAX, self::MENU_ITEM_POST_TYPE, array(
|
160 |
-
'labels' => array(
|
161 |
-
/* translators: this is about a food menu */
|
162 |
-
'name' => __( 'Menu Sections', 'essential-content-types' ),
|
163 |
-
/* translators: this is about a food menu */
|
164 |
-
'singular_name' => __( 'Menu Section', 'essential-content-types' ),
|
165 |
-
/* translators: this is about a food menu */
|
166 |
-
'search_items' => __( 'Search Menu Sections', 'essential-content-types' ),
|
167 |
-
/* translators: this is about a food menu */
|
168 |
-
'all_items' => __( 'All Menu Sections', 'essential-content-types' ),
|
169 |
-
/* translators: this is about a food menu */
|
170 |
-
'parent_item' => __( 'Parent Menu Section', 'essential-content-types' ),
|
171 |
-
/* translators: this is about a food menu */
|
172 |
-
'parent_item_colon' => __( 'Parent Menu Section:', 'essential-content-types' ),
|
173 |
-
/* translators: this is about a food menu */
|
174 |
-
'edit_item' => __( 'Edit Menu Section', 'essential-content-types' ),
|
175 |
-
/* translators: this is about a food menu */
|
176 |
-
'view_item' => __( 'View Menu Section', 'essential-content-types' ),
|
177 |
-
/* translators: this is about a food menu */
|
178 |
-
'update_item' => __( 'Update Menu Section', 'essential-content-types' ),
|
179 |
-
/* translators: this is about a food menu */
|
180 |
-
'add_new_item' => __( 'Add New Menu Section', 'essential-content-types' ),
|
181 |
-
/* translators: this is about a food menu */
|
182 |
-
'new_item_name' => __( 'New Menu Sections Name', 'essential-content-types' ),
|
183 |
-
'items_list_navigation' => __( 'Menu section list navigation', 'essential-content-types' ),
|
184 |
-
'items_list' => __( 'Menu section list', 'essential-content-types' ),
|
185 |
-
),
|
186 |
-
'rewrite' => array(
|
187 |
-
'slug' => 'menu',
|
188 |
-
'with_front' => false,
|
189 |
-
'hierarchical' => true,
|
190 |
-
),
|
191 |
-
'hierarchical' => true,
|
192 |
-
'show_tagcloud' => false,
|
193 |
-
'query_var' => 'menu',
|
194 |
-
) );
|
195 |
-
}
|
196 |
-
}
|
197 |
-
|
198 |
-
function register_post_types() {
|
199 |
-
if ( post_type_exists( self::MENU_ITEM_POST_TYPE ) ) {
|
200 |
-
return;
|
201 |
-
}
|
202 |
-
|
203 |
-
register_post_type( self::MENU_ITEM_POST_TYPE, array(
|
204 |
-
'description' => __( "Items on your restaurant's menu", 'essential-content-types' ),
|
205 |
-
|
206 |
-
'labels' => array(
|
207 |
-
/* translators: this is about a food menu */
|
208 |
-
'name' => __( 'Menu Items', 'essential-content-types' ),
|
209 |
-
/* translators: this is about a food menu */
|
210 |
-
'singular_name' => __( 'Menu Item', 'essential-content-types' ),
|
211 |
-
/* translators: this is about a food menu */
|
212 |
-
'menu_name' => __( 'Food Menus', 'essential-content-types' ),
|
213 |
-
/* translators: this is about a food menu */
|
214 |
-
'all_items' => __( 'Menu Items', 'essential-content-types' ),
|
215 |
-
/* translators: this is about a food menu */
|
216 |
-
'add_new' => __( 'Add One Item', 'essential-content-types' ),
|
217 |
-
/* translators: this is about a food menu */
|
218 |
-
'add_new_item' => __( 'Add Menu Item', 'essential-content-types' ),
|
219 |
-
/* translators: this is about a food menu */
|
220 |
-
'edit_item' => __( 'Edit Menu Item', 'essential-content-types' ),
|
221 |
-
/* translators: this is about a food menu */
|
222 |
-
'new_item' => __( 'New Menu Item', 'essential-content-types' ),
|
223 |
-
/* translators: this is about a food menu */
|
224 |
-
'view_item' => __( 'View Menu Item', 'essential-content-types' ),
|
225 |
-
/* translators: this is about a food menu */
|
226 |
-
'search_items' => __( 'Search Menu Items', 'essential-content-types' ),
|
227 |
-
/* translators: this is about a food menu */
|
228 |
-
'not_found' => __( 'No Menu Items found', 'essential-content-types' ),
|
229 |
-
/* translators: this is about a food menu */
|
230 |
-
'not_found_in_trash' => __( 'No Menu Items found in Trash', 'essential-content-types' ),
|
231 |
-
'filter_items_list' => __( 'Filter menu items list', 'essential-content-types' ),
|
232 |
-
'items_list_navigation' => __( 'Menu item list navigation', 'essential-content-types' ),
|
233 |
-
'items_list' => __( 'Menu items list', 'essential-content-types' ),
|
234 |
-
),
|
235 |
-
'supports' => array(
|
236 |
-
'title',
|
237 |
-
'editor',
|
238 |
-
'excerpt',
|
239 |
-
),
|
240 |
-
'rewrite' => array(
|
241 |
-
'slug' => 'item',
|
242 |
-
'with_front' => false,
|
243 |
-
'feeds' => false,
|
244 |
-
'pages' => false,
|
245 |
-
),
|
246 |
-
'register_meta_box_cb' => array( $this, 'register_menu_item_meta_boxes' ),
|
247 |
-
|
248 |
-
'public' => true,
|
249 |
-
'show_ui' => true, // set to false to replace with custom UI
|
250 |
-
'menu_position' => 20, // below Pages
|
251 |
-
'capability_type' => 'page',
|
252 |
-
'map_meta_cap' => true,
|
253 |
-
'has_archive' => false,
|
254 |
-
'query_var' => 'item',
|
255 |
-
) );
|
256 |
-
}
|
257 |
-
|
258 |
-
|
259 |
-
/**
|
260 |
-
* Update messages for the Menu Item admin.
|
261 |
-
*/
|
262 |
-
function updated_messages( $messages ) {
|
263 |
-
global $post;
|
264 |
-
|
265 |
-
$messages[self::MENU_ITEM_POST_TYPE] = array(
|
266 |
-
0 => '', // Unused. Messages start at index 1.
|
267 |
-
/* translators: this is about a food menu */
|
268 |
-
1 => sprintf( __( 'Menu item updated. <a href="%s">View item</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
269 |
-
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
270 |
-
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
271 |
-
/* translators: this is about a food menu */
|
272 |
-
4 => esc_html__( 'Menu item updated.', 'essential-content-types' ),
|
273 |
-
/* translators: %s: date and time of the revision */
|
274 |
-
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Menu item restored to revision from %s', 'essential-content-types' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
275 |
-
/* translators: this is about a food menu */
|
276 |
-
6 => sprintf( __( 'Menu item published. <a href="%s">View item</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
277 |
-
/* translators: this is about a food menu */
|
278 |
-
7 => esc_html__( 'Menu item saved.', 'essential-content-types' ),
|
279 |
-
/* translators: this is about a food menu */
|
280 |
-
8 => sprintf( __( 'Menu item submitted. <a target="_blank" href="%s">Preview item</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
281 |
-
/* translators: this is about a food menu */
|
282 |
-
9 => sprintf( __( 'Menu item scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview item</a>', 'essential-content-types' ),
|
283 |
-
// translators: Publish box date format, see http://php.net/date
|
284 |
-
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
|
285 |
-
/* translators: this is about a food menu */
|
286 |
-
10 => sprintf( __( 'Menu item draft updated. <a target="_blank" href="%s">Preview item</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
287 |
-
);
|
288 |
-
|
289 |
-
return $messages;
|
290 |
-
}
|
291 |
-
|
292 |
-
|
293 |
-
/**
|
294 |
-
* Nova Styles and Scripts
|
295 |
-
*/
|
296 |
-
function enqueue_ect_food_styles( $hook ) {
|
297 |
-
global $post_type;
|
298 |
-
$pages = array( 'edit.php', 'post.php', 'post-new.php' );
|
299 |
-
|
300 |
-
if ( in_array( $hook, $pages ) && $post_type == self::MENU_ITEM_POST_TYPE ) {
|
301 |
-
wp_enqueue_style( 'ect-food-menu-style', plugins_url( 'css/ect-food-menu.css', __FILE__ ), array(), $this->version );
|
302 |
-
}
|
303 |
-
|
304 |
-
wp_enqueue_style( 'ect-food-menu-font', plugins_url( 'css/ect-food-menu-font.css', __FILE__ ), array(), $this->version );
|
305 |
-
}
|
306 |
-
|
307 |
-
|
308 |
-
/**
|
309 |
-
* Change ‘Enter Title Here’ text for the Menu Item.
|
310 |
-
*/
|
311 |
-
function change_default_title( $title ) {
|
312 |
-
$screen = get_current_screen();
|
313 |
-
|
314 |
-
if ( self::MENU_ITEM_POST_TYPE == $screen->post_type )
|
315 |
-
/* translators: this is about a food menu */
|
316 |
-
$title = esc_html__( "Enter the menu item's name here", 'essential-content-types' );
|
317 |
-
|
318 |
-
return $title;
|
319 |
-
}
|
320 |
-
|
321 |
-
|
322 |
-
/**
|
323 |
-
* Add to Dashboard At A Glance
|
324 |
-
*/
|
325 |
-
function add_to_dashboard() {
|
326 |
-
$number_menu_items = wp_count_posts( self::MENU_ITEM_POST_TYPE );
|
327 |
-
|
328 |
-
if ( current_user_can( 'administrator' ) ) {
|
329 |
-
$number_menu_items_published = sprintf( '<a href="%1$s">%2$s</a>',
|
330 |
-
esc_url( get_admin_url( get_current_blog_id(), 'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE ) ),
|
331 |
-
sprintf( _n( '%1$d Food Menu Item', '%1$d Food Menu Items', intval( $number_menu_items->publish ), 'essential-content-types' ), number_format_i18n( $number_menu_items->publish ) )
|
332 |
-
);
|
333 |
-
}
|
334 |
-
else {
|
335 |
-
$number_menu_items_published = sprintf( '<span>%1$s</span>',
|
336 |
-
sprintf( _n( '%1$d Food Menu Item', '%1$d Food Menu Items', intval( $number_menu_items->publish ), 'essential-content-types' ), number_format_i18n( $number_menu_items->publish ) )
|
337 |
-
);
|
338 |
-
}
|
339 |
-
|
340 |
-
echo '<li class="ect-food-menu-count">' . $number_menu_items_published . '</li>';
|
341 |
-
}
|
342 |
-
|
343 |
-
|
344 |
-
/**
|
345 |
-
* Query
|
346 |
-
*/
|
347 |
-
function is_menu_item_query( $query ) {
|
348 |
-
if (
|
349 |
-
( isset( $query->query_vars['taxonomy'] ) && self::MENU_TAX == $query->query_vars['taxonomy'] )
|
350 |
-
||
|
351 |
-
( isset( $query->query_vars['post_type'] ) && self::MENU_ITEM_POST_TYPE == $query->query_vars['post_type'] )
|
352 |
-
) {
|
353 |
-
return true;
|
354 |
-
}
|
355 |
-
|
356 |
-
return false;
|
357 |
-
}
|
358 |
-
|
359 |
-
function sort_menu_item_queries_by_menu_order( $query ) {
|
360 |
-
if ( ! $this->is_menu_item_query( $query ) ) {
|
361 |
-
return;
|
362 |
-
}
|
363 |
-
|
364 |
-
$query->query_vars['orderby'] = 'menu_order';
|
365 |
-
$query->query_vars['order'] = 'ASC';
|
366 |
-
|
367 |
-
// For now, just turn off paging so we can sort by taxonmy later
|
368 |
-
// If we want paging in the future, we'll need to add the taxonomy sort here (or at least before the DB query is made)
|
369 |
-
$query->query_vars['posts_per_page'] = -1;
|
370 |
-
}
|
371 |
-
|
372 |
-
function sort_menu_item_queries_by_menu_taxonomy( $posts, $query ) {
|
373 |
-
if ( !$posts ) {
|
374 |
-
return $posts;
|
375 |
-
}
|
376 |
-
|
377 |
-
if ( !$this->is_menu_item_query( $query ) ) {
|
378 |
-
return $posts;
|
379 |
-
}
|
380 |
-
|
381 |
-
$grouped_by_term = array();
|
382 |
-
|
383 |
-
foreach ( $posts as $post ) {
|
384 |
-
$term = $this->get_menu_item_menu_leaf( $post->ID );
|
385 |
-
if ( !$term || is_wp_error( $term ) ) {
|
386 |
-
$term_id = 0;
|
387 |
-
} else {
|
388 |
-
$term_id = $term->term_id;
|
389 |
-
}
|
390 |
-
|
391 |
-
if ( !isset( $grouped_by_term["$term_id"] ) ) {
|
392 |
-
$grouped_by_term["$term_id"] = array();
|
393 |
-
}
|
394 |
-
|
395 |
-
$grouped_by_term["$term_id"][] = $post;
|
396 |
-
}
|
397 |
-
|
398 |
-
$term_order = get_option( 'ect_food_menu_order', array() );
|
399 |
-
|
400 |
-
$return = array();
|
401 |
-
foreach ( $term_order as $term_id ) {
|
402 |
-
if ( isset( $grouped_by_term["$term_id"] ) ) {
|
403 |
-
$return = array_merge( $return, $grouped_by_term["$term_id"] );
|
404 |
-
unset( $grouped_by_term["$term_id"] );
|
405 |
-
}
|
406 |
-
}
|
407 |
-
|
408 |
-
foreach ( $grouped_by_term as $term_id => $posts ) {
|
409 |
-
$return = array_merge( $return, $posts );
|
410 |
-
}
|
411 |
-
|
412 |
-
return $return;
|
413 |
-
}
|
414 |
-
|
415 |
-
|
416 |
-
/**
|
417 |
-
* Add Many Items
|
418 |
-
*/
|
419 |
-
function add_admin_menus() {
|
420 |
-
$hook = add_submenu_page(
|
421 |
-
'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE,
|
422 |
-
__( 'Add Many Items', 'essential-content-types' ),
|
423 |
-
__( 'Add Many Items', 'essential-content-types' ),
|
424 |
-
'edit_pages',
|
425 |
-
'add_many_ect_food_items',
|
426 |
-
array( $this, 'add_many_new_items_page' )
|
427 |
-
);
|
428 |
-
|
429 |
-
add_action( "load-$hook", array( $this, 'add_many_new_items_page_load' ) );
|
430 |
-
|
431 |
-
add_action( 'current_screen', array( $this, 'current_screen_load' ) );
|
432 |
-
|
433 |
-
//Adjust 'Add Many Items' submenu position
|
434 |
-
if ( isset( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] ) ) {
|
435 |
-
$submenu_item = array_pop( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] );
|
436 |
-
$GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE][11] = $submenu_item;
|
437 |
-
ksort( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] );
|
438 |
-
}
|
439 |
-
|
440 |
-
|
441 |
-
$this->setup_menu_item_columns();
|
442 |
-
|
443 |
-
wp_register_script(
|
444 |
-
'ect-food-menu-checkboxes',
|
445 |
-
plugin_dir_url( __FILE__ ) . 'js/ect-food-menu-menu-checkboxes.js',
|
446 |
-
array( 'jquery' ),
|
447 |
-
$this->version,
|
448 |
-
false
|
449 |
-
);
|
450 |
-
}
|
451 |
-
|
452 |
-
|
453 |
-
/**
|
454 |
-
* Custom Nova Icon CSS
|
455 |
-
*/
|
456 |
-
function set_custom_font_icon() {
|
457 |
-
?>
|
458 |
-
<style type="text/css">
|
459 |
-
#menu-posts-ect_food_menu_item .wp-menu-image:before {
|
460 |
-
font-family: 'nova-font' !important;
|
461 |
-
content: '\e603' !important;
|
462 |
-
}
|
463 |
-
</style>
|
464 |
-
<?php
|
465 |
-
}
|
466 |
-
|
467 |
-
function current_screen_load() {
|
468 |
-
$screen = get_current_screen();
|
469 |
-
if ( 'edit-ect_food_menu_item' !== $screen->id ) {
|
470 |
-
return;
|
471 |
-
}
|
472 |
-
|
473 |
-
$this->edit_menu_items_page_load();
|
474 |
-
add_filter( 'admin_notices', array( $this, 'admin_notices' ) );
|
475 |
-
}
|
476 |
-
|
477 |
-
/* Edit Items List */
|
478 |
-
|
479 |
-
function admin_notices() {
|
480 |
-
if ( isset( $_GET['ect_food_reordered'] ) )
|
481 |
-
/* translators: this is about a food menu */
|
482 |
-
printf( '<div class="updated"><p>%s</p></div>', __( 'Menu Items re-ordered.', 'essential-content-types' ) );
|
483 |
-
}
|
484 |
-
|
485 |
-
function no_title_sorting( $columns ) {
|
486 |
-
if ( isset( $columns['title'] ) )
|
487 |
-
unset( $columns['title'] );
|
488 |
-
return $columns;
|
489 |
-
}
|
490 |
-
|
491 |
-
function setup_menu_item_columns() {
|
492 |
-
add_filter( sprintf( 'manage_edit-%s_sortable_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'no_title_sorting' ) );
|
493 |
-
add_filter( sprintf( 'manage_%s_posts_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_columns' ) );
|
494 |
-
|
495 |
-
add_action( sprintf( 'manage_%s_posts_custom_column', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_column_callback' ), 10, 2 );
|
496 |
-
}
|
497 |
-
|
498 |
-
function menu_item_columns( $columns ) {
|
499 |
-
unset( $columns['date'], $columns['likes'] );
|
500 |
-
|
501 |
-
$columns['thumbnail'] = __( 'Thumbnail', 'essential-content-types' );
|
502 |
-
$columns['labels'] = __( 'Labels', 'essential-content-types' );
|
503 |
-
$columns['price'] = __( 'Price', 'essential-content-types' );
|
504 |
-
$columns['order'] = __( 'Order', 'essential-content-types' );
|
505 |
-
|
506 |
-
return $columns;
|
507 |
-
}
|
508 |
-
|
509 |
-
function menu_item_column_callback( $column, $post_id ) {
|
510 |
-
$screen = get_current_screen();
|
511 |
-
|
512 |
-
switch ( $column ) {
|
513 |
-
case 'thumbnail':
|
514 |
-
echo get_the_post_thumbnail( $post_id, array( 50, 50 ) );
|
515 |
-
break;
|
516 |
-
case 'labels' :
|
517 |
-
$this->list_admin_labels( $post_id );
|
518 |
-
break;
|
519 |
-
case 'price' :
|
520 |
-
$this->display_price( $post_id );
|
521 |
-
break;
|
522 |
-
case 'order' :
|
523 |
-
$url = admin_url( $screen->parent_file );
|
524 |
-
|
525 |
-
$up_url = add_query_arg( array(
|
526 |
-
'action' => 'move-item-up',
|
527 |
-
'post_id' => (int) $post_id,
|
528 |
-
), wp_nonce_url( $url, 'ect_food_move_item_up_' . $post_id ) );
|
529 |
-
|
530 |
-
$down_url = add_query_arg( array(
|
531 |
-
'action' => 'move-item-down',
|
532 |
-
'post_id' => (int) $post_id,
|
533 |
-
), wp_nonce_url( $url, 'ect_food_move_item_down_' . $post_id ) );
|
534 |
-
$menu_item = get_post($post_id);
|
535 |
-
$this->get_menu_by_post_id( $post_id );
|
536 |
-
if ( $term_id = $this->get_menu_by_post_id( $post_id ) ) {
|
537 |
-
$term_id = $term_id->term_id;
|
538 |
-
}
|
539 |
-
?>
|
540 |
-
<input type="hidden" class="menu-order-value" name="ect_food_order[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $menu_item->menu_order ) ?>" />
|
541 |
-
<input type="hidden" class='ect-food-menu-term' name="ect_food_menu_term[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $term_id ); ?>">
|
542 |
-
|
543 |
-
<span class="hide-if-js">
|
544 |
-
— <a class="ect-food-move-item-up" data-post-id="<?php echo (int) $post_id; ?>" href="<?php echo esc_url( $up_url ); ?>">up</a>
|
545 |
-
<br />
|
546 |
-
— <a class="ect-food-move-item-down" data-post-id="<?php echo (int) $post_id; ?>" href="<?php echo esc_url( $down_url ); ?>">down</a>
|
547 |
-
</span>
|
548 |
-
<?php
|
549 |
-
break;
|
550 |
-
}
|
551 |
-
}
|
552 |
-
|
553 |
-
function get_menu_by_post_id( $post_id = null ) {
|
554 |
-
if ( ! $post_id )
|
555 |
-
return false;
|
556 |
-
|
557 |
-
$terms = get_the_terms( $post_id, self::MENU_TAX );
|
558 |
-
|
559 |
-
if ( ! is_array( $terms ) )
|
560 |
-
return false;
|
561 |
-
|
562 |
-
return array_pop( $terms );
|
563 |
-
}
|
564 |
-
|
565 |
-
/**
|
566 |
-
* Fires on a menu edit page. We might have drag-n-drop reordered
|
567 |
-
*/
|
568 |
-
function maybe_reorder_menu_items() {
|
569 |
-
// make sure we clicked our button
|
570 |
-
if ( ! ( isset( $_REQUEST['menu_reorder_submit'] ) && $_REQUEST['menu_reorder_submit'] === __( 'Save New Order', 'essential-content-types' ) ) )
|
571 |
-
return;
|
572 |
-
;
|
573 |
-
|
574 |
-
// make sure we have the nonce
|
575 |
-
if ( ! ( isset( $_REQUEST['drag-drop-reorder'] ) && wp_verify_nonce( $_REQUEST['drag-drop-reorder'], 'drag-drop-reorder' ) ) )
|
576 |
-
return;
|
577 |
-
|
578 |
-
$term_pairs = array_map( 'absint', $_REQUEST['ect_food_menu_term'] );
|
579 |
-
$order_pairs = array_map( 'absint', $_REQUEST['ect_food_order'] );
|
580 |
-
|
581 |
-
foreach( $order_pairs as $ID => $menu_order ) {
|
582 |
-
$ID = absint( $ID );
|
583 |
-
unset( $order_pairs[$ID] );
|
584 |
-
if ( $ID < 0 )
|
585 |
-
continue;
|
586 |
-
|
587 |
-
$post = get_post( $ID );
|
588 |
-
if ( ! $post )
|
589 |
-
continue;
|
590 |
-
|
591 |
-
// save a write if the order hasn't changed
|
592 |
-
if ( $menu_order != $post->menu_order )
|
593 |
-
wp_update_post( compact( 'ID', 'menu_order' ) );
|
594 |
-
|
595 |
-
// save a write if the term hasn't changed
|
596 |
-
if ( $term_pairs[$ID] != $this->get_menu_by_post_id( $ID )->term_id )
|
597 |
-
wp_set_object_terms( $ID, $term_pairs[$ID], self::MENU_TAX );
|
598 |
-
|
599 |
-
}
|
600 |
-
|
601 |
-
$redirect = add_query_arg( array(
|
602 |
-
'post_type' => self::MENU_ITEM_POST_TYPE,
|
603 |
-
'ect_food_reordered' => '1'
|
604 |
-
), admin_url( 'edit.php' ) );
|
605 |
-
wp_safe_redirect( $redirect );
|
606 |
-
exit;
|
607 |
-
|
608 |
-
}
|
609 |
-
|
610 |
-
function edit_menu_items_page_load() {
|
611 |
-
if ( isset( $_GET['action'] ) ) {
|
612 |
-
$this->handle_menu_item_actions();
|
613 |
-
}
|
614 |
-
|
615 |
-
$this->maybe_reorder_menu_items();
|
616 |
-
|
617 |
-
wp_enqueue_script(
|
618 |
-
'ect-food-drag-drop',
|
619 |
-
plugin_dir_url( __FILE__ ) . 'js/ect-food-menu-drag-drop.js',
|
620 |
-
array( 'jquery-ui-sortable' ),
|
621 |
-
$this->version,
|
622 |
-
true
|
623 |
-
);
|
624 |
-
|
625 |
-
wp_localize_script( 'ect-food-drag-drop', '_novaDragDrop', array(
|
626 |
-
'nonce' => wp_create_nonce( 'drag-drop-reorder' ),
|
627 |
-
'nonceName' => 'drag-drop-reorder',
|
628 |
-
'reorder' => __( 'Save New Order', 'essential-content-types' ),
|
629 |
-
'reorderName' => 'menu_reorder_submit'
|
630 |
-
) );
|
631 |
-
add_action( 'the_post', array( $this, 'show_menu_titles_in_menu_item_list' ) );
|
632 |
-
}
|
633 |
-
|
634 |
-
function handle_menu_item_actions() {
|
635 |
-
$action = (string) $_GET['action'];
|
636 |
-
|
637 |
-
switch ( $action ) {
|
638 |
-
case 'move-item-up' :
|
639 |
-
case 'move-item-down' :
|
640 |
-
$reorder = false;
|
641 |
-
|
642 |
-
$post_id = (int) $_GET['post_id'];
|
643 |
-
|
644 |
-
$term = $this->get_menu_item_menu_leaf( $post_id );
|
645 |
-
|
646 |
-
// Get all posts in that term
|
647 |
-
$query = new WP_Query( array(
|
648 |
-
'taxonomy' => self::MENU_TAX,
|
649 |
-
'term' => $term->slug,
|
650 |
-
) );
|
651 |
-
|
652 |
-
$order = array();
|
653 |
-
foreach ( $query->posts as $post ) {
|
654 |
-
$order[] = $post->ID;
|
655 |
-
}
|
656 |
-
|
657 |
-
if ( 'move-item-up' == $action ) {
|
658 |
-
check_admin_referer( 'ect_food_move_item_up_' . $post_id );
|
659 |
-
|
660 |
-
$first_post_id = $order[0];
|
661 |
-
if ( $post_id == $first_post_id ) {
|
662 |
-
break;
|
663 |
-
}
|
664 |
-
|
665 |
-
foreach ( $order as $menu_order => $order_post_id ) {
|
666 |
-
if ( $post_id != $order_post_id ) {
|
667 |
-
continue;
|
668 |
-
}
|
669 |
-
|
670 |
-
$swap_post_id = $order[$menu_order - 1];
|
671 |
-
$order[$menu_order - 1] = $post_id;
|
672 |
-
$order[$menu_order] = $swap_post_id;
|
673 |
-
|
674 |
-
$reorder = true;
|
675 |
-
break;
|
676 |
-
}
|
677 |
-
} else {
|
678 |
-
check_admin_referer( 'ect_food_move_item_down_' . $post_id );
|
679 |
-
|
680 |
-
$last_post_id = end( $order );
|
681 |
-
if ( $post_id == $last_post_id ) {
|
682 |
-
break;
|
683 |
-
}
|
684 |
-
|
685 |
-
foreach ( $order as $menu_order => $order_post_id ) {
|
686 |
-
if ( $post_id != $order_post_id ) {
|
687 |
-
continue;
|
688 |
-
}
|
689 |
-
|
690 |
-
$swap_post_id = $order[$menu_order + 1];
|
691 |
-
$order[$menu_order + 1] = $post_id;
|
692 |
-
$order[$menu_order] = $swap_post_id;
|
693 |
-
|
694 |
-
$reorder = true;
|
695 |
-
}
|
696 |
-
}
|
697 |
-
|
698 |
-
if ( $reorder ) {
|
699 |
-
foreach ( $order as $menu_order => $ID ) {
|
700 |
-
wp_update_post( compact( 'ID', 'menu_order' ) );
|
701 |
-
}
|
702 |
-
}
|
703 |
-
|
704 |
-
break;
|
705 |
-
case 'move-menu-up' :
|
706 |
-
case 'move-menu-down' :
|
707 |
-
$reorder = false;
|
708 |
-
|
709 |
-
$term_id = (int) $_GET['term_id'];
|
710 |
-
|
711 |
-
$terms = $this->get_menus();
|
712 |
-
|
713 |
-
$order = array();
|
714 |
-
foreach ( $terms as $term ) {
|
715 |
-
$order[] = $term->term_id;
|
716 |
-
}
|
717 |
-
|
718 |
-
if ( 'move-menu-up' == $action ) {
|
719 |
-
check_admin_referer( 'ect_food_move_menu_up_' . $term_id );
|
720 |
-
|
721 |
-
$first_term_id = $order[0];
|
722 |
-
if ( $term_id == $first_term_id ) {
|
723 |
-
break;
|
724 |
-
}
|
725 |
-
|
726 |
-
foreach ( $order as $menu_order => $order_term_id ) {
|
727 |
-
if ( $term_id != $order_term_id ) {
|
728 |
-
continue;
|
729 |
-
}
|
730 |
-
|
731 |
-
$swap_term_id = $order[$menu_order - 1];
|
732 |
-
$order[$menu_order - 1] = $term_id;
|
733 |
-
$order[$menu_order] = $swap_term_id;
|
734 |
-
|
735 |
-
$reorder = true;
|
736 |
-
break;
|
737 |
-
}
|
738 |
-
} else {
|
739 |
-
check_admin_referer( 'ect_food_move_menu_down_' . $term_id );
|
740 |
-
|
741 |
-
$last_term_id = end( $order );
|
742 |
-
if ( $term_id == $last_term_id ) {
|
743 |
-
break;
|
744 |
-
}
|
745 |
-
|
746 |
-
foreach ( $order as $menu_order => $order_term_id ) {
|
747 |
-
if ( $term_id != $order_term_id ) {
|
748 |
-
continue;
|
749 |
-
}
|
750 |
-
|
751 |
-
$swap_term_id = $order[$menu_order + 1];
|
752 |
-
$order[$menu_order + 1] = $term_id;
|
753 |
-
$order[$menu_order] = $swap_term_id;
|
754 |
-
|
755 |
-
$reorder = true;
|
756 |
-
}
|
757 |
-
}
|
758 |
-
|
759 |
-
if ( $reorder ) {
|
760 |
-
update_option( 'ect_food_menu_order', $order );
|
761 |
-
}
|
762 |
-
|
763 |
-
break;
|
764 |
-
default :
|
765 |
-
return;
|
766 |
-
}
|
767 |
-
|
768 |
-
$redirect = add_query_arg( array(
|
769 |
-
'post_type' => self::MENU_ITEM_POST_TYPE,
|
770 |
-
'ect_food_reordered' => '1'
|
771 |
-
), admin_url( 'edit.php' ) );
|
772 |
-
wp_safe_redirect( $redirect );
|
773 |
-
exit;
|
774 |
-
}
|
775 |
-
|
776 |
-
/*
|
777 |
-
* Add menu title rows to the list table
|
778 |
-
*/
|
779 |
-
function show_menu_titles_in_menu_item_list( $post ) {
|
780 |
-
global $wp_list_table;
|
781 |
-
|
782 |
-
static $last_term_id = false;
|
783 |
-
|
784 |
-
$term = $this->get_menu_item_menu_leaf( $post->ID );
|
785 |
-
|
786 |
-
$term_id = $term instanceof WP_Term ? $term->term_id : null;
|
787 |
-
|
788 |
-
if ( false !== $last_term_id && $last_term_id === $term_id ) {
|
789 |
-
return;
|
790 |
-
}
|
791 |
-
|
792 |
-
if ( is_null( $term_id ) ) {
|
793 |
-
$last_term_id = null;
|
794 |
-
$term_name = '';
|
795 |
-
$parent_count = 0;
|
796 |
-
} else {
|
797 |
-
$last_term_id = $term->term_id;
|
798 |
-
$term_name = $term->name;
|
799 |
-
$parent_count = 0;
|
800 |
-
$current_term = $term;
|
801 |
-
while ( $current_term->parent ) {
|
802 |
-
$parent_count++;
|
803 |
-
$current_term = get_term( $current_term->parent, self::MENU_TAX );
|
804 |
-
}
|
805 |
-
}
|
806 |
-
|
807 |
-
$non_order_column_count = $wp_list_table->get_column_count() - 1;
|
808 |
-
|
809 |
-
$screen = get_current_screen();
|
810 |
-
|
811 |
-
$url = admin_url( $screen->parent_file );
|
812 |
-
|
813 |
-
$up_url = add_query_arg( array(
|
814 |
-
'action' => 'move-menu-up',
|
815 |
-
'term_id' => (int) $term_id,
|
816 |
-
), wp_nonce_url( $url, 'ect_food_move_menu_up_' . $term_id ) );
|
817 |
-
|
818 |
-
$down_url = add_query_arg( array(
|
819 |
-
'action' => 'move-menu-down',
|
820 |
-
'term_id' => (int) $term_id,
|
821 |
-
), wp_nonce_url( $url, 'ect_food_move_menu_down_' . $term_id ) );
|
822 |
-
|
823 |
-
?>
|
824 |
-
<tr class="no-items menu-label-row" data-term_id="<?php echo esc_attr( $term_id ) ?>">
|
825 |
-
<td class="colspanchange" colspan="<?php echo (int) $non_order_column_count; ?>">
|
826 |
-
<h3><?php
|
827 |
-
echo str_repeat( ' — ', (int) $parent_count );
|
828 |
-
|
829 |
-
if ( $term instanceof WP_Term ) {
|
830 |
-
echo esc_html( sanitize_term_field( 'name', $term_name, $term_id, self::MENU_TAX, 'display' ) );
|
831 |
-
edit_term_link( __( 'edit', 'essential-content-types' ), '<span class="edit-ect-food-section"><span class="dashicon dashicon-edit"></span>', '</span>', $term );
|
832 |
-
|
833 |
-
} else {
|
834 |
-
_e( 'Uncategorized' , 'essential-content-types' );
|
835 |
-
}
|
836 |
-
?></h3>
|
837 |
-
</td>
|
838 |
-
<td>
|
839 |
-
<?php if ( $term instanceof WP_Term ) { ?>
|
840 |
-
<a class="ect-food-move-menu-up" title="<?php esc_attr_e( 'Move menu section up', 'essential-content-types' ); ?>" href="<?php echo esc_url( $up_url ); ?>"><?php esc_html_e( 'UP', 'essential-content-types' ); ?></a>
|
841 |
-
<br />
|
842 |
-
<a class="ect-food-move-menu-down" title="<?php esc_attr_e( 'Move menu section down', 'essential-content-types' ); ?>" href="<?php echo esc_url( $down_url ); ?>"><?php esc_html_e( 'DOWN', 'essential-content-types' ); ?></a>
|
843 |
-
<?php } ?>
|
844 |
-
</td>
|
845 |
-
</tr>
|
846 |
-
<?php
|
847 |
-
}
|
848 |
-
|
849 |
-
/* Edit Many Items */
|
850 |
-
|
851 |
-
function add_many_new_items_page_load() {
|
852 |
-
if ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
|
853 |
-
$this->process_form_request();
|
854 |
-
exit;
|
855 |
-
}
|
856 |
-
|
857 |
-
$this->enqueue_many_items_scripts();
|
858 |
-
}
|
859 |
-
|
860 |
-
function enqueue_many_items_scripts() {
|
861 |
-
wp_enqueue_script(
|
862 |
-
'ect-food-many-items',
|
863 |
-
plugin_dir_url( __FILE__ ) . 'js/ect-food-menu-many-items.js',
|
864 |
-
array( 'jquery' ),
|
865 |
-
$this->version,
|
866 |
-
true
|
867 |
-
);
|
868 |
-
}
|
869 |
-
|
870 |
-
function process_form_request() {
|
871 |
-
if ( !isset( $_POST['ect_food_title'] ) || !is_array( $_POST['ect_food_title'] ) ) {
|
872 |
-
return;
|
873 |
-
}
|
874 |
-
|
875 |
-
$is_ajax = !empty( $_POST['ajax'] );
|
876 |
-
|
877 |
-
if ( $is_ajax ) {
|
878 |
-
check_ajax_referer( 'ect_food_many_items' );
|
879 |
-
} else {
|
880 |
-
check_admin_referer( 'ect_food_many_items' );
|
881 |
-
}
|
882 |
-
|
883 |
-
foreach ( array_keys( $_POST['ect_food_title'] ) as $key ) :
|
884 |
-
// $_POST is already slashed
|
885 |
-
$post_details = array(
|
886 |
-
'post_status' => 'publish',
|
887 |
-
'post_type' => self::MENU_ITEM_POST_TYPE,
|
888 |
-
'post_content' => $_POST['ect_food_content'][$key],
|
889 |
-
'post_title' => $_POST['ect_food_title'][$key],
|
890 |
-
'tax_input' => array(
|
891 |
-
self::MENU_ITEM_LABEL_TAX => $_POST['ect_food_labels'][$key],
|
892 |
-
self::MENU_TAX => isset( $_POST['ect_food_menu_tax'] ) ? $_POST['ect_food_menu_tax'] : null,
|
893 |
-
),
|
894 |
-
);
|
895 |
-
|
896 |
-
$post_id = wp_insert_post( $post_details );
|
897 |
-
if ( !$post_id || is_wp_error( $post_id ) ) {
|
898 |
-
continue;
|
899 |
-
}
|
900 |
-
|
901 |
-
$this->set_price( $post_id, isset( $_POST['ect_food_price'][$key] ) ? stripslashes( $_POST['ect_food_price'][$key] ) : '' );
|
902 |
-
|
903 |
-
if ( $is_ajax ) :
|
904 |
-
$post = get_post( $post_id );
|
905 |
-
$GLOBALS['post'] = $post;
|
906 |
-
setup_postdata( $post );
|
907 |
-
|
908 |
-
?>
|
909 |
-
<td><?php the_title(); ?></td>
|
910 |
-
<td class="ect-food-price"><?php $this->display_price(); ?></td>
|
911 |
-
<td><?php $this->list_labels( $post_id ); ?></td>
|
912 |
-
<td><?php the_content(); ?></td>
|
913 |
-
<?php
|
914 |
-
endif;
|
915 |
-
|
916 |
-
endforeach;
|
917 |
-
|
918 |
-
if ( $is_ajax ) {
|
919 |
-
exit;
|
920 |
-
}
|
921 |
-
|
922 |
-
wp_safe_redirect( admin_url( 'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE ) );
|
923 |
-
exit;
|
924 |
-
}
|
925 |
-
|
926 |
-
function add_many_new_items_page() {
|
927 |
-
?>
|
928 |
-
<div class="wrap">
|
929 |
-
<h2><?php esc_html_e( 'Add Many Items', 'essential-content-types' ); ?></h2>
|
930 |
-
|
931 |
-
<p><?php _e( 'Use the <kbd>TAB</kbd> key on your keyboard to move between colums and the <kbd>ENTER</kbd> or <kbd>RETURN</kbd> key to save each row and move on to the next.', 'essential-content-types' ); ?></p>
|
932 |
-
|
933 |
-
<form method="post" action="" enctype="multipart/form-data">
|
934 |
-
<p><h3><?php esc_html_e( 'Add to section:', 'essential-content-types' ); ?> <?php wp_dropdown_categories( array(
|
935 |
-
'id' => 'ect-food-menu-tax',
|
936 |
-
'name' => 'ect_food_menu_tax',
|
937 |
-
'taxonomy' => self::MENU_TAX,
|
938 |
-
'hide_empty' => false,
|
939 |
-
'hierarchical' => true,
|
940 |
-
) ); ?></h3></p>
|
941 |
-
|
942 |
-
<table class="many-items-table wp-list-table widefat">
|
943 |
-
<thead>
|
944 |
-
<tr>
|
945 |
-
<th scope="col"><?php esc_html_e( 'Name', 'essential-content-types' ); ?></th>
|
946 |
-
<th scope="col" class="ect-food-price"><?php esc_html_e( 'Price', 'essential-content-types' ); ?></th>
|
947 |
-
<th scope="col"><?php _e( 'Labels: <small>spicy, favorite, etc. <em>Separate Labels with commas</em></small>', 'essential-content-types' ); ?></th>
|
948 |
-
<th scope="col"><?php esc_html_e( 'Description', 'essential-content-types' ); ?></th>
|
949 |
-
</tr>
|
950 |
-
</thead>
|
951 |
-
<tbody>
|
952 |
-
<tr>
|
953 |
-
<td><input type="text" name="ect_food_title[]" aria-required="true" /></td>
|
954 |
-
<td class="ect-food-price"><input type="text" name="ect_food_price[]" /></td>
|
955 |
-
<td><input type="text" name="ect_food_labels[]" /></td>
|
956 |
-
<td><textarea name="ect_food_content[]" cols="20" rows="1"></textarea>
|
957 |
-
</tr>
|
958 |
-
</tbody>
|
959 |
-
<tbody>
|
960 |
-
<tr>
|
961 |
-
<td><input type="text" name="ect_food_title[]" aria-required="true" /></td>
|
962 |
-
<td class="ect-food-price"><input type="text" name="ect_food_price[]" /></td>
|
963 |
-
<td><input type="text" name="ect_food_labels[]" /></td>
|
964 |
-
<td><textarea name="ect_food_content[]" cols="20" rows="1"></textarea>
|
965 |
-
</tr>
|
966 |
-
</tbody>
|
967 |
-
<tfoot>
|
968 |
-
<tr>
|
969 |
-
<th><a class="button button-secondary ect-food-new-row"><span class="dashicon dashicon-plus"></span> <?php esc_html_e( 'New Row' , 'essential-content-types' ); ?></a></th>
|
970 |
-
<th class="ect-food-price"></th>
|
971 |
-
<th></th>
|
972 |
-
<th></th>
|
973 |
-
</tr>
|
974 |
-
</tfoot>
|
975 |
-
</table>
|
976 |
-
|
977 |
-
<p class="submit">
|
978 |
-
<input type="submit" class="button-primary" value="<?php esc_attr_e( 'Add These New Menu Items', 'essential-content-types' ); ?>" />
|
979 |
-
<?php wp_nonce_field( 'ect_food_many_items' ); ?>
|
980 |
-
</p>
|
981 |
-
</form>
|
982 |
-
</div>
|
983 |
-
<?php
|
984 |
-
}
|
985 |
-
|
986 |
-
/* Edit One Item */
|
987 |
-
|
988 |
-
function register_menu_item_meta_boxes() {
|
989 |
-
wp_enqueue_script( 'ect-food-menu-checkboxes' );
|
990 |
-
|
991 |
-
add_meta_box( 'menu_item_price', __( 'Price', 'essential-content-types' ), array( $this, 'menu_item_price_meta_box' ), null, 'side', 'high' );
|
992 |
-
}
|
993 |
-
|
994 |
-
function menu_item_price_meta_box( $post, $meta_box ) {
|
995 |
-
$price = $this->get_price( $post->ID );
|
996 |
-
?>
|
997 |
-
<label for="ect-food-price-<?php echo (int) $post->ID; ?>" class="screen-reader-text"><?php esc_html_e( 'Price', 'essential-content-types' ); ?></label>
|
998 |
-
<input type="text" id="ect-food-price-<?php echo (int) $post->ID; ?>" class="widefat" name="ect_food_price[<?php echo (int) $post->ID; ?>]" value="<?php echo esc_attr( $price ); ?>" />
|
999 |
-
<?php
|
1000 |
-
}
|
1001 |
-
|
1002 |
-
function add_post_meta( $post_id ) {
|
1003 |
-
if ( !isset( $_POST['ect_food_price'][$post_id] ) ) {
|
1004 |
-
return;
|
1005 |
-
}
|
1006 |
-
|
1007 |
-
$this->set_price( $post_id, stripslashes( $_POST['ect_food_price'][$post_id] ) );
|
1008 |
-
}
|
1009 |
-
|
1010 |
-
/* Data */
|
1011 |
-
|
1012 |
-
function get_menus( $args = array() ) {
|
1013 |
-
$args = wp_parse_args( $args, array(
|
1014 |
-
'hide_empty' => false,
|
1015 |
-
) );
|
1016 |
-
|
1017 |
-
$terms = get_terms( self::MENU_TAX, $args );
|
1018 |
-
if ( !$terms || is_wp_error( $terms ) ) {
|
1019 |
-
return array();
|
1020 |
-
}
|
1021 |
-
|
1022 |
-
$terms_by_id = array();
|
1023 |
-
foreach ( $terms as $term ) {
|
1024 |
-
$terms_by_id["{$term->term_id}"] = $term;
|
1025 |
-
}
|
1026 |
-
|
1027 |
-
$term_order = get_option( 'ect_food_menu_order', array() );
|
1028 |
-
|
1029 |
-
$return = array();
|
1030 |
-
foreach ( $term_order as $term_id ) {
|
1031 |
-
if ( isset( $terms_by_id["$term_id"] ) ) {
|
1032 |
-
$return[] = $terms_by_id["$term_id"];
|
1033 |
-
unset( $terms_by_id["$term_id"] );
|
1034 |
-
}
|
1035 |
-
}
|
1036 |
-
|
1037 |
-
foreach ( $terms_by_id as $term_id => $term ) {
|
1038 |
-
$return[] = $term;
|
1039 |
-
}
|
1040 |
-
|
1041 |
-
return $return;
|
1042 |
-
}
|
1043 |
-
|
1044 |
-
function get_menu_item_menu_leaf( $post_id ) {
|
1045 |
-
// Get first menu taxonomy "leaf"
|
1046 |
-
$term_ids = wp_get_object_terms( $post_id, self::MENU_TAX, array( 'fields' => 'ids' ) );
|
1047 |
-
|
1048 |
-
foreach ( $term_ids as $term_id ) {
|
1049 |
-
$children = get_term_children( $term_id, self::MENU_TAX );
|
1050 |
-
if ( ! $children ) {
|
1051 |
-
break;
|
1052 |
-
}
|
1053 |
-
}
|
1054 |
-
|
1055 |
-
if ( ! isset( $term_id ) ) {
|
1056 |
-
return false;
|
1057 |
-
}
|
1058 |
-
|
1059 |
-
return get_term( $term_id, self::MENU_TAX );
|
1060 |
-
|
1061 |
-
}
|
1062 |
-
|
1063 |
-
function list_labels( $post_id = 0 ) {
|
1064 |
-
$post = get_post( $post_id );
|
1065 |
-
echo get_the_term_list( $post->ID, self::MENU_ITEM_LABEL_TAX, '', _x( ', ', 'Nova label separator', 'essential-content-types' ), '' );
|
1066 |
-
}
|
1067 |
-
|
1068 |
-
function list_admin_labels( $post_id = 0 ) {
|
1069 |
-
$post = get_post( $post_id );
|
1070 |
-
$labels = get_the_terms( $post->ID, self::MENU_ITEM_LABEL_TAX );
|
1071 |
-
if ( !empty( $labels ) ) {
|
1072 |
-
$out = array();
|
1073 |
-
foreach ( $labels as $label ) {
|
1074 |
-
$out[] = sprintf( '<a href="%s">%s</a>',
|
1075 |
-
esc_url( add_query_arg( array(
|
1076 |
-
'post_type' => self::MENU_ITEM_POST_TYPE,
|
1077 |
-
'taxonomy' => self::MENU_ITEM_LABEL_TAX,
|
1078 |
-
'term' => $label->slug
|
1079 |
-
), 'edit.php' ) ),
|
1080 |
-
esc_html( sanitize_term_field( 'name', $label->name, $label->term_id, self::MENU_ITEM_LABEL_TAX, 'display' ) )
|
1081 |
-
);
|
1082 |
-
}
|
1083 |
-
|
1084 |
-
echo join( _x( ', ', 'Nova label separator', 'essential-content-types' ), $out );
|
1085 |
-
} else {
|
1086 |
-
esc_html_e( 'No Labels', 'essential-content-types' );
|
1087 |
-
}
|
1088 |
-
}
|
1089 |
-
|
1090 |
-
function set_price( $post_id = 0, $price = '' ) {
|
1091 |
-
$post = get_post( $post_id );
|
1092 |
-
|
1093 |
-
return update_post_meta( $post->ID, 'ect_food_price', $price );
|
1094 |
-
}
|
1095 |
-
|
1096 |
-
function get_price( $post_id = 0 ) {
|
1097 |
-
$post = get_post( $post_id );
|
1098 |
-
|
1099 |
-
return get_post_meta( $post->ID, 'ect_food_price', true );
|
1100 |
-
}
|
1101 |
-
|
1102 |
-
function display_price( $post_id = 0 ) {
|
1103 |
-
echo esc_html( $this->get_price( $post_id ) );
|
1104 |
-
}
|
1105 |
-
|
1106 |
-
/* Menu Item Loop Markup */
|
1107 |
-
|
1108 |
-
/* Does not support nested loops */
|
1109 |
-
|
1110 |
-
function get_menu_item_loop_markup( $field = null ) {
|
1111 |
-
return $this->menu_item_loop_markup;
|
1112 |
-
}
|
1113 |
-
|
1114 |
-
/**
|
1115 |
-
* Sets up the loop markup.
|
1116 |
-
* Attached to the 'template_include' *filter*,
|
1117 |
-
* which fires only during a real blog view (not in admin, feeds, etc.)
|
1118 |
-
*
|
1119 |
-
* @param string Template File
|
1120 |
-
* @return string Template File. VERY Important.
|
1121 |
-
*/
|
1122 |
-
function setup_menu_item_loop_markup__in_filter( $template ) {
|
1123 |
-
add_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
|
1124 |
-
|
1125 |
-
return $template;
|
1126 |
-
}
|
1127 |
-
|
1128 |
-
/**
|
1129 |
-
* If the Query is a Menu Item Query, start outputing the Menu Item Loop Marku
|
1130 |
-
* Attached to the 'loop_start' action.
|
1131 |
-
*
|
1132 |
-
* @param WP_Query
|
1133 |
-
*/
|
1134 |
-
function start_menu_item_loop( $query ) {
|
1135 |
-
if ( !$this->is_menu_item_query( $query ) ) {
|
1136 |
-
return;
|
1137 |
-
}
|
1138 |
-
|
1139 |
-
$this->menu_item_loop_last_term_id = false;
|
1140 |
-
$this->menu_item_loop_current_term = false;
|
1141 |
-
|
1142 |
-
add_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
|
1143 |
-
add_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
|
1144 |
-
}
|
1145 |
-
|
1146 |
-
/**
|
1147 |
-
* Outputs the Menu Item Loop Marku
|
1148 |
-
* Attached to the 'the_post' action.
|
1149 |
-
*
|
1150 |
-
* @param WP_Post
|
1151 |
-
*/
|
1152 |
-
function menu_item_loop_each_post( $post ) {
|
1153 |
-
$this->menu_item_loop_current_term = $this->get_menu_item_menu_leaf( $post->ID );
|
1154 |
-
|
1155 |
-
if ( false === $this->menu_item_loop_last_term_id ) {
|
1156 |
-
// We're at the very beginning of the loop
|
1157 |
-
|
1158 |
-
$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
|
1159 |
-
$this->menu_item_loop_header(); // Output the menu's header
|
1160 |
-
} elseif ( $this->menu_item_loop_last_term_id != $this->menu_item_loop_current_term->term_id ) {
|
1161 |
-
// We're not at the very beginning but still need to start a new menu section. End the previous menu section first.
|
1162 |
-
|
1163 |
-
$this->menu_item_loop_close_element( 'menu' ); // End the previous menu section
|
1164 |
-
$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
|
1165 |
-
$this->menu_item_loop_header(); // Output the menu's header
|
1166 |
-
}
|
1167 |
-
|
1168 |
-
$this->menu_item_loop_last_term_id = isset( $this->menu_item_loop_current_term->term_id ) ? $this->menu_item_loop_current_term->term_id : '' ;
|
1169 |
-
}
|
1170 |
-
|
1171 |
-
/**
|
1172 |
-
* If the Query is a Menu Item Query, stop outputing the Menu Item Loop Marku
|
1173 |
-
* Attached to the 'loop_end' action.
|
1174 |
-
*
|
1175 |
-
* @param WP_Query
|
1176 |
-
*/
|
1177 |
-
function stop_menu_item_loop( $query ) {
|
1178 |
-
if ( !$this->is_menu_item_query( $query ) ) {
|
1179 |
-
return;
|
1180 |
-
}
|
1181 |
-
|
1182 |
-
remove_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
|
1183 |
-
remove_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
|
1184 |
-
remove_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
|
1185 |
-
|
1186 |
-
$this->menu_item_loop_close_element( 'menu' ); // End the last menu section
|
1187 |
-
}
|
1188 |
-
|
1189 |
-
/**
|
1190 |
-
* Outputs the Menu Group Header
|
1191 |
-
*/
|
1192 |
-
function menu_item_loop_header() {
|
1193 |
-
$this->menu_item_loop_open_element( 'menu_header' );
|
1194 |
-
$this->menu_item_loop_open_element( 'menu_title' );
|
1195 |
-
echo isset( $this->menu_item_loop_current_term->name ) ? esc_html( $this->menu_item_loop_current_term->name ) : ''; // @todo tax filter
|
1196 |
-
$this->menu_item_loop_close_element( 'menu_title' );
|
1197 |
-
if ( isset( $this->menu_item_loop_current_term->description ) && $this->menu_item_loop_current_term->description ) :
|
1198 |
-
$this->menu_item_loop_open_element( 'menu_description' );
|
1199 |
-
echo esc_html( $this->menu_item_loop_current_term->description ); // @todo kses, tax filter
|
1200 |
-
$this->menu_item_loop_close_element( 'menu_description' );
|
1201 |
-
endif;
|
1202 |
-
$this->menu_item_loop_close_element( 'menu_header' );
|
1203 |
-
}
|
1204 |
-
|
1205 |
-
/**
|
1206 |
-
* Outputs a Menu Item Markup element opening tag
|
1207 |
-
*
|
1208 |
-
* @param string $field - Menu Item Markup settings field.
|
1209 |
-
*/
|
1210 |
-
function menu_item_loop_open_element( $field ) {
|
1211 |
-
$markup = $this->get_menu_item_loop_markup();
|
1212 |
-
/**
|
1213 |
-
* Filter a menu item's element opening tag.
|
1214 |
-
*
|
1215 |
-
* @module custom-content-types
|
1216 |
-
*
|
1217 |
-
* @since 4.4.0
|
1218 |
-
*
|
1219 |
-
* @param string $tag Menu item's element opening tag.
|
1220 |
-
* @param string $field Menu Item Markup settings field.
|
1221 |
-
* @param array $markup Array of markup elements for the menu item.
|
1222 |
-
* @param false|object $term Taxonomy term for current menu item.
|
1223 |
-
*/
|
1224 |
-
echo apply_filters(
|
1225 |
-
'essential-content-types_ect_food_menu_item_loop_open_element',
|
1226 |
-
'<' . tag_escape( $markup["{$field}_tag"] ) . $this->menu_item_loop_class( $markup["{$field}_class"] ) . ">\n",
|
1227 |
-
$field,
|
1228 |
-
$markup,
|
1229 |
-
$this->menu_item_loop_current_term
|
1230 |
-
);
|
1231 |
-
}
|
1232 |
-
|
1233 |
-
/**
|
1234 |
-
* Outputs a Menu Item Markup element closing tag
|
1235 |
-
*
|
1236 |
-
* @param string $field - Menu Item Markup settings field
|
1237 |
-
*/
|
1238 |
-
function menu_item_loop_close_element( $field ) {
|
1239 |
-
$markup = $this->get_menu_item_loop_markup();
|
1240 |
-
/**
|
1241 |
-
* Filter a menu item's element closing tag.
|
1242 |
-
*
|
1243 |
-
* @module custom-content-types
|
1244 |
-
*
|
1245 |
-
* @since 4.4.0
|
1246 |
-
*
|
1247 |
-
* @param string $tag Menu item's element closing tag.
|
1248 |
-
* @param string $field Menu Item Markup settings field.
|
1249 |
-
* @param array $markup Array of markup elements for the menu item.
|
1250 |
-
* @param false|object $term Taxonomy term for current menu item.
|
1251 |
-
*/
|
1252 |
-
echo apply_filters(
|
1253 |
-
'essential-content-types_ect_food_menu_item_loop_close_element',
|
1254 |
-
'</' . tag_escape( $markup["{$field}_tag"] ) . ">\n",
|
1255 |
-
$field,
|
1256 |
-
$markup,
|
1257 |
-
$this->menu_item_loop_current_term
|
1258 |
-
);
|
1259 |
-
}
|
1260 |
-
|
1261 |
-
/**
|
1262 |
-
* Returns a Menu Item Markup element's class attribute.
|
1263 |
-
*
|
1264 |
-
* @param string $class Class name.
|
1265 |
-
* @return string HTML class attribute with leading whitespace.
|
1266 |
-
*/
|
1267 |
-
function menu_item_loop_class( $class ) {
|
1268 |
-
if ( ! $class ) {
|
1269 |
-
return '';
|
1270 |
-
}
|
1271 |
-
|
1272 |
-
/**
|
1273 |
-
* Filter a menu Item Markup element's class attribute.
|
1274 |
-
*
|
1275 |
-
* @module custom-content-types
|
1276 |
-
*
|
1277 |
-
* @since 4.4.0
|
1278 |
-
*
|
1279 |
-
* @param string $tag Menu Item Markup element's class attribute.
|
1280 |
-
* @param string $class Menu Item Class name.
|
1281 |
-
* @param false|object $term Taxonomy term for current menu item.
|
1282 |
-
*/
|
1283 |
-
return apply_filters(
|
1284 |
-
'essential-content-types_ect_food_menu_item_loop_class',
|
1285 |
-
' class="' . esc_attr( $class ) . '"',
|
1286 |
-
$class,
|
1287 |
-
$this->menu_item_loop_current_term
|
1288 |
-
);
|
1289 |
-
}
|
1290 |
-
|
1291 |
-
/**
|
1292 |
-
* Our [food_menu] shortcode.
|
1293 |
-
* Prints Food Menu data styled to look good on *any* theme.
|
1294 |
-
*
|
1295 |
-
* @return ect_food_shortcode_html
|
1296 |
-
*/
|
1297 |
-
static function ect_food_shortcode( $atts ) {
|
1298 |
-
// Default attributes
|
1299 |
-
$atts = shortcode_atts( array(
|
1300 |
-
'include_type' => false,
|
1301 |
-
'include_tag' => false,
|
1302 |
-
'showposts' => -1,
|
1303 |
-
), $atts, 'food_menu' );
|
1304 |
-
|
1305 |
-
// A little sanitization
|
1306 |
-
if ( $atts['include_type'] ) {
|
1307 |
-
$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
|
1308 |
-
}
|
1309 |
-
|
1310 |
-
if ( $atts['include_tag'] ) {
|
1311 |
-
$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
|
1312 |
-
}
|
1313 |
-
|
1314 |
-
$atts['showposts'] = intval( $atts['showposts'] );
|
1315 |
-
|
1316 |
-
// enqueue shortcode styles when shortcode is used
|
1317 |
-
wp_enqueue_style( 'ect-food-menu-style', plugins_url( 'css/food-menu-shortcode.css', __FILE__ ), array(), '20140326' );
|
1318 |
-
wp_enqueue_script( 'ect-food-menu-script', plugins_url( 'js/food-menu-shortcode.js', __FILE__ ) , array( 'jquery' ), '20180530', false );
|
1319 |
-
|
1320 |
-
return self::ect_food_shortcode_html( $atts );
|
1321 |
-
}
|
1322 |
-
|
1323 |
-
/**
|
1324 |
-
* Query to retrieve entries from the Food Menu post_type.
|
1325 |
-
*
|
1326 |
-
* @return object
|
1327 |
-
*/
|
1328 |
-
static function ect_food_query( $atts ) {
|
1329 |
-
// Default query arguments
|
1330 |
-
$default = array(
|
1331 |
-
'posts_per_page' => $atts['showposts'],
|
1332 |
-
);
|
1333 |
-
|
1334 |
-
$args = wp_parse_args( $atts, $default );
|
1335 |
-
$args['post_type'] = self::MENU_ITEM_POST_TYPE; // Force this post type
|
1336 |
-
|
1337 |
-
if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
|
1338 |
-
$args['tax_query'] = array();
|
1339 |
-
}
|
1340 |
-
|
1341 |
-
// If 'include_type' has been set use it on the main query
|
1342 |
-
if ( false != $atts['include_type'] ) {
|
1343 |
-
array_push( $args['tax_query'], array(
|
1344 |
-
'taxonomy' => self::MENU_TAX,
|
1345 |
-
'field' => 'slug',
|
1346 |
-
'terms' => $atts['include_type'],
|
1347 |
-
) );
|
1348 |
-
}
|
1349 |
-
|
1350 |
-
// If 'include_tag' has been set use it on the main query
|
1351 |
-
if ( false != $atts['include_tag'] ) {
|
1352 |
-
array_push( $args['tax_query'], array(
|
1353 |
-
'taxonomy' => self::MENU_ITEM_LABEL_TAX,
|
1354 |
-
'field' => 'slug',
|
1355 |
-
'terms' => $atts['include_tag'],
|
1356 |
-
) );
|
1357 |
-
}
|
1358 |
-
|
1359 |
-
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
1360 |
-
$args['tax_query']['relation'] = 'AND';
|
1361 |
-
}
|
1362 |
-
|
1363 |
-
// Run the query and return
|
1364 |
-
$query = new WP_Query( $args );
|
1365 |
-
return $query;
|
1366 |
-
}
|
1367 |
-
|
1368 |
-
/**
|
1369 |
-
* The Food Menu shortcode loop.
|
1370 |
-
*
|
1371 |
-
* @return html
|
1372 |
-
*/
|
1373 |
-
static function ect_food_shortcode_html( $atts ) {
|
1374 |
-
|
1375 |
-
$query = self::ect_food_query( $atts );
|
1376 |
-
ob_start();
|
1377 |
-
|
1378 |
-
// If we have posts, create the html
|
1379 |
-
// with hect_food markup
|
1380 |
-
if ( $query->have_posts() ) {
|
1381 |
-
|
1382 |
-
/**
|
1383 |
-
* Hook: ect_before_food_menu_loop.
|
1384 |
-
*
|
1385 |
-
* @hooked ect_food_menu_section
|
1386 |
-
*/
|
1387 |
-
$layout = ect_get_layout();
|
1388 |
-
do_action( 'ect_before_food_menu_loop' );
|
1389 |
-
?>
|
1390 |
-
<?php
|
1391 |
-
|
1392 |
-
ect_get_template_part( 'ect', 'menu', $atts );
|
1393 |
-
|
1394 |
-
// If comments are open or we have at least one comment, load up the comment template
|
1395 |
-
if ( comments_open() || '0' != get_comments_number() ) {
|
1396 |
-
comments_template( '', true );
|
1397 |
-
}
|
1398 |
-
?>
|
1399 |
-
<?php
|
1400 |
-
|
1401 |
-
/**
|
1402 |
-
* Hook: ect_after_food_menu_loop.
|
1403 |
-
*
|
1404 |
-
* @hooked
|
1405 |
-
*/
|
1406 |
-
do_action( 'ect_after_food_menu_loop' );
|
1407 |
-
|
1408 |
-
} else {
|
1409 |
-
/**
|
1410 |
-
* Hook: ect_no_food_menu_found.
|
1411 |
-
*
|
1412 |
-
* @hooked ect_no_food_menu_found
|
1413 |
-
*/
|
1414 |
-
do_action( 'ect_no_food_menu_found' );
|
1415 |
-
}
|
1416 |
-
|
1417 |
-
$html = ob_get_clean();
|
1418 |
-
|
1419 |
-
// If there is a [food-menu] within a [food-menu], remove the shortcode
|
1420 |
-
if ( has_shortcode( $html, 'food-menu' ) ){
|
1421 |
-
remove_shortcode( 'food-menu' );
|
1422 |
-
}
|
1423 |
-
|
1424 |
-
// Return the HTML block
|
1425 |
-
return $html;
|
1426 |
-
}
|
1427 |
-
}
|
1428 |
-
|
1429 |
-
add_action( 'init', array( 'Essential_Content_Food_Menu', 'init' ) );
|
1430 |
-
|
1431 |
-
|
1432 |
-
/**
|
1433 |
-
* Add Food Menu support
|
1434 |
-
*/
|
1435 |
-
function essential_content_food_menu_support() {
|
1436 |
-
/*
|
1437 |
-
* Adding theme support for Food Menu Item CPT.
|
1438 |
-
*/
|
1439 |
-
add_theme_support( 'ect_food_menu_item' );
|
1440 |
-
}
|
1441 |
-
add_action( 'after_setup_theme', 'essential_content_food_menu_support' );
|
1442 |
-
|
1443 |
-
|
1444 |
-
if( ! function_exists( 'essential_content_no_food_menu_found' ) ):
|
1445 |
-
/**
|
1446 |
-
* No items found text
|
1447 |
-
*
|
1448 |
-
* @return html
|
1449 |
-
*/
|
1450 |
-
function essential_content_no_food_menu_found() {
|
1451 |
-
echo "<p><em>" . esc_html__( 'Your Food Menu Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . "</em></p>";
|
1452 |
-
}
|
1453 |
-
endif;
|
1454 |
-
add_action( 'ect_no_food_menu_found', 'essential_content_no_food_menu_found', 10 );
|
1455 |
-
|
1456 |
-
|
1457 |
-
if( ! function_exists( 'essential_content_food_menu_section_open' ) ):
|
1458 |
-
/**
|
1459 |
-
* Open section
|
1460 |
-
*
|
1461 |
-
* @return html
|
1462 |
-
*/
|
1463 |
-
function essential_content_food_menu_section_open() {
|
1464 |
-
echo '<div class="ect-menu ect-section">';
|
1465 |
-
echo '<div class="ect-wrapper">';
|
1466 |
-
}
|
1467 |
-
endif;
|
1468 |
-
add_action( 'ect_before_food_menu_loop', 'essential_content_food_menu_section_open', 10, 1 );
|
1469 |
-
|
1470 |
-
|
1471 |
-
if( ! function_exists( 'essential_content_food_menu_loop_start' ) ):
|
1472 |
-
/**
|
1473 |
-
* open wrapper before loop
|
1474 |
-
*
|
1475 |
-
*/
|
1476 |
-
function essential_content_food_menu_loop_start(){
|
1477 |
-
echo '<div class="section-content-wrapper menu-content-wrapper">';
|
1478 |
-
}
|
1479 |
-
endif;
|
1480 |
-
add_action( 'ect_before_food_menu_loop', 'essential_content_food_menu_loop_start', 30 );
|
1481 |
-
|
1482 |
-
|
1483 |
-
if( ! function_exists( 'essential_content_food_menu_loop_end' ) ):
|
1484 |
-
/**
|
1485 |
-
* close wrapper after loop
|
1486 |
-
*
|
1487 |
-
*/
|
1488 |
-
function essential_content_food_menu_loop_end(){
|
1489 |
-
echo '</div><!-- .menu-content-wrapper -->';
|
1490 |
-
}
|
1491 |
-
endif;
|
1492 |
-
add_action( 'ect_after_food_menu_loop', 'essential_content_food_menu_loop_end', 10 );
|
1493 |
-
|
1494 |
-
|
1495 |
-
if( ! function_exists( 'essential_content_food_menu_section_close' ) ):
|
1496 |
-
/**
|
1497 |
-
* Close section
|
1498 |
-
*
|
1499 |
-
* @return html
|
1500 |
-
*/
|
1501 |
-
function essential_content_food_menu_section_close() {
|
1502 |
-
echo '</div><!-- .ect-wrapper -->';
|
1503 |
-
echo '</div><!-- .ect-section -->';
|
1504 |
-
}
|
1505 |
-
endif;
|
1506 |
-
add_action( 'ect_after_food_menu_loop', 'essential_content_food_menu_section_close', 20 );
|
1507 |
-
|
1508 |
-
function essential_content_food_menu_get_menus( $args = array() ) {
|
1509 |
-
$args = wp_parse_args( $args, array(
|
1510 |
-
'hide_empty' => false,
|
1511 |
-
) );
|
1512 |
-
|
1513 |
-
$terms = get_terms( 'ect_food_menu', $args );
|
1514 |
-
if ( !$terms || is_wp_error( $terms ) ) {
|
1515 |
-
return array();
|
1516 |
-
}
|
1517 |
-
|
1518 |
-
$terms_by_id = array();
|
1519 |
-
foreach ( $terms as $term ) {
|
1520 |
-
$terms_by_id["{$term->term_id}"] = $term;
|
1521 |
-
}
|
1522 |
-
|
1523 |
-
$term_order = get_option( 'ect_food_menu_order', array() );
|
1524 |
-
|
1525 |
-
$return = array();
|
1526 |
-
foreach ( $term_order as $term_id ) {
|
1527 |
-
if ( isset( $terms_by_id["$term_id"] ) ) {
|
1528 |
-
$return[] = $terms_by_id["$term_id"];
|
1529 |
-
unset( $terms_by_id["$term_id"] );
|
1530 |
-
}
|
1531 |
-
}
|
1532 |
-
|
1533 |
-
foreach ( $terms_by_id as $term_id => $term ) {
|
1534 |
-
$return[] = $term;
|
1535 |
-
}
|
1536 |
-
|
1537 |
-
return $return;
|
1538 |
}
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
* Put the following code in your theme's Food Menu Page Template to customize the markup of the menu.
|
4 |
+
|
5 |
+
if ( class_exists( 'Essential_Content_Food_Menu' ) ) {
|
6 |
+
Essential_Content_Food_Menu::init( array(
|
7 |
+
'menu_tag' => 'section',
|
8 |
+
'menu_class' => 'menu-items',
|
9 |
+
'menu_header_tag' => 'header',
|
10 |
+
'menu_header_class' => 'menu-group-header',
|
11 |
+
'menu_title_tag' => 'h1',
|
12 |
+
'menu_title_class' => 'menu-group-title',
|
13 |
+
'menu_description_tag' => 'div',
|
14 |
+
'menu_description_class' => 'menu-group-description',
|
15 |
+
) );
|
16 |
+
}
|
17 |
+
|
18 |
+
*/
|
19 |
+
|
20 |
+
/* @todo
|
21 |
+
|
22 |
+
Bulk/Quick edit response of Menu Item rows is broken.
|
23 |
+
|
24 |
+
Drag and Drop reordering.
|
25 |
+
*/
|
26 |
+
|
27 |
+
class Essential_Content_Food_Menu {
|
28 |
+
const MENU_ITEM_POST_TYPE = 'ect_food_menu_item';
|
29 |
+
const MENU_ITEM_LABEL_TAX = 'ect_food_menu_item_label';
|
30 |
+
const MENU_TAX = 'ect_food_menu';
|
31 |
+
|
32 |
+
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
33 |
+
|
34 |
+
protected $default_menu_item_loop_markup = array(
|
35 |
+
'menu_tag' => 'section',
|
36 |
+
'menu_class' => 'menu-items',
|
37 |
+
'menu_header_tag' => 'header',
|
38 |
+
'menu_header_class' => 'menu-group-header',
|
39 |
+
'menu_title_tag' => 'h1',
|
40 |
+
'menu_title_class' => 'menu-group-title',
|
41 |
+
'menu_description_tag' => 'div',
|
42 |
+
'menu_description_class' => 'menu-group-description',
|
43 |
+
);
|
44 |
+
|
45 |
+
protected $menu_item_loop_markup = array();
|
46 |
+
protected $menu_item_loop_last_term_id = false;
|
47 |
+
protected $menu_item_loop_current_term = false;
|
48 |
+
|
49 |
+
static function init( $menu_item_loop_markup = array() ) {
|
50 |
+
static $instance = false;
|
51 |
+
|
52 |
+
if ( !$instance ) {
|
53 |
+
$instance = new Essential_Content_Food_Menu;
|
54 |
+
}
|
55 |
+
|
56 |
+
if ( $menu_item_loop_markup ) {
|
57 |
+
$instance->menu_item_loop_markup = wp_parse_args( $menu_item_loop_markup, $instance->default_menu_item_loop_markup );
|
58 |
+
}
|
59 |
+
|
60 |
+
return $instance;
|
61 |
+
}
|
62 |
+
|
63 |
+
function __construct() {
|
64 |
+
if ( ! $this->site_supports_food_menu() )
|
65 |
+
return;
|
66 |
+
|
67 |
+
$this->register_taxonomies();
|
68 |
+
$this->register_post_types();
|
69 |
+
add_action( 'admin_menu', array( $this, 'add_admin_menus' ) );
|
70 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_ect_food_styles' ) );
|
71 |
+
add_action( 'admin_head', array( $this, 'set_custom_font_icon' ) );
|
72 |
+
|
73 |
+
// Enable Omnisearch for Menu Items.
|
74 |
+
if ( class_exists( 'Jetpack_Omnisearch_Posts' ) )
|
75 |
+
new Jetpack_Omnisearch_Posts( self::MENU_ITEM_POST_TYPE );
|
76 |
+
|
77 |
+
// Always sort menu items correctly
|
78 |
+
add_action( 'parse_query', array( $this, 'sort_menu_item_queries_by_menu_order' ) );
|
79 |
+
add_filter( 'posts_results', array( $this, 'sort_menu_item_queries_by_menu_taxonomy' ), 10, 2 );
|
80 |
+
|
81 |
+
add_action( 'wp_insert_post', array( $this, 'add_post_meta' ) );
|
82 |
+
|
83 |
+
$this->menu_item_loop_markup = $this->default_menu_item_loop_markup;
|
84 |
+
|
85 |
+
// Only output our Menu Item Loop Markup on a real blog view. Not feeds, XML-RPC, admin, etc.
|
86 |
+
add_filter( 'template_include', array( $this, 'setup_menu_item_loop_markup__in_filter' ) );
|
87 |
+
|
88 |
+
add_filter( 'enter_title_here', array( $this, 'change_default_title' ) );
|
89 |
+
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
90 |
+
add_filter( 'dashboard_glance_items', array( $this, 'add_to_dashboard' ) );
|
91 |
+
|
92 |
+
add_filter( 'body_class', array( $this, 'custom_class' ) );
|
93 |
+
|
94 |
+
// register food_menu shortcode (legacy)
|
95 |
+
add_shortcode( 'food_menu', array( $this, 'ect_food_shortcode' ) );
|
96 |
+
}
|
97 |
+
|
98 |
+
public function custom_class( $classes ) {
|
99 |
+
global $post;
|
100 |
+
if( isset( $post->post_content ) && has_shortcode( $post->post_content, 'food_menu' ) ) {
|
101 |
+
$classes[] = 'page-template-menu-page';
|
102 |
+
}
|
103 |
+
return $classes;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Should this Custom Post Type be made available?
|
108 |
+
*/
|
109 |
+
function site_supports_food_menu() {
|
110 |
+
// If we're on WordPress.com, and it has the menu site vertical.
|
111 |
+
if ( function_exists( 'site_vertical' ) && 'ect_food_menu' == site_vertical() )
|
112 |
+
return true;
|
113 |
+
|
114 |
+
// Else, if the current theme requests it.
|
115 |
+
if ( current_theme_supports( self::MENU_ITEM_POST_TYPE ) )
|
116 |
+
return true;
|
117 |
+
}
|
118 |
+
|
119 |
+
/* Setup */
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Register Taxonomies and Post Type
|
123 |
+
*/
|
124 |
+
function register_taxonomies() {
|
125 |
+
if ( ! taxonomy_exists( self::MENU_ITEM_LABEL_TAX ) ) {
|
126 |
+
register_taxonomy( self::MENU_ITEM_LABEL_TAX, self::MENU_ITEM_POST_TYPE, array(
|
127 |
+
'labels' => array(
|
128 |
+
/* translators: this is about a food menu */
|
129 |
+
'name' => __( 'Menu Item Labels', 'essential-content-types' ),
|
130 |
+
/* translators: this is about a food menu */
|
131 |
+
'singular_name' => __( 'Menu Item Label', 'essential-content-types' ),
|
132 |
+
/* translators: this is about a food menu */
|
133 |
+
'search_items' => __( 'Search Menu Item Labels', 'essential-content-types' ),
|
134 |
+
'popular_items' => __( 'Popular Labels', 'essential-content-types' ),
|
135 |
+
/* translators: this is about a food menu */
|
136 |
+
'all_items' => __( 'All Menu Item Labels', 'essential-content-types' ),
|
137 |
+
/* translators: this is about a food menu */
|
138 |
+
'edit_item' => __( 'Edit Menu Item Label', 'essential-content-types' ),
|
139 |
+
/* translators: this is about a food menu */
|
140 |
+
'view_item' => __( 'View Menu Item Label', 'essential-content-types' ),
|
141 |
+
/* translators: this is about a food menu */
|
142 |
+
'update_item' => __( 'Update Menu Item Label', 'essential-content-types' ),
|
143 |
+
/* translators: this is about a food menu */
|
144 |
+
'add_new_item' => __( 'Add New Menu Item Label', 'essential-content-types' ),
|
145 |
+
/* translators: this is about a food menu */
|
146 |
+
'new_item_name' => __( 'New Menu Item Label Name', 'essential-content-types' ),
|
147 |
+
'separate_items_with_commas' => __( 'For example, spicy, favorite, etc. <br /> Separate Labels with commas', 'essential-content-types' ),
|
148 |
+
'add_or_remove_items' => __( 'Add or remove Labels', 'essential-content-types' ),
|
149 |
+
'choose_from_most_used' => __( 'Choose from the most used Labels', 'essential-content-types' ),
|
150 |
+
'items_list_navigation' => __( 'Menu item label list navigation', 'essential-content-types' ),
|
151 |
+
'items_list' => __( 'Menu item labels list', 'essential-content-types' ),
|
152 |
+
),
|
153 |
+
'no_tagcloud' => __( 'No Labels found', 'essential-content-types' ),
|
154 |
+
'hierarchical' => false,
|
155 |
+
) );
|
156 |
+
}
|
157 |
+
|
158 |
+
if ( ! taxonomy_exists( self::MENU_TAX ) ) {
|
159 |
+
register_taxonomy( self::MENU_TAX, self::MENU_ITEM_POST_TYPE, array(
|
160 |
+
'labels' => array(
|
161 |
+
/* translators: this is about a food menu */
|
162 |
+
'name' => __( 'Menu Sections', 'essential-content-types' ),
|
163 |
+
/* translators: this is about a food menu */
|
164 |
+
'singular_name' => __( 'Menu Section', 'essential-content-types' ),
|
165 |
+
/* translators: this is about a food menu */
|
166 |
+
'search_items' => __( 'Search Menu Sections', 'essential-content-types' ),
|
167 |
+
/* translators: this is about a food menu */
|
168 |
+
'all_items' => __( 'All Menu Sections', 'essential-content-types' ),
|
169 |
+
/* translators: this is about a food menu */
|
170 |
+
'parent_item' => __( 'Parent Menu Section', 'essential-content-types' ),
|
171 |
+
/* translators: this is about a food menu */
|
172 |
+
'parent_item_colon' => __( 'Parent Menu Section:', 'essential-content-types' ),
|
173 |
+
/* translators: this is about a food menu */
|
174 |
+
'edit_item' => __( 'Edit Menu Section', 'essential-content-types' ),
|
175 |
+
/* translators: this is about a food menu */
|
176 |
+
'view_item' => __( 'View Menu Section', 'essential-content-types' ),
|
177 |
+
/* translators: this is about a food menu */
|
178 |
+
'update_item' => __( 'Update Menu Section', 'essential-content-types' ),
|
179 |
+
/* translators: this is about a food menu */
|
180 |
+
'add_new_item' => __( 'Add New Menu Section', 'essential-content-types' ),
|
181 |
+
/* translators: this is about a food menu */
|
182 |
+
'new_item_name' => __( 'New Menu Sections Name', 'essential-content-types' ),
|
183 |
+
'items_list_navigation' => __( 'Menu section list navigation', 'essential-content-types' ),
|
184 |
+
'items_list' => __( 'Menu section list', 'essential-content-types' ),
|
185 |
+
),
|
186 |
+
'rewrite' => array(
|
187 |
+
'slug' => 'menu',
|
188 |
+
'with_front' => false,
|
189 |
+
'hierarchical' => true,
|
190 |
+
),
|
191 |
+
'hierarchical' => true,
|
192 |
+
'show_tagcloud' => false,
|
193 |
+
'query_var' => 'menu',
|
194 |
+
) );
|
195 |
+
}
|
196 |
+
}
|
197 |
+
|
198 |
+
function register_post_types() {
|
199 |
+
if ( post_type_exists( self::MENU_ITEM_POST_TYPE ) ) {
|
200 |
+
return;
|
201 |
+
}
|
202 |
+
|
203 |
+
register_post_type( self::MENU_ITEM_POST_TYPE, array(
|
204 |
+
'description' => __( "Items on your restaurant's menu", 'essential-content-types' ),
|
205 |
+
|
206 |
+
'labels' => array(
|
207 |
+
/* translators: this is about a food menu */
|
208 |
+
'name' => __( 'Menu Items', 'essential-content-types' ),
|
209 |
+
/* translators: this is about a food menu */
|
210 |
+
'singular_name' => __( 'Menu Item', 'essential-content-types' ),
|
211 |
+
/* translators: this is about a food menu */
|
212 |
+
'menu_name' => __( 'Food Menus', 'essential-content-types' ),
|
213 |
+
/* translators: this is about a food menu */
|
214 |
+
'all_items' => __( 'Menu Items', 'essential-content-types' ),
|
215 |
+
/* translators: this is about a food menu */
|
216 |
+
'add_new' => __( 'Add One Item', 'essential-content-types' ),
|
217 |
+
/* translators: this is about a food menu */
|
218 |
+
'add_new_item' => __( 'Add Menu Item', 'essential-content-types' ),
|
219 |
+
/* translators: this is about a food menu */
|
220 |
+
'edit_item' => __( 'Edit Menu Item', 'essential-content-types' ),
|
221 |
+
/* translators: this is about a food menu */
|
222 |
+
'new_item' => __( 'New Menu Item', 'essential-content-types' ),
|
223 |
+
/* translators: this is about a food menu */
|
224 |
+
'view_item' => __( 'View Menu Item', 'essential-content-types' ),
|
225 |
+
/* translators: this is about a food menu */
|
226 |
+
'search_items' => __( 'Search Menu Items', 'essential-content-types' ),
|
227 |
+
/* translators: this is about a food menu */
|
228 |
+
'not_found' => __( 'No Menu Items found', 'essential-content-types' ),
|
229 |
+
/* translators: this is about a food menu */
|
230 |
+
'not_found_in_trash' => __( 'No Menu Items found in Trash', 'essential-content-types' ),
|
231 |
+
'filter_items_list' => __( 'Filter menu items list', 'essential-content-types' ),
|
232 |
+
'items_list_navigation' => __( 'Menu item list navigation', 'essential-content-types' ),
|
233 |
+
'items_list' => __( 'Menu items list', 'essential-content-types' ),
|
234 |
+
),
|
235 |
+
'supports' => array(
|
236 |
+
'title',
|
237 |
+
'editor',
|
238 |
+
'excerpt',
|
239 |
+
),
|
240 |
+
'rewrite' => array(
|
241 |
+
'slug' => 'item',
|
242 |
+
'with_front' => false,
|
243 |
+
'feeds' => false,
|
244 |
+
'pages' => false,
|
245 |
+
),
|
246 |
+
'register_meta_box_cb' => array( $this, 'register_menu_item_meta_boxes' ),
|
247 |
+
|
248 |
+
'public' => true,
|
249 |
+
'show_ui' => true, // set to false to replace with custom UI
|
250 |
+
'menu_position' => 20, // below Pages
|
251 |
+
'capability_type' => 'page',
|
252 |
+
'map_meta_cap' => true,
|
253 |
+
'has_archive' => false,
|
254 |
+
'query_var' => 'item',
|
255 |
+
) );
|
256 |
+
}
|
257 |
+
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Update messages for the Menu Item admin.
|
261 |
+
*/
|
262 |
+
function updated_messages( $messages ) {
|
263 |
+
global $post;
|
264 |
+
|
265 |
+
$messages[self::MENU_ITEM_POST_TYPE] = array(
|
266 |
+
0 => '', // Unused. Messages start at index 1.
|
267 |
+
/* translators: this is about a food menu */
|
268 |
+
1 => sprintf( __( 'Menu item updated. <a href="%s">View item</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
269 |
+
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
270 |
+
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
271 |
+
/* translators: this is about a food menu */
|
272 |
+
4 => esc_html__( 'Menu item updated.', 'essential-content-types' ),
|
273 |
+
/* translators: %s: date and time of the revision */
|
274 |
+
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Menu item restored to revision from %s', 'essential-content-types' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
275 |
+
/* translators: this is about a food menu */
|
276 |
+
6 => sprintf( __( 'Menu item published. <a href="%s">View item</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
277 |
+
/* translators: this is about a food menu */
|
278 |
+
7 => esc_html__( 'Menu item saved.', 'essential-content-types' ),
|
279 |
+
/* translators: this is about a food menu */
|
280 |
+
8 => sprintf( __( 'Menu item submitted. <a target="_blank" href="%s">Preview item</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
281 |
+
/* translators: this is about a food menu */
|
282 |
+
9 => sprintf( __( 'Menu item scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview item</a>', 'essential-content-types' ),
|
283 |
+
// translators: Publish box date format, see http://php.net/date
|
284 |
+
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
|
285 |
+
/* translators: this is about a food menu */
|
286 |
+
10 => sprintf( __( 'Menu item draft updated. <a target="_blank" href="%s">Preview item</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
287 |
+
);
|
288 |
+
|
289 |
+
return $messages;
|
290 |
+
}
|
291 |
+
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Nova Styles and Scripts
|
295 |
+
*/
|
296 |
+
function enqueue_ect_food_styles( $hook ) {
|
297 |
+
global $post_type;
|
298 |
+
$pages = array( 'edit.php', 'post.php', 'post-new.php' );
|
299 |
+
|
300 |
+
if ( in_array( $hook, $pages ) && $post_type == self::MENU_ITEM_POST_TYPE ) {
|
301 |
+
wp_enqueue_style( 'ect-food-menu-style', plugins_url( 'css/ect-food-menu.css', __FILE__ ), array(), $this->version );
|
302 |
+
}
|
303 |
+
|
304 |
+
wp_enqueue_style( 'ect-food-menu-font', plugins_url( 'css/ect-food-menu-font.css', __FILE__ ), array(), $this->version );
|
305 |
+
}
|
306 |
+
|
307 |
+
|
308 |
+
/**
|
309 |
+
* Change ‘Enter Title Here’ text for the Menu Item.
|
310 |
+
*/
|
311 |
+
function change_default_title( $title ) {
|
312 |
+
$screen = get_current_screen();
|
313 |
+
|
314 |
+
if ( self::MENU_ITEM_POST_TYPE == $screen->post_type )
|
315 |
+
/* translators: this is about a food menu */
|
316 |
+
$title = esc_html__( "Enter the menu item's name here", 'essential-content-types' );
|
317 |
+
|
318 |
+
return $title;
|
319 |
+
}
|
320 |
+
|
321 |
+
|
322 |
+
/**
|
323 |
+
* Add to Dashboard At A Glance
|
324 |
+
*/
|
325 |
+
function add_to_dashboard() {
|
326 |
+
$number_menu_items = wp_count_posts( self::MENU_ITEM_POST_TYPE );
|
327 |
+
|
328 |
+
if ( current_user_can( 'administrator' ) ) {
|
329 |
+
$number_menu_items_published = sprintf( '<a href="%1$s">%2$s</a>',
|
330 |
+
esc_url( get_admin_url( get_current_blog_id(), 'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE ) ),
|
331 |
+
sprintf( _n( '%1$d Food Menu Item', '%1$d Food Menu Items', intval( $number_menu_items->publish ), 'essential-content-types' ), number_format_i18n( $number_menu_items->publish ) )
|
332 |
+
);
|
333 |
+
}
|
334 |
+
else {
|
335 |
+
$number_menu_items_published = sprintf( '<span>%1$s</span>',
|
336 |
+
sprintf( _n( '%1$d Food Menu Item', '%1$d Food Menu Items', intval( $number_menu_items->publish ), 'essential-content-types' ), number_format_i18n( $number_menu_items->publish ) )
|
337 |
+
);
|
338 |
+
}
|
339 |
+
|
340 |
+
echo '<li class="ect-food-menu-count">' . $number_menu_items_published . '</li>';
|
341 |
+
}
|
342 |
+
|
343 |
+
|
344 |
+
/**
|
345 |
+
* Query
|
346 |
+
*/
|
347 |
+
function is_menu_item_query( $query ) {
|
348 |
+
if (
|
349 |
+
( isset( $query->query_vars['taxonomy'] ) && self::MENU_TAX == $query->query_vars['taxonomy'] )
|
350 |
+
||
|
351 |
+
( isset( $query->query_vars['post_type'] ) && self::MENU_ITEM_POST_TYPE == $query->query_vars['post_type'] )
|
352 |
+
) {
|
353 |
+
return true;
|
354 |
+
}
|
355 |
+
|
356 |
+
return false;
|
357 |
+
}
|
358 |
+
|
359 |
+
function sort_menu_item_queries_by_menu_order( $query ) {
|
360 |
+
if ( ! $this->is_menu_item_query( $query ) ) {
|
361 |
+
return;
|
362 |
+
}
|
363 |
+
|
364 |
+
$query->query_vars['orderby'] = 'menu_order';
|
365 |
+
$query->query_vars['order'] = 'ASC';
|
366 |
+
|
367 |
+
// For now, just turn off paging so we can sort by taxonmy later
|
368 |
+
// If we want paging in the future, we'll need to add the taxonomy sort here (or at least before the DB query is made)
|
369 |
+
$query->query_vars['posts_per_page'] = -1;
|
370 |
+
}
|
371 |
+
|
372 |
+
function sort_menu_item_queries_by_menu_taxonomy( $posts, $query ) {
|
373 |
+
if ( !$posts ) {
|
374 |
+
return $posts;
|
375 |
+
}
|
376 |
+
|
377 |
+
if ( !$this->is_menu_item_query( $query ) ) {
|
378 |
+
return $posts;
|
379 |
+
}
|
380 |
+
|
381 |
+
$grouped_by_term = array();
|
382 |
+
|
383 |
+
foreach ( $posts as $post ) {
|
384 |
+
$term = $this->get_menu_item_menu_leaf( $post->ID );
|
385 |
+
if ( !$term || is_wp_error( $term ) ) {
|
386 |
+
$term_id = 0;
|
387 |
+
} else {
|
388 |
+
$term_id = $term->term_id;
|
389 |
+
}
|
390 |
+
|
391 |
+
if ( !isset( $grouped_by_term["$term_id"] ) ) {
|
392 |
+
$grouped_by_term["$term_id"] = array();
|
393 |
+
}
|
394 |
+
|
395 |
+
$grouped_by_term["$term_id"][] = $post;
|
396 |
+
}
|
397 |
+
|
398 |
+
$term_order = get_option( 'ect_food_menu_order', array() );
|
399 |
+
|
400 |
+
$return = array();
|
401 |
+
foreach ( $term_order as $term_id ) {
|
402 |
+
if ( isset( $grouped_by_term["$term_id"] ) ) {
|
403 |
+
$return = array_merge( $return, $grouped_by_term["$term_id"] );
|
404 |
+
unset( $grouped_by_term["$term_id"] );
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
foreach ( $grouped_by_term as $term_id => $posts ) {
|
409 |
+
$return = array_merge( $return, $posts );
|
410 |
+
}
|
411 |
+
|
412 |
+
return $return;
|
413 |
+
}
|
414 |
+
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Add Many Items
|
418 |
+
*/
|
419 |
+
function add_admin_menus() {
|
420 |
+
$hook = add_submenu_page(
|
421 |
+
'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE,
|
422 |
+
__( 'Add Many Items', 'essential-content-types' ),
|
423 |
+
__( 'Add Many Items', 'essential-content-types' ),
|
424 |
+
'edit_pages',
|
425 |
+
'add_many_ect_food_items',
|
426 |
+
array( $this, 'add_many_new_items_page' )
|
427 |
+
);
|
428 |
+
|
429 |
+
add_action( "load-$hook", array( $this, 'add_many_new_items_page_load' ) );
|
430 |
+
|
431 |
+
add_action( 'current_screen', array( $this, 'current_screen_load' ) );
|
432 |
+
|
433 |
+
//Adjust 'Add Many Items' submenu position
|
434 |
+
if ( isset( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] ) ) {
|
435 |
+
$submenu_item = array_pop( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] );
|
436 |
+
$GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE][11] = $submenu_item;
|
437 |
+
ksort( $GLOBALS['submenu']['edit.php?post_type=' . self::MENU_ITEM_POST_TYPE] );
|
438 |
+
}
|
439 |
+
|
440 |
+
|
441 |
+
$this->setup_menu_item_columns();
|
442 |
+
|
443 |
+
wp_register_script(
|
444 |
+
'ect-food-menu-checkboxes',
|
445 |
+
plugin_dir_url( __FILE__ ) . 'js/ect-food-menu-menu-checkboxes.js',
|
446 |
+
array( 'jquery' ),
|
447 |
+
$this->version,
|
448 |
+
false
|
449 |
+
);
|
450 |
+
}
|
451 |
+
|
452 |
+
|
453 |
+
/**
|
454 |
+
* Custom Nova Icon CSS
|
455 |
+
*/
|
456 |
+
function set_custom_font_icon() {
|
457 |
+
?>
|
458 |
+
<style type="text/css">
|
459 |
+
#menu-posts-ect_food_menu_item .wp-menu-image:before {
|
460 |
+
font-family: 'nova-font' !important;
|
461 |
+
content: '\e603' !important;
|
462 |
+
}
|
463 |
+
</style>
|
464 |
+
<?php
|
465 |
+
}
|
466 |
+
|
467 |
+
function current_screen_load() {
|
468 |
+
$screen = get_current_screen();
|
469 |
+
if ( 'edit-ect_food_menu_item' !== $screen->id ) {
|
470 |
+
return;
|
471 |
+
}
|
472 |
+
|
473 |
+
$this->edit_menu_items_page_load();
|
474 |
+
add_filter( 'admin_notices', array( $this, 'admin_notices' ) );
|
475 |
+
}
|
476 |
+
|
477 |
+
/* Edit Items List */
|
478 |
+
|
479 |
+
function admin_notices() {
|
480 |
+
if ( isset( $_GET['ect_food_reordered'] ) )
|
481 |
+
/* translators: this is about a food menu */
|
482 |
+
printf( '<div class="updated"><p>%s</p></div>', __( 'Menu Items re-ordered.', 'essential-content-types' ) );
|
483 |
+
}
|
484 |
+
|
485 |
+
function no_title_sorting( $columns ) {
|
486 |
+
if ( isset( $columns['title'] ) )
|
487 |
+
unset( $columns['title'] );
|
488 |
+
return $columns;
|
489 |
+
}
|
490 |
+
|
491 |
+
function setup_menu_item_columns() {
|
492 |
+
add_filter( sprintf( 'manage_edit-%s_sortable_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'no_title_sorting' ) );
|
493 |
+
add_filter( sprintf( 'manage_%s_posts_columns', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_columns' ) );
|
494 |
+
|
495 |
+
add_action( sprintf( 'manage_%s_posts_custom_column', self::MENU_ITEM_POST_TYPE ), array( $this, 'menu_item_column_callback' ), 10, 2 );
|
496 |
+
}
|
497 |
+
|
498 |
+
function menu_item_columns( $columns ) {
|
499 |
+
unset( $columns['date'], $columns['likes'] );
|
500 |
+
|
501 |
+
$columns['thumbnail'] = __( 'Thumbnail', 'essential-content-types' );
|
502 |
+
$columns['labels'] = __( 'Labels', 'essential-content-types' );
|
503 |
+
$columns['price'] = __( 'Price', 'essential-content-types' );
|
504 |
+
$columns['order'] = __( 'Order', 'essential-content-types' );
|
505 |
+
|
506 |
+
return $columns;
|
507 |
+
}
|
508 |
+
|
509 |
+
function menu_item_column_callback( $column, $post_id ) {
|
510 |
+
$screen = get_current_screen();
|
511 |
+
|
512 |
+
switch ( $column ) {
|
513 |
+
case 'thumbnail':
|
514 |
+
echo get_the_post_thumbnail( $post_id, array( 50, 50 ) );
|
515 |
+
break;
|
516 |
+
case 'labels' :
|
517 |
+
$this->list_admin_labels( $post_id );
|
518 |
+
break;
|
519 |
+
case 'price' :
|
520 |
+
$this->display_price( $post_id );
|
521 |
+
break;
|
522 |
+
case 'order' :
|
523 |
+
$url = admin_url( $screen->parent_file );
|
524 |
+
|
525 |
+
$up_url = add_query_arg( array(
|
526 |
+
'action' => 'move-item-up',
|
527 |
+
'post_id' => (int) $post_id,
|
528 |
+
), wp_nonce_url( $url, 'ect_food_move_item_up_' . $post_id ) );
|
529 |
+
|
530 |
+
$down_url = add_query_arg( array(
|
531 |
+
'action' => 'move-item-down',
|
532 |
+
'post_id' => (int) $post_id,
|
533 |
+
), wp_nonce_url( $url, 'ect_food_move_item_down_' . $post_id ) );
|
534 |
+
$menu_item = get_post($post_id);
|
535 |
+
$this->get_menu_by_post_id( $post_id );
|
536 |
+
if ( $term_id = $this->get_menu_by_post_id( $post_id ) ) {
|
537 |
+
$term_id = $term_id->term_id;
|
538 |
+
}
|
539 |
+
?>
|
540 |
+
<input type="hidden" class="menu-order-value" name="ect_food_order[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $menu_item->menu_order ) ?>" />
|
541 |
+
<input type="hidden" class='ect-food-menu-term' name="ect_food_menu_term[<?php echo (int) $post_id ?>]" value="<?php echo esc_attr( $term_id ); ?>">
|
542 |
+
|
543 |
+
<span class="hide-if-js">
|
544 |
+
— <a class="ect-food-move-item-up" data-post-id="<?php echo (int) $post_id; ?>" href="<?php echo esc_url( $up_url ); ?>">up</a>
|
545 |
+
<br />
|
546 |
+
— <a class="ect-food-move-item-down" data-post-id="<?php echo (int) $post_id; ?>" href="<?php echo esc_url( $down_url ); ?>">down</a>
|
547 |
+
</span>
|
548 |
+
<?php
|
549 |
+
break;
|
550 |
+
}
|
551 |
+
}
|
552 |
+
|
553 |
+
function get_menu_by_post_id( $post_id = null ) {
|
554 |
+
if ( ! $post_id )
|
555 |
+
return false;
|
556 |
+
|
557 |
+
$terms = get_the_terms( $post_id, self::MENU_TAX );
|
558 |
+
|
559 |
+
if ( ! is_array( $terms ) )
|
560 |
+
return false;
|
561 |
+
|
562 |
+
return array_pop( $terms );
|
563 |
+
}
|
564 |
+
|
565 |
+
/**
|
566 |
+
* Fires on a menu edit page. We might have drag-n-drop reordered
|
567 |
+
*/
|
568 |
+
function maybe_reorder_menu_items() {
|
569 |
+
// make sure we clicked our button
|
570 |
+
if ( ! ( isset( $_REQUEST['menu_reorder_submit'] ) && $_REQUEST['menu_reorder_submit'] === __( 'Save New Order', 'essential-content-types' ) ) )
|
571 |
+
return;
|
572 |
+
;
|
573 |
+
|
574 |
+
// make sure we have the nonce
|
575 |
+
if ( ! ( isset( $_REQUEST['drag-drop-reorder'] ) && wp_verify_nonce( $_REQUEST['drag-drop-reorder'], 'drag-drop-reorder' ) ) )
|
576 |
+
return;
|
577 |
+
|
578 |
+
$term_pairs = array_map( 'absint', $_REQUEST['ect_food_menu_term'] );
|
579 |
+
$order_pairs = array_map( 'absint', $_REQUEST['ect_food_order'] );
|
580 |
+
|
581 |
+
foreach( $order_pairs as $ID => $menu_order ) {
|
582 |
+
$ID = absint( $ID );
|
583 |
+
unset( $order_pairs[$ID] );
|
584 |
+
if ( $ID < 0 )
|
585 |
+
continue;
|
586 |
+
|
587 |
+
$post = get_post( $ID );
|
588 |
+
if ( ! $post )
|
589 |
+
continue;
|
590 |
+
|
591 |
+
// save a write if the order hasn't changed
|
592 |
+
if ( $menu_order != $post->menu_order )
|
593 |
+
wp_update_post( compact( 'ID', 'menu_order' ) );
|
594 |
+
|
595 |
+
// save a write if the term hasn't changed
|
596 |
+
if ( $term_pairs[$ID] != $this->get_menu_by_post_id( $ID )->term_id )
|
597 |
+
wp_set_object_terms( $ID, $term_pairs[$ID], self::MENU_TAX );
|
598 |
+
|
599 |
+
}
|
600 |
+
|
601 |
+
$redirect = add_query_arg( array(
|
602 |
+
'post_type' => self::MENU_ITEM_POST_TYPE,
|
603 |
+
'ect_food_reordered' => '1'
|
604 |
+
), admin_url( 'edit.php' ) );
|
605 |
+
wp_safe_redirect( $redirect );
|
606 |
+
exit;
|
607 |
+
|
608 |
+
}
|
609 |
+
|
610 |
+
function edit_menu_items_page_load() {
|
611 |
+
if ( isset( $_GET['action'] ) ) {
|
612 |
+
$this->handle_menu_item_actions();
|
613 |
+
}
|
614 |
+
|
615 |
+
$this->maybe_reorder_menu_items();
|
616 |
+
|
617 |
+
wp_enqueue_script(
|
618 |
+
'ect-food-drag-drop',
|
619 |
+
plugin_dir_url( __FILE__ ) . 'js/ect-food-menu-drag-drop.js',
|
620 |
+
array( 'jquery-ui-sortable' ),
|
621 |
+
$this->version,
|
622 |
+
true
|
623 |
+
);
|
624 |
+
|
625 |
+
wp_localize_script( 'ect-food-drag-drop', '_novaDragDrop', array(
|
626 |
+
'nonce' => wp_create_nonce( 'drag-drop-reorder' ),
|
627 |
+
'nonceName' => 'drag-drop-reorder',
|
628 |
+
'reorder' => __( 'Save New Order', 'essential-content-types' ),
|
629 |
+
'reorderName' => 'menu_reorder_submit'
|
630 |
+
) );
|
631 |
+
add_action( 'the_post', array( $this, 'show_menu_titles_in_menu_item_list' ) );
|
632 |
+
}
|
633 |
+
|
634 |
+
function handle_menu_item_actions() {
|
635 |
+
$action = (string) $_GET['action'];
|
636 |
+
|
637 |
+
switch ( $action ) {
|
638 |
+
case 'move-item-up' :
|
639 |
+
case 'move-item-down' :
|
640 |
+
$reorder = false;
|
641 |
+
|
642 |
+
$post_id = (int) $_GET['post_id'];
|
643 |
+
|
644 |
+
$term = $this->get_menu_item_menu_leaf( $post_id );
|
645 |
+
|
646 |
+
// Get all posts in that term
|
647 |
+
$query = new WP_Query( array(
|
648 |
+
'taxonomy' => self::MENU_TAX,
|
649 |
+
'term' => $term->slug,
|
650 |
+
) );
|
651 |
+
|
652 |
+
$order = array();
|
653 |
+
foreach ( $query->posts as $post ) {
|
654 |
+
$order[] = $post->ID;
|
655 |
+
}
|
656 |
+
|
657 |
+
if ( 'move-item-up' == $action ) {
|
658 |
+
check_admin_referer( 'ect_food_move_item_up_' . $post_id );
|
659 |
+
|
660 |
+
$first_post_id = $order[0];
|
661 |
+
if ( $post_id == $first_post_id ) {
|
662 |
+
break;
|
663 |
+
}
|
664 |
+
|
665 |
+
foreach ( $order as $menu_order => $order_post_id ) {
|
666 |
+
if ( $post_id != $order_post_id ) {
|
667 |
+
continue;
|
668 |
+
}
|
669 |
+
|
670 |
+
$swap_post_id = $order[$menu_order - 1];
|
671 |
+
$order[$menu_order - 1] = $post_id;
|
672 |
+
$order[$menu_order] = $swap_post_id;
|
673 |
+
|
674 |
+
$reorder = true;
|
675 |
+
break;
|
676 |
+
}
|
677 |
+
} else {
|
678 |
+
check_admin_referer( 'ect_food_move_item_down_' . $post_id );
|
679 |
+
|
680 |
+
$last_post_id = end( $order );
|
681 |
+
if ( $post_id == $last_post_id ) {
|
682 |
+
break;
|
683 |
+
}
|
684 |
+
|
685 |
+
foreach ( $order as $menu_order => $order_post_id ) {
|
686 |
+
if ( $post_id != $order_post_id ) {
|
687 |
+
continue;
|
688 |
+
}
|
689 |
+
|
690 |
+
$swap_post_id = $order[$menu_order + 1];
|
691 |
+
$order[$menu_order + 1] = $post_id;
|
692 |
+
$order[$menu_order] = $swap_post_id;
|
693 |
+
|
694 |
+
$reorder = true;
|
695 |
+
}
|
696 |
+
}
|
697 |
+
|
698 |
+
if ( $reorder ) {
|
699 |
+
foreach ( $order as $menu_order => $ID ) {
|
700 |
+
wp_update_post( compact( 'ID', 'menu_order' ) );
|
701 |
+
}
|
702 |
+
}
|
703 |
+
|
704 |
+
break;
|
705 |
+
case 'move-menu-up' :
|
706 |
+
case 'move-menu-down' :
|
707 |
+
$reorder = false;
|
708 |
+
|
709 |
+
$term_id = (int) $_GET['term_id'];
|
710 |
+
|
711 |
+
$terms = $this->get_menus();
|
712 |
+
|
713 |
+
$order = array();
|
714 |
+
foreach ( $terms as $term ) {
|
715 |
+
$order[] = $term->term_id;
|
716 |
+
}
|
717 |
+
|
718 |
+
if ( 'move-menu-up' == $action ) {
|
719 |
+
check_admin_referer( 'ect_food_move_menu_up_' . $term_id );
|
720 |
+
|
721 |
+
$first_term_id = $order[0];
|
722 |
+
if ( $term_id == $first_term_id ) {
|
723 |
+
break;
|
724 |
+
}
|
725 |
+
|
726 |
+
foreach ( $order as $menu_order => $order_term_id ) {
|
727 |
+
if ( $term_id != $order_term_id ) {
|
728 |
+
continue;
|
729 |
+
}
|
730 |
+
|
731 |
+
$swap_term_id = $order[$menu_order - 1];
|
732 |
+
$order[$menu_order - 1] = $term_id;
|
733 |
+
$order[$menu_order] = $swap_term_id;
|
734 |
+
|
735 |
+
$reorder = true;
|
736 |
+
break;
|
737 |
+
}
|
738 |
+
} else {
|
739 |
+
check_admin_referer( 'ect_food_move_menu_down_' . $term_id );
|
740 |
+
|
741 |
+
$last_term_id = end( $order );
|
742 |
+
if ( $term_id == $last_term_id ) {
|
743 |
+
break;
|
744 |
+
}
|
745 |
+
|
746 |
+
foreach ( $order as $menu_order => $order_term_id ) {
|
747 |
+
if ( $term_id != $order_term_id ) {
|
748 |
+
continue;
|
749 |
+
}
|
750 |
+
|
751 |
+
$swap_term_id = $order[$menu_order + 1];
|
752 |
+
$order[$menu_order + 1] = $term_id;
|
753 |
+
$order[$menu_order] = $swap_term_id;
|
754 |
+
|
755 |
+
$reorder = true;
|
756 |
+
}
|
757 |
+
}
|
758 |
+
|
759 |
+
if ( $reorder ) {
|
760 |
+
update_option( 'ect_food_menu_order', $order );
|
761 |
+
}
|
762 |
+
|
763 |
+
break;
|
764 |
+
default :
|
765 |
+
return;
|
766 |
+
}
|
767 |
+
|
768 |
+
$redirect = add_query_arg( array(
|
769 |
+
'post_type' => self::MENU_ITEM_POST_TYPE,
|
770 |
+
'ect_food_reordered' => '1'
|
771 |
+
), admin_url( 'edit.php' ) );
|
772 |
+
wp_safe_redirect( $redirect );
|
773 |
+
exit;
|
774 |
+
}
|
775 |
+
|
776 |
+
/*
|
777 |
+
* Add menu title rows to the list table
|
778 |
+
*/
|
779 |
+
function show_menu_titles_in_menu_item_list( $post ) {
|
780 |
+
global $wp_list_table;
|
781 |
+
|
782 |
+
static $last_term_id = false;
|
783 |
+
|
784 |
+
$term = $this->get_menu_item_menu_leaf( $post->ID );
|
785 |
+
|
786 |
+
$term_id = $term instanceof WP_Term ? $term->term_id : null;
|
787 |
+
|
788 |
+
if ( false !== $last_term_id && $last_term_id === $term_id ) {
|
789 |
+
return;
|
790 |
+
}
|
791 |
+
|
792 |
+
if ( is_null( $term_id ) ) {
|
793 |
+
$last_term_id = null;
|
794 |
+
$term_name = '';
|
795 |
+
$parent_count = 0;
|
796 |
+
} else {
|
797 |
+
$last_term_id = $term->term_id;
|
798 |
+
$term_name = $term->name;
|
799 |
+
$parent_count = 0;
|
800 |
+
$current_term = $term;
|
801 |
+
while ( $current_term->parent ) {
|
802 |
+
$parent_count++;
|
803 |
+
$current_term = get_term( $current_term->parent, self::MENU_TAX );
|
804 |
+
}
|
805 |
+
}
|
806 |
+
|
807 |
+
$non_order_column_count = $wp_list_table->get_column_count() - 1;
|
808 |
+
|
809 |
+
$screen = get_current_screen();
|
810 |
+
|
811 |
+
$url = admin_url( $screen->parent_file );
|
812 |
+
|
813 |
+
$up_url = add_query_arg( array(
|
814 |
+
'action' => 'move-menu-up',
|
815 |
+
'term_id' => (int) $term_id,
|
816 |
+
), wp_nonce_url( $url, 'ect_food_move_menu_up_' . $term_id ) );
|
817 |
+
|
818 |
+
$down_url = add_query_arg( array(
|
819 |
+
'action' => 'move-menu-down',
|
820 |
+
'term_id' => (int) $term_id,
|
821 |
+
), wp_nonce_url( $url, 'ect_food_move_menu_down_' . $term_id ) );
|
822 |
+
|
823 |
+
?>
|
824 |
+
<tr class="no-items menu-label-row" data-term_id="<?php echo esc_attr( $term_id ) ?>">
|
825 |
+
<td class="colspanchange" colspan="<?php echo (int) $non_order_column_count; ?>">
|
826 |
+
<h3><?php
|
827 |
+
echo str_repeat( ' — ', (int) $parent_count );
|
828 |
+
|
829 |
+
if ( $term instanceof WP_Term ) {
|
830 |
+
echo esc_html( sanitize_term_field( 'name', $term_name, $term_id, self::MENU_TAX, 'display' ) );
|
831 |
+
edit_term_link( __( 'edit', 'essential-content-types' ), '<span class="edit-ect-food-section"><span class="dashicon dashicon-edit"></span>', '</span>', $term );
|
832 |
+
|
833 |
+
} else {
|
834 |
+
_e( 'Uncategorized' , 'essential-content-types' );
|
835 |
+
}
|
836 |
+
?></h3>
|
837 |
+
</td>
|
838 |
+
<td>
|
839 |
+
<?php if ( $term instanceof WP_Term ) { ?>
|
840 |
+
<a class="ect-food-move-menu-up" title="<?php esc_attr_e( 'Move menu section up', 'essential-content-types' ); ?>" href="<?php echo esc_url( $up_url ); ?>"><?php esc_html_e( 'UP', 'essential-content-types' ); ?></a>
|
841 |
+
<br />
|
842 |
+
<a class="ect-food-move-menu-down" title="<?php esc_attr_e( 'Move menu section down', 'essential-content-types' ); ?>" href="<?php echo esc_url( $down_url ); ?>"><?php esc_html_e( 'DOWN', 'essential-content-types' ); ?></a>
|
843 |
+
<?php } ?>
|
844 |
+
</td>
|
845 |
+
</tr>
|
846 |
+
<?php
|
847 |
+
}
|
848 |
+
|
849 |
+
/* Edit Many Items */
|
850 |
+
|
851 |
+
function add_many_new_items_page_load() {
|
852 |
+
if ( 'POST' === strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
|
853 |
+
$this->process_form_request();
|
854 |
+
exit;
|
855 |
+
}
|
856 |
+
|
857 |
+
$this->enqueue_many_items_scripts();
|
858 |
+
}
|
859 |
+
|
860 |
+
function enqueue_many_items_scripts() {
|
861 |
+
wp_enqueue_script(
|
862 |
+
'ect-food-many-items',
|
863 |
+
plugin_dir_url( __FILE__ ) . 'js/ect-food-menu-many-items.js',
|
864 |
+
array( 'jquery' ),
|
865 |
+
$this->version,
|
866 |
+
true
|
867 |
+
);
|
868 |
+
}
|
869 |
+
|
870 |
+
function process_form_request() {
|
871 |
+
if ( !isset( $_POST['ect_food_title'] ) || !is_array( $_POST['ect_food_title'] ) ) {
|
872 |
+
return;
|
873 |
+
}
|
874 |
+
|
875 |
+
$is_ajax = !empty( $_POST['ajax'] );
|
876 |
+
|
877 |
+
if ( $is_ajax ) {
|
878 |
+
check_ajax_referer( 'ect_food_many_items' );
|
879 |
+
} else {
|
880 |
+
check_admin_referer( 'ect_food_many_items' );
|
881 |
+
}
|
882 |
+
|
883 |
+
foreach ( array_keys( $_POST['ect_food_title'] ) as $key ) :
|
884 |
+
// $_POST is already slashed
|
885 |
+
$post_details = array(
|
886 |
+
'post_status' => 'publish',
|
887 |
+
'post_type' => self::MENU_ITEM_POST_TYPE,
|
888 |
+
'post_content' => $_POST['ect_food_content'][$key],
|
889 |
+
'post_title' => $_POST['ect_food_title'][$key],
|
890 |
+
'tax_input' => array(
|
891 |
+
self::MENU_ITEM_LABEL_TAX => $_POST['ect_food_labels'][$key],
|
892 |
+
self::MENU_TAX => isset( $_POST['ect_food_menu_tax'] ) ? $_POST['ect_food_menu_tax'] : null,
|
893 |
+
),
|
894 |
+
);
|
895 |
+
|
896 |
+
$post_id = wp_insert_post( $post_details );
|
897 |
+
if ( !$post_id || is_wp_error( $post_id ) ) {
|
898 |
+
continue;
|
899 |
+
}
|
900 |
+
|
901 |
+
$this->set_price( $post_id, isset( $_POST['ect_food_price'][$key] ) ? stripslashes( $_POST['ect_food_price'][$key] ) : '' );
|
902 |
+
|
903 |
+
if ( $is_ajax ) :
|
904 |
+
$post = get_post( $post_id );
|
905 |
+
$GLOBALS['post'] = $post;
|
906 |
+
setup_postdata( $post );
|
907 |
+
|
908 |
+
?>
|
909 |
+
<td><?php the_title(); ?></td>
|
910 |
+
<td class="ect-food-price"><?php $this->display_price(); ?></td>
|
911 |
+
<td><?php $this->list_labels( $post_id ); ?></td>
|
912 |
+
<td><?php the_content(); ?></td>
|
913 |
+
<?php
|
914 |
+
endif;
|
915 |
+
|
916 |
+
endforeach;
|
917 |
+
|
918 |
+
if ( $is_ajax ) {
|
919 |
+
exit;
|
920 |
+
}
|
921 |
+
|
922 |
+
wp_safe_redirect( admin_url( 'edit.php?post_type=' . self::MENU_ITEM_POST_TYPE ) );
|
923 |
+
exit;
|
924 |
+
}
|
925 |
+
|
926 |
+
function add_many_new_items_page() {
|
927 |
+
?>
|
928 |
+
<div class="wrap">
|
929 |
+
<h2><?php esc_html_e( 'Add Many Items', 'essential-content-types' ); ?></h2>
|
930 |
+
|
931 |
+
<p><?php _e( 'Use the <kbd>TAB</kbd> key on your keyboard to move between colums and the <kbd>ENTER</kbd> or <kbd>RETURN</kbd> key to save each row and move on to the next.', 'essential-content-types' ); ?></p>
|
932 |
+
|
933 |
+
<form method="post" action="" enctype="multipart/form-data">
|
934 |
+
<p><h3><?php esc_html_e( 'Add to section:', 'essential-content-types' ); ?> <?php wp_dropdown_categories( array(
|
935 |
+
'id' => 'ect-food-menu-tax',
|
936 |
+
'name' => 'ect_food_menu_tax',
|
937 |
+
'taxonomy' => self::MENU_TAX,
|
938 |
+
'hide_empty' => false,
|
939 |
+
'hierarchical' => true,
|
940 |
+
) ); ?></h3></p>
|
941 |
+
|
942 |
+
<table class="many-items-table wp-list-table widefat">
|
943 |
+
<thead>
|
944 |
+
<tr>
|
945 |
+
<th scope="col"><?php esc_html_e( 'Name', 'essential-content-types' ); ?></th>
|
946 |
+
<th scope="col" class="ect-food-price"><?php esc_html_e( 'Price', 'essential-content-types' ); ?></th>
|
947 |
+
<th scope="col"><?php _e( 'Labels: <small>spicy, favorite, etc. <em>Separate Labels with commas</em></small>', 'essential-content-types' ); ?></th>
|
948 |
+
<th scope="col"><?php esc_html_e( 'Description', 'essential-content-types' ); ?></th>
|
949 |
+
</tr>
|
950 |
+
</thead>
|
951 |
+
<tbody>
|
952 |
+
<tr>
|
953 |
+
<td><input type="text" name="ect_food_title[]" aria-required="true" /></td>
|
954 |
+
<td class="ect-food-price"><input type="text" name="ect_food_price[]" /></td>
|
955 |
+
<td><input type="text" name="ect_food_labels[]" /></td>
|
956 |
+
<td><textarea name="ect_food_content[]" cols="20" rows="1"></textarea>
|
957 |
+
</tr>
|
958 |
+
</tbody>
|
959 |
+
<tbody>
|
960 |
+
<tr>
|
961 |
+
<td><input type="text" name="ect_food_title[]" aria-required="true" /></td>
|
962 |
+
<td class="ect-food-price"><input type="text" name="ect_food_price[]" /></td>
|
963 |
+
<td><input type="text" name="ect_food_labels[]" /></td>
|
964 |
+
<td><textarea name="ect_food_content[]" cols="20" rows="1"></textarea>
|
965 |
+
</tr>
|
966 |
+
</tbody>
|
967 |
+
<tfoot>
|
968 |
+
<tr>
|
969 |
+
<th><a class="button button-secondary ect-food-new-row"><span class="dashicon dashicon-plus"></span> <?php esc_html_e( 'New Row' , 'essential-content-types' ); ?></a></th>
|
970 |
+
<th class="ect-food-price"></th>
|
971 |
+
<th></th>
|
972 |
+
<th></th>
|
973 |
+
</tr>
|
974 |
+
</tfoot>
|
975 |
+
</table>
|
976 |
+
|
977 |
+
<p class="submit">
|
978 |
+
<input type="submit" class="button-primary" value="<?php esc_attr_e( 'Add These New Menu Items', 'essential-content-types' ); ?>" />
|
979 |
+
<?php wp_nonce_field( 'ect_food_many_items' ); ?>
|
980 |
+
</p>
|
981 |
+
</form>
|
982 |
+
</div>
|
983 |
+
<?php
|
984 |
+
}
|
985 |
+
|
986 |
+
/* Edit One Item */
|
987 |
+
|
988 |
+
function register_menu_item_meta_boxes() {
|
989 |
+
wp_enqueue_script( 'ect-food-menu-checkboxes' );
|
990 |
+
|
991 |
+
add_meta_box( 'menu_item_price', __( 'Price', 'essential-content-types' ), array( $this, 'menu_item_price_meta_box' ), null, 'side', 'high' );
|
992 |
+
}
|
993 |
+
|
994 |
+
function menu_item_price_meta_box( $post, $meta_box ) {
|
995 |
+
$price = $this->get_price( $post->ID );
|
996 |
+
?>
|
997 |
+
<label for="ect-food-price-<?php echo (int) $post->ID; ?>" class="screen-reader-text"><?php esc_html_e( 'Price', 'essential-content-types' ); ?></label>
|
998 |
+
<input type="text" id="ect-food-price-<?php echo (int) $post->ID; ?>" class="widefat" name="ect_food_price[<?php echo (int) $post->ID; ?>]" value="<?php echo esc_attr( $price ); ?>" />
|
999 |
+
<?php
|
1000 |
+
}
|
1001 |
+
|
1002 |
+
function add_post_meta( $post_id ) {
|
1003 |
+
if ( !isset( $_POST['ect_food_price'][$post_id] ) ) {
|
1004 |
+
return;
|
1005 |
+
}
|
1006 |
+
|
1007 |
+
$this->set_price( $post_id, stripslashes( $_POST['ect_food_price'][$post_id] ) );
|
1008 |
+
}
|
1009 |
+
|
1010 |
+
/* Data */
|
1011 |
+
|
1012 |
+
function get_menus( $args = array() ) {
|
1013 |
+
$args = wp_parse_args( $args, array(
|
1014 |
+
'hide_empty' => false,
|
1015 |
+
) );
|
1016 |
+
|
1017 |
+
$terms = get_terms( self::MENU_TAX, $args );
|
1018 |
+
if ( !$terms || is_wp_error( $terms ) ) {
|
1019 |
+
return array();
|
1020 |
+
}
|
1021 |
+
|
1022 |
+
$terms_by_id = array();
|
1023 |
+
foreach ( $terms as $term ) {
|
1024 |
+
$terms_by_id["{$term->term_id}"] = $term;
|
1025 |
+
}
|
1026 |
+
|
1027 |
+
$term_order = get_option( 'ect_food_menu_order', array() );
|
1028 |
+
|
1029 |
+
$return = array();
|
1030 |
+
foreach ( $term_order as $term_id ) {
|
1031 |
+
if ( isset( $terms_by_id["$term_id"] ) ) {
|
1032 |
+
$return[] = $terms_by_id["$term_id"];
|
1033 |
+
unset( $terms_by_id["$term_id"] );
|
1034 |
+
}
|
1035 |
+
}
|
1036 |
+
|
1037 |
+
foreach ( $terms_by_id as $term_id => $term ) {
|
1038 |
+
$return[] = $term;
|
1039 |
+
}
|
1040 |
+
|
1041 |
+
return $return;
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
function get_menu_item_menu_leaf( $post_id ) {
|
1045 |
+
// Get first menu taxonomy "leaf"
|
1046 |
+
$term_ids = wp_get_object_terms( $post_id, self::MENU_TAX, array( 'fields' => 'ids' ) );
|
1047 |
+
|
1048 |
+
foreach ( $term_ids as $term_id ) {
|
1049 |
+
$children = get_term_children( $term_id, self::MENU_TAX );
|
1050 |
+
if ( ! $children ) {
|
1051 |
+
break;
|
1052 |
+
}
|
1053 |
+
}
|
1054 |
+
|
1055 |
+
if ( ! isset( $term_id ) ) {
|
1056 |
+
return false;
|
1057 |
+
}
|
1058 |
+
|
1059 |
+
return get_term( $term_id, self::MENU_TAX );
|
1060 |
+
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
function list_labels( $post_id = 0 ) {
|
1064 |
+
$post = get_post( $post_id );
|
1065 |
+
echo get_the_term_list( $post->ID, self::MENU_ITEM_LABEL_TAX, '', _x( ', ', 'Nova label separator', 'essential-content-types' ), '' );
|
1066 |
+
}
|
1067 |
+
|
1068 |
+
function list_admin_labels( $post_id = 0 ) {
|
1069 |
+
$post = get_post( $post_id );
|
1070 |
+
$labels = get_the_terms( $post->ID, self::MENU_ITEM_LABEL_TAX );
|
1071 |
+
if ( !empty( $labels ) ) {
|
1072 |
+
$out = array();
|
1073 |
+
foreach ( $labels as $label ) {
|
1074 |
+
$out[] = sprintf( '<a href="%s">%s</a>',
|
1075 |
+
esc_url( add_query_arg( array(
|
1076 |
+
'post_type' => self::MENU_ITEM_POST_TYPE,
|
1077 |
+
'taxonomy' => self::MENU_ITEM_LABEL_TAX,
|
1078 |
+
'term' => $label->slug
|
1079 |
+
), 'edit.php' ) ),
|
1080 |
+
esc_html( sanitize_term_field( 'name', $label->name, $label->term_id, self::MENU_ITEM_LABEL_TAX, 'display' ) )
|
1081 |
+
);
|
1082 |
+
}
|
1083 |
+
|
1084 |
+
echo join( _x( ', ', 'Nova label separator', 'essential-content-types' ), $out );
|
1085 |
+
} else {
|
1086 |
+
esc_html_e( 'No Labels', 'essential-content-types' );
|
1087 |
+
}
|
1088 |
+
}
|
1089 |
+
|
1090 |
+
function set_price( $post_id = 0, $price = '' ) {
|
1091 |
+
$post = get_post( $post_id );
|
1092 |
+
|
1093 |
+
return update_post_meta( $post->ID, 'ect_food_price', $price );
|
1094 |
+
}
|
1095 |
+
|
1096 |
+
function get_price( $post_id = 0 ) {
|
1097 |
+
$post = get_post( $post_id );
|
1098 |
+
|
1099 |
+
return get_post_meta( $post->ID, 'ect_food_price', true );
|
1100 |
+
}
|
1101 |
+
|
1102 |
+
function display_price( $post_id = 0 ) {
|
1103 |
+
echo esc_html( $this->get_price( $post_id ) );
|
1104 |
+
}
|
1105 |
+
|
1106 |
+
/* Menu Item Loop Markup */
|
1107 |
+
|
1108 |
+
/* Does not support nested loops */
|
1109 |
+
|
1110 |
+
function get_menu_item_loop_markup( $field = null ) {
|
1111 |
+
return $this->menu_item_loop_markup;
|
1112 |
+
}
|
1113 |
+
|
1114 |
+
/**
|
1115 |
+
* Sets up the loop markup.
|
1116 |
+
* Attached to the 'template_include' *filter*,
|
1117 |
+
* which fires only during a real blog view (not in admin, feeds, etc.)
|
1118 |
+
*
|
1119 |
+
* @param string Template File
|
1120 |
+
* @return string Template File. VERY Important.
|
1121 |
+
*/
|
1122 |
+
function setup_menu_item_loop_markup__in_filter( $template ) {
|
1123 |
+
add_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
|
1124 |
+
|
1125 |
+
return $template;
|
1126 |
+
}
|
1127 |
+
|
1128 |
+
/**
|
1129 |
+
* If the Query is a Menu Item Query, start outputing the Menu Item Loop Marku
|
1130 |
+
* Attached to the 'loop_start' action.
|
1131 |
+
*
|
1132 |
+
* @param WP_Query
|
1133 |
+
*/
|
1134 |
+
function start_menu_item_loop( $query ) {
|
1135 |
+
if ( !$this->is_menu_item_query( $query ) ) {
|
1136 |
+
return;
|
1137 |
+
}
|
1138 |
+
|
1139 |
+
$this->menu_item_loop_last_term_id = false;
|
1140 |
+
$this->menu_item_loop_current_term = false;
|
1141 |
+
|
1142 |
+
add_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
|
1143 |
+
add_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
|
1144 |
+
}
|
1145 |
+
|
1146 |
+
/**
|
1147 |
+
* Outputs the Menu Item Loop Marku
|
1148 |
+
* Attached to the 'the_post' action.
|
1149 |
+
*
|
1150 |
+
* @param WP_Post
|
1151 |
+
*/
|
1152 |
+
function menu_item_loop_each_post( $post ) {
|
1153 |
+
$this->menu_item_loop_current_term = $this->get_menu_item_menu_leaf( $post->ID );
|
1154 |
+
|
1155 |
+
if ( false === $this->menu_item_loop_last_term_id ) {
|
1156 |
+
// We're at the very beginning of the loop
|
1157 |
+
|
1158 |
+
$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
|
1159 |
+
$this->menu_item_loop_header(); // Output the menu's header
|
1160 |
+
} elseif ( $this->menu_item_loop_last_term_id != $this->menu_item_loop_current_term->term_id ) {
|
1161 |
+
// We're not at the very beginning but still need to start a new menu section. End the previous menu section first.
|
1162 |
+
|
1163 |
+
$this->menu_item_loop_close_element( 'menu' ); // End the previous menu section
|
1164 |
+
$this->menu_item_loop_open_element( 'menu' ); // Start a new menu section
|
1165 |
+
$this->menu_item_loop_header(); // Output the menu's header
|
1166 |
+
}
|
1167 |
+
|
1168 |
+
$this->menu_item_loop_last_term_id = isset( $this->menu_item_loop_current_term->term_id ) ? $this->menu_item_loop_current_term->term_id : '' ;
|
1169 |
+
}
|
1170 |
+
|
1171 |
+
/**
|
1172 |
+
* If the Query is a Menu Item Query, stop outputing the Menu Item Loop Marku
|
1173 |
+
* Attached to the 'loop_end' action.
|
1174 |
+
*
|
1175 |
+
* @param WP_Query
|
1176 |
+
*/
|
1177 |
+
function stop_menu_item_loop( $query ) {
|
1178 |
+
if ( !$this->is_menu_item_query( $query ) ) {
|
1179 |
+
return;
|
1180 |
+
}
|
1181 |
+
|
1182 |
+
remove_action( 'the_post', array( $this, 'menu_item_loop_each_post' ) );
|
1183 |
+
remove_action( 'loop_start', array( $this, 'start_menu_item_loop' ) );
|
1184 |
+
remove_action( 'loop_end', array( $this, 'stop_menu_item_loop' ) );
|
1185 |
+
|
1186 |
+
$this->menu_item_loop_close_element( 'menu' ); // End the last menu section
|
1187 |
+
}
|
1188 |
+
|
1189 |
+
/**
|
1190 |
+
* Outputs the Menu Group Header
|
1191 |
+
*/
|
1192 |
+
function menu_item_loop_header() {
|
1193 |
+
$this->menu_item_loop_open_element( 'menu_header' );
|
1194 |
+
$this->menu_item_loop_open_element( 'menu_title' );
|
1195 |
+
echo isset( $this->menu_item_loop_current_term->name ) ? esc_html( $this->menu_item_loop_current_term->name ) : ''; // @todo tax filter
|
1196 |
+
$this->menu_item_loop_close_element( 'menu_title' );
|
1197 |
+
if ( isset( $this->menu_item_loop_current_term->description ) && $this->menu_item_loop_current_term->description ) :
|
1198 |
+
$this->menu_item_loop_open_element( 'menu_description' );
|
1199 |
+
echo esc_html( $this->menu_item_loop_current_term->description ); // @todo kses, tax filter
|
1200 |
+
$this->menu_item_loop_close_element( 'menu_description' );
|
1201 |
+
endif;
|
1202 |
+
$this->menu_item_loop_close_element( 'menu_header' );
|
1203 |
+
}
|
1204 |
+
|
1205 |
+
/**
|
1206 |
+
* Outputs a Menu Item Markup element opening tag
|
1207 |
+
*
|
1208 |
+
* @param string $field - Menu Item Markup settings field.
|
1209 |
+
*/
|
1210 |
+
function menu_item_loop_open_element( $field ) {
|
1211 |
+
$markup = $this->get_menu_item_loop_markup();
|
1212 |
+
/**
|
1213 |
+
* Filter a menu item's element opening tag.
|
1214 |
+
*
|
1215 |
+
* @module custom-content-types
|
1216 |
+
*
|
1217 |
+
* @since 4.4.0
|
1218 |
+
*
|
1219 |
+
* @param string $tag Menu item's element opening tag.
|
1220 |
+
* @param string $field Menu Item Markup settings field.
|
1221 |
+
* @param array $markup Array of markup elements for the menu item.
|
1222 |
+
* @param false|object $term Taxonomy term for current menu item.
|
1223 |
+
*/
|
1224 |
+
echo apply_filters(
|
1225 |
+
'essential-content-types_ect_food_menu_item_loop_open_element',
|
1226 |
+
'<' . tag_escape( $markup["{$field}_tag"] ) . $this->menu_item_loop_class( $markup["{$field}_class"] ) . ">\n",
|
1227 |
+
$field,
|
1228 |
+
$markup,
|
1229 |
+
$this->menu_item_loop_current_term
|
1230 |
+
);
|
1231 |
+
}
|
1232 |
+
|
1233 |
+
/**
|
1234 |
+
* Outputs a Menu Item Markup element closing tag
|
1235 |
+
*
|
1236 |
+
* @param string $field - Menu Item Markup settings field
|
1237 |
+
*/
|
1238 |
+
function menu_item_loop_close_element( $field ) {
|
1239 |
+
$markup = $this->get_menu_item_loop_markup();
|
1240 |
+
/**
|
1241 |
+
* Filter a menu item's element closing tag.
|
1242 |
+
*
|
1243 |
+
* @module custom-content-types
|
1244 |
+
*
|
1245 |
+
* @since 4.4.0
|
1246 |
+
*
|
1247 |
+
* @param string $tag Menu item's element closing tag.
|
1248 |
+
* @param string $field Menu Item Markup settings field.
|
1249 |
+
* @param array $markup Array of markup elements for the menu item.
|
1250 |
+
* @param false|object $term Taxonomy term for current menu item.
|
1251 |
+
*/
|
1252 |
+
echo apply_filters(
|
1253 |
+
'essential-content-types_ect_food_menu_item_loop_close_element',
|
1254 |
+
'</' . tag_escape( $markup["{$field}_tag"] ) . ">\n",
|
1255 |
+
$field,
|
1256 |
+
$markup,
|
1257 |
+
$this->menu_item_loop_current_term
|
1258 |
+
);
|
1259 |
+
}
|
1260 |
+
|
1261 |
+
/**
|
1262 |
+
* Returns a Menu Item Markup element's class attribute.
|
1263 |
+
*
|
1264 |
+
* @param string $class Class name.
|
1265 |
+
* @return string HTML class attribute with leading whitespace.
|
1266 |
+
*/
|
1267 |
+
function menu_item_loop_class( $class ) {
|
1268 |
+
if ( ! $class ) {
|
1269 |
+
return '';
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
/**
|
1273 |
+
* Filter a menu Item Markup element's class attribute.
|
1274 |
+
*
|
1275 |
+
* @module custom-content-types
|
1276 |
+
*
|
1277 |
+
* @since 4.4.0
|
1278 |
+
*
|
1279 |
+
* @param string $tag Menu Item Markup element's class attribute.
|
1280 |
+
* @param string $class Menu Item Class name.
|
1281 |
+
* @param false|object $term Taxonomy term for current menu item.
|
1282 |
+
*/
|
1283 |
+
return apply_filters(
|
1284 |
+
'essential-content-types_ect_food_menu_item_loop_class',
|
1285 |
+
' class="' . esc_attr( $class ) . '"',
|
1286 |
+
$class,
|
1287 |
+
$this->menu_item_loop_current_term
|
1288 |
+
);
|
1289 |
+
}
|
1290 |
+
|
1291 |
+
/**
|
1292 |
+
* Our [food_menu] shortcode.
|
1293 |
+
* Prints Food Menu data styled to look good on *any* theme.
|
1294 |
+
*
|
1295 |
+
* @return ect_food_shortcode_html
|
1296 |
+
*/
|
1297 |
+
static function ect_food_shortcode( $atts ) {
|
1298 |
+
// Default attributes
|
1299 |
+
$atts = shortcode_atts( array(
|
1300 |
+
'include_type' => false,
|
1301 |
+
'include_tag' => false,
|
1302 |
+
'showposts' => -1,
|
1303 |
+
), $atts, 'food_menu' );
|
1304 |
+
|
1305 |
+
// A little sanitization
|
1306 |
+
if ( $atts['include_type'] ) {
|
1307 |
+
$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
if ( $atts['include_tag'] ) {
|
1311 |
+
$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
|
1312 |
+
}
|
1313 |
+
|
1314 |
+
$atts['showposts'] = intval( $atts['showposts'] );
|
1315 |
+
|
1316 |
+
// enqueue shortcode styles when shortcode is used
|
1317 |
+
wp_enqueue_style( 'ect-food-menu-style', plugins_url( 'css/food-menu-shortcode.css', __FILE__ ), array(), '20140326' );
|
1318 |
+
wp_enqueue_script( 'ect-food-menu-script', plugins_url( 'js/food-menu-shortcode.js', __FILE__ ) , array( 'jquery' ), '20180530', false );
|
1319 |
+
|
1320 |
+
return self::ect_food_shortcode_html( $atts );
|
1321 |
+
}
|
1322 |
+
|
1323 |
+
/**
|
1324 |
+
* Query to retrieve entries from the Food Menu post_type.
|
1325 |
+
*
|
1326 |
+
* @return object
|
1327 |
+
*/
|
1328 |
+
static function ect_food_query( $atts ) {
|
1329 |
+
// Default query arguments
|
1330 |
+
$default = array(
|
1331 |
+
'posts_per_page' => $atts['showposts'],
|
1332 |
+
);
|
1333 |
+
|
1334 |
+
$args = wp_parse_args( $atts, $default );
|
1335 |
+
$args['post_type'] = self::MENU_ITEM_POST_TYPE; // Force this post type
|
1336 |
+
|
1337 |
+
if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
|
1338 |
+
$args['tax_query'] = array();
|
1339 |
+
}
|
1340 |
+
|
1341 |
+
// If 'include_type' has been set use it on the main query
|
1342 |
+
if ( false != $atts['include_type'] ) {
|
1343 |
+
array_push( $args['tax_query'], array(
|
1344 |
+
'taxonomy' => self::MENU_TAX,
|
1345 |
+
'field' => 'slug',
|
1346 |
+
'terms' => $atts['include_type'],
|
1347 |
+
) );
|
1348 |
+
}
|
1349 |
+
|
1350 |
+
// If 'include_tag' has been set use it on the main query
|
1351 |
+
if ( false != $atts['include_tag'] ) {
|
1352 |
+
array_push( $args['tax_query'], array(
|
1353 |
+
'taxonomy' => self::MENU_ITEM_LABEL_TAX,
|
1354 |
+
'field' => 'slug',
|
1355 |
+
'terms' => $atts['include_tag'],
|
1356 |
+
) );
|
1357 |
+
}
|
1358 |
+
|
1359 |
+
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
1360 |
+
$args['tax_query']['relation'] = 'AND';
|
1361 |
+
}
|
1362 |
+
|
1363 |
+
// Run the query and return
|
1364 |
+
$query = new WP_Query( $args );
|
1365 |
+
return $query;
|
1366 |
+
}
|
1367 |
+
|
1368 |
+
/**
|
1369 |
+
* The Food Menu shortcode loop.
|
1370 |
+
*
|
1371 |
+
* @return html
|
1372 |
+
*/
|
1373 |
+
static function ect_food_shortcode_html( $atts ) {
|
1374 |
+
|
1375 |
+
$query = self::ect_food_query( $atts );
|
1376 |
+
ob_start();
|
1377 |
+
|
1378 |
+
// If we have posts, create the html
|
1379 |
+
// with hect_food markup
|
1380 |
+
if ( $query->have_posts() ) {
|
1381 |
+
|
1382 |
+
/**
|
1383 |
+
* Hook: ect_before_food_menu_loop.
|
1384 |
+
*
|
1385 |
+
* @hooked ect_food_menu_section
|
1386 |
+
*/
|
1387 |
+
$layout = ect_get_layout();
|
1388 |
+
do_action( 'ect_before_food_menu_loop' );
|
1389 |
+
?>
|
1390 |
+
<?php
|
1391 |
+
|
1392 |
+
ect_get_template_part( 'ect', 'menu', $atts );
|
1393 |
+
|
1394 |
+
// If comments are open or we have at least one comment, load up the comment template
|
1395 |
+
if ( comments_open() || '0' != get_comments_number() ) {
|
1396 |
+
comments_template( '', true );
|
1397 |
+
}
|
1398 |
+
?>
|
1399 |
+
<?php
|
1400 |
+
|
1401 |
+
/**
|
1402 |
+
* Hook: ect_after_food_menu_loop.
|
1403 |
+
*
|
1404 |
+
* @hooked
|
1405 |
+
*/
|
1406 |
+
do_action( 'ect_after_food_menu_loop' );
|
1407 |
+
|
1408 |
+
} else {
|
1409 |
+
/**
|
1410 |
+
* Hook: ect_no_food_menu_found.
|
1411 |
+
*
|
1412 |
+
* @hooked ect_no_food_menu_found
|
1413 |
+
*/
|
1414 |
+
do_action( 'ect_no_food_menu_found' );
|
1415 |
+
}
|
1416 |
+
|
1417 |
+
$html = ob_get_clean();
|
1418 |
+
|
1419 |
+
// If there is a [food-menu] within a [food-menu], remove the shortcode
|
1420 |
+
if ( has_shortcode( $html, 'food-menu' ) ){
|
1421 |
+
remove_shortcode( 'food-menu' );
|
1422 |
+
}
|
1423 |
+
|
1424 |
+
// Return the HTML block
|
1425 |
+
return $html;
|
1426 |
+
}
|
1427 |
+
}
|
1428 |
+
|
1429 |
+
add_action( 'init', array( 'Essential_Content_Food_Menu', 'init' ) );
|
1430 |
+
|
1431 |
+
|
1432 |
+
/**
|
1433 |
+
* Add Food Menu support
|
1434 |
+
*/
|
1435 |
+
function essential_content_food_menu_support() {
|
1436 |
+
/*
|
1437 |
+
* Adding theme support for Food Menu Item CPT.
|
1438 |
+
*/
|
1439 |
+
add_theme_support( 'ect_food_menu_item' );
|
1440 |
+
}
|
1441 |
+
add_action( 'after_setup_theme', 'essential_content_food_menu_support' );
|
1442 |
+
|
1443 |
+
|
1444 |
+
if( ! function_exists( 'essential_content_no_food_menu_found' ) ):
|
1445 |
+
/**
|
1446 |
+
* No items found text
|
1447 |
+
*
|
1448 |
+
* @return html
|
1449 |
+
*/
|
1450 |
+
function essential_content_no_food_menu_found() {
|
1451 |
+
echo "<p><em>" . esc_html__( 'Your Food Menu Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . "</em></p>";
|
1452 |
+
}
|
1453 |
+
endif;
|
1454 |
+
add_action( 'ect_no_food_menu_found', 'essential_content_no_food_menu_found', 10 );
|
1455 |
+
|
1456 |
+
|
1457 |
+
if( ! function_exists( 'essential_content_food_menu_section_open' ) ):
|
1458 |
+
/**
|
1459 |
+
* Open section
|
1460 |
+
*
|
1461 |
+
* @return html
|
1462 |
+
*/
|
1463 |
+
function essential_content_food_menu_section_open() {
|
1464 |
+
echo '<div class="ect-menu ect-section">';
|
1465 |
+
echo '<div class="ect-wrapper">';
|
1466 |
+
}
|
1467 |
+
endif;
|
1468 |
+
add_action( 'ect_before_food_menu_loop', 'essential_content_food_menu_section_open', 10, 1 );
|
1469 |
+
|
1470 |
+
|
1471 |
+
if( ! function_exists( 'essential_content_food_menu_loop_start' ) ):
|
1472 |
+
/**
|
1473 |
+
* open wrapper before loop
|
1474 |
+
*
|
1475 |
+
*/
|
1476 |
+
function essential_content_food_menu_loop_start(){
|
1477 |
+
echo '<div class="section-content-wrapper menu-content-wrapper">';
|
1478 |
+
}
|
1479 |
+
endif;
|
1480 |
+
add_action( 'ect_before_food_menu_loop', 'essential_content_food_menu_loop_start', 30 );
|
1481 |
+
|
1482 |
+
|
1483 |
+
if( ! function_exists( 'essential_content_food_menu_loop_end' ) ):
|
1484 |
+
/**
|
1485 |
+
* close wrapper after loop
|
1486 |
+
*
|
1487 |
+
*/
|
1488 |
+
function essential_content_food_menu_loop_end(){
|
1489 |
+
echo '</div><!-- .menu-content-wrapper -->';
|
1490 |
+
}
|
1491 |
+
endif;
|
1492 |
+
add_action( 'ect_after_food_menu_loop', 'essential_content_food_menu_loop_end', 10 );
|
1493 |
+
|
1494 |
+
|
1495 |
+
if( ! function_exists( 'essential_content_food_menu_section_close' ) ):
|
1496 |
+
/**
|
1497 |
+
* Close section
|
1498 |
+
*
|
1499 |
+
* @return html
|
1500 |
+
*/
|
1501 |
+
function essential_content_food_menu_section_close() {
|
1502 |
+
echo '</div><!-- .ect-wrapper -->';
|
1503 |
+
echo '</div><!-- .ect-section -->';
|
1504 |
+
}
|
1505 |
+
endif;
|
1506 |
+
add_action( 'ect_after_food_menu_loop', 'essential_content_food_menu_section_close', 20 );
|
1507 |
+
|
1508 |
+
function essential_content_food_menu_get_menus( $args = array() ) {
|
1509 |
+
$args = wp_parse_args( $args, array(
|
1510 |
+
'hide_empty' => false,
|
1511 |
+
) );
|
1512 |
+
|
1513 |
+
$terms = get_terms( 'ect_food_menu', $args );
|
1514 |
+
if ( !$terms || is_wp_error( $terms ) ) {
|
1515 |
+
return array();
|
1516 |
+
}
|
1517 |
+
|
1518 |
+
$terms_by_id = array();
|
1519 |
+
foreach ( $terms as $term ) {
|
1520 |
+
$terms_by_id["{$term->term_id}"] = $term;
|
1521 |
+
}
|
1522 |
+
|
1523 |
+
$term_order = get_option( 'ect_food_menu_order', array() );
|
1524 |
+
|
1525 |
+
$return = array();
|
1526 |
+
foreach ( $term_order as $term_id ) {
|
1527 |
+
if ( isset( $terms_by_id["$term_id"] ) ) {
|
1528 |
+
$return[] = $terms_by_id["$term_id"];
|
1529 |
+
unset( $terms_by_id["$term_id"] );
|
1530 |
+
}
|
1531 |
+
}
|
1532 |
+
|
1533 |
+
foreach ( $terms_by_id as $term_id => $term ) {
|
1534 |
+
$return[] = $term;
|
1535 |
+
}
|
1536 |
+
|
1537 |
+
return $return;
|
1538 |
}
|
admin/class-portfolio.php
CHANGED
@@ -1,882 +1,882 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Support JetPack Portfolio
|
5 |
-
*/
|
6 |
-
class Essential_Content_Jetpack_Portfolio {
|
7 |
-
const CUSTOM_POST_TYPE = 'jetpack-portfolio';
|
8 |
-
const CUSTOM_TAXONOMY_TYPE = 'jetpack-portfolio-type';
|
9 |
-
const CUSTOM_TAXONOMY_TAG = 'jetpack-portfolio-tag';
|
10 |
-
const OPTION_NAME = 'jetpack_portfolio';
|
11 |
-
const OPTION_READING_SETTING = 'jetpack_portfolio_posts_per_page';
|
12 |
-
|
13 |
-
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
14 |
-
|
15 |
-
static function init() {
|
16 |
-
static $instance = false;
|
17 |
-
|
18 |
-
if ( ! $instance ) {
|
19 |
-
$instance = new Essential_Content_Jetpack_Portfolio;
|
20 |
-
}
|
21 |
-
|
22 |
-
return $instance;
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Conditionally hook into WordPress.
|
27 |
-
*
|
28 |
-
* Setup user option for enabling CPT
|
29 |
-
* If user has CPT enabled, show in admin
|
30 |
-
*/
|
31 |
-
function __construct() {
|
32 |
-
// Add an option to enable the CPT
|
33 |
-
add_action( 'admin_init', array( $this, 'settings_api_init' ) );
|
34 |
-
|
35 |
-
// Check on theme switch if theme supports CPT and setting is disabled
|
36 |
-
add_action( 'after_switch_theme', array( $this, 'activation_post_type_support' ) );
|
37 |
-
|
38 |
-
// Make sure the post types are loaded for imports
|
39 |
-
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
40 |
-
|
41 |
-
// Add to REST API post type whitelist
|
42 |
-
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_portfolio_rest_api_type' ) );
|
43 |
-
|
44 |
-
$setting = 1;
|
45 |
-
|
46 |
-
if ( class_exists( 'Jetpack_Options' ) ) {
|
47 |
-
$setting = Jetpack_Options::get_option_and_ensure_autoload( self::OPTION_NAME, '0' );
|
48 |
-
}
|
49 |
-
|
50 |
-
// Bail early if Portfolio option is not set and the theme doesn't declare support
|
51 |
-
if ( empty( $setting ) && ! $this->site_supports_custom_post_type() ) {
|
52 |
-
return;
|
53 |
-
}
|
54 |
-
|
55 |
-
// Enable Omnisearch for Portfolio Items.
|
56 |
-
if ( class_exists( 'Jetpack_Omnisearch_Posts' ) )
|
57 |
-
new Jetpack_Omnisearch_Posts( self::CUSTOM_POST_TYPE );
|
58 |
-
|
59 |
-
// CPT magic
|
60 |
-
$this->register_post_types();
|
61 |
-
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
62 |
-
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
63 |
-
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE), array( $this, 'flush_rules_on_first_project' ) );
|
64 |
-
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
65 |
-
|
66 |
-
// Admin Customization
|
67 |
-
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
68 |
-
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE), array( $this, 'edit_admin_columns' ) );
|
69 |
-
add_filter( sprintf( 'manage_%s_posts_custom_column', self::CUSTOM_POST_TYPE), array( $this, 'image_column' ), 10, 2 );
|
70 |
-
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
71 |
-
|
72 |
-
add_image_size( 'jetpack-portfolio-admin-thumb', 50, 50, true );
|
73 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
|
74 |
-
|
75 |
-
// register jetpack_portfolio shortcode and portfolio shortcode (legacy)
|
76 |
-
add_shortcode( 'portfolio', array( $this, 'portfolio_shortcode' ) );
|
77 |
-
add_shortcode( 'jetpack_portfolio', array( $this, 'portfolio_shortcode' ) );
|
78 |
-
|
79 |
-
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
80 |
-
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ) );
|
81 |
-
|
82 |
-
// If CPT was enabled programatically and no CPT items exist when user switches away, disable
|
83 |
-
if ( $setting && $this->site_supports_custom_post_type() ) {
|
84 |
-
add_action( 'switch_theme', array( $this, 'deactivation_post_type_support' ) );
|
85 |
-
}
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Add a checkbox field in 'Settings' > 'Writing'
|
90 |
-
* for enabling CPT functionality.
|
91 |
-
*
|
92 |
-
* @return null
|
93 |
-
*/
|
94 |
-
function settings_api_init() {
|
95 |
-
add_settings_field(
|
96 |
-
self::OPTION_NAME,
|
97 |
-
'<span class="cpt-options">' . esc_html__( 'Portfolio Projects', 'essential-content-types' ) . '</span>',
|
98 |
-
array( $this, 'setting_html' ),
|
99 |
-
'writing',
|
100 |
-
'jetpack_cpt_section'
|
101 |
-
);
|
102 |
-
register_setting(
|
103 |
-
'writing',
|
104 |
-
self::OPTION_NAME,
|
105 |
-
'intval'
|
106 |
-
);
|
107 |
-
|
108 |
-
// Check if CPT is enabled first so that intval doesn't get set to NULL on re-registering
|
109 |
-
if ( get_option( self::OPTION_NAME, '0' ) || current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
110 |
-
register_setting(
|
111 |
-
'writing',
|
112 |
-
self::OPTION_READING_SETTING,
|
113 |
-
'intval'
|
114 |
-
);
|
115 |
-
}
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* HTML code to display a checkbox true/false option
|
120 |
-
* for the Portfolio CPT setting.
|
121 |
-
*
|
122 |
-
* @return html
|
123 |
-
*/
|
124 |
-
function setting_html() {
|
125 |
-
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) : ?>
|
126 |
-
<p><?php printf( /* translators: %s is the name of a custom post type such as "jetpack-portfolio" */ __( 'Your theme supports <strong>%s</strong>', 'essential-content-types' ), self::CUSTOM_POST_TYPE ); ?></p>
|
127 |
-
<?php else : ?>
|
128 |
-
<label for="<?php echo esc_attr( self::OPTION_NAME ); ?>">
|
129 |
-
<input name="<?php echo esc_attr( self::OPTION_NAME ); ?>" id="<?php echo esc_attr( self::OPTION_NAME ); ?>" <?php echo checked( get_option( self::OPTION_NAME, '0' ), true, false ); ?> type="checkbox" value="1" />
|
130 |
-
<?php esc_html_e( 'Enable Portfolio Projects for this site.', 'essential-content-types' ); ?>
|
131 |
-
<a target="_blank" href="http://en.support.wordpress.com/portfolios/"><?php esc_html_e( 'Learn More', 'essential-content-types' ); ?></a>
|
132 |
-
</label>
|
133 |
-
<?php endif;
|
134 |
-
if ( get_option( self::OPTION_NAME, '0' ) || current_theme_supports( self::CUSTOM_POST_TYPE ) ) :
|
135 |
-
printf( '<p><label for="%1$s">%2$s</label></p>',
|
136 |
-
esc_attr( self::OPTION_READING_SETTING ),
|
137 |
-
/* translators: %1$s is replaced with an input field for numbers */
|
138 |
-
sprintf( __( 'Portfolio pages display at most %1$s projects', 'essential-content-types' ),
|
139 |
-
sprintf( '<input name="%1$s" id="%1$s" type="number" step="1" min="1" value="%2$s" class="small-text" />',
|
140 |
-
esc_attr( self::OPTION_READING_SETTING ),
|
141 |
-
esc_attr( get_option( self::OPTION_READING_SETTING, '10' ) )
|
142 |
-
)
|
143 |
-
)
|
144 |
-
);
|
145 |
-
endif;
|
146 |
-
}
|
147 |
-
|
148 |
-
/**
|
149 |
-
* Should this Custom Post Type be made available?
|
150 |
-
*/
|
151 |
-
function site_supports_custom_post_type() {
|
152 |
-
// If the current theme requests it.
|
153 |
-
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) || get_option( self::OPTION_NAME, '0' ) ) {
|
154 |
-
return true;
|
155 |
-
}
|
156 |
-
|
157 |
-
// Otherwise, say no unless something wants to filter us to say yes.
|
158 |
-
/** This action is documented in modules/custom-post-types/nova.php */
|
159 |
-
return (bool) apply_filters( 'jetpack_enable_cpt', false, self::CUSTOM_POST_TYPE );
|
160 |
-
}
|
161 |
-
|
162 |
-
/*
|
163 |
-
* Flush permalinks when CPT option is turned on/off
|
164 |
-
*/
|
165 |
-
function flush_rules_on_enable() {
|
166 |
-
flush_rewrite_rules();
|
167 |
-
}
|
168 |
-
|
169 |
-
/*
|
170 |
-
* Count published projects and flush permalinks when first projects is published
|
171 |
-
*/
|
172 |
-
function flush_rules_on_first_project() {
|
173 |
-
$projects = get_transient( 'jetpack-portfolio-count-cache' );
|
174 |
-
|
175 |
-
if ( false === $projects ) {
|
176 |
-
flush_rewrite_rules();
|
177 |
-
$projects = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
178 |
-
|
179 |
-
if ( ! empty( $projects ) ) {
|
180 |
-
set_transient( 'jetpack-portfolio-count-cache', $projects, HOUR_IN_SECONDS * 12 );
|
181 |
-
}
|
182 |
-
}
|
183 |
-
}
|
184 |
-
|
185 |
-
/*
|
186 |
-
* Flush permalinks when CPT supported theme is activated
|
187 |
-
*/
|
188 |
-
function flush_rules_on_switch() {
|
189 |
-
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
190 |
-
flush_rewrite_rules();
|
191 |
-
}
|
192 |
-
}
|
193 |
-
|
194 |
-
/**
|
195 |
-
* On plugin/theme activation, check if current theme supports CPT
|
196 |
-
*/
|
197 |
-
static function activation_post_type_support() {
|
198 |
-
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
199 |
-
update_option( self::OPTION_NAME, '1' );
|
200 |
-
}
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* On theme switch, check if CPT item exists and disable if not
|
205 |
-
*/
|
206 |
-
function deactivation_post_type_support() {
|
207 |
-
$portfolios = get_posts( array(
|
208 |
-
'fields' => 'ids',
|
209 |
-
'posts_per_page' => 1,
|
210 |
-
'post_type' => self::CUSTOM_POST_TYPE,
|
211 |
-
'suppress_filters' => false
|
212 |
-
) );
|
213 |
-
|
214 |
-
if ( empty( $portfolios ) ) {
|
215 |
-
update_option( self::OPTION_NAME, '0' );
|
216 |
-
}
|
217 |
-
}
|
218 |
-
|
219 |
-
/**
|
220 |
-
* Register Post Type
|
221 |
-
*/
|
222 |
-
function register_post_types() {
|
223 |
-
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
224 |
-
return;
|
225 |
-
}
|
226 |
-
|
227 |
-
$args = array(
|
228 |
-
'description' => __( 'Portfolio Items', 'essential-content-types' ),
|
229 |
-
'labels' => array(
|
230 |
-
'name' => esc_html__( 'Projects', 'essential-content-types' ),
|
231 |
-
'singular_name' => esc_html__( 'Project', 'essential-content-types' ),
|
232 |
-
'menu_name' => esc_html__( 'Portfolio', 'essential-content-types' ),
|
233 |
-
'all_items' => esc_html__( 'All Projects', 'essential-content-types' ),
|
234 |
-
'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
|
235 |
-
'add_new_item' => esc_html__( 'Add New Project', 'essential-content-types' ),
|
236 |
-
'edit_item' => esc_html__( 'Edit Project', 'essential-content-types' ),
|
237 |
-
'new_item' => esc_html__( 'New Project', 'essential-content-types' ),
|
238 |
-
'view_item' => esc_html__( 'View Project', 'essential-content-types' ),
|
239 |
-
'search_items' => esc_html__( 'Search Projects', 'essential-content-types' ),
|
240 |
-
'not_found' => esc_html__( 'No Projects found', 'essential-content-types' ),
|
241 |
-
'not_found_in_trash' => esc_html__( 'No Projects found in Trash', 'essential-content-types' ),
|
242 |
-
'filter_items_list' => esc_html__( 'Filter projects list', 'essential-content-types' ),
|
243 |
-
'items_list_navigation' => esc_html__( 'Project list navigation', 'essential-content-types' ),
|
244 |
-
'items_list' => esc_html__( 'Projects list', 'essential-content-types' ),
|
245 |
-
),
|
246 |
-
'supports' => array(
|
247 |
-
'title',
|
248 |
-
'editor',
|
249 |
-
'excerpt',
|
250 |
-
'thumbnail',
|
251 |
-
'author',
|
252 |
-
'comments',
|
253 |
-
'publicize',
|
254 |
-
),
|
255 |
-
'rewrite' => array(
|
256 |
-
'slug' => 'portfolio',
|
257 |
-
'with_front' => false,
|
258 |
-
'feeds' => true,
|
259 |
-
'pages' => true,
|
260 |
-
),
|
261 |
-
'public' => true,
|
262 |
-
'show_ui' => true,
|
263 |
-
'menu_position' => 20, // below Pages
|
264 |
-
'menu_icon' => 'dashicons-portfolio', // 3.8+ dashicon option
|
265 |
-
'capability_type' => 'page',
|
266 |
-
'map_meta_cap' => true,
|
267 |
-
'taxonomies' => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
|
268 |
-
'has_archive' => true,
|
269 |
-
'query_var' => 'portfolio',
|
270 |
-
'show_in_rest' => true,
|
271 |
-
);
|
272 |
-
|
273 |
-
$description = get_option( 'jetpack_portfolio_content' );
|
274 |
-
if ( '' !== $description ) {
|
275 |
-
$args['description'] = $description;
|
276 |
-
}
|
277 |
-
|
278 |
-
register_post_type( self::CUSTOM_POST_TYPE, $args );
|
279 |
-
|
280 |
-
register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
|
281 |
-
'hierarchical' => true,
|
282 |
-
'labels' => array(
|
283 |
-
'name' => esc_html__( 'Project Types', 'essential-content-types' ),
|
284 |
-
'singular_name' => esc_html__( 'Project Type', 'essential-content-types' ),
|
285 |
-
'menu_name' => esc_html__( 'Project Types', 'essential-content-types' ),
|
286 |
-
'all_items' => esc_html__( 'All Project Types', 'essential-content-types' ),
|
287 |
-
'edit_item' => esc_html__( 'Edit Project Type', 'essential-content-types' ),
|
288 |
-
'view_item' => esc_html__( 'View Project Type', 'essential-content-types' ),
|
289 |
-
'update_item' => esc_html__( 'Update Project Type', 'essential-content-types' ),
|
290 |
-
'add_new_item' => esc_html__( 'Add New Project Type', 'essential-content-types' ),
|
291 |
-
'new_item_name' => esc_html__( 'New Project Type Name', 'essential-content-types' ),
|
292 |
-
'parent_item' => esc_html__( 'Parent Project Type', 'essential-content-types' ),
|
293 |
-
'parent_item_colon' => esc_html__( 'Parent Project Type:', 'essential-content-types' ),
|
294 |
-
'search_items' => esc_html__( 'Search Project Types', 'essential-content-types' ),
|
295 |
-
'items_list_navigation' => esc_html__( 'Project type list navigation', 'essential-content-types' ),
|
296 |
-
'items_list' => esc_html__( 'Project type list', 'essential-content-types' ),
|
297 |
-
),
|
298 |
-
'public' => true,
|
299 |
-
'show_ui' => true,
|
300 |
-
'show_in_nav_menus' => true,
|
301 |
-
'show_in_rest' => true,
|
302 |
-
'show_admin_column' => true,
|
303 |
-
'query_var' => true,
|
304 |
-
'rewrite' => array( 'slug' => 'project-type' ),
|
305 |
-
) );
|
306 |
-
|
307 |
-
register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
|
308 |
-
'hierarchical' => false,
|
309 |
-
'labels' => array(
|
310 |
-
'name' => esc_html__( 'Project Tags', 'essential-content-types' ),
|
311 |
-
'singular_name' => esc_html__( 'Project Tag', 'essential-content-types' ),
|
312 |
-
'menu_name' => esc_html__( 'Project Tags', 'essential-content-types' ),
|
313 |
-
'all_items' => esc_html__( 'All Project Tags', 'essential-content-types' ),
|
314 |
-
'edit_item' => esc_html__( 'Edit Project Tag', 'essential-content-types' ),
|
315 |
-
'view_item' => esc_html__( 'View Project Tag', 'essential-content-types' ),
|
316 |
-
'update_item' => esc_html__( 'Update Project Tag', 'essential-content-types' ),
|
317 |
-
'add_new_item' => esc_html__( 'Add New Project Tag', 'essential-content-types' ),
|
318 |
-
'new_item_name' => esc_html__( 'New Project Tag Name', 'essential-content-types' ),
|
319 |
-
'search_items' => esc_html__( 'Search Project Tags', 'essential-content-types' ),
|
320 |
-
'popular_items' => esc_html__( 'Popular Project Tags', 'essential-content-types' ),
|
321 |
-
'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
|
322 |
-
'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
|
323 |
-
'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
|
324 |
-
'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
|
325 |
-
'items_list_navigation' => esc_html__( 'Project tag list navigation', 'essential-content-types' ),
|
326 |
-
'items_list' => esc_html__( 'Project tag list', 'essential-content-types' ),
|
327 |
-
),
|
328 |
-
'public' => true,
|
329 |
-
'show_ui' => true,
|
330 |
-
'show_in_nav_menus' => true,
|
331 |
-
'show_in_rest' => true,
|
332 |
-
'show_admin_column' => true,
|
333 |
-
'query_var' => true,
|
334 |
-
'rewrite' => array( 'slug' => 'project-tag' ),
|
335 |
-
) );
|
336 |
-
}
|
337 |
-
|
338 |
-
/**
|
339 |
-
* Update messages for the Portfolio admin.
|
340 |
-
*/
|
341 |
-
function updated_messages( $messages ) {
|
342 |
-
global $post;
|
343 |
-
|
344 |
-
$messages[self::CUSTOM_POST_TYPE] = array(
|
345 |
-
0 => '', // Unused. Messages start at index 1.
|
346 |
-
1 => sprintf( __( 'Project updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
|
347 |
-
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
348 |
-
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
349 |
-
4 => esc_html__( 'Project updated.', 'essential-content-types' ),
|
350 |
-
/* translators: %s: date and time of the revision */
|
351 |
-
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Project restored to revision from %s', 'essential-content-types'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
352 |
-
6 => sprintf( __( 'Project published. <a href="%s">View project</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
353 |
-
7 => esc_html__( 'Project saved.', 'essential-content-types' ),
|
354 |
-
8 => sprintf( __( 'Project submitted. <a target="_blank" href="%s">Preview project</a>', 'essential-content-types'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
355 |
-
9 => sprintf( __( 'Project scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview project</a>', 'essential-content-types' ),
|
356 |
-
// translators: Publish box date format, see http://php.net/date
|
357 |
-
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
|
358 |
-
10 => sprintf( __( 'Project item draft updated. <a target="_blank" href="%s">Preview project</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
359 |
-
);
|
360 |
-
|
361 |
-
return $messages;
|
362 |
-
}
|
363 |
-
|
364 |
-
/**
|
365 |
-
* Change ‘Title’ column label
|
366 |
-
* Add Featured Image column
|
367 |
-
*/
|
368 |
-
function edit_admin_columns( $columns ) {
|
369 |
-
// change 'Title' to 'Project'
|
370 |
-
$columns['title'] = __( 'Project', 'essential-content-types' );
|
371 |
-
if ( current_theme_supports( 'post-thumbnails' ) ) {
|
372 |
-
// add featured image before 'Project'
|
373 |
-
$columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
|
374 |
-
}
|
375 |
-
|
376 |
-
return $columns;
|
377 |
-
}
|
378 |
-
|
379 |
-
/**
|
380 |
-
* Add featured image to column
|
381 |
-
*/
|
382 |
-
function image_column( $column, $post_id ) {
|
383 |
-
global $post;
|
384 |
-
switch ( $column ) {
|
385 |
-
case 'thumbnail':
|
386 |
-
echo get_the_post_thumbnail( $post_id, 'jetpack-portfolio-admin-thumb' );
|
387 |
-
break;
|
388 |
-
}
|
389 |
-
}
|
390 |
-
|
391 |
-
/**
|
392 |
-
* Adjust image column width
|
393 |
-
*/
|
394 |
-
function enqueue_admin_styles( $hook ) {
|
395 |
-
$screen = get_current_screen();
|
396 |
-
|
397 |
-
if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
|
398 |
-
wp_add_inline_style( 'wp-admin', '.column-thumbnail img:nth-of-type(2) { display: none; } .manage-column.column-thumbnail { width: 50px; } @media screen and (max-width: 360px) { .column-thumbnail{ display:none; } }' );
|
399 |
-
}
|
400 |
-
}
|
401 |
-
|
402 |
-
/**
|
403 |
-
* Adds portfolio section to the Customizer.
|
404 |
-
*/
|
405 |
-
function customize_register( $wp_customize ) {
|
406 |
-
$options = get_theme_support( self::CUSTOM_POST_TYPE );
|
407 |
-
|
408 |
-
if ( ( ! isset( $options[0]['title'] ) || true !== $options[0]['title'] ) && ( ! isset( $options[0]['content'] ) || true !== $options[0]['content'] ) && ( ! isset( $options[0]['featured-image'] ) || true !== $options[0]['featured-image'] ) ) {
|
409 |
-
return;
|
410 |
-
}
|
411 |
-
|
412 |
-
$wp_customize->add_panel( 'ect_plugin_options', array(
|
413 |
-
'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
|
414 |
-
'priority' => 1,
|
415 |
-
) );
|
416 |
-
|
417 |
-
$wp_customize->add_section( 'jetpack_portfolio', array(
|
418 |
-
'title' => esc_html__( 'Portfolio', 'essential-content-types' ),
|
419 |
-
'theme_supports' => self::CUSTOM_POST_TYPE,
|
420 |
-
'priority' => 130,
|
421 |
-
'panel' => 'ect_plugin_options',
|
422 |
-
) );
|
423 |
-
|
424 |
-
if ( isset( $options[0]['title'] ) && true === $options[0]['title'] ) {
|
425 |
-
$wp_customize->add_setting( 'jetpack_portfolio_title', array(
|
426 |
-
'default' => esc_html__( 'Projects', 'essential-content-types' ),
|
427 |
-
'type' => 'option',
|
428 |
-
'sanitize_callback' => 'sanitize_text_field',
|
429 |
-
'sanitize_js_callback' => 'sanitize_text_field',
|
430 |
-
) );
|
431 |
-
|
432 |
-
$wp_customize->add_control( 'jetpack_portfolio_title', array(
|
433 |
-
'section' => 'jetpack_portfolio',
|
434 |
-
'label' => esc_html__( 'Portfolio Archive Title', 'essential-content-types' ),
|
435 |
-
'type' => 'text',
|
436 |
-
) );
|
437 |
-
}
|
438 |
-
|
439 |
-
if ( isset( $options[0]['content'] ) && true === $options[0]['content'] ) {
|
440 |
-
$wp_customize->add_setting( 'jetpack_portfolio_content', array(
|
441 |
-
'default' => '',
|
442 |
-
'type' => 'option',
|
443 |
-
'sanitize_callback' => 'wp_kses_post',
|
444 |
-
'sanitize_js_callback' => 'wp_kses_post',
|
445 |
-
) );
|
446 |
-
|
447 |
-
$wp_customize->add_control( 'jetpack_portfolio_content', array(
|
448 |
-
'section' => 'jetpack_portfolio',
|
449 |
-
'label' => esc_html__( 'Portfolio Archive Content', 'essential-content-types' ),
|
450 |
-
'type' => 'textarea',
|
451 |
-
) );
|
452 |
-
}
|
453 |
-
|
454 |
-
if ( isset( $options[0]['featured-image'] ) && true === $options[0]['featured-image'] ) {
|
455 |
-
$wp_customize->add_setting( 'jetpack_portfolio_featured_image', array(
|
456 |
-
'default' => '',
|
457 |
-
'type' => 'option',
|
458 |
-
'sanitize_callback' => 'attachment_url_to_postid',
|
459 |
-
'sanitize_js_callback' => 'attachment_url_to_postid',
|
460 |
-
'theme_supports' => 'post-thumbnails',
|
461 |
-
) );
|
462 |
-
|
463 |
-
$wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'jetpack_portfolio_featured_image', array(
|
464 |
-
'section' => 'jetpack_portfolio',
|
465 |
-
'label' => esc_html__( 'Portfolio Archive Featured Image', 'essential-content-types' ),
|
466 |
-
) ) );
|
467 |
-
}
|
468 |
-
}
|
469 |
-
|
470 |
-
/**
|
471 |
-
* Follow CPT reading setting on CPT archive and taxonomy pages
|
472 |
-
*/
|
473 |
-
function query_reading_setting( $query ) {
|
474 |
-
if ( ! is_admin() &&
|
475 |
-
$query->is_main_query() &&
|
476 |
-
( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
|
477 |
-
) {
|
478 |
-
$post_per_page = ( null != get_option('posts_per_page') ) ? get_option('posts_per_page') : '10';
|
479 |
-
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
|
480 |
-
}
|
481 |
-
}
|
482 |
-
|
483 |
-
/**
|
484 |
-
* Add to REST API post type whitelist
|
485 |
-
*/
|
486 |
-
function allow_portfolio_rest_api_type( $post_types ) {
|
487 |
-
$post_types[] = self::CUSTOM_POST_TYPE;
|
488 |
-
|
489 |
-
return $post_types;
|
490 |
-
}
|
491 |
-
|
492 |
-
/**
|
493 |
-
* Our [portfolio] shortcode.
|
494 |
-
* Prints Portfolio data styled to look good on *any* theme.
|
495 |
-
*
|
496 |
-
* @return portfolio_shortcode_html
|
497 |
-
*/
|
498 |
-
static function portfolio_shortcode( $atts ) {
|
499 |
-
// Default attributes
|
500 |
-
$atts = shortcode_atts( array(
|
501 |
-
'display_types' => true,
|
502 |
-
'display_tags' => true,
|
503 |
-
'display_content' => true,
|
504 |
-
'display_author' => false,
|
505 |
-
'show_filter' => false,
|
506 |
-
'include_type' => false,
|
507 |
-
'include_tag' => false,
|
508 |
-
'columns' => 2,
|
509 |
-
'showposts' => -1,
|
510 |
-
'order' => 'asc',
|
511 |
-
'orderby' => 'date',
|
512 |
-
), $atts, 'portfolio' );
|
513 |
-
|
514 |
-
// A little sanitization
|
515 |
-
if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
|
516 |
-
$atts['display_types'] = false;
|
517 |
-
}
|
518 |
-
|
519 |
-
if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
|
520 |
-
$atts['display_tags'] = false;
|
521 |
-
}
|
522 |
-
|
523 |
-
if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
|
524 |
-
$atts['display_author'] = false;
|
525 |
-
}
|
526 |
-
|
527 |
-
if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
|
528 |
-
$atts['display_content'] = false;
|
529 |
-
}
|
530 |
-
|
531 |
-
if ( $atts['include_type'] ) {
|
532 |
-
$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
|
533 |
-
}
|
534 |
-
|
535 |
-
if ( $atts['include_tag'] ) {
|
536 |
-
$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
|
537 |
-
}
|
538 |
-
|
539 |
-
// Check if column value is set to valid numbers or else set default value as 2
|
540 |
-
if( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
|
541 |
-
$atts['columns'] = absint( $atts['columns'] );
|
542 |
-
} else {
|
543 |
-
$atts['columns'] = 2;
|
544 |
-
}
|
545 |
-
|
546 |
-
$atts['showposts'] = intval( $atts['showposts'] );
|
547 |
-
|
548 |
-
|
549 |
-
if ( $atts['order'] ) {
|
550 |
-
$atts['order'] = urldecode( $atts['order'] );
|
551 |
-
$atts['order'] = strtoupper( $atts['order'] );
|
552 |
-
if ( 'DESC' != $atts['order'] ) {
|
553 |
-
$atts['order'] = 'ASC';
|
554 |
-
}
|
555 |
-
}
|
556 |
-
|
557 |
-
if ( $atts['orderby'] ) {
|
558 |
-
$atts['orderby'] = urldecode( $atts['orderby'] );
|
559 |
-
$atts['orderby'] = strtolower( $atts['orderby'] );
|
560 |
-
$allowed_keys = array( 'author', 'date', 'title', 'rand' );
|
561 |
-
|
562 |
-
$parsed = array();
|
563 |
-
foreach ( explode( ',', $atts['orderby'] ) as $portfolio_index_number => $orderby ) {
|
564 |
-
if ( ! in_array( $orderby, $allowed_keys ) ) {
|
565 |
-
continue;
|
566 |
-
}
|
567 |
-
$parsed[] = $orderby;
|
568 |
-
}
|
569 |
-
|
570 |
-
if ( empty( $parsed ) ) {
|
571 |
-
unset( $atts['orderby'] );
|
572 |
-
} else {
|
573 |
-
$atts['orderby'] = implode( ' ', $parsed );
|
574 |
-
}
|
575 |
-
}
|
576 |
-
|
577 |
-
// enqueue shortcode styles when shortcode is used
|
578 |
-
wp_enqueue_style( 'jetpack-portfolio-style', plugins_url( 'css/portfolio-shortcode.css', __FILE__ ), array(), '20140326' );
|
579 |
-
|
580 |
-
return self::portfolio_shortcode_html( $atts );
|
581 |
-
}
|
582 |
-
|
583 |
-
/**
|
584 |
-
* Query to retrieve entries from the Portfolio post_type.
|
585 |
-
*
|
586 |
-
* @return object
|
587 |
-
*/
|
588 |
-
static function portfolio_query( $atts ) {
|
589 |
-
// Default query arguments
|
590 |
-
$default = array(
|
591 |
-
'order' => $atts['order'],
|
592 |
-
'orderby' => $atts['orderby'],
|
593 |
-
'posts_per_page' => $atts['showposts'],
|
594 |
-
);
|
595 |
-
|
596 |
-
$args = wp_parse_args( $atts, $default );
|
597 |
-
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
598 |
-
|
599 |
-
if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
|
600 |
-
$args['tax_query'] = array();
|
601 |
-
}
|
602 |
-
|
603 |
-
// If 'include_type' has been set use it on the main query
|
604 |
-
if ( false != $atts['include_type'] ) {
|
605 |
-
array_push( $args['tax_query'], array(
|
606 |
-
'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
|
607 |
-
'field' => 'slug',
|
608 |
-
'terms' => $atts['include_type'],
|
609 |
-
) );
|
610 |
-
}
|
611 |
-
|
612 |
-
// If 'include_tag' has been set use it on the main query
|
613 |
-
if ( false != $atts['include_tag'] ) {
|
614 |
-
array_push( $args['tax_query'], array(
|
615 |
-
'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
|
616 |
-
'field' => 'slug',
|
617 |
-
'terms' => $atts['include_tag'],
|
618 |
-
) );
|
619 |
-
}
|
620 |
-
|
621 |
-
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
622 |
-
$args['tax_query']['relation'] = 'AND';
|
623 |
-
}
|
624 |
-
|
625 |
-
// Run the query and return
|
626 |
-
$query = new WP_Query( $args );
|
627 |
-
return $query;
|
628 |
-
}
|
629 |
-
|
630 |
-
/**
|
631 |
-
* The Portfolio shortcode loop.
|
632 |
-
*
|
633 |
-
* @todo add theme color styles
|
634 |
-
* @return html
|
635 |
-
*/
|
636 |
-
|
637 |
-
static function portfolio_shortcode_html( $atts ) {
|
638 |
-
|
639 |
-
$query = self::portfolio_query( $atts );
|
640 |
-
|
641 |
-
ob_start();
|
642 |
-
|
643 |
-
// If we have posts, create the html
|
644 |
-
// with hportfolio markup
|
645 |
-
if ( $query->have_posts() ) {
|
646 |
-
|
647 |
-
|
648 |
-
/**
|
649 |
-
* Hook: ect_before_portfolio_loop.
|
650 |
-
*
|
651 |
-
* @hooked ect_portfolio_section
|
652 |
-
*/
|
653 |
-
$layout = ect_get_layout();
|
654 |
-
do_action( 'ect_before_portfolio_loop', $layout[$atts['columns']] );
|
655 |
-
?>
|
656 |
-
<?php
|
657 |
-
//ect_portfolio_loop_start( $layout[$atts['columns']] );
|
658 |
-
while ( $query->have_posts() ) {
|
659 |
-
$query->the_post();
|
660 |
-
ect_get_template_part( 'content', 'portfolio', $atts );
|
661 |
-
/**
|
662 |
-
* Hook: ect_portfolio_loop.
|
663 |
-
*
|
664 |
-
* @hooked
|
665 |
-
*/
|
666 |
-
}
|
667 |
-
wp_reset_postdata();
|
668 |
-
//ect_portfolio_loop_end();
|
669 |
-
?>
|
670 |
-
<?php
|
671 |
-
|
672 |
-
/**
|
673 |
-
* Hook: ect_after_portfolio_loop.
|
674 |
-
*
|
675 |
-
* @hooked
|
676 |
-
*/
|
677 |
-
do_action( 'ect_after_portfolio_loop' );
|
678 |
-
|
679 |
-
} else {
|
680 |
-
/**
|
681 |
-
* Hook: ect_no_portfolio_found.
|
682 |
-
*
|
683 |
-
* @hooked ect_no_portfolio_found
|
684 |
-
*/
|
685 |
-
do_action( 'ect_no_portfolio_found' );
|
686 |
-
}
|
687 |
-
|
688 |
-
$html = ob_get_clean();
|
689 |
-
|
690 |
-
// If there is a [portfolio] within a [portfolio], remove the shortcode
|
691 |
-
if ( has_shortcode( $html, 'portfolio' ) ){
|
692 |
-
remove_shortcode( 'portfolio' );
|
693 |
-
}
|
694 |
-
|
695 |
-
// Return the HTML block
|
696 |
-
return $html;
|
697 |
-
}
|
698 |
-
|
699 |
-
/**
|
700 |
-
* Displays the project type that a project belongs to.
|
701 |
-
*
|
702 |
-
* @return html
|
703 |
-
*/
|
704 |
-
static function get_project_type( $post_id ) {
|
705 |
-
$project_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
|
706 |
-
|
707 |
-
// If no types, return empty string
|
708 |
-
if ( empty( $project_types ) || is_wp_error( $project_types ) ) {
|
709 |
-
return;
|
710 |
-
}
|
711 |
-
|
712 |
-
$html = '<div class="project-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
|
713 |
-
$types = array();
|
714 |
-
// Loop thorugh all the types
|
715 |
-
foreach ( $project_types as $project_type ) {
|
716 |
-
$project_type_link = get_term_link( $project_type, self::CUSTOM_TAXONOMY_TYPE );
|
717 |
-
|
718 |
-
if ( is_wp_error( $project_type_link ) ) {
|
719 |
-
return $project_type_link;
|
720 |
-
}
|
721 |
-
|
722 |
-
$types[] = '<a href="' . esc_url( $project_type_link ) . '" rel="tag">' . esc_html( $project_type->name ) . '</a>';
|
723 |
-
}
|
724 |
-
$html .= ' '.implode( ', ', $types );
|
725 |
-
$html .= '</div>';
|
726 |
-
|
727 |
-
return $html;
|
728 |
-
}
|
729 |
-
|
730 |
-
/**
|
731 |
-
* Displays the project tags that a project belongs to.
|
732 |
-
*
|
733 |
-
* @return html
|
734 |
-
*/
|
735 |
-
static function get_project_tags( $post_id ) {
|
736 |
-
$project_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
|
737 |
-
|
738 |
-
// If no tags, return empty string
|
739 |
-
if ( empty( $project_tags ) || is_wp_error( $project_tags ) ) {
|
740 |
-
return false;
|
741 |
-
}
|
742 |
-
|
743 |
-
$html = '<div class="project-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
|
744 |
-
$tags = array();
|
745 |
-
// Loop thorugh all the tags
|
746 |
-
foreach ( $project_tags as $project_tag ) {
|
747 |
-
$project_tag_link = get_term_link( $project_tag, self::CUSTOM_TAXONOMY_TYPE );
|
748 |
-
|
749 |
-
if ( is_wp_error( $project_tag_link ) ) {
|
750 |
-
return $project_tag_link;
|
751 |
-
}
|
752 |
-
|
753 |
-
$tags[] = '<a href="' . esc_url( $project_tag_link ) . '" rel="tag">' . esc_html( $project_tag->name ) . '</a>';
|
754 |
-
}
|
755 |
-
$html .= ' '. implode( ', ', $tags );
|
756 |
-
$html .= '</div>';
|
757 |
-
|
758 |
-
return $html;
|
759 |
-
}
|
760 |
-
|
761 |
-
/**
|
762 |
-
* Displays the author of the current portfolio project.
|
763 |
-
*
|
764 |
-
* @return html
|
765 |
-
*/
|
766 |
-
static function get_project_author() {
|
767 |
-
$html = '<div class="project-author">';
|
768 |
-
/* translators: %1$s is link to author posts, %2$s is author display name */
|
769 |
-
$html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
|
770 |
-
esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
|
771 |
-
esc_html( get_the_author() )
|
772 |
-
);
|
773 |
-
$html .= '</div>';
|
774 |
-
|
775 |
-
return $html;
|
776 |
-
}
|
777 |
-
}
|
778 |
-
add_action( 'init', array( 'Essential_Content_Jetpack_Portfolio', 'init' ) );
|
779 |
-
|
780 |
-
/**
|
781 |
-
* Add Portfolio support
|
782 |
-
*/
|
783 |
-
function essential_content_portfolio_support() {
|
784 |
-
/*
|
785 |
-
* Adding theme support for Jetpack Portfolio CPT.
|
786 |
-
*/
|
787 |
-
add_theme_support( 'jetpack-portfolio', array(
|
788 |
-
'title' => true,
|
789 |
-
'content' => true,
|
790 |
-
'featured-image' => true,
|
791 |
-
) );
|
792 |
-
add_image_size( 'ect-jetpack-portfolio-featured', 640, 640, true );
|
793 |
-
}
|
794 |
-
add_action( 'after_setup_theme', 'essential_content_portfolio_support' );
|
795 |
-
|
796 |
-
|
797 |
-
if( ! function_exists( 'essential_content_get_portfolio_thumbnail_link' ) ):
|
798 |
-
/**
|
799 |
-
* Display the featured image if it's available
|
800 |
-
*
|
801 |
-
* @return html
|
802 |
-
*/
|
803 |
-
function essential_content_get_portfolio_thumbnail_link( $post_id ) {
|
804 |
-
if ( has_post_thumbnail( $post_id ) ) {
|
805 |
-
/**
|
806 |
-
* Change the Portfolio thumbnail size.
|
807 |
-
*
|
808 |
-
* @module custom-content-types
|
809 |
-
*
|
810 |
-
* @since 3.4.0
|
811 |
-
*
|
812 |
-
* @param string|array $var Either a registered size keyword or size array.
|
813 |
-
*/
|
814 |
-
return '<a class="portfolio-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'jetpack_portfolio_thumbnail_size', 'ect-jetpack-portfolio-featured' ) ) . '</a>';
|
815 |
-
}
|
816 |
-
}
|
817 |
-
endif;
|
818 |
-
|
819 |
-
|
820 |
-
if( ! function_exists( 'essential_content_no_portfolio_found' ) ):
|
821 |
-
/**
|
822 |
-
* No items found text
|
823 |
-
*
|
824 |
-
* @return html
|
825 |
-
*/
|
826 |
-
function essential_content_no_portfolio_found() {
|
827 |
-
echo "<p><em>" . esc_html__( 'Your Portfolio Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . "</em></p>";
|
828 |
-
}
|
829 |
-
endif;
|
830 |
-
add_action( 'ect_no_portfolio_found', 'essential_content_no_portfolio_found', 10 );
|
831 |
-
|
832 |
-
|
833 |
-
if( ! function_exists( 'essential_content_portfolio_section_open' ) ):
|
834 |
-
/**
|
835 |
-
* Open section
|
836 |
-
*
|
837 |
-
* @return html
|
838 |
-
*/
|
839 |
-
function essential_content_portfolio_section_open( $layout ) {
|
840 |
-
echo '<div class="ect-portfolio ect-section">';
|
841 |
-
echo '<div class="ect-wrapper">';
|
842 |
-
}
|
843 |
-
endif;
|
844 |
-
add_action( 'ect_before_portfolio_loop', 'essential_content_portfolio_section_open', 10, 1 );
|
845 |
-
|
846 |
-
|
847 |
-
if( ! function_exists( 'essential_content_portfolio_loop_start' ) ):
|
848 |
-
/**
|
849 |
-
* open wrapper before loop
|
850 |
-
*
|
851 |
-
*/
|
852 |
-
function essential_content_portfolio_loop_start( $layout = null ){
|
853 |
-
echo '<div class="section-content-wrapper portfolio-content-wrapper ' . $layout . '">';
|
854 |
-
}
|
855 |
-
endif;
|
856 |
-
add_action( 'ect_before_portfolio_loop', 'essential_content_portfolio_loop_start', 30 );
|
857 |
-
|
858 |
-
|
859 |
-
if( ! function_exists( 'essential_content_portfolio_loop_end' ) ):
|
860 |
-
/**
|
861 |
-
* close wrapper after loop
|
862 |
-
*
|
863 |
-
*/
|
864 |
-
function essential_content_portfolio_loop_end(){
|
865 |
-
echo '</div><!-- .portfolio-content-wrapper -->';
|
866 |
-
}
|
867 |
-
endif;
|
868 |
-
add_action( 'ect_after_portfolio_loop', 'essential_content_portfolio_loop_end', 10 );
|
869 |
-
|
870 |
-
|
871 |
-
if( ! function_exists( 'essential_content_portfolio_section_close' ) ):
|
872 |
-
/**
|
873 |
-
* Close section
|
874 |
-
*
|
875 |
-
* @return html
|
876 |
-
*/
|
877 |
-
function essential_content_portfolio_section_close() {
|
878 |
-
echo '</div><!-- .ect-wrapper -->';
|
879 |
-
echo '</div><!-- .ect-section -->';
|
880 |
-
}
|
881 |
-
endif;
|
882 |
add_action( 'ect_after_portfolio_loop', 'essential_content_portfolio_section_close', 20 );
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Support JetPack Portfolio
|
5 |
+
*/
|
6 |
+
class Essential_Content_Jetpack_Portfolio {
|
7 |
+
const CUSTOM_POST_TYPE = 'jetpack-portfolio';
|
8 |
+
const CUSTOM_TAXONOMY_TYPE = 'jetpack-portfolio-type';
|
9 |
+
const CUSTOM_TAXONOMY_TAG = 'jetpack-portfolio-tag';
|
10 |
+
const OPTION_NAME = 'jetpack_portfolio';
|
11 |
+
const OPTION_READING_SETTING = 'jetpack_portfolio_posts_per_page';
|
12 |
+
|
13 |
+
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
14 |
+
|
15 |
+
static function init() {
|
16 |
+
static $instance = false;
|
17 |
+
|
18 |
+
if ( ! $instance ) {
|
19 |
+
$instance = new Essential_Content_Jetpack_Portfolio;
|
20 |
+
}
|
21 |
+
|
22 |
+
return $instance;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Conditionally hook into WordPress.
|
27 |
+
*
|
28 |
+
* Setup user option for enabling CPT
|
29 |
+
* If user has CPT enabled, show in admin
|
30 |
+
*/
|
31 |
+
function __construct() {
|
32 |
+
// Add an option to enable the CPT
|
33 |
+
add_action( 'admin_init', array( $this, 'settings_api_init' ) );
|
34 |
+
|
35 |
+
// Check on theme switch if theme supports CPT and setting is disabled
|
36 |
+
add_action( 'after_switch_theme', array( $this, 'activation_post_type_support' ) );
|
37 |
+
|
38 |
+
// Make sure the post types are loaded for imports
|
39 |
+
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
40 |
+
|
41 |
+
// Add to REST API post type whitelist
|
42 |
+
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_portfolio_rest_api_type' ) );
|
43 |
+
|
44 |
+
$setting = 1;
|
45 |
+
|
46 |
+
if ( class_exists( 'Jetpack_Options' ) ) {
|
47 |
+
$setting = Jetpack_Options::get_option_and_ensure_autoload( self::OPTION_NAME, '0' );
|
48 |
+
}
|
49 |
+
|
50 |
+
// Bail early if Portfolio option is not set and the theme doesn't declare support
|
51 |
+
if ( empty( $setting ) && ! $this->site_supports_custom_post_type() ) {
|
52 |
+
return;
|
53 |
+
}
|
54 |
+
|
55 |
+
// Enable Omnisearch for Portfolio Items.
|
56 |
+
if ( class_exists( 'Jetpack_Omnisearch_Posts' ) )
|
57 |
+
new Jetpack_Omnisearch_Posts( self::CUSTOM_POST_TYPE );
|
58 |
+
|
59 |
+
// CPT magic
|
60 |
+
$this->register_post_types();
|
61 |
+
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
62 |
+
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
63 |
+
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE), array( $this, 'flush_rules_on_first_project' ) );
|
64 |
+
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
65 |
+
|
66 |
+
// Admin Customization
|
67 |
+
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
68 |
+
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE), array( $this, 'edit_admin_columns' ) );
|
69 |
+
add_filter( sprintf( 'manage_%s_posts_custom_column', self::CUSTOM_POST_TYPE), array( $this, 'image_column' ), 10, 2 );
|
70 |
+
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
71 |
+
|
72 |
+
add_image_size( 'jetpack-portfolio-admin-thumb', 50, 50, true );
|
73 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
|
74 |
+
|
75 |
+
// register jetpack_portfolio shortcode and portfolio shortcode (legacy)
|
76 |
+
add_shortcode( 'portfolio', array( $this, 'portfolio_shortcode' ) );
|
77 |
+
add_shortcode( 'jetpack_portfolio', array( $this, 'portfolio_shortcode' ) );
|
78 |
+
|
79 |
+
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
80 |
+
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ) );
|
81 |
+
|
82 |
+
// If CPT was enabled programatically and no CPT items exist when user switches away, disable
|
83 |
+
if ( $setting && $this->site_supports_custom_post_type() ) {
|
84 |
+
add_action( 'switch_theme', array( $this, 'deactivation_post_type_support' ) );
|
85 |
+
}
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Add a checkbox field in 'Settings' > 'Writing'
|
90 |
+
* for enabling CPT functionality.
|
91 |
+
*
|
92 |
+
* @return null
|
93 |
+
*/
|
94 |
+
function settings_api_init() {
|
95 |
+
add_settings_field(
|
96 |
+
self::OPTION_NAME,
|
97 |
+
'<span class="cpt-options">' . esc_html__( 'Portfolio Projects', 'essential-content-types' ) . '</span>',
|
98 |
+
array( $this, 'setting_html' ),
|
99 |
+
'writing',
|
100 |
+
'jetpack_cpt_section'
|
101 |
+
);
|
102 |
+
register_setting(
|
103 |
+
'writing',
|
104 |
+
self::OPTION_NAME,
|
105 |
+
'intval'
|
106 |
+
);
|
107 |
+
|
108 |
+
// Check if CPT is enabled first so that intval doesn't get set to NULL on re-registering
|
109 |
+
if ( get_option( self::OPTION_NAME, '0' ) || current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
110 |
+
register_setting(
|
111 |
+
'writing',
|
112 |
+
self::OPTION_READING_SETTING,
|
113 |
+
'intval'
|
114 |
+
);
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* HTML code to display a checkbox true/false option
|
120 |
+
* for the Portfolio CPT setting.
|
121 |
+
*
|
122 |
+
* @return html
|
123 |
+
*/
|
124 |
+
function setting_html() {
|
125 |
+
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) : ?>
|
126 |
+
<p><?php printf( /* translators: %s is the name of a custom post type such as "jetpack-portfolio" */ __( 'Your theme supports <strong>%s</strong>', 'essential-content-types' ), self::CUSTOM_POST_TYPE ); ?></p>
|
127 |
+
<?php else : ?>
|
128 |
+
<label for="<?php echo esc_attr( self::OPTION_NAME ); ?>">
|
129 |
+
<input name="<?php echo esc_attr( self::OPTION_NAME ); ?>" id="<?php echo esc_attr( self::OPTION_NAME ); ?>" <?php echo checked( get_option( self::OPTION_NAME, '0' ), true, false ); ?> type="checkbox" value="1" />
|
130 |
+
<?php esc_html_e( 'Enable Portfolio Projects for this site.', 'essential-content-types' ); ?>
|
131 |
+
<a target="_blank" href="http://en.support.wordpress.com/portfolios/"><?php esc_html_e( 'Learn More', 'essential-content-types' ); ?></a>
|
132 |
+
</label>
|
133 |
+
<?php endif;
|
134 |
+
if ( get_option( self::OPTION_NAME, '0' ) || current_theme_supports( self::CUSTOM_POST_TYPE ) ) :
|
135 |
+
printf( '<p><label for="%1$s">%2$s</label></p>',
|
136 |
+
esc_attr( self::OPTION_READING_SETTING ),
|
137 |
+
/* translators: %1$s is replaced with an input field for numbers */
|
138 |
+
sprintf( __( 'Portfolio pages display at most %1$s projects', 'essential-content-types' ),
|
139 |
+
sprintf( '<input name="%1$s" id="%1$s" type="number" step="1" min="1" value="%2$s" class="small-text" />',
|
140 |
+
esc_attr( self::OPTION_READING_SETTING ),
|
141 |
+
esc_attr( get_option( self::OPTION_READING_SETTING, '10' ) )
|
142 |
+
)
|
143 |
+
)
|
144 |
+
);
|
145 |
+
endif;
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Should this Custom Post Type be made available?
|
150 |
+
*/
|
151 |
+
function site_supports_custom_post_type() {
|
152 |
+
// If the current theme requests it.
|
153 |
+
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) || get_option( self::OPTION_NAME, '0' ) ) {
|
154 |
+
return true;
|
155 |
+
}
|
156 |
+
|
157 |
+
// Otherwise, say no unless something wants to filter us to say yes.
|
158 |
+
/** This action is documented in modules/custom-post-types/nova.php */
|
159 |
+
return (bool) apply_filters( 'jetpack_enable_cpt', false, self::CUSTOM_POST_TYPE );
|
160 |
+
}
|
161 |
+
|
162 |
+
/*
|
163 |
+
* Flush permalinks when CPT option is turned on/off
|
164 |
+
*/
|
165 |
+
function flush_rules_on_enable() {
|
166 |
+
flush_rewrite_rules();
|
167 |
+
}
|
168 |
+
|
169 |
+
/*
|
170 |
+
* Count published projects and flush permalinks when first projects is published
|
171 |
+
*/
|
172 |
+
function flush_rules_on_first_project() {
|
173 |
+
$projects = get_transient( 'jetpack-portfolio-count-cache' );
|
174 |
+
|
175 |
+
if ( false === $projects ) {
|
176 |
+
flush_rewrite_rules();
|
177 |
+
$projects = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
178 |
+
|
179 |
+
if ( ! empty( $projects ) ) {
|
180 |
+
set_transient( 'jetpack-portfolio-count-cache', $projects, HOUR_IN_SECONDS * 12 );
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
/*
|
186 |
+
* Flush permalinks when CPT supported theme is activated
|
187 |
+
*/
|
188 |
+
function flush_rules_on_switch() {
|
189 |
+
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
190 |
+
flush_rewrite_rules();
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* On plugin/theme activation, check if current theme supports CPT
|
196 |
+
*/
|
197 |
+
static function activation_post_type_support() {
|
198 |
+
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
199 |
+
update_option( self::OPTION_NAME, '1' );
|
200 |
+
}
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* On theme switch, check if CPT item exists and disable if not
|
205 |
+
*/
|
206 |
+
function deactivation_post_type_support() {
|
207 |
+
$portfolios = get_posts( array(
|
208 |
+
'fields' => 'ids',
|
209 |
+
'posts_per_page' => 1,
|
210 |
+
'post_type' => self::CUSTOM_POST_TYPE,
|
211 |
+
'suppress_filters' => false
|
212 |
+
) );
|
213 |
+
|
214 |
+
if ( empty( $portfolios ) ) {
|
215 |
+
update_option( self::OPTION_NAME, '0' );
|
216 |
+
}
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Register Post Type
|
221 |
+
*/
|
222 |
+
function register_post_types() {
|
223 |
+
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
224 |
+
return;
|
225 |
+
}
|
226 |
+
|
227 |
+
$args = array(
|
228 |
+
'description' => __( 'Portfolio Items', 'essential-content-types' ),
|
229 |
+
'labels' => array(
|
230 |
+
'name' => esc_html__( 'Projects', 'essential-content-types' ),
|
231 |
+
'singular_name' => esc_html__( 'Project', 'essential-content-types' ),
|
232 |
+
'menu_name' => esc_html__( 'Portfolio', 'essential-content-types' ),
|
233 |
+
'all_items' => esc_html__( 'All Projects', 'essential-content-types' ),
|
234 |
+
'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
|
235 |
+
'add_new_item' => esc_html__( 'Add New Project', 'essential-content-types' ),
|
236 |
+
'edit_item' => esc_html__( 'Edit Project', 'essential-content-types' ),
|
237 |
+
'new_item' => esc_html__( 'New Project', 'essential-content-types' ),
|
238 |
+
'view_item' => esc_html__( 'View Project', 'essential-content-types' ),
|
239 |
+
'search_items' => esc_html__( 'Search Projects', 'essential-content-types' ),
|
240 |
+
'not_found' => esc_html__( 'No Projects found', 'essential-content-types' ),
|
241 |
+
'not_found_in_trash' => esc_html__( 'No Projects found in Trash', 'essential-content-types' ),
|
242 |
+
'filter_items_list' => esc_html__( 'Filter projects list', 'essential-content-types' ),
|
243 |
+
'items_list_navigation' => esc_html__( 'Project list navigation', 'essential-content-types' ),
|
244 |
+
'items_list' => esc_html__( 'Projects list', 'essential-content-types' ),
|
245 |
+
),
|
246 |
+
'supports' => array(
|
247 |
+
'title',
|
248 |
+
'editor',
|
249 |
+
'excerpt',
|
250 |
+
'thumbnail',
|
251 |
+
'author',
|
252 |
+
'comments',
|
253 |
+
'publicize',
|
254 |
+
),
|
255 |
+
'rewrite' => array(
|
256 |
+
'slug' => 'portfolio',
|
257 |
+
'with_front' => false,
|
258 |
+
'feeds' => true,
|
259 |
+
'pages' => true,
|
260 |
+
),
|
261 |
+
'public' => true,
|
262 |
+
'show_ui' => true,
|
263 |
+
'menu_position' => 20, // below Pages
|
264 |
+
'menu_icon' => 'dashicons-portfolio', // 3.8+ dashicon option
|
265 |
+
'capability_type' => 'page',
|
266 |
+
'map_meta_cap' => true,
|
267 |
+
'taxonomies' => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
|
268 |
+
'has_archive' => true,
|
269 |
+
'query_var' => 'portfolio',
|
270 |
+
'show_in_rest' => true,
|
271 |
+
);
|
272 |
+
|
273 |
+
$description = get_option( 'jetpack_portfolio_content' );
|
274 |
+
if ( '' !== $description ) {
|
275 |
+
$args['description'] = $description;
|
276 |
+
}
|
277 |
+
|
278 |
+
register_post_type( self::CUSTOM_POST_TYPE, $args );
|
279 |
+
|
280 |
+
register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
|
281 |
+
'hierarchical' => true,
|
282 |
+
'labels' => array(
|
283 |
+
'name' => esc_html__( 'Project Types', 'essential-content-types' ),
|
284 |
+
'singular_name' => esc_html__( 'Project Type', 'essential-content-types' ),
|
285 |
+
'menu_name' => esc_html__( 'Project Types', 'essential-content-types' ),
|
286 |
+
'all_items' => esc_html__( 'All Project Types', 'essential-content-types' ),
|
287 |
+
'edit_item' => esc_html__( 'Edit Project Type', 'essential-content-types' ),
|
288 |
+
'view_item' => esc_html__( 'View Project Type', 'essential-content-types' ),
|
289 |
+
'update_item' => esc_html__( 'Update Project Type', 'essential-content-types' ),
|
290 |
+
'add_new_item' => esc_html__( 'Add New Project Type', 'essential-content-types' ),
|
291 |
+
'new_item_name' => esc_html__( 'New Project Type Name', 'essential-content-types' ),
|
292 |
+
'parent_item' => esc_html__( 'Parent Project Type', 'essential-content-types' ),
|
293 |
+
'parent_item_colon' => esc_html__( 'Parent Project Type:', 'essential-content-types' ),
|
294 |
+
'search_items' => esc_html__( 'Search Project Types', 'essential-content-types' ),
|
295 |
+
'items_list_navigation' => esc_html__( 'Project type list navigation', 'essential-content-types' ),
|
296 |
+
'items_list' => esc_html__( 'Project type list', 'essential-content-types' ),
|
297 |
+
),
|
298 |
+
'public' => true,
|
299 |
+
'show_ui' => true,
|
300 |
+
'show_in_nav_menus' => true,
|
301 |
+
'show_in_rest' => true,
|
302 |
+
'show_admin_column' => true,
|
303 |
+
'query_var' => true,
|
304 |
+
'rewrite' => array( 'slug' => 'project-type' ),
|
305 |
+
) );
|
306 |
+
|
307 |
+
register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
|
308 |
+
'hierarchical' => false,
|
309 |
+
'labels' => array(
|
310 |
+
'name' => esc_html__( 'Project Tags', 'essential-content-types' ),
|
311 |
+
'singular_name' => esc_html__( 'Project Tag', 'essential-content-types' ),
|
312 |
+
'menu_name' => esc_html__( 'Project Tags', 'essential-content-types' ),
|
313 |
+
'all_items' => esc_html__( 'All Project Tags', 'essential-content-types' ),
|
314 |
+
'edit_item' => esc_html__( 'Edit Project Tag', 'essential-content-types' ),
|
315 |
+
'view_item' => esc_html__( 'View Project Tag', 'essential-content-types' ),
|
316 |
+
'update_item' => esc_html__( 'Update Project Tag', 'essential-content-types' ),
|
317 |
+
'add_new_item' => esc_html__( 'Add New Project Tag', 'essential-content-types' ),
|
318 |
+
'new_item_name' => esc_html__( 'New Project Tag Name', 'essential-content-types' ),
|
319 |
+
'search_items' => esc_html__( 'Search Project Tags', 'essential-content-types' ),
|
320 |
+
'popular_items' => esc_html__( 'Popular Project Tags', 'essential-content-types' ),
|
321 |
+
'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
|
322 |
+
'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
|
323 |
+
'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
|
324 |
+
'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
|
325 |
+
'items_list_navigation' => esc_html__( 'Project tag list navigation', 'essential-content-types' ),
|
326 |
+
'items_list' => esc_html__( 'Project tag list', 'essential-content-types' ),
|
327 |
+
),
|
328 |
+
'public' => true,
|
329 |
+
'show_ui' => true,
|
330 |
+
'show_in_nav_menus' => true,
|
331 |
+
'show_in_rest' => true,
|
332 |
+
'show_admin_column' => true,
|
333 |
+
'query_var' => true,
|
334 |
+
'rewrite' => array( 'slug' => 'project-tag' ),
|
335 |
+
) );
|
336 |
+
}
|
337 |
+
|
338 |
+
/**
|
339 |
+
* Update messages for the Portfolio admin.
|
340 |
+
*/
|
341 |
+
function updated_messages( $messages ) {
|
342 |
+
global $post;
|
343 |
+
|
344 |
+
$messages[self::CUSTOM_POST_TYPE] = array(
|
345 |
+
0 => '', // Unused. Messages start at index 1.
|
346 |
+
1 => sprintf( __( 'Project updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
|
347 |
+
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
348 |
+
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
349 |
+
4 => esc_html__( 'Project updated.', 'essential-content-types' ),
|
350 |
+
/* translators: %s: date and time of the revision */
|
351 |
+
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Project restored to revision from %s', 'essential-content-types'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
352 |
+
6 => sprintf( __( 'Project published. <a href="%s">View project</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
353 |
+
7 => esc_html__( 'Project saved.', 'essential-content-types' ),
|
354 |
+
8 => sprintf( __( 'Project submitted. <a target="_blank" href="%s">Preview project</a>', 'essential-content-types'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
355 |
+
9 => sprintf( __( 'Project scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview project</a>', 'essential-content-types' ),
|
356 |
+
// translators: Publish box date format, see http://php.net/date
|
357 |
+
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
|
358 |
+
10 => sprintf( __( 'Project item draft updated. <a target="_blank" href="%s">Preview project</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
359 |
+
);
|
360 |
+
|
361 |
+
return $messages;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Change ‘Title’ column label
|
366 |
+
* Add Featured Image column
|
367 |
+
*/
|
368 |
+
function edit_admin_columns( $columns ) {
|
369 |
+
// change 'Title' to 'Project'
|
370 |
+
$columns['title'] = __( 'Project', 'essential-content-types' );
|
371 |
+
if ( current_theme_supports( 'post-thumbnails' ) ) {
|
372 |
+
// add featured image before 'Project'
|
373 |
+
$columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
|
374 |
+
}
|
375 |
+
|
376 |
+
return $columns;
|
377 |
+
}
|
378 |
+
|
379 |
+
/**
|
380 |
+
* Add featured image to column
|
381 |
+
*/
|
382 |
+
function image_column( $column, $post_id ) {
|
383 |
+
global $post;
|
384 |
+
switch ( $column ) {
|
385 |
+
case 'thumbnail':
|
386 |
+
echo get_the_post_thumbnail( $post_id, 'jetpack-portfolio-admin-thumb' );
|
387 |
+
break;
|
388 |
+
}
|
389 |
+
}
|
390 |
+
|
391 |
+
/**
|
392 |
+
* Adjust image column width
|
393 |
+
*/
|
394 |
+
function enqueue_admin_styles( $hook ) {
|
395 |
+
$screen = get_current_screen();
|
396 |
+
|
397 |
+
if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
|
398 |
+
wp_add_inline_style( 'wp-admin', '.column-thumbnail img:nth-of-type(2) { display: none; } .manage-column.column-thumbnail { width: 50px; } @media screen and (max-width: 360px) { .column-thumbnail{ display:none; } }' );
|
399 |
+
}
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Adds portfolio section to the Customizer.
|
404 |
+
*/
|
405 |
+
function customize_register( $wp_customize ) {
|
406 |
+
$options = get_theme_support( self::CUSTOM_POST_TYPE );
|
407 |
+
|
408 |
+
if ( ( ! isset( $options[0]['title'] ) || true !== $options[0]['title'] ) && ( ! isset( $options[0]['content'] ) || true !== $options[0]['content'] ) && ( ! isset( $options[0]['featured-image'] ) || true !== $options[0]['featured-image'] ) ) {
|
409 |
+
return;
|
410 |
+
}
|
411 |
+
|
412 |
+
$wp_customize->add_panel( 'ect_plugin_options', array(
|
413 |
+
'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
|
414 |
+
'priority' => 1,
|
415 |
+
) );
|
416 |
+
|
417 |
+
$wp_customize->add_section( 'jetpack_portfolio', array(
|
418 |
+
'title' => esc_html__( 'Portfolio', 'essential-content-types' ),
|
419 |
+
'theme_supports' => self::CUSTOM_POST_TYPE,
|
420 |
+
'priority' => 130,
|
421 |
+
'panel' => 'ect_plugin_options',
|
422 |
+
) );
|
423 |
+
|
424 |
+
if ( isset( $options[0]['title'] ) && true === $options[0]['title'] ) {
|
425 |
+
$wp_customize->add_setting( 'jetpack_portfolio_title', array(
|
426 |
+
'default' => esc_html__( 'Projects', 'essential-content-types' ),
|
427 |
+
'type' => 'option',
|
428 |
+
'sanitize_callback' => 'sanitize_text_field',
|
429 |
+
'sanitize_js_callback' => 'sanitize_text_field',
|
430 |
+
) );
|
431 |
+
|
432 |
+
$wp_customize->add_control( 'jetpack_portfolio_title', array(
|
433 |
+
'section' => 'jetpack_portfolio',
|
434 |
+
'label' => esc_html__( 'Portfolio Archive Title', 'essential-content-types' ),
|
435 |
+
'type' => 'text',
|
436 |
+
) );
|
437 |
+
}
|
438 |
+
|
439 |
+
if ( isset( $options[0]['content'] ) && true === $options[0]['content'] ) {
|
440 |
+
$wp_customize->add_setting( 'jetpack_portfolio_content', array(
|
441 |
+
'default' => '',
|
442 |
+
'type' => 'option',
|
443 |
+
'sanitize_callback' => 'wp_kses_post',
|
444 |
+
'sanitize_js_callback' => 'wp_kses_post',
|
445 |
+
) );
|
446 |
+
|
447 |
+
$wp_customize->add_control( 'jetpack_portfolio_content', array(
|
448 |
+
'section' => 'jetpack_portfolio',
|
449 |
+
'label' => esc_html__( 'Portfolio Archive Content', 'essential-content-types' ),
|
450 |
+
'type' => 'textarea',
|
451 |
+
) );
|
452 |
+
}
|
453 |
+
|
454 |
+
if ( isset( $options[0]['featured-image'] ) && true === $options[0]['featured-image'] ) {
|
455 |
+
$wp_customize->add_setting( 'jetpack_portfolio_featured_image', array(
|
456 |
+
'default' => '',
|
457 |
+
'type' => 'option',
|
458 |
+
'sanitize_callback' => 'attachment_url_to_postid',
|
459 |
+
'sanitize_js_callback' => 'attachment_url_to_postid',
|
460 |
+
'theme_supports' => 'post-thumbnails',
|
461 |
+
) );
|
462 |
+
|
463 |
+
$wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'jetpack_portfolio_featured_image', array(
|
464 |
+
'section' => 'jetpack_portfolio',
|
465 |
+
'label' => esc_html__( 'Portfolio Archive Featured Image', 'essential-content-types' ),
|
466 |
+
) ) );
|
467 |
+
}
|
468 |
+
}
|
469 |
+
|
470 |
+
/**
|
471 |
+
* Follow CPT reading setting on CPT archive and taxonomy pages
|
472 |
+
*/
|
473 |
+
function query_reading_setting( $query ) {
|
474 |
+
if ( ! is_admin() &&
|
475 |
+
$query->is_main_query() &&
|
476 |
+
( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
|
477 |
+
) {
|
478 |
+
$post_per_page = ( null != get_option('posts_per_page') ) ? get_option('posts_per_page') : '10';
|
479 |
+
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
|
480 |
+
}
|
481 |
+
}
|
482 |
+
|
483 |
+
/**
|
484 |
+
* Add to REST API post type whitelist
|
485 |
+
*/
|
486 |
+
function allow_portfolio_rest_api_type( $post_types ) {
|
487 |
+
$post_types[] = self::CUSTOM_POST_TYPE;
|
488 |
+
|
489 |
+
return $post_types;
|
490 |
+
}
|
491 |
+
|
492 |
+
/**
|
493 |
+
* Our [portfolio] shortcode.
|
494 |
+
* Prints Portfolio data styled to look good on *any* theme.
|
495 |
+
*
|
496 |
+
* @return portfolio_shortcode_html
|
497 |
+
*/
|
498 |
+
static function portfolio_shortcode( $atts ) {
|
499 |
+
// Default attributes
|
500 |
+
$atts = shortcode_atts( array(
|
501 |
+
'display_types' => true,
|
502 |
+
'display_tags' => true,
|
503 |
+
'display_content' => true,
|
504 |
+
'display_author' => false,
|
505 |
+
'show_filter' => false,
|
506 |
+
'include_type' => false,
|
507 |
+
'include_tag' => false,
|
508 |
+
'columns' => 2,
|
509 |
+
'showposts' => -1,
|
510 |
+
'order' => 'asc',
|
511 |
+
'orderby' => 'date',
|
512 |
+
), $atts, 'portfolio' );
|
513 |
+
|
514 |
+
// A little sanitization
|
515 |
+
if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
|
516 |
+
$atts['display_types'] = false;
|
517 |
+
}
|
518 |
+
|
519 |
+
if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
|
520 |
+
$atts['display_tags'] = false;
|
521 |
+
}
|
522 |
+
|
523 |
+
if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
|
524 |
+
$atts['display_author'] = false;
|
525 |
+
}
|
526 |
+
|
527 |
+
if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
|
528 |
+
$atts['display_content'] = false;
|
529 |
+
}
|
530 |
+
|
531 |
+
if ( $atts['include_type'] ) {
|
532 |
+
$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
|
533 |
+
}
|
534 |
+
|
535 |
+
if ( $atts['include_tag'] ) {
|
536 |
+
$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
|
537 |
+
}
|
538 |
+
|
539 |
+
// Check if column value is set to valid numbers or else set default value as 2
|
540 |
+
if( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
|
541 |
+
$atts['columns'] = absint( $atts['columns'] );
|
542 |
+
} else {
|
543 |
+
$atts['columns'] = 2;
|
544 |
+
}
|
545 |
+
|
546 |
+
$atts['showposts'] = intval( $atts['showposts'] );
|
547 |
+
|
548 |
+
|
549 |
+
if ( $atts['order'] ) {
|
550 |
+
$atts['order'] = urldecode( $atts['order'] );
|
551 |
+
$atts['order'] = strtoupper( $atts['order'] );
|
552 |
+
if ( 'DESC' != $atts['order'] ) {
|
553 |
+
$atts['order'] = 'ASC';
|
554 |
+
}
|
555 |
+
}
|
556 |
+
|
557 |
+
if ( $atts['orderby'] ) {
|
558 |
+
$atts['orderby'] = urldecode( $atts['orderby'] );
|
559 |
+
$atts['orderby'] = strtolower( $atts['orderby'] );
|
560 |
+
$allowed_keys = array( 'author', 'date', 'title', 'rand' );
|
561 |
+
|
562 |
+
$parsed = array();
|
563 |
+
foreach ( explode( ',', $atts['orderby'] ) as $portfolio_index_number => $orderby ) {
|
564 |
+
if ( ! in_array( $orderby, $allowed_keys ) ) {
|
565 |
+
continue;
|
566 |
+
}
|
567 |
+
$parsed[] = $orderby;
|
568 |
+
}
|
569 |
+
|
570 |
+
if ( empty( $parsed ) ) {
|
571 |
+
unset( $atts['orderby'] );
|
572 |
+
} else {
|
573 |
+
$atts['orderby'] = implode( ' ', $parsed );
|
574 |
+
}
|
575 |
+
}
|
576 |
+
|
577 |
+
// enqueue shortcode styles when shortcode is used
|
578 |
+
wp_enqueue_style( 'jetpack-portfolio-style', plugins_url( 'css/portfolio-shortcode.css', __FILE__ ), array(), '20140326' );
|
579 |
+
|
580 |
+
return self::portfolio_shortcode_html( $atts );
|
581 |
+
}
|
582 |
+
|
583 |
+
/**
|
584 |
+
* Query to retrieve entries from the Portfolio post_type.
|
585 |
+
*
|
586 |
+
* @return object
|
587 |
+
*/
|
588 |
+
static function portfolio_query( $atts ) {
|
589 |
+
// Default query arguments
|
590 |
+
$default = array(
|
591 |
+
'order' => $atts['order'],
|
592 |
+
'orderby' => $atts['orderby'],
|
593 |
+
'posts_per_page' => $atts['showposts'],
|
594 |
+
);
|
595 |
+
|
596 |
+
$args = wp_parse_args( $atts, $default );
|
597 |
+
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
598 |
+
|
599 |
+
if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
|
600 |
+
$args['tax_query'] = array();
|
601 |
+
}
|
602 |
+
|
603 |
+
// If 'include_type' has been set use it on the main query
|
604 |
+
if ( false != $atts['include_type'] ) {
|
605 |
+
array_push( $args['tax_query'], array(
|
606 |
+
'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
|
607 |
+
'field' => 'slug',
|
608 |
+
'terms' => $atts['include_type'],
|
609 |
+
) );
|
610 |
+
}
|
611 |
+
|
612 |
+
// If 'include_tag' has been set use it on the main query
|
613 |
+
if ( false != $atts['include_tag'] ) {
|
614 |
+
array_push( $args['tax_query'], array(
|
615 |
+
'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
|
616 |
+
'field' => 'slug',
|
617 |
+
'terms' => $atts['include_tag'],
|
618 |
+
) );
|
619 |
+
}
|
620 |
+
|
621 |
+
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
622 |
+
$args['tax_query']['relation'] = 'AND';
|
623 |
+
}
|
624 |
+
|
625 |
+
// Run the query and return
|
626 |
+
$query = new WP_Query( $args );
|
627 |
+
return $query;
|
628 |
+
}
|
629 |
+
|
630 |
+
/**
|
631 |
+
* The Portfolio shortcode loop.
|
632 |
+
*
|
633 |
+
* @todo add theme color styles
|
634 |
+
* @return html
|
635 |
+
*/
|
636 |
+
|
637 |
+
static function portfolio_shortcode_html( $atts ) {
|
638 |
+
|
639 |
+
$query = self::portfolio_query( $atts );
|
640 |
+
|
641 |
+
ob_start();
|
642 |
+
|
643 |
+
// If we have posts, create the html
|
644 |
+
// with hportfolio markup
|
645 |
+
if ( $query->have_posts() ) {
|
646 |
+
|
647 |
+
|
648 |
+
/**
|
649 |
+
* Hook: ect_before_portfolio_loop.
|
650 |
+
*
|
651 |
+
* @hooked ect_portfolio_section
|
652 |
+
*/
|
653 |
+
$layout = ect_get_layout();
|
654 |
+
do_action( 'ect_before_portfolio_loop', $layout[$atts['columns']] );
|
655 |
+
?>
|
656 |
+
<?php
|
657 |
+
//ect_portfolio_loop_start( $layout[$atts['columns']] );
|
658 |
+
while ( $query->have_posts() ) {
|
659 |
+
$query->the_post();
|
660 |
+
ect_get_template_part( 'content', 'portfolio', $atts );
|
661 |
+
/**
|
662 |
+
* Hook: ect_portfolio_loop.
|
663 |
+
*
|
664 |
+
* @hooked
|
665 |
+
*/
|
666 |
+
}
|
667 |
+
wp_reset_postdata();
|
668 |
+
//ect_portfolio_loop_end();
|
669 |
+
?>
|
670 |
+
<?php
|
671 |
+
|
672 |
+
/**
|
673 |
+
* Hook: ect_after_portfolio_loop.
|
674 |
+
*
|
675 |
+
* @hooked
|
676 |
+
*/
|
677 |
+
do_action( 'ect_after_portfolio_loop' );
|
678 |
+
|
679 |
+
} else {
|
680 |
+
/**
|
681 |
+
* Hook: ect_no_portfolio_found.
|
682 |
+
*
|
683 |
+
* @hooked ect_no_portfolio_found
|
684 |
+
*/
|
685 |
+
do_action( 'ect_no_portfolio_found' );
|
686 |
+
}
|
687 |
+
|
688 |
+
$html = ob_get_clean();
|
689 |
+
|
690 |
+
// If there is a [portfolio] within a [portfolio], remove the shortcode
|
691 |
+
if ( has_shortcode( $html, 'portfolio' ) ){
|
692 |
+
remove_shortcode( 'portfolio' );
|
693 |
+
}
|
694 |
+
|
695 |
+
// Return the HTML block
|
696 |
+
return $html;
|
697 |
+
}
|
698 |
+
|
699 |
+
/**
|
700 |
+
* Displays the project type that a project belongs to.
|
701 |
+
*
|
702 |
+
* @return html
|
703 |
+
*/
|
704 |
+
static function get_project_type( $post_id ) {
|
705 |
+
$project_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
|
706 |
+
|
707 |
+
// If no types, return empty string
|
708 |
+
if ( empty( $project_types ) || is_wp_error( $project_types ) ) {
|
709 |
+
return;
|
710 |
+
}
|
711 |
+
|
712 |
+
$html = '<div class="project-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
|
713 |
+
$types = array();
|
714 |
+
// Loop thorugh all the types
|
715 |
+
foreach ( $project_types as $project_type ) {
|
716 |
+
$project_type_link = get_term_link( $project_type, self::CUSTOM_TAXONOMY_TYPE );
|
717 |
+
|
718 |
+
if ( is_wp_error( $project_type_link ) ) {
|
719 |
+
return $project_type_link;
|
720 |
+
}
|
721 |
+
|
722 |
+
$types[] = '<a href="' . esc_url( $project_type_link ) . '" rel="tag">' . esc_html( $project_type->name ) . '</a>';
|
723 |
+
}
|
724 |
+
$html .= ' '.implode( ', ', $types );
|
725 |
+
$html .= '</div>';
|
726 |
+
|
727 |
+
return $html;
|
728 |
+
}
|
729 |
+
|
730 |
+
/**
|
731 |
+
* Displays the project tags that a project belongs to.
|
732 |
+
*
|
733 |
+
* @return html
|
734 |
+
*/
|
735 |
+
static function get_project_tags( $post_id ) {
|
736 |
+
$project_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
|
737 |
+
|
738 |
+
// If no tags, return empty string
|
739 |
+
if ( empty( $project_tags ) || is_wp_error( $project_tags ) ) {
|
740 |
+
return false;
|
741 |
+
}
|
742 |
+
|
743 |
+
$html = '<div class="project-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
|
744 |
+
$tags = array();
|
745 |
+
// Loop thorugh all the tags
|
746 |
+
foreach ( $project_tags as $project_tag ) {
|
747 |
+
$project_tag_link = get_term_link( $project_tag, self::CUSTOM_TAXONOMY_TYPE );
|
748 |
+
|
749 |
+
if ( is_wp_error( $project_tag_link ) ) {
|
750 |
+
return $project_tag_link;
|
751 |
+
}
|
752 |
+
|
753 |
+
$tags[] = '<a href="' . esc_url( $project_tag_link ) . '" rel="tag">' . esc_html( $project_tag->name ) . '</a>';
|
754 |
+
}
|
755 |
+
$html .= ' '. implode( ', ', $tags );
|
756 |
+
$html .= '</div>';
|
757 |
+
|
758 |
+
return $html;
|
759 |
+
}
|
760 |
+
|
761 |
+
/**
|
762 |
+
* Displays the author of the current portfolio project.
|
763 |
+
*
|
764 |
+
* @return html
|
765 |
+
*/
|
766 |
+
static function get_project_author() {
|
767 |
+
$html = '<div class="project-author">';
|
768 |
+
/* translators: %1$s is link to author posts, %2$s is author display name */
|
769 |
+
$html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
|
770 |
+
esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
|
771 |
+
esc_html( get_the_author() )
|
772 |
+
);
|
773 |
+
$html .= '</div>';
|
774 |
+
|
775 |
+
return $html;
|
776 |
+
}
|
777 |
+
}
|
778 |
+
add_action( 'init', array( 'Essential_Content_Jetpack_Portfolio', 'init' ) );
|
779 |
+
|
780 |
+
/**
|
781 |
+
* Add Portfolio support
|
782 |
+
*/
|
783 |
+
function essential_content_portfolio_support() {
|
784 |
+
/*
|
785 |
+
* Adding theme support for Jetpack Portfolio CPT.
|
786 |
+
*/
|
787 |
+
add_theme_support( 'jetpack-portfolio', array(
|
788 |
+
'title' => true,
|
789 |
+
'content' => true,
|
790 |
+
'featured-image' => true,
|
791 |
+
) );
|
792 |
+
add_image_size( 'ect-jetpack-portfolio-featured', 640, 640, true );
|
793 |
+
}
|
794 |
+
add_action( 'after_setup_theme', 'essential_content_portfolio_support' );
|
795 |
+
|
796 |
+
|
797 |
+
if( ! function_exists( 'essential_content_get_portfolio_thumbnail_link' ) ):
|
798 |
+
/**
|
799 |
+
* Display the featured image if it's available
|
800 |
+
*
|
801 |
+
* @return html
|
802 |
+
*/
|
803 |
+
function essential_content_get_portfolio_thumbnail_link( $post_id ) {
|
804 |
+
if ( has_post_thumbnail( $post_id ) ) {
|
805 |
+
/**
|
806 |
+
* Change the Portfolio thumbnail size.
|
807 |
+
*
|
808 |
+
* @module custom-content-types
|
809 |
+
*
|
810 |
+
* @since 3.4.0
|
811 |
+
*
|
812 |
+
* @param string|array $var Either a registered size keyword or size array.
|
813 |
+
*/
|
814 |
+
return '<a class="portfolio-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'jetpack_portfolio_thumbnail_size', 'ect-jetpack-portfolio-featured' ) ) . '</a>';
|
815 |
+
}
|
816 |
+
}
|
817 |
+
endif;
|
818 |
+
|
819 |
+
|
820 |
+
if( ! function_exists( 'essential_content_no_portfolio_found' ) ):
|
821 |
+
/**
|
822 |
+
* No items found text
|
823 |
+
*
|
824 |
+
* @return html
|
825 |
+
*/
|
826 |
+
function essential_content_no_portfolio_found() {
|
827 |
+
echo "<p><em>" . esc_html__( 'Your Portfolio Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . "</em></p>";
|
828 |
+
}
|
829 |
+
endif;
|
830 |
+
add_action( 'ect_no_portfolio_found', 'essential_content_no_portfolio_found', 10 );
|
831 |
+
|
832 |
+
|
833 |
+
if( ! function_exists( 'essential_content_portfolio_section_open' ) ):
|
834 |
+
/**
|
835 |
+
* Open section
|
836 |
+
*
|
837 |
+
* @return html
|
838 |
+
*/
|
839 |
+
function essential_content_portfolio_section_open( $layout ) {
|
840 |
+
echo '<div class="ect-portfolio ect-section">';
|
841 |
+
echo '<div class="ect-wrapper">';
|
842 |
+
}
|
843 |
+
endif;
|
844 |
+
add_action( 'ect_before_portfolio_loop', 'essential_content_portfolio_section_open', 10, 1 );
|
845 |
+
|
846 |
+
|
847 |
+
if( ! function_exists( 'essential_content_portfolio_loop_start' ) ):
|
848 |
+
/**
|
849 |
+
* open wrapper before loop
|
850 |
+
*
|
851 |
+
*/
|
852 |
+
function essential_content_portfolio_loop_start( $layout = null ){
|
853 |
+
echo '<div class="section-content-wrapper portfolio-content-wrapper ' . $layout . '">';
|
854 |
+
}
|
855 |
+
endif;
|
856 |
+
add_action( 'ect_before_portfolio_loop', 'essential_content_portfolio_loop_start', 30 );
|
857 |
+
|
858 |
+
|
859 |
+
if( ! function_exists( 'essential_content_portfolio_loop_end' ) ):
|
860 |
+
/**
|
861 |
+
* close wrapper after loop
|
862 |
+
*
|
863 |
+
*/
|
864 |
+
function essential_content_portfolio_loop_end(){
|
865 |
+
echo '</div><!-- .portfolio-content-wrapper -->';
|
866 |
+
}
|
867 |
+
endif;
|
868 |
+
add_action( 'ect_after_portfolio_loop', 'essential_content_portfolio_loop_end', 10 );
|
869 |
+
|
870 |
+
|
871 |
+
if( ! function_exists( 'essential_content_portfolio_section_close' ) ):
|
872 |
+
/**
|
873 |
+
* Close section
|
874 |
+
*
|
875 |
+
* @return html
|
876 |
+
*/
|
877 |
+
function essential_content_portfolio_section_close() {
|
878 |
+
echo '</div><!-- .ect-wrapper -->';
|
879 |
+
echo '</div><!-- .ect-section -->';
|
880 |
+
}
|
881 |
+
endif;
|
882 |
add_action( 'ect_after_portfolio_loop', 'essential_content_portfolio_section_close', 20 );
|
admin/class-service.php
CHANGED
@@ -1,736 +1,736 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Support JetPack Service
|
5 |
-
*/
|
6 |
-
class Essential_Content_Service {
|
7 |
-
const CUSTOM_POST_TYPE = 'ect-service';
|
8 |
-
const CUSTOM_TAXONOMY_TYPE = 'ect-service-type';
|
9 |
-
const CUSTOM_TAXONOMY_TAG = 'ect-service-tag';
|
10 |
-
const OPTION_NAME = 'ect-service';
|
11 |
-
const OPTION_READING_SETTING = 'ect_service_posts_per_page';
|
12 |
-
|
13 |
-
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
14 |
-
|
15 |
-
static function init() {
|
16 |
-
static $instance = false;
|
17 |
-
|
18 |
-
if ( ! $instance ) {
|
19 |
-
$instance = new Essential_Content_Service;
|
20 |
-
}
|
21 |
-
|
22 |
-
return $instance;
|
23 |
-
}
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Conditionally hook into WordPress.
|
27 |
-
*
|
28 |
-
* Setup user option for enabling CPT
|
29 |
-
* If user has CPT enabled, show in admin
|
30 |
-
*/
|
31 |
-
function __construct() {
|
32 |
-
// Make sure the post types are loaded for imports
|
33 |
-
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
34 |
-
|
35 |
-
// Add to REST API post type whitelist
|
36 |
-
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_service_rest_api_type' ) );
|
37 |
-
|
38 |
-
// CPT magic
|
39 |
-
$this->register_post_types();
|
40 |
-
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
41 |
-
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
42 |
-
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE), array( $this, 'flush_rules_on_first_content' ) );
|
43 |
-
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
44 |
-
|
45 |
-
// Admin Customization
|
46 |
-
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
47 |
-
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE), array( $this, 'edit_admin_columns' ) );
|
48 |
-
add_filter( sprintf( 'manage_%s_posts_custom_column', self::CUSTOM_POST_TYPE), array( $this, 'image_column' ), 10, 2 );
|
49 |
-
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
50 |
-
|
51 |
-
add_image_size( 'service-admin-thumb', 50, 50, true );
|
52 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
|
53 |
-
|
54 |
-
// register service shortcode and services shortcode (legacy)
|
55 |
-
add_shortcode( 'services', array( $this, 'service_shortcode' ) );
|
56 |
-
add_shortcode( 'ect_services', array( $this, 'service_shortcode' ) );
|
57 |
-
|
58 |
-
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
59 |
-
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ) );
|
60 |
-
}
|
61 |
-
|
62 |
-
/*
|
63 |
-
* Flush permalinks when CPT option is turned on/off
|
64 |
-
*/
|
65 |
-
function flush_rules_on_enable() {
|
66 |
-
flush_rewrite_rules();
|
67 |
-
}
|
68 |
-
|
69 |
-
/*
|
70 |
-
* Count published contents and flush permalinks when first contents is published
|
71 |
-
*/
|
72 |
-
function flush_rules_on_first_content() {
|
73 |
-
$contents = get_transient( 'service-count-cache' );
|
74 |
-
|
75 |
-
if ( false === $contents ) {
|
76 |
-
flush_rewrite_rules();
|
77 |
-
$contents = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
78 |
-
|
79 |
-
if ( ! empty( $contents ) ) {
|
80 |
-
set_transient( 'service-count-cache', $contents, HOUR_IN_SECONDS * 12 );
|
81 |
-
}
|
82 |
-
}
|
83 |
-
}
|
84 |
-
|
85 |
-
/*
|
86 |
-
* Flush permalinks when CPT supported theme is activated
|
87 |
-
*/
|
88 |
-
function flush_rules_on_switch() {
|
89 |
-
flush_rewrite_rules();
|
90 |
-
}
|
91 |
-
|
92 |
-
/**
|
93 |
-
* Register Post Type
|
94 |
-
*/
|
95 |
-
function register_post_types() {
|
96 |
-
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
97 |
-
return;
|
98 |
-
}
|
99 |
-
|
100 |
-
$args = array(
|
101 |
-
'description' => esc_html__( 'Service Items', 'essential-content-types' ),
|
102 |
-
'labels' => array(
|
103 |
-
'name' => esc_html__( 'Services', 'essential-content-types' ),
|
104 |
-
'singular_name' => esc_html__( 'Service', 'essential-content-types' ),
|
105 |
-
'menu_name' => esc_html__( 'Service', 'essential-content-types' ),
|
106 |
-
'all_items' => esc_html__( 'All Services', 'essential-content-types' ),
|
107 |
-
'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
|
108 |
-
'add_new_item' => esc_html__( 'Add New Service', 'essential-content-types' ),
|
109 |
-
'edit_item' => esc_html__( 'Edit Service', 'essential-content-types' ),
|
110 |
-
'new_item' => esc_html__( 'New Service', 'essential-content-types' ),
|
111 |
-
'view_item' => esc_html__( 'View Service', 'essential-content-types' ),
|
112 |
-
'search_items' => esc_html__( 'Search Services', 'essential-content-types' ),
|
113 |
-
'not_found' => esc_html__( 'No Services found', 'essential-content-types' ),
|
114 |
-
'not_found_in_trash' => esc_html__( 'No Services found in Trash', 'essential-content-types' ),
|
115 |
-
'filter_items_list' => esc_html__( 'Filter contents list', 'essential-content-types' ),
|
116 |
-
'items_list_navigation' => esc_html__( 'Service list navigation', 'essential-content-types' ),
|
117 |
-
'items_list' => esc_html__( 'Services list', 'essential-content-types' ),
|
118 |
-
),
|
119 |
-
'supports' => array(
|
120 |
-
'title',
|
121 |
-
'editor',
|
122 |
-
'excerpt',
|
123 |
-
'thumbnail',
|
124 |
-
'author',
|
125 |
-
'comments',
|
126 |
-
),
|
127 |
-
'rewrite' => array(
|
128 |
-
'slug' => 'service',
|
129 |
-
'with_front' => false,
|
130 |
-
'feeds' => true,
|
131 |
-
'pages' => true,
|
132 |
-
),
|
133 |
-
'public' => true,
|
134 |
-
'show_ui' => true,
|
135 |
-
'menu_position' => 20, // below Pages
|
136 |
-
'menu_icon' => 'dashicons-exerpt-view', // 3.8+ dashicon option
|
137 |
-
'capability_type' => 'page',
|
138 |
-
'map_meta_cap' => true,
|
139 |
-
'taxonomies' => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
|
140 |
-
'has_archive' => true,
|
141 |
-
'query_var' => 'service',
|
142 |
-
'show_in_rest' => true,
|
143 |
-
);
|
144 |
-
|
145 |
-
$description = get_option( 'ect_service_content' );
|
146 |
-
if ( '' !== $description ) {
|
147 |
-
$args['description'] = $description;
|
148 |
-
}
|
149 |
-
|
150 |
-
register_post_type( self::CUSTOM_POST_TYPE, $args );
|
151 |
-
|
152 |
-
register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
|
153 |
-
'hierarchical' => true,
|
154 |
-
'labels' => array(
|
155 |
-
'name' => esc_html__( 'Service Types', 'essential-content-types' ),
|
156 |
-
'singular_name' => esc_html__( 'Service Type', 'essential-content-types' ),
|
157 |
-
'menu_name' => esc_html__( 'Service Types', 'essential-content-types' ),
|
158 |
-
'all_items' => esc_html__( 'All Service Types', 'essential-content-types' ),
|
159 |
-
'edit_item' => esc_html__( 'Edit Service Type', 'essential-content-types' ),
|
160 |
-
'view_item' => esc_html__( 'View Service Type', 'essential-content-types' ),
|
161 |
-
'update_item' => esc_html__( 'Update Service Type', 'essential-content-types' ),
|
162 |
-
'add_new_item' => esc_html__( 'Add New Service Type', 'essential-content-types' ),
|
163 |
-
'new_item_name' => esc_html__( 'New Service Type Name', 'essential-content-types' ),
|
164 |
-
'parent_item' => esc_html__( 'Parent Service Type', 'essential-content-types' ),
|
165 |
-
'parent_item_colon' => esc_html__( 'Parent Service Type:', 'essential-content-types' ),
|
166 |
-
'search_items' => esc_html__( 'Search Service Types', 'essential-content-types' ),
|
167 |
-
'items_list_navigation' => esc_html__( 'Service type list navigation', 'essential-content-types' ),
|
168 |
-
'items_list' => esc_html__( 'Service type list', 'essential-content-types' ),
|
169 |
-
),
|
170 |
-
'public' => true,
|
171 |
-
'show_ui' => true,
|
172 |
-
'show_in_nav_menus' => true,
|
173 |
-
'show_in_rest' => true,
|
174 |
-
'show_admin_column' => true,
|
175 |
-
'query_var' => true,
|
176 |
-
'rewrite' => array( 'slug' => 'service-type' ),
|
177 |
-
) );
|
178 |
-
|
179 |
-
register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
|
180 |
-
'hierarchical' => false,
|
181 |
-
'labels' => array(
|
182 |
-
'name' => esc_html__( 'Service Tags', 'essential-content-types' ),
|
183 |
-
'singular_name' => esc_html__( 'Service Tag', 'essential-content-types' ),
|
184 |
-
'menu_name' => esc_html__( 'Service Tags', 'essential-content-types' ),
|
185 |
-
'all_items' => esc_html__( 'All Service Tags', 'essential-content-types' ),
|
186 |
-
'edit_item' => esc_html__( 'Edit Service Tag', 'essential-content-types' ),
|
187 |
-
'view_item' => esc_html__( 'View Service Tag', 'essential-content-types' ),
|
188 |
-
'update_item' => esc_html__( 'Update Service Tag', 'essential-content-types' ),
|
189 |
-
'add_new_item' => esc_html__( 'Add New Service Tag', 'essential-content-types' ),
|
190 |
-
'new_item_name' => esc_html__( 'New Service Tag Name', 'essential-content-types' ),
|
191 |
-
'search_items' => esc_html__( 'Search Service Tags', 'essential-content-types' ),
|
192 |
-
'popular_items' => esc_html__( 'Popular Service Tags', 'essential-content-types' ),
|
193 |
-
'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
|
194 |
-
'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
|
195 |
-
'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
|
196 |
-
'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
|
197 |
-
'items_list_navigation' => esc_html__( 'Service tag list navigation', 'essential-content-types' ),
|
198 |
-
'items_list' => esc_html__( 'Service tag list', 'essential-content-types' ),
|
199 |
-
),
|
200 |
-
'public' => true,
|
201 |
-
'show_ui' => true,
|
202 |
-
'show_in_nav_menus' => true,
|
203 |
-
'show_in_rest' => true,
|
204 |
-
'show_admin_column' => true,
|
205 |
-
'query_var' => true,
|
206 |
-
'rewrite' => array( 'slug' => 'service-tag' ),
|
207 |
-
) );
|
208 |
-
}
|
209 |
-
|
210 |
-
/**
|
211 |
-
* Update messages for the Services admin.
|
212 |
-
*/
|
213 |
-
function updated_messages( $messages ) {
|
214 |
-
global $post;
|
215 |
-
|
216 |
-
$messages[self::CUSTOM_POST_TYPE] = array(
|
217 |
-
0 => '', // Unused. Messages start at index 1.
|
218 |
-
1 => sprintf( __( 'Service updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
|
219 |
-
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
220 |
-
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
221 |
-
4 => esc_html__( 'Service updated.', 'essential-content-types' ),
|
222 |
-
/* translators: %s: date and time of the revision */
|
223 |
-
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Service restored to revision from %s', 'essential-content-types'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
224 |
-
6 => sprintf( __( 'Service published. <a href="%s">View content</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
225 |
-
7 => esc_html__( 'Service saved.', 'essential-content-types' ),
|
226 |
-
8 => sprintf( __( 'Service submitted. <a target="_blank" href="%s">Preview content</a>', 'essential-content-types'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
227 |
-
9 => sprintf( __( 'Service scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview service</a>', 'essential-content-types' ),
|
228 |
-
// translators: Publish box date format, see http://php.net/date
|
229 |
-
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
|
230 |
-
10 => sprintf( __( 'Service item draft updated. <a target="_blank" href="%s">Preview content</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
231 |
-
);
|
232 |
-
|
233 |
-
return $messages;
|
234 |
-
}
|
235 |
-
|
236 |
-
/**
|
237 |
-
* Change ‘Title’ column label
|
238 |
-
* Add Featured Image column
|
239 |
-
*/
|
240 |
-
function edit_admin_columns( $columns ) {
|
241 |
-
// change 'Title' to 'Content'
|
242 |
-
$columns['title'] = __( 'Service', 'essential-content-types' );
|
243 |
-
if ( current_theme_supports( 'post-thumbnails' ) ) {
|
244 |
-
// add featured image before 'Content'
|
245 |
-
$columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
|
246 |
-
}
|
247 |
-
|
248 |
-
return $columns;
|
249 |
-
}
|
250 |
-
|
251 |
-
/**
|
252 |
-
* Add featured image to column
|
253 |
-
*/
|
254 |
-
function image_column( $column, $post_id ) {
|
255 |
-
global $post;
|
256 |
-
switch ( $column ) {
|
257 |
-
case 'thumbnail':
|
258 |
-
echo get_the_post_thumbnail( $post_id, 'service-admin-thumb' );
|
259 |
-
break;
|
260 |
-
}
|
261 |
-
}
|
262 |
-
|
263 |
-
/**
|
264 |
-
* Adjust image column width
|
265 |
-
*/
|
266 |
-
function enqueue_admin_styles( $hook ) {
|
267 |
-
$screen = get_current_screen();
|
268 |
-
|
269 |
-
if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
|
270 |
-
wp_add_inline_style( 'wp-admin', '.column-thumbnail img:nth-of-type(2) { display: none; } .manage-column.column-thumbnail { width: 50px; } @media screen and (max-width: 360px) { .column-thumbnail{ display:none; } }' );
|
271 |
-
}
|
272 |
-
}
|
273 |
-
|
274 |
-
/**
|
275 |
-
* Adds service section to the Customizer.
|
276 |
-
*/
|
277 |
-
function customize_register( $wp_customize ) {
|
278 |
-
$wp_customize->add_panel( 'ect_plugin_options', array(
|
279 |
-
'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
|
280 |
-
'priority' => 1,
|
281 |
-
) );
|
282 |
-
|
283 |
-
$wp_customize->add_section( 'ect_service', array(
|
284 |
-
'title' => esc_html__( 'Services', 'essential-content-types' ),
|
285 |
-
'priority' => 130,
|
286 |
-
'panel' => 'ect_plugin_options',
|
287 |
-
) );
|
288 |
-
|
289 |
-
$wp_customize->add_setting( 'ect_service_title', array(
|
290 |
-
'default' => esc_html__( 'Services', 'essential-content-types' ),
|
291 |
-
'type' => 'option',
|
292 |
-
'sanitize_callback' => 'sanitize_text_field',
|
293 |
-
'sanitize_js_callback' => 'sanitize_text_field',
|
294 |
-
) );
|
295 |
-
|
296 |
-
$wp_customize->add_control( 'ect_service_title', array(
|
297 |
-
'section' => 'ect_service',
|
298 |
-
'label' => esc_html__( 'Service Archive Title', 'essential-content-types' ),
|
299 |
-
'type' => 'text',
|
300 |
-
) );
|
301 |
-
|
302 |
-
$wp_customize->add_setting( 'ect_service_content', array(
|
303 |
-
'default' => '',
|
304 |
-
'type' => 'option',
|
305 |
-
'sanitize_callback' => 'wp_kses_post',
|
306 |
-
'sanitize_js_callback' => 'wp_kses_post',
|
307 |
-
) );
|
308 |
-
|
309 |
-
$wp_customize->add_control( 'ect_service_content', array(
|
310 |
-
'section' => 'ect_service',
|
311 |
-
'label' => esc_html__( 'Service Archive Content', 'essential-content-types' ),
|
312 |
-
'type' => 'textarea',
|
313 |
-
) );
|
314 |
-
|
315 |
-
$wp_customize->add_setting( 'ect_service_featured_image', array(
|
316 |
-
'default' => '',
|
317 |
-
'type' => 'option',
|
318 |
-
'sanitize_callback' => 'attachment_url_to_postid',
|
319 |
-
'sanitize_js_callback' => 'attachment_url_to_postid',
|
320 |
-
'theme_supports' => 'post-thumbnails',
|
321 |
-
) );
|
322 |
-
|
323 |
-
$wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'ect_service_featured_image', array(
|
324 |
-
'section' => 'ect_service',
|
325 |
-
'label' => esc_html__( 'Service Archive Featured Image', 'essential-content-types' ),
|
326 |
-
) ) );
|
327 |
-
}
|
328 |
-
|
329 |
-
/**
|
330 |
-
* Follow CPT reading setting on CPT archive and taxonomy pages
|
331 |
-
*/
|
332 |
-
function query_reading_setting( $query ) {
|
333 |
-
if ( ! is_admin() &&
|
334 |
-
$query->is_main_query() &&
|
335 |
-
( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
|
336 |
-
) {
|
337 |
-
$post_per_page = ( null != get_option('posts_per_page') ) ? get_option('posts_per_page') : '10';
|
338 |
-
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
|
339 |
-
}
|
340 |
-
}
|
341 |
-
|
342 |
-
/**
|
343 |
-
* Add to REST API post type whitelist
|
344 |
-
*/
|
345 |
-
function allow_service_rest_api_type( $post_types ) {
|
346 |
-
$post_types[] = self::CUSTOM_POST_TYPE;
|
347 |
-
|
348 |
-
return $post_types;
|
349 |
-
}
|
350 |
-
|
351 |
-
/**
|
352 |
-
* Our [services] shortcode.
|
353 |
-
* Prints Service data styled to look good on *any* theme.
|
354 |
-
*
|
355 |
-
* @return service_shortcode_html
|
356 |
-
*/
|
357 |
-
static function service_shortcode( $atts ) {
|
358 |
-
// Default attributes
|
359 |
-
$atts = shortcode_atts( array(
|
360 |
-
'image' => true,
|
361 |
-
'display_types' => true,
|
362 |
-
'display_tags' => true,
|
363 |
-
'display_content' => true,
|
364 |
-
'display_author' => false,
|
365 |
-
'show_filter' => false,
|
366 |
-
'include_type' => false,
|
367 |
-
'include_tag' => false,
|
368 |
-
'columns' => 2,
|
369 |
-
'showposts' => -1,
|
370 |
-
'order' => 'asc',
|
371 |
-
'orderby' => 'date',
|
372 |
-
), $atts, 'services' );
|
373 |
-
|
374 |
-
// A little sanitization
|
375 |
-
if ( $atts['image'] && 'true' != $atts['image'] ) {
|
376 |
-
$atts['image'] = false;
|
377 |
-
}
|
378 |
-
|
379 |
-
if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
|
380 |
-
$atts['display_types'] = false;
|
381 |
-
}
|
382 |
-
|
383 |
-
if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
|
384 |
-
$atts['display_tags'] = false;
|
385 |
-
}
|
386 |
-
|
387 |
-
if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
|
388 |
-
$atts['display_author'] = false;
|
389 |
-
}
|
390 |
-
|
391 |
-
if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
|
392 |
-
$atts['display_content'] = false;
|
393 |
-
}
|
394 |
-
|
395 |
-
if ( $atts['include_type'] ) {
|
396 |
-
$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
|
397 |
-
}
|
398 |
-
|
399 |
-
if ( $atts['include_tag'] ) {
|
400 |
-
$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
|
401 |
-
}
|
402 |
-
|
403 |
-
// Check if column value is set to valid numbers or else set default value as 2
|
404 |
-
if( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
|
405 |
-
$atts['columns'] = absint( $atts['columns'] );
|
406 |
-
} else {
|
407 |
-
$atts['columns'] = 2;
|
408 |
-
}
|
409 |
-
|
410 |
-
$atts['showposts'] = intval( $atts['showposts'] );
|
411 |
-
|
412 |
-
|
413 |
-
if ( $atts['order'] ) {
|
414 |
-
$atts['order'] = urldecode( $atts['order'] );
|
415 |
-
$atts['order'] = strtoupper( $atts['order'] );
|
416 |
-
if ( 'DESC' != $atts['order'] ) {
|
417 |
-
$atts['order'] = 'ASC';
|
418 |
-
}
|
419 |
-
}
|
420 |
-
|
421 |
-
if ( $atts['orderby'] ) {
|
422 |
-
$atts['orderby'] = urldecode( $atts['orderby'] );
|
423 |
-
$atts['orderby'] = strtolower( $atts['orderby'] );
|
424 |
-
$allowed_keys = array( 'author', 'date', 'title', 'rand' );
|
425 |
-
|
426 |
-
$parsed = array();
|
427 |
-
foreach ( explode( ',', $atts['orderby'] ) as $service_index_number => $orderby ) {
|
428 |
-
if ( ! in_array( $orderby, $allowed_keys ) ) {
|
429 |
-
continue;
|
430 |
-
}
|
431 |
-
$parsed[] = $orderby;
|
432 |
-
}
|
433 |
-
|
434 |
-
if ( empty( $parsed ) ) {
|
435 |
-
unset( $atts['orderby'] );
|
436 |
-
} else {
|
437 |
-
$atts['orderby'] = implode( ' ', $parsed );
|
438 |
-
}
|
439 |
-
}
|
440 |
-
|
441 |
-
// enqueue shortcode styles when shortcode is used
|
442 |
-
wp_enqueue_style( 'service-style', plugins_url( 'css/service-shortcode.css', __FILE__ ), array(), '20140326' );
|
443 |
-
|
444 |
-
return self::service_shortcode_html( $atts );
|
445 |
-
}
|
446 |
-
|
447 |
-
/**
|
448 |
-
* Query to retrieve entries from the Service post_type.
|
449 |
-
*
|
450 |
-
* @return object
|
451 |
-
*/
|
452 |
-
static function service_query( $atts ) {
|
453 |
-
// Default query arguments
|
454 |
-
$default = array(
|
455 |
-
'order' => $atts['order'],
|
456 |
-
'orderby' => $atts['orderby'],
|
457 |
-
'posts_per_page' => $atts['showposts'],
|
458 |
-
);
|
459 |
-
|
460 |
-
$args = wp_parse_args( $atts, $default );
|
461 |
-
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
462 |
-
|
463 |
-
if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
|
464 |
-
$args['tax_query'] = array();
|
465 |
-
}
|
466 |
-
|
467 |
-
// If 'include_type' has been set use it on the main query
|
468 |
-
if ( false != $atts['include_type'] ) {
|
469 |
-
array_push( $args['tax_query'], array(
|
470 |
-
'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
|
471 |
-
'field' => 'slug',
|
472 |
-
'terms' => $atts['include_type'],
|
473 |
-
) );
|
474 |
-
}
|
475 |
-
|
476 |
-
// If 'include_tag' has been set use it on the main query
|
477 |
-
if ( false != $atts['include_tag'] ) {
|
478 |
-
array_push( $args['tax_query'], array(
|
479 |
-
'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
|
480 |
-
'field' => 'slug',
|
481 |
-
'terms' => $atts['include_tag'],
|
482 |
-
) );
|
483 |
-
}
|
484 |
-
|
485 |
-
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
486 |
-
$args['tax_query']['relation'] = 'AND';
|
487 |
-
}
|
488 |
-
|
489 |
-
// Run the query and return
|
490 |
-
$query = new WP_Query( $args );
|
491 |
-
return $query;
|
492 |
-
}
|
493 |
-
|
494 |
-
/**
|
495 |
-
* The Service shortcode loop.
|
496 |
-
*
|
497 |
-
* @todo add theme color styles
|
498 |
-
* @return html
|
499 |
-
*/
|
500 |
-
|
501 |
-
static function service_shortcode_html( $atts ) {
|
502 |
-
|
503 |
-
$query = self::service_query( $atts );
|
504 |
-
$atts['service_index_number'] = 0;
|
505 |
-
|
506 |
-
ob_start();
|
507 |
-
|
508 |
-
// If we have posts, create the html
|
509 |
-
// with service markup
|
510 |
-
if ( $query->have_posts() ) {
|
511 |
-
|
512 |
-
/**
|
513 |
-
* Hook: ect_before_service_loop.
|
514 |
-
*
|
515 |
-
* @hooked
|
516 |
-
*/
|
517 |
-
$layout = ect_get_layout();
|
518 |
-
do_action( 'ect_before_service_loop', $layout[$atts['columns']] );
|
519 |
-
|
520 |
-
?>
|
521 |
-
<?php
|
522 |
-
while ( $query->have_posts() ) {
|
523 |
-
$query->the_post();
|
524 |
-
ect_get_template_part( 'content', 'service', $atts );
|
525 |
-
/**
|
526 |
-
* Hook: ect_service_loop.
|
527 |
-
*
|
528 |
-
* @hooked
|
529 |
-
*/
|
530 |
-
}
|
531 |
-
wp_reset_postdata();
|
532 |
-
?>
|
533 |
-
<?php
|
534 |
-
|
535 |
-
/**
|
536 |
-
* Hook: ect_after_service_loop.
|
537 |
-
*
|
538 |
-
* @hooked
|
539 |
-
*/
|
540 |
-
do_action( 'ect_after_service_loop' );
|
541 |
-
|
542 |
-
} else {
|
543 |
-
/**
|
544 |
-
* Hook: ect_no_service_found.
|
545 |
-
*
|
546 |
-
* @hooked ect_no_service_found
|
547 |
-
*/
|
548 |
-
do_action( 'ect_no_service_found' );
|
549 |
-
}
|
550 |
-
|
551 |
-
$html = ob_get_clean();
|
552 |
-
|
553 |
-
// If there is a [services] within a [services], remove the shortcode
|
554 |
-
if ( has_shortcode( $html, 'services' ) ){
|
555 |
-
remove_shortcode( 'services' );
|
556 |
-
}
|
557 |
-
|
558 |
-
// Return the HTML block
|
559 |
-
return $html;
|
560 |
-
}
|
561 |
-
|
562 |
-
/**
|
563 |
-
* Displays the content type that a content belongs to.
|
564 |
-
*
|
565 |
-
* @return html
|
566 |
-
*/
|
567 |
-
static function get_content_type( $post_id ) {
|
568 |
-
$content_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
|
569 |
-
|
570 |
-
// If no types, return empty string
|
571 |
-
if ( empty( $content_types ) || is_wp_error( $content_types ) ) {
|
572 |
-
return;
|
573 |
-
}
|
574 |
-
|
575 |
-
$html = '<div class="content-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
|
576 |
-
$types = array();
|
577 |
-
// Loop thorugh all the types
|
578 |
-
foreach ( $content_types as $content_type ) {
|
579 |
-
$content_type_link = get_term_link( $content_type, self::CUSTOM_TAXONOMY_TYPE );
|
580 |
-
|
581 |
-
if ( is_wp_error( $content_type_link ) ) {
|
582 |
-
return $content_type_link;
|
583 |
-
}
|
584 |
-
|
585 |
-
$types[] = '<a href="' . esc_url( $content_type_link ) . '" rel="tag">' . esc_html( $content_type->name ) . '</a>';
|
586 |
-
}
|
587 |
-
$html .= ' '.implode( ', ', $types );
|
588 |
-
$html .= '</div>';
|
589 |
-
|
590 |
-
return $html;
|
591 |
-
}
|
592 |
-
|
593 |
-
/**
|
594 |
-
* Displays the content tags that a content belongs to.
|
595 |
-
*
|
596 |
-
* @return html
|
597 |
-
*/
|
598 |
-
static function get_content_tags( $post_id ) {
|
599 |
-
$content_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
|
600 |
-
|
601 |
-
// If no tags, return empty string
|
602 |
-
if ( empty( $content_tags ) || is_wp_error( $content_tags ) ) {
|
603 |
-
return false;
|
604 |
-
}
|
605 |
-
|
606 |
-
$html = '<div class="content-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
|
607 |
-
$tags = array();
|
608 |
-
// Loop thorugh all the tags
|
609 |
-
foreach ( $content_tags as $content_tag ) {
|
610 |
-
$content_tag_link = get_term_link( $content_tag, self::CUSTOM_TAXONOMY_TYPE );
|
611 |
-
|
612 |
-
if ( is_wp_error( $content_tag_link ) ) {
|
613 |
-
return $content_tag_link;
|
614 |
-
}
|
615 |
-
|
616 |
-
$tags[] = '<a href="' . esc_url( $content_tag_link ) . '" rel="tag">' . esc_html( $content_tag->name ) . '</a>';
|
617 |
-
}
|
618 |
-
$html .= ' '. implode( ', ', $tags );
|
619 |
-
$html .= '</div>';
|
620 |
-
|
621 |
-
return $html;
|
622 |
-
}
|
623 |
-
|
624 |
-
/**
|
625 |
-
* Displays the author of the current service content.
|
626 |
-
*
|
627 |
-
* @return html
|
628 |
-
*/
|
629 |
-
static function get_content_author() {
|
630 |
-
$html = '<div class="content-author">';
|
631 |
-
/* translators: %1$s is link to author posts, %2$s is author display name */
|
632 |
-
$html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
|
633 |
-
esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
|
634 |
-
esc_html( get_the_author() )
|
635 |
-
);
|
636 |
-
$html .= '</div>';
|
637 |
-
|
638 |
-
return $html;
|
639 |
-
}
|
640 |
-
}
|
641 |
-
add_action( 'init', array( 'Essential_Content_Service', 'init' ) );
|
642 |
-
|
643 |
-
|
644 |
-
/**
|
645 |
-
* Add Service support
|
646 |
-
*/
|
647 |
-
function essential_content_service_support() {
|
648 |
-
/*
|
649 |
-
* Adding theme support for Jetpack Service CPT.
|
650 |
-
*/
|
651 |
-
add_image_size( 'ect-service', 640, 640, true );
|
652 |
-
}
|
653 |
-
add_action( 'after_setup_theme', 'essential_content_service_support' );
|
654 |
-
|
655 |
-
|
656 |
-
if( ! function_exists( 'essential_content_get_service_thumbnail_link' ) ):
|
657 |
-
function essential_content_get_service_thumbnail_link( $post_id, $size ) {
|
658 |
-
if ( has_post_thumbnail( $post_id ) ) {
|
659 |
-
/**
|
660 |
-
* Change the Service thumbnail size.
|
661 |
-
*
|
662 |
-
* @module custom-content-types
|
663 |
-
*
|
664 |
-
* @since 3.4.0
|
665 |
-
*
|
666 |
-
* @param string|array $var Either a registered size keyword or size array.
|
667 |
-
*/
|
668 |
-
return '<a class="service-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'service_thumbnail_size', $size ) ) . '</a>';
|
669 |
-
}
|
670 |
-
}
|
671 |
-
endif;
|
672 |
-
|
673 |
-
|
674 |
-
if( ! function_exists( 'essential_content_no_service_found' ) ):
|
675 |
-
/**
|
676 |
-
* No items found text
|
677 |
-
*
|
678 |
-
* @return html
|
679 |
-
*/
|
680 |
-
function essential_content_no_service_found() {
|
681 |
-
echo "<p><em>" . esc_html__( 'Your Service Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . "</em></p>";
|
682 |
-
}
|
683 |
-
add_action( 'ect_no_service_found', 'essential_content_no_service_found', 10 );
|
684 |
-
endif;
|
685 |
-
|
686 |
-
|
687 |
-
if( ! function_exists( 'essential_content_service_section_open' ) ):
|
688 |
-
/**
|
689 |
-
* Open section
|
690 |
-
*
|
691 |
-
* @return html
|
692 |
-
*/
|
693 |
-
function essential_content_service_section_open( $layout ) {
|
694 |
-
echo '<div class="ect-service ect-section">';
|
695 |
-
echo '<div class="ect-wrapper">';
|
696 |
-
}
|
697 |
-
endif;
|
698 |
-
add_action( 'ect_before_service_loop', 'essential_content_service_section_open', 10, 1 );
|
699 |
-
|
700 |
-
|
701 |
-
if( ! function_exists( 'essential_content_service_loop_start' ) ):
|
702 |
-
/**
|
703 |
-
* open wrapper before loop
|
704 |
-
*
|
705 |
-
*/
|
706 |
-
function essential_content_service_loop_start( $layout = null ){
|
707 |
-
echo '<div class="section-content-wrapper service-content-wrapper ' . $layout . '">';
|
708 |
-
}
|
709 |
-
endif;
|
710 |
-
add_action( 'ect_before_service_loop', 'essential_content_service_loop_start', 30 );
|
711 |
-
|
712 |
-
|
713 |
-
if( ! function_exists( 'essential_content_service_loop_end' ) ):
|
714 |
-
/**
|
715 |
-
* close wrapper after loop
|
716 |
-
*
|
717 |
-
*/
|
718 |
-
function essential_content_service_loop_end(){
|
719 |
-
echo '</div><!-- .service-content-wrapper -->';
|
720 |
-
}
|
721 |
-
endif;
|
722 |
-
add_action( 'ect_after_service_loop', 'essential_content_service_loop_end', 10 );
|
723 |
-
|
724 |
-
|
725 |
-
if( ! function_exists( 'essential_content_service_section_close' ) ):
|
726 |
-
/**
|
727 |
-
* Close section
|
728 |
-
*
|
729 |
-
* @return html
|
730 |
-
*/
|
731 |
-
function essential_content_service_section_close() {
|
732 |
-
echo '</div><!-- .ect-wrapper -->';
|
733 |
-
echo '</div><!-- .ect-section -->';
|
734 |
-
}
|
735 |
-
endif;
|
736 |
add_action( 'ect_after_service_loop', 'essential_content_service_section_close', 20 );
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Support JetPack Service
|
5 |
+
*/
|
6 |
+
class Essential_Content_Service {
|
7 |
+
const CUSTOM_POST_TYPE = 'ect-service';
|
8 |
+
const CUSTOM_TAXONOMY_TYPE = 'ect-service-type';
|
9 |
+
const CUSTOM_TAXONOMY_TAG = 'ect-service-tag';
|
10 |
+
const OPTION_NAME = 'ect-service';
|
11 |
+
const OPTION_READING_SETTING = 'ect_service_posts_per_page';
|
12 |
+
|
13 |
+
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
14 |
+
|
15 |
+
static function init() {
|
16 |
+
static $instance = false;
|
17 |
+
|
18 |
+
if ( ! $instance ) {
|
19 |
+
$instance = new Essential_Content_Service;
|
20 |
+
}
|
21 |
+
|
22 |
+
return $instance;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Conditionally hook into WordPress.
|
27 |
+
*
|
28 |
+
* Setup user option for enabling CPT
|
29 |
+
* If user has CPT enabled, show in admin
|
30 |
+
*/
|
31 |
+
function __construct() {
|
32 |
+
// Make sure the post types are loaded for imports
|
33 |
+
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
34 |
+
|
35 |
+
// Add to REST API post type whitelist
|
36 |
+
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_service_rest_api_type' ) );
|
37 |
+
|
38 |
+
// CPT magic
|
39 |
+
$this->register_post_types();
|
40 |
+
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
41 |
+
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
42 |
+
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE), array( $this, 'flush_rules_on_first_content' ) );
|
43 |
+
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
44 |
+
|
45 |
+
// Admin Customization
|
46 |
+
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
47 |
+
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE), array( $this, 'edit_admin_columns' ) );
|
48 |
+
add_filter( sprintf( 'manage_%s_posts_custom_column', self::CUSTOM_POST_TYPE), array( $this, 'image_column' ), 10, 2 );
|
49 |
+
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
50 |
+
|
51 |
+
add_image_size( 'service-admin-thumb', 50, 50, true );
|
52 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
|
53 |
+
|
54 |
+
// register service shortcode and services shortcode (legacy)
|
55 |
+
add_shortcode( 'services', array( $this, 'service_shortcode' ) );
|
56 |
+
add_shortcode( 'ect_services', array( $this, 'service_shortcode' ) );
|
57 |
+
|
58 |
+
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
59 |
+
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ) );
|
60 |
+
}
|
61 |
+
|
62 |
+
/*
|
63 |
+
* Flush permalinks when CPT option is turned on/off
|
64 |
+
*/
|
65 |
+
function flush_rules_on_enable() {
|
66 |
+
flush_rewrite_rules();
|
67 |
+
}
|
68 |
+
|
69 |
+
/*
|
70 |
+
* Count published contents and flush permalinks when first contents is published
|
71 |
+
*/
|
72 |
+
function flush_rules_on_first_content() {
|
73 |
+
$contents = get_transient( 'service-count-cache' );
|
74 |
+
|
75 |
+
if ( false === $contents ) {
|
76 |
+
flush_rewrite_rules();
|
77 |
+
$contents = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
78 |
+
|
79 |
+
if ( ! empty( $contents ) ) {
|
80 |
+
set_transient( 'service-count-cache', $contents, HOUR_IN_SECONDS * 12 );
|
81 |
+
}
|
82 |
+
}
|
83 |
+
}
|
84 |
+
|
85 |
+
/*
|
86 |
+
* Flush permalinks when CPT supported theme is activated
|
87 |
+
*/
|
88 |
+
function flush_rules_on_switch() {
|
89 |
+
flush_rewrite_rules();
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Register Post Type
|
94 |
+
*/
|
95 |
+
function register_post_types() {
|
96 |
+
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
97 |
+
return;
|
98 |
+
}
|
99 |
+
|
100 |
+
$args = array(
|
101 |
+
'description' => esc_html__( 'Service Items', 'essential-content-types' ),
|
102 |
+
'labels' => array(
|
103 |
+
'name' => esc_html__( 'Services', 'essential-content-types' ),
|
104 |
+
'singular_name' => esc_html__( 'Service', 'essential-content-types' ),
|
105 |
+
'menu_name' => esc_html__( 'Service', 'essential-content-types' ),
|
106 |
+
'all_items' => esc_html__( 'All Services', 'essential-content-types' ),
|
107 |
+
'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
|
108 |
+
'add_new_item' => esc_html__( 'Add New Service', 'essential-content-types' ),
|
109 |
+
'edit_item' => esc_html__( 'Edit Service', 'essential-content-types' ),
|
110 |
+
'new_item' => esc_html__( 'New Service', 'essential-content-types' ),
|
111 |
+
'view_item' => esc_html__( 'View Service', 'essential-content-types' ),
|
112 |
+
'search_items' => esc_html__( 'Search Services', 'essential-content-types' ),
|
113 |
+
'not_found' => esc_html__( 'No Services found', 'essential-content-types' ),
|
114 |
+
'not_found_in_trash' => esc_html__( 'No Services found in Trash', 'essential-content-types' ),
|
115 |
+
'filter_items_list' => esc_html__( 'Filter contents list', 'essential-content-types' ),
|
116 |
+
'items_list_navigation' => esc_html__( 'Service list navigation', 'essential-content-types' ),
|
117 |
+
'items_list' => esc_html__( 'Services list', 'essential-content-types' ),
|
118 |
+
),
|
119 |
+
'supports' => array(
|
120 |
+
'title',
|
121 |
+
'editor',
|
122 |
+
'excerpt',
|
123 |
+
'thumbnail',
|
124 |
+
'author',
|
125 |
+
'comments',
|
126 |
+
),
|
127 |
+
'rewrite' => array(
|
128 |
+
'slug' => 'service',
|
129 |
+
'with_front' => false,
|
130 |
+
'feeds' => true,
|
131 |
+
'pages' => true,
|
132 |
+
),
|
133 |
+
'public' => true,
|
134 |
+
'show_ui' => true,
|
135 |
+
'menu_position' => 20, // below Pages
|
136 |
+
'menu_icon' => 'dashicons-exerpt-view', // 3.8+ dashicon option
|
137 |
+
'capability_type' => 'page',
|
138 |
+
'map_meta_cap' => true,
|
139 |
+
'taxonomies' => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
|
140 |
+
'has_archive' => true,
|
141 |
+
'query_var' => 'service',
|
142 |
+
'show_in_rest' => true,
|
143 |
+
);
|
144 |
+
|
145 |
+
$description = get_option( 'ect_service_content' );
|
146 |
+
if ( '' !== $description ) {
|
147 |
+
$args['description'] = $description;
|
148 |
+
}
|
149 |
+
|
150 |
+
register_post_type( self::CUSTOM_POST_TYPE, $args );
|
151 |
+
|
152 |
+
register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
|
153 |
+
'hierarchical' => true,
|
154 |
+
'labels' => array(
|
155 |
+
'name' => esc_html__( 'Service Types', 'essential-content-types' ),
|
156 |
+
'singular_name' => esc_html__( 'Service Type', 'essential-content-types' ),
|
157 |
+
'menu_name' => esc_html__( 'Service Types', 'essential-content-types' ),
|
158 |
+
'all_items' => esc_html__( 'All Service Types', 'essential-content-types' ),
|
159 |
+
'edit_item' => esc_html__( 'Edit Service Type', 'essential-content-types' ),
|
160 |
+
'view_item' => esc_html__( 'View Service Type', 'essential-content-types' ),
|
161 |
+
'update_item' => esc_html__( 'Update Service Type', 'essential-content-types' ),
|
162 |
+
'add_new_item' => esc_html__( 'Add New Service Type', 'essential-content-types' ),
|
163 |
+
'new_item_name' => esc_html__( 'New Service Type Name', 'essential-content-types' ),
|
164 |
+
'parent_item' => esc_html__( 'Parent Service Type', 'essential-content-types' ),
|
165 |
+
'parent_item_colon' => esc_html__( 'Parent Service Type:', 'essential-content-types' ),
|
166 |
+
'search_items' => esc_html__( 'Search Service Types', 'essential-content-types' ),
|
167 |
+
'items_list_navigation' => esc_html__( 'Service type list navigation', 'essential-content-types' ),
|
168 |
+
'items_list' => esc_html__( 'Service type list', 'essential-content-types' ),
|
169 |
+
),
|
170 |
+
'public' => true,
|
171 |
+
'show_ui' => true,
|
172 |
+
'show_in_nav_menus' => true,
|
173 |
+
'show_in_rest' => true,
|
174 |
+
'show_admin_column' => true,
|
175 |
+
'query_var' => true,
|
176 |
+
'rewrite' => array( 'slug' => 'service-type' ),
|
177 |
+
) );
|
178 |
+
|
179 |
+
register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
|
180 |
+
'hierarchical' => false,
|
181 |
+
'labels' => array(
|
182 |
+
'name' => esc_html__( 'Service Tags', 'essential-content-types' ),
|
183 |
+
'singular_name' => esc_html__( 'Service Tag', 'essential-content-types' ),
|
184 |
+
'menu_name' => esc_html__( 'Service Tags', 'essential-content-types' ),
|
185 |
+
'all_items' => esc_html__( 'All Service Tags', 'essential-content-types' ),
|
186 |
+
'edit_item' => esc_html__( 'Edit Service Tag', 'essential-content-types' ),
|
187 |
+
'view_item' => esc_html__( 'View Service Tag', 'essential-content-types' ),
|
188 |
+
'update_item' => esc_html__( 'Update Service Tag', 'essential-content-types' ),
|
189 |
+
'add_new_item' => esc_html__( 'Add New Service Tag', 'essential-content-types' ),
|
190 |
+
'new_item_name' => esc_html__( 'New Service Tag Name', 'essential-content-types' ),
|
191 |
+
'search_items' => esc_html__( 'Search Service Tags', 'essential-content-types' ),
|
192 |
+
'popular_items' => esc_html__( 'Popular Service Tags', 'essential-content-types' ),
|
193 |
+
'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
|
194 |
+
'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
|
195 |
+
'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
|
196 |
+
'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
|
197 |
+
'items_list_navigation' => esc_html__( 'Service tag list navigation', 'essential-content-types' ),
|
198 |
+
'items_list' => esc_html__( 'Service tag list', 'essential-content-types' ),
|
199 |
+
),
|
200 |
+
'public' => true,
|
201 |
+
'show_ui' => true,
|
202 |
+
'show_in_nav_menus' => true,
|
203 |
+
'show_in_rest' => true,
|
204 |
+
'show_admin_column' => true,
|
205 |
+
'query_var' => true,
|
206 |
+
'rewrite' => array( 'slug' => 'service-tag' ),
|
207 |
+
) );
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Update messages for the Services admin.
|
212 |
+
*/
|
213 |
+
function updated_messages( $messages ) {
|
214 |
+
global $post;
|
215 |
+
|
216 |
+
$messages[self::CUSTOM_POST_TYPE] = array(
|
217 |
+
0 => '', // Unused. Messages start at index 1.
|
218 |
+
1 => sprintf( __( 'Service updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
|
219 |
+
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
220 |
+
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
221 |
+
4 => esc_html__( 'Service updated.', 'essential-content-types' ),
|
222 |
+
/* translators: %s: date and time of the revision */
|
223 |
+
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Service restored to revision from %s', 'essential-content-types'), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
224 |
+
6 => sprintf( __( 'Service published. <a href="%s">View content</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
225 |
+
7 => esc_html__( 'Service saved.', 'essential-content-types' ),
|
226 |
+
8 => sprintf( __( 'Service submitted. <a target="_blank" href="%s">Preview content</a>', 'essential-content-types'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
227 |
+
9 => sprintf( __( 'Service scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview service</a>', 'essential-content-types' ),
|
228 |
+
// translators: Publish box date format, see http://php.net/date
|
229 |
+
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
|
230 |
+
10 => sprintf( __( 'Service item draft updated. <a target="_blank" href="%s">Preview content</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
231 |
+
);
|
232 |
+
|
233 |
+
return $messages;
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Change ‘Title’ column label
|
238 |
+
* Add Featured Image column
|
239 |
+
*/
|
240 |
+
function edit_admin_columns( $columns ) {
|
241 |
+
// change 'Title' to 'Content'
|
242 |
+
$columns['title'] = __( 'Service', 'essential-content-types' );
|
243 |
+
if ( current_theme_supports( 'post-thumbnails' ) ) {
|
244 |
+
// add featured image before 'Content'
|
245 |
+
$columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
|
246 |
+
}
|
247 |
+
|
248 |
+
return $columns;
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Add featured image to column
|
253 |
+
*/
|
254 |
+
function image_column( $column, $post_id ) {
|
255 |
+
global $post;
|
256 |
+
switch ( $column ) {
|
257 |
+
case 'thumbnail':
|
258 |
+
echo get_the_post_thumbnail( $post_id, 'service-admin-thumb' );
|
259 |
+
break;
|
260 |
+
}
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Adjust image column width
|
265 |
+
*/
|
266 |
+
function enqueue_admin_styles( $hook ) {
|
267 |
+
$screen = get_current_screen();
|
268 |
+
|
269 |
+
if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
|
270 |
+
wp_add_inline_style( 'wp-admin', '.column-thumbnail img:nth-of-type(2) { display: none; } .manage-column.column-thumbnail { width: 50px; } @media screen and (max-width: 360px) { .column-thumbnail{ display:none; } }' );
|
271 |
+
}
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Adds service section to the Customizer.
|
276 |
+
*/
|
277 |
+
function customize_register( $wp_customize ) {
|
278 |
+
$wp_customize->add_panel( 'ect_plugin_options', array(
|
279 |
+
'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
|
280 |
+
'priority' => 1,
|
281 |
+
) );
|
282 |
+
|
283 |
+
$wp_customize->add_section( 'ect_service', array(
|
284 |
+
'title' => esc_html__( 'Services', 'essential-content-types' ),
|
285 |
+
'priority' => 130,
|
286 |
+
'panel' => 'ect_plugin_options',
|
287 |
+
) );
|
288 |
+
|
289 |
+
$wp_customize->add_setting( 'ect_service_title', array(
|
290 |
+
'default' => esc_html__( 'Services', 'essential-content-types' ),
|
291 |
+
'type' => 'option',
|
292 |
+
'sanitize_callback' => 'sanitize_text_field',
|
293 |
+
'sanitize_js_callback' => 'sanitize_text_field',
|
294 |
+
) );
|
295 |
+
|
296 |
+
$wp_customize->add_control( 'ect_service_title', array(
|
297 |
+
'section' => 'ect_service',
|
298 |
+
'label' => esc_html__( 'Service Archive Title', 'essential-content-types' ),
|
299 |
+
'type' => 'text',
|
300 |
+
) );
|
301 |
+
|
302 |
+
$wp_customize->add_setting( 'ect_service_content', array(
|
303 |
+
'default' => '',
|
304 |
+
'type' => 'option',
|
305 |
+
'sanitize_callback' => 'wp_kses_post',
|
306 |
+
'sanitize_js_callback' => 'wp_kses_post',
|
307 |
+
) );
|
308 |
+
|
309 |
+
$wp_customize->add_control( 'ect_service_content', array(
|
310 |
+
'section' => 'ect_service',
|
311 |
+
'label' => esc_html__( 'Service Archive Content', 'essential-content-types' ),
|
312 |
+
'type' => 'textarea',
|
313 |
+
) );
|
314 |
+
|
315 |
+
$wp_customize->add_setting( 'ect_service_featured_image', array(
|
316 |
+
'default' => '',
|
317 |
+
'type' => 'option',
|
318 |
+
'sanitize_callback' => 'attachment_url_to_postid',
|
319 |
+
'sanitize_js_callback' => 'attachment_url_to_postid',
|
320 |
+
'theme_supports' => 'post-thumbnails',
|
321 |
+
) );
|
322 |
+
|
323 |
+
$wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'ect_service_featured_image', array(
|
324 |
+
'section' => 'ect_service',
|
325 |
+
'label' => esc_html__( 'Service Archive Featured Image', 'essential-content-types' ),
|
326 |
+
) ) );
|
327 |
+
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* Follow CPT reading setting on CPT archive and taxonomy pages
|
331 |
+
*/
|
332 |
+
function query_reading_setting( $query ) {
|
333 |
+
if ( ! is_admin() &&
|
334 |
+
$query->is_main_query() &&
|
335 |
+
( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
|
336 |
+
) {
|
337 |
+
$post_per_page = ( null != get_option('posts_per_page') ) ? get_option('posts_per_page') : '10';
|
338 |
+
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
|
339 |
+
}
|
340 |
+
}
|
341 |
+
|
342 |
+
/**
|
343 |
+
* Add to REST API post type whitelist
|
344 |
+
*/
|
345 |
+
function allow_service_rest_api_type( $post_types ) {
|
346 |
+
$post_types[] = self::CUSTOM_POST_TYPE;
|
347 |
+
|
348 |
+
return $post_types;
|
349 |
+
}
|
350 |
+
|
351 |
+
/**
|
352 |
+
* Our [services] shortcode.
|
353 |
+
* Prints Service data styled to look good on *any* theme.
|
354 |
+
*
|
355 |
+
* @return service_shortcode_html
|
356 |
+
*/
|
357 |
+
static function service_shortcode( $atts ) {
|
358 |
+
// Default attributes
|
359 |
+
$atts = shortcode_atts( array(
|
360 |
+
'image' => true,
|
361 |
+
'display_types' => true,
|
362 |
+
'display_tags' => true,
|
363 |
+
'display_content' => true,
|
364 |
+
'display_author' => false,
|
365 |
+
'show_filter' => false,
|
366 |
+
'include_type' => false,
|
367 |
+
'include_tag' => false,
|
368 |
+
'columns' => 2,
|
369 |
+
'showposts' => -1,
|
370 |
+
'order' => 'asc',
|
371 |
+
'orderby' => 'date',
|
372 |
+
), $atts, 'services' );
|
373 |
+
|
374 |
+
// A little sanitization
|
375 |
+
if ( $atts['image'] && 'true' != $atts['image'] ) {
|
376 |
+
$atts['image'] = false;
|
377 |
+
}
|
378 |
+
|
379 |
+
if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
|
380 |
+
$atts['display_types'] = false;
|
381 |
+
}
|
382 |
+
|
383 |
+
if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
|
384 |
+
$atts['display_tags'] = false;
|
385 |
+
}
|
386 |
+
|
387 |
+
if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
|
388 |
+
$atts['display_author'] = false;
|
389 |
+
}
|
390 |
+
|
391 |
+
if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
|
392 |
+
$atts['display_content'] = false;
|
393 |
+
}
|
394 |
+
|
395 |
+
if ( $atts['include_type'] ) {
|
396 |
+
$atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
|
397 |
+
}
|
398 |
+
|
399 |
+
if ( $atts['include_tag'] ) {
|
400 |
+
$atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
|
401 |
+
}
|
402 |
+
|
403 |
+
// Check if column value is set to valid numbers or else set default value as 2
|
404 |
+
if( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
|
405 |
+
$atts['columns'] = absint( $atts['columns'] );
|
406 |
+
} else {
|
407 |
+
$atts['columns'] = 2;
|
408 |
+
}
|
409 |
+
|
410 |
+
$atts['showposts'] = intval( $atts['showposts'] );
|
411 |
+
|
412 |
+
|
413 |
+
if ( $atts['order'] ) {
|
414 |
+
$atts['order'] = urldecode( $atts['order'] );
|
415 |
+
$atts['order'] = strtoupper( $atts['order'] );
|
416 |
+
if ( 'DESC' != $atts['order'] ) {
|
417 |
+
$atts['order'] = 'ASC';
|
418 |
+
}
|
419 |
+
}
|
420 |
+
|
421 |
+
if ( $atts['orderby'] ) {
|
422 |
+
$atts['orderby'] = urldecode( $atts['orderby'] );
|
423 |
+
$atts['orderby'] = strtolower( $atts['orderby'] );
|
424 |
+
$allowed_keys = array( 'author', 'date', 'title', 'rand' );
|
425 |
+
|
426 |
+
$parsed = array();
|
427 |
+
foreach ( explode( ',', $atts['orderby'] ) as $service_index_number => $orderby ) {
|
428 |
+
if ( ! in_array( $orderby, $allowed_keys ) ) {
|
429 |
+
continue;
|
430 |
+
}
|
431 |
+
$parsed[] = $orderby;
|
432 |
+
}
|
433 |
+
|
434 |
+
if ( empty( $parsed ) ) {
|
435 |
+
unset( $atts['orderby'] );
|
436 |
+
} else {
|
437 |
+
$atts['orderby'] = implode( ' ', $parsed );
|
438 |
+
}
|
439 |
+
}
|
440 |
+
|
441 |
+
// enqueue shortcode styles when shortcode is used
|
442 |
+
wp_enqueue_style( 'service-style', plugins_url( 'css/service-shortcode.css', __FILE__ ), array(), '20140326' );
|
443 |
+
|
444 |
+
return self::service_shortcode_html( $atts );
|
445 |
+
}
|
446 |
+
|
447 |
+
/**
|
448 |
+
* Query to retrieve entries from the Service post_type.
|
449 |
+
*
|
450 |
+
* @return object
|
451 |
+
*/
|
452 |
+
static function service_query( $atts ) {
|
453 |
+
// Default query arguments
|
454 |
+
$default = array(
|
455 |
+
'order' => $atts['order'],
|
456 |
+
'orderby' => $atts['orderby'],
|
457 |
+
'posts_per_page' => $atts['showposts'],
|
458 |
+
);
|
459 |
+
|
460 |
+
$args = wp_parse_args( $atts, $default );
|
461 |
+
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
462 |
+
|
463 |
+
if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
|
464 |
+
$args['tax_query'] = array();
|
465 |
+
}
|
466 |
+
|
467 |
+
// If 'include_type' has been set use it on the main query
|
468 |
+
if ( false != $atts['include_type'] ) {
|
469 |
+
array_push( $args['tax_query'], array(
|
470 |
+
'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
|
471 |
+
'field' => 'slug',
|
472 |
+
'terms' => $atts['include_type'],
|
473 |
+
) );
|
474 |
+
}
|
475 |
+
|
476 |
+
// If 'include_tag' has been set use it on the main query
|
477 |
+
if ( false != $atts['include_tag'] ) {
|
478 |
+
array_push( $args['tax_query'], array(
|
479 |
+
'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
|
480 |
+
'field' => 'slug',
|
481 |
+
'terms' => $atts['include_tag'],
|
482 |
+
) );
|
483 |
+
}
|
484 |
+
|
485 |
+
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
486 |
+
$args['tax_query']['relation'] = 'AND';
|
487 |
+
}
|
488 |
+
|
489 |
+
// Run the query and return
|
490 |
+
$query = new WP_Query( $args );
|
491 |
+
return $query;
|
492 |
+
}
|
493 |
+
|
494 |
+
/**
|
495 |
+
* The Service shortcode loop.
|
496 |
+
*
|
497 |
+
* @todo add theme color styles
|
498 |
+
* @return html
|
499 |
+
*/
|
500 |
+
|
501 |
+
static function service_shortcode_html( $atts ) {
|
502 |
+
|
503 |
+
$query = self::service_query( $atts );
|
504 |
+
$atts['service_index_number'] = 0;
|
505 |
+
|
506 |
+
ob_start();
|
507 |
+
|
508 |
+
// If we have posts, create the html
|
509 |
+
// with service markup
|
510 |
+
if ( $query->have_posts() ) {
|
511 |
+
|
512 |
+
/**
|
513 |
+
* Hook: ect_before_service_loop.
|
514 |
+
*
|
515 |
+
* @hooked
|
516 |
+
*/
|
517 |
+
$layout = ect_get_layout();
|
518 |
+
do_action( 'ect_before_service_loop', $layout[$atts['columns']] );
|
519 |
+
|
520 |
+
?>
|
521 |
+
<?php
|
522 |
+
while ( $query->have_posts() ) {
|
523 |
+
$query->the_post();
|
524 |
+
ect_get_template_part( 'content', 'service', $atts );
|
525 |
+
/**
|
526 |
+
* Hook: ect_service_loop.
|
527 |
+
*
|
528 |
+
* @hooked
|
529 |
+
*/
|
530 |
+
}
|
531 |
+
wp_reset_postdata();
|
532 |
+
?>
|
533 |
+
<?php
|
534 |
+
|
535 |
+
/**
|
536 |
+
* Hook: ect_after_service_loop.
|
537 |
+
*
|
538 |
+
* @hooked
|
539 |
+
*/
|
540 |
+
do_action( 'ect_after_service_loop' );
|
541 |
+
|
542 |
+
} else {
|
543 |
+
/**
|
544 |
+
* Hook: ect_no_service_found.
|
545 |
+
*
|
546 |
+
* @hooked ect_no_service_found
|
547 |
+
*/
|
548 |
+
do_action( 'ect_no_service_found' );
|
549 |
+
}
|
550 |
+
|
551 |
+
$html = ob_get_clean();
|
552 |
+
|
553 |
+
// If there is a [services] within a [services], remove the shortcode
|
554 |
+
if ( has_shortcode( $html, 'services' ) ){
|
555 |
+
remove_shortcode( 'services' );
|
556 |
+
}
|
557 |
+
|
558 |
+
// Return the HTML block
|
559 |
+
return $html;
|
560 |
+
}
|
561 |
+
|
562 |
+
/**
|
563 |
+
* Displays the content type that a content belongs to.
|
564 |
+
*
|
565 |
+
* @return html
|
566 |
+
*/
|
567 |
+
static function get_content_type( $post_id ) {
|
568 |
+
$content_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
|
569 |
+
|
570 |
+
// If no types, return empty string
|
571 |
+
if ( empty( $content_types ) || is_wp_error( $content_types ) ) {
|
572 |
+
return;
|
573 |
+
}
|
574 |
+
|
575 |
+
$html = '<div class="content-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
|
576 |
+
$types = array();
|
577 |
+
// Loop thorugh all the types
|
578 |
+
foreach ( $content_types as $content_type ) {
|
579 |
+
$content_type_link = get_term_link( $content_type, self::CUSTOM_TAXONOMY_TYPE );
|
580 |
+
|
581 |
+
if ( is_wp_error( $content_type_link ) ) {
|
582 |
+
return $content_type_link;
|
583 |
+
}
|
584 |
+
|
585 |
+
$types[] = '<a href="' . esc_url( $content_type_link ) . '" rel="tag">' . esc_html( $content_type->name ) . '</a>';
|
586 |
+
}
|
587 |
+
$html .= ' '.implode( ', ', $types );
|
588 |
+
$html .= '</div>';
|
589 |
+
|
590 |
+
return $html;
|
591 |
+
}
|
592 |
+
|
593 |
+
/**
|
594 |
+
* Displays the content tags that a content belongs to.
|
595 |
+
*
|
596 |
+
* @return html
|
597 |
+
*/
|
598 |
+
static function get_content_tags( $post_id ) {
|
599 |
+
$content_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
|
600 |
+
|
601 |
+
// If no tags, return empty string
|
602 |
+
if ( empty( $content_tags ) || is_wp_error( $content_tags ) ) {
|
603 |
+
return false;
|
604 |
+
}
|
605 |
+
|
606 |
+
$html = '<div class="content-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
|
607 |
+
$tags = array();
|
608 |
+
// Loop thorugh all the tags
|
609 |
+
foreach ( $content_tags as $content_tag ) {
|
610 |
+
$content_tag_link = get_term_link( $content_tag, self::CUSTOM_TAXONOMY_TYPE );
|
611 |
+
|
612 |
+
if ( is_wp_error( $content_tag_link ) ) {
|
613 |
+
return $content_tag_link;
|
614 |
+
}
|
615 |
+
|
616 |
+
$tags[] = '<a href="' . esc_url( $content_tag_link ) . '" rel="tag">' . esc_html( $content_tag->name ) . '</a>';
|
617 |
+
}
|
618 |
+
$html .= ' '. implode( ', ', $tags );
|
619 |
+
$html .= '</div>';
|
620 |
+
|
621 |
+
return $html;
|
622 |
+
}
|
623 |
+
|
624 |
+
/**
|
625 |
+
* Displays the author of the current service content.
|
626 |
+
*
|
627 |
+
* @return html
|
628 |
+
*/
|
629 |
+
static function get_content_author() {
|
630 |
+
$html = '<div class="content-author">';
|
631 |
+
/* translators: %1$s is link to author posts, %2$s is author display name */
|
632 |
+
$html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
|
633 |
+
esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
|
634 |
+
esc_html( get_the_author() )
|
635 |
+
);
|
636 |
+
$html .= '</div>';
|
637 |
+
|
638 |
+
return $html;
|
639 |
+
}
|
640 |
+
}
|
641 |
+
add_action( 'init', array( 'Essential_Content_Service', 'init' ) );
|
642 |
+
|
643 |
+
|
644 |
+
/**
|
645 |
+
* Add Service support
|
646 |
+
*/
|
647 |
+
function essential_content_service_support() {
|
648 |
+
/*
|
649 |
+
* Adding theme support for Jetpack Service CPT.
|
650 |
+
*/
|
651 |
+
add_image_size( 'ect-service', 640, 640, true );
|
652 |
+
}
|
653 |
+
add_action( 'after_setup_theme', 'essential_content_service_support' );
|
654 |
+
|
655 |
+
|
656 |
+
if( ! function_exists( 'essential_content_get_service_thumbnail_link' ) ):
|
657 |
+
function essential_content_get_service_thumbnail_link( $post_id, $size ) {
|
658 |
+
if ( has_post_thumbnail( $post_id ) ) {
|
659 |
+
/**
|
660 |
+
* Change the Service thumbnail size.
|
661 |
+
*
|
662 |
+
* @module custom-content-types
|
663 |
+
*
|
664 |
+
* @since 3.4.0
|
665 |
+
*
|
666 |
+
* @param string|array $var Either a registered size keyword or size array.
|
667 |
+
*/
|
668 |
+
return '<a class="service-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'service_thumbnail_size', $size ) ) . '</a>';
|
669 |
+
}
|
670 |
+
}
|
671 |
+
endif;
|
672 |
+
|
673 |
+
|
674 |
+
if( ! function_exists( 'essential_content_no_service_found' ) ):
|
675 |
+
/**
|
676 |
+
* No items found text
|
677 |
+
*
|
678 |
+
* @return html
|
679 |
+
*/
|
680 |
+
function essential_content_no_service_found() {
|
681 |
+
echo "<p><em>" . esc_html__( 'Your Service Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . "</em></p>";
|
682 |
+
}
|
683 |
+
add_action( 'ect_no_service_found', 'essential_content_no_service_found', 10 );
|
684 |
+
endif;
|
685 |
+
|
686 |
+
|
687 |
+
if( ! function_exists( 'essential_content_service_section_open' ) ):
|
688 |
+
/**
|
689 |
+
* Open section
|
690 |
+
*
|
691 |
+
* @return html
|
692 |
+
*/
|
693 |
+
function essential_content_service_section_open( $layout ) {
|
694 |
+
echo '<div class="ect-service ect-section">';
|
695 |
+
echo '<div class="ect-wrapper">';
|
696 |
+
}
|
697 |
+
endif;
|
698 |
+
add_action( 'ect_before_service_loop', 'essential_content_service_section_open', 10, 1 );
|
699 |
+
|
700 |
+
|
701 |
+
if( ! function_exists( 'essential_content_service_loop_start' ) ):
|
702 |
+
/**
|
703 |
+
* open wrapper before loop
|
704 |
+
*
|
705 |
+
*/
|
706 |
+
function essential_content_service_loop_start( $layout = null ){
|
707 |
+
echo '<div class="section-content-wrapper service-content-wrapper ' . $layout . '">';
|
708 |
+
}
|
709 |
+
endif;
|
710 |
+
add_action( 'ect_before_service_loop', 'essential_content_service_loop_start', 30 );
|
711 |
+
|
712 |
+
|
713 |
+
if( ! function_exists( 'essential_content_service_loop_end' ) ):
|
714 |
+
/**
|
715 |
+
* close wrapper after loop
|
716 |
+
*
|
717 |
+
*/
|
718 |
+
function essential_content_service_loop_end(){
|
719 |
+
echo '</div><!-- .service-content-wrapper -->';
|
720 |
+
}
|
721 |
+
endif;
|
722 |
+
add_action( 'ect_after_service_loop', 'essential_content_service_loop_end', 10 );
|
723 |
+
|
724 |
+
|
725 |
+
if( ! function_exists( 'essential_content_service_section_close' ) ):
|
726 |
+
/**
|
727 |
+
* Close section
|
728 |
+
*
|
729 |
+
* @return html
|
730 |
+
*/
|
731 |
+
function essential_content_service_section_close() {
|
732 |
+
echo '</div><!-- .ect-wrapper -->';
|
733 |
+
echo '</div><!-- .ect-section -->';
|
734 |
+
}
|
735 |
+
endif;
|
736 |
add_action( 'ect_after_service_loop', 'essential_content_service_section_close', 20 );
|
admin/class-testimonial.php
CHANGED
@@ -1,1075 +1,1075 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Support JetPack Testimonial
|
5 |
-
*/
|
6 |
-
class Essential_Content_Jetpack_Testimonial {
|
7 |
-
const CUSTOM_POST_TYPE = 'jetpack-testimonial';
|
8 |
-
const OPTION_NAME = 'jetpack_testimonial';
|
9 |
-
const OPTION_READING_SETTING = 'jetpack_testimonial_posts_per_page';
|
10 |
-
|
11 |
-
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
12 |
-
|
13 |
-
static function init() {
|
14 |
-
static $instance = false;
|
15 |
-
|
16 |
-
if ( ! $instance ) {
|
17 |
-
$instance = new Essential_Content_Jetpack_Testimonial;
|
18 |
-
}
|
19 |
-
|
20 |
-
return $instance;
|
21 |
-
}
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Conditionally hook into WordPress.
|
25 |
-
*
|
26 |
-
* Setup user option for enabling CPT.
|
27 |
-
* If user has CPT enabled, show in admin.
|
28 |
-
*/
|
29 |
-
function __construct() {
|
30 |
-
// Make sure the post types are loaded for imports
|
31 |
-
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
32 |
-
|
33 |
-
// If called via REST API, we need to register later in lifecycle
|
34 |
-
add_action( 'restapi_theme_init', array( $this, 'maybe_register_cpt' ) );
|
35 |
-
|
36 |
-
// Add to REST API post type whitelist
|
37 |
-
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_cpt_rest_api_type' ) );
|
38 |
-
|
39 |
-
$this->maybe_register_cpt();
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Registers the custom post types and adds action/filter handlers, but
|
44 |
-
* only if the site supports it
|
45 |
-
*/
|
46 |
-
function maybe_register_cpt() {
|
47 |
-
// Add an option to enable the CPT
|
48 |
-
add_action( 'admin_init', array( $this, 'settings_api_init' ) );
|
49 |
-
|
50 |
-
// Check on theme switch if theme supports CPT and setting is disabled
|
51 |
-
add_action( 'after_switch_theme', array( $this, 'activation_post_type_support' ) );
|
52 |
-
|
53 |
-
$setting = 1;
|
54 |
-
|
55 |
-
if ( class_exists( 'Jetpack_Options' ) ) {
|
56 |
-
$setting = Jetpack_Options::get_option_and_ensure_autoload( self::OPTION_NAME, '0' );
|
57 |
-
}
|
58 |
-
|
59 |
-
// Bail early if Testimonial option is not set and the theme doesn't declare support
|
60 |
-
if ( empty( $setting ) && ! $this->site_supports_custom_post_type() ) {
|
61 |
-
return;
|
62 |
-
}
|
63 |
-
|
64 |
-
// Enable Omnisearch for CPT.
|
65 |
-
if ( class_exists( 'Jetpack_Omnisearch_Posts' ) ) {
|
66 |
-
new Jetpack_Omnisearch_Posts( self::CUSTOM_POST_TYPE );
|
67 |
-
}
|
68 |
-
|
69 |
-
// CPT magic
|
70 |
-
$this->register_post_types();
|
71 |
-
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
72 |
-
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
73 |
-
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE ), array( $this, 'flush_rules_on_first_testimonial' ) );
|
74 |
-
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
75 |
-
|
76 |
-
// Admin Customization
|
77 |
-
add_filter( 'enter_title_here', array( $this, 'change_default_title' ) );
|
78 |
-
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE ), array( $this, 'edit_title_column_label' ) );
|
79 |
-
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
80 |
-
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
81 |
-
|
82 |
-
// Only add the 'Customize' sub-menu if the theme supports it.
|
83 |
-
$num_testimonials = self::count_testimonials();
|
84 |
-
if ( ! empty( $num_testimonials ) && current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
85 |
-
add_action( 'admin_menu', array( $this, 'add_customize_page' ) );
|
86 |
-
}
|
87 |
-
|
88 |
-
// Add to Jetpack XML sitemap
|
89 |
-
add_filter( 'jetpack_sitemap_post_types', array( $this, 'add_to_sitemap' ) );
|
90 |
-
|
91 |
-
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
92 |
-
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ), 20 );
|
93 |
-
add_filter( 'infinite_scroll_settings', array( $this, 'infinite_scroll_click_posts_per_page' ) );
|
94 |
-
|
95 |
-
// Register [jetpack_testimonials] always and
|
96 |
-
// register [testimonials] if [testimonials] isn't already set
|
97 |
-
add_shortcode( 'jetpack_testimonials', array( $this, 'jetpack_testimonial_shortcode' ) );
|
98 |
-
|
99 |
-
if ( ! shortcode_exists( 'testimonials' ) ) {
|
100 |
-
add_shortcode( 'testimonials', array( $this, 'jetpack_testimonial_shortcode' ) );
|
101 |
-
}
|
102 |
-
|
103 |
-
// If CPT was enabled programatically and no CPT items exist when user switches away, disable
|
104 |
-
if ( $setting && $this->site_supports_custom_post_type() ) {
|
105 |
-
add_action( 'switch_theme', array( $this, 'deactivation_post_type_support' ) );
|
106 |
-
}
|
107 |
-
}
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Add a checkbox field in 'Settings' > 'Writing'
|
111 |
-
* for enabling CPT functionality.
|
112 |
-
*
|
113 |
-
* @return null
|
114 |
-
*/
|
115 |
-
function settings_api_init() {
|
116 |
-
add_settings_field(
|
117 |
-
self::OPTION_NAME,
|
118 |
-
'<span class="cpt-options">' . __( 'Testimonials', 'essential-content-types' ) . '</span>',
|
119 |
-
array( $this, 'setting_html' ),
|
120 |
-
'writing',
|
121 |
-
'jetpack_cpt_section'
|
122 |
-
);
|
123 |
-
|
124 |
-
register_setting(
|
125 |
-
'writing',
|
126 |
-
self::OPTION_NAME,
|
127 |
-
'intval'
|
128 |
-
);
|
129 |
-
|
130 |
-
// Check if CPT is enabled first so that intval doesn't get set to NULL on re-registering
|
131 |
-
if ( $this->site_supports_custom_post_type() ) {
|
132 |
-
register_setting(
|
133 |
-
'writing',
|
134 |
-
self::OPTION_READING_SETTING,
|
135 |
-
'intval'
|
136 |
-
);
|
137 |
-
}
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* HTML code to display a checkbox true/false option
|
142 |
-
* for the CPT setting.
|
143 |
-
*
|
144 |
-
* @return html
|
145 |
-
*/
|
146 |
-
function setting_html() {
|
147 |
-
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) : ?>
|
148 |
-
<p><?php printf( __( 'Your theme supports Testimonials', 'essential-content-types' ) ); ?></p>
|
149 |
-
<?php else : ?>
|
150 |
-
<label for="<?php echo esc_attr( self::OPTION_NAME ); ?>">
|
151 |
-
<input name="<?php echo esc_attr( self::OPTION_NAME ); ?>" id="<?php echo esc_attr( self::OPTION_NAME ); ?>" <?php echo checked( get_option( self::OPTION_NAME, '0' ), true, false ); ?> type="checkbox" value="1" />
|
152 |
-
<?php esc_html_e( 'Enable Testimonials for this site.', 'essential-content-types' ); ?>
|
153 |
-
<a target="_blank" href="http://en.support.wordpress.com/testimonials/"><?php esc_html_e( 'Learn More', 'essential-content-types' ); ?></a>
|
154 |
-
</label>
|
155 |
-
<?php
|
156 |
-
endif;
|
157 |
-
|
158 |
-
if ( $this->site_supports_custom_post_type() ) :
|
159 |
-
printf(
|
160 |
-
'<p><label for="%1$s">%2$s</label></p>',
|
161 |
-
esc_attr( self::OPTION_READING_SETTING ),
|
162 |
-
/* translators: %1$s is replaced with an input field for numbers */
|
163 |
-
sprintf(
|
164 |
-
__( 'Testimonial pages display at most %1$s testimonials', 'essential-content-types' ),
|
165 |
-
sprintf(
|
166 |
-
'<input name="%1$s" id="%1$s" type="number" step="1" min="1" value="%2$s" class="small-text" />',
|
167 |
-
esc_attr( self::OPTION_READING_SETTING ),
|
168 |
-
esc_attr( get_option( self::OPTION_READING_SETTING, '10' ) )
|
169 |
-
)
|
170 |
-
)
|
171 |
-
);
|
172 |
-
endif;
|
173 |
-
}
|
174 |
-
|
175 |
-
/**
|
176 |
-
* Should this Custom Post Type be made available?
|
177 |
-
*/
|
178 |
-
function site_supports_custom_post_type() {
|
179 |
-
// If the current theme requests it.
|
180 |
-
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) || get_option( self::OPTION_NAME, '0' ) ) {
|
181 |
-
return true;
|
182 |
-
}
|
183 |
-
|
184 |
-
// Otherwise, say no unless something wants to filter us to say yes.
|
185 |
-
/** This action is documented in modules/custom-post-types/nova.php */
|
186 |
-
return (bool) apply_filters( 'jetpack_enable_cpt', false, self::CUSTOM_POST_TYPE );
|
187 |
-
}
|
188 |
-
|
189 |
-
/**
|
190 |
-
* Add to REST API post type whitelist
|
191 |
-
*/
|
192 |
-
function allow_cpt_rest_api_type( $post_types ) {
|
193 |
-
$post_types[] = self::CUSTOM_POST_TYPE;
|
194 |
-
|
195 |
-
return $post_types;
|
196 |
-
}
|
197 |
-
|
198 |
-
|
199 |
-
/*
|
200 |
-
* Flush permalinks when CPT option is turned on/off
|
201 |
-
*/
|
202 |
-
function flush_rules_on_enable() {
|
203 |
-
flush_rewrite_rules();
|
204 |
-
}
|
205 |
-
|
206 |
-
/*
|
207 |
-
* Count published testimonials and flush permalinks when first testimonial is published
|
208 |
-
*/
|
209 |
-
function flush_rules_on_first_testimonial() {
|
210 |
-
$testimonials = get_transient( 'jetpack-testimonial-count-cache' );
|
211 |
-
|
212 |
-
if ( false === $testimonials ) {
|
213 |
-
flush_rewrite_rules();
|
214 |
-
$testimonials = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
215 |
-
|
216 |
-
if ( ! empty( $testimonials ) ) {
|
217 |
-
set_transient( 'jetpack-testimonial-count-cache', $testimonials, HOUR_IN_SECONDS * 12 );
|
218 |
-
}
|
219 |
-
}
|
220 |
-
}
|
221 |
-
|
222 |
-
/*
|
223 |
-
* Flush permalinks when CPT supported theme is activated
|
224 |
-
*/
|
225 |
-
function flush_rules_on_switch() {
|
226 |
-
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
227 |
-
flush_rewrite_rules();
|
228 |
-
}
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* On plugin/theme activation, check if current theme supports CPT
|
233 |
-
*/
|
234 |
-
static function activation_post_type_support() {
|
235 |
-
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
236 |
-
update_option( self::OPTION_NAME, '1' );
|
237 |
-
}
|
238 |
-
}
|
239 |
-
|
240 |
-
/**
|
241 |
-
* On theme switch, check if CPT item exists and disable if not
|
242 |
-
*/
|
243 |
-
function deactivation_post_type_support() {
|
244 |
-
$testimonials = get_posts(
|
245 |
-
array(
|
246 |
-
'fields' => 'ids',
|
247 |
-
'posts_per_page' => 1,
|
248 |
-
'post_type' => self::CUSTOM_POST_TYPE,
|
249 |
-
'suppress_filters' => false,
|
250 |
-
)
|
251 |
-
);
|
252 |
-
|
253 |
-
if ( empty( $testimonials ) ) {
|
254 |
-
update_option( self::OPTION_NAME, '0' );
|
255 |
-
}
|
256 |
-
}
|
257 |
-
|
258 |
-
/**
|
259 |
-
* Register Post Type
|
260 |
-
*/
|
261 |
-
function register_post_types() {
|
262 |
-
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
263 |
-
return;
|
264 |
-
}
|
265 |
-
|
266 |
-
$args = array(
|
267 |
-
'description' => __( 'Customer Testimonials', 'essential-content-types' ),
|
268 |
-
'labels' => array(
|
269 |
-
'name' => esc_html__( 'Testimonials', 'essential-content-types' ),
|
270 |
-
'singular_name' => esc_html__( 'Testimonial', 'essential-content-types' ),
|
271 |
-
'menu_name' => esc_html__( 'Testimonials', 'essential-content-types' ),
|
272 |
-
'all_items' => esc_html__( 'All Testimonials', 'essential-content-types' ),
|
273 |
-
'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
|
274 |
-
'add_new_item' => esc_html__( 'Add New Testimonial', 'essential-content-types' ),
|
275 |
-
'edit_item' => esc_html__( 'Edit Testimonial', 'essential-content-types' ),
|
276 |
-
'new_item' => esc_html__( 'New Testimonial', 'essential-content-types' ),
|
277 |
-
'view_item' => esc_html__( 'View Testimonial', 'essential-content-types' ),
|
278 |
-
'search_items' => esc_html__( 'Search Testimonials', 'essential-content-types' ),
|
279 |
-
'not_found' => esc_html__( 'No Testimonials found', 'essential-content-types' ),
|
280 |
-
'not_found_in_trash' => esc_html__( 'No Testimonials found in Trash', 'essential-content-types' ),
|
281 |
-
'filter_items_list' => esc_html__( 'Filter Testimonials list', 'essential-content-types' ),
|
282 |
-
'items_list_navigation' => esc_html__( 'Testimonial list navigation', 'essential-content-types' ),
|
283 |
-
'items_list' => esc_html__( 'Testimonials list', 'essential-content-types' ),
|
284 |
-
),
|
285 |
-
'supports' => array(
|
286 |
-
'title',
|
287 |
-
'editor',
|
288 |
-
'excerpt',
|
289 |
-
'thumbnail',
|
290 |
-
'page-attributes',
|
291 |
-
'revisions',
|
292 |
-
),
|
293 |
-
'rewrite' => array(
|
294 |
-
'slug' => 'testimonial',
|
295 |
-
'with_front' => false,
|
296 |
-
'feeds' => false,
|
297 |
-
'pages' => true,
|
298 |
-
),
|
299 |
-
'public' => true,
|
300 |
-
'show_ui' => true,
|
301 |
-
'menu_position' => 20, // below Pages
|
302 |
-
'menu_icon' => 'dashicons-testimonial',
|
303 |
-
'capability_type' => 'page',
|
304 |
-
'map_meta_cap' => true,
|
305 |
-
'has_archive' => true,
|
306 |
-
'query_var' => 'testimonial',
|
307 |
-
'show_in_rest' => true,
|
308 |
-
);
|
309 |
-
|
310 |
-
$description = get_option( 'jetpack_testimonial_content' );
|
311 |
-
if ( '' !== $description ) {
|
312 |
-
$args['description'] = $description;
|
313 |
-
}
|
314 |
-
|
315 |
-
register_post_type( self::CUSTOM_POST_TYPE, $args );
|
316 |
-
}
|
317 |
-
|
318 |
-
/**
|
319 |
-
* Update messages for the Testimonial admin.
|
320 |
-
*/
|
321 |
-
function updated_messages( $messages ) {
|
322 |
-
global $post;
|
323 |
-
|
324 |
-
$messages[ self::CUSTOM_POST_TYPE ] = array(
|
325 |
-
0 => '', // Unused. Messages start at index 1.
|
326 |
-
1 => sprintf( __( 'Testimonial updated. <a href="%s">View testimonial</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
327 |
-
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
328 |
-
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
329 |
-
4 => esc_html__( 'Testimonial updated.', 'essential-content-types' ),
|
330 |
-
/* translators: %s: date and time of the revision */
|
331 |
-
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Testimonial restored to revision from %s', 'essential-content-types' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
332 |
-
6 => sprintf( __( 'Testimonial published. <a href="%s">View testimonial</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
333 |
-
7 => esc_html__( 'Testimonial saved.', 'essential-content-types' ),
|
334 |
-
8 => sprintf( __( 'Testimonial submitted. <a target="_blank" href="%s">Preview testimonial</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
335 |
-
9 => sprintf(
|
336 |
-
__( 'Testimonial scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview testimonial</a>', 'essential-content-types' ),
|
337 |
-
// translators: Publish box date format, see http://php.net/date
|
338 |
-
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ),
|
339 |
-
esc_url( get_permalink( $post->ID ) )
|
340 |
-
),
|
341 |
-
10 => sprintf( __( 'Testimonial draft updated. <a target="_blank" href="%s">Preview testimonial</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
342 |
-
);
|
343 |
-
|
344 |
-
return $messages;
|
345 |
-
}
|
346 |
-
|
347 |
-
/**
|
348 |
-
* Change ‘Enter Title Here’ text for the Testimonial.
|
349 |
-
*/
|
350 |
-
function change_default_title( $title ) {
|
351 |
-
$screen = get_current_screen();
|
352 |
-
|
353 |
-
if ( self::CUSTOM_POST_TYPE == $screen->post_type ) {
|
354 |
-
$title = esc_html__( "Enter the customer's name here", 'essential-content-types' );
|
355 |
-
}
|
356 |
-
|
357 |
-
return $title;
|
358 |
-
}
|
359 |
-
|
360 |
-
/**
|
361 |
-
* Change ‘Title’ column label on all Testimonials page.
|
362 |
-
*/
|
363 |
-
function edit_title_column_label( $columns ) {
|
364 |
-
$columns['title'] = esc_html__( 'Customer Name', 'essential-content-types' );
|
365 |
-
|
366 |
-
return $columns;
|
367 |
-
}
|
368 |
-
|
369 |
-
/**
|
370 |
-
* Follow CPT reading setting on CPT archive page
|
371 |
-
*/
|
372 |
-
function query_reading_setting( $query ) {
|
373 |
-
if ( ! is_admin()
|
374 |
-
&& $query->is_main_query()
|
375 |
-
&& $query->is_post_type_archive( self::CUSTOM_POST_TYPE )
|
376 |
-
) {
|
377 |
-
$post_per_page = ( null != get_option( 'posts_per_page' ) ) ? get_option( 'posts_per_page' ) : '10';
|
378 |
-
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
|
379 |
-
}
|
380 |
-
}
|
381 |
-
|
382 |
-
/*
|
383 |
-
* If Infinite Scroll is set to 'click', use our custom reading setting instead of core's `posts_per_page`.
|
384 |
-
*/
|
385 |
-
function infinite_scroll_click_posts_per_page( $settings ) {
|
386 |
-
global $wp_query;
|
387 |
-
|
388 |
-
if ( ! is_admin() && true === $settings['click_handle'] && $wp_query->is_post_type_archive( self::CUSTOM_POST_TYPE ) ) {
|
389 |
-
$settings['posts_per_page'] = get_option( self::OPTION_READING_SETTING, $settings['posts_per_page'] );
|
390 |
-
}
|
391 |
-
|
392 |
-
return $settings;
|
393 |
-
}
|
394 |
-
|
395 |
-
/**
|
396 |
-
* Add CPT to Dotcom sitemap
|
397 |
-
*/
|
398 |
-
function add_to_sitemap( $post_types ) {
|
399 |
-
$post_types[] = self::CUSTOM_POST_TYPE;
|
400 |
-
|
401 |
-
return $post_types;
|
402 |
-
}
|
403 |
-
|
404 |
-
function set_testimonial_option() {
|
405 |
-
$testimonials = wp_count_posts( self::CUSTOM_POST_TYPE );
|
406 |
-
$published_testimonials = $testimonials->publish;
|
407 |
-
|
408 |
-
update_option( self::OPTION_NAME, $published_testimonials );
|
409 |
-
}
|
410 |
-
|
411 |
-
function count_testimonials() {
|
412 |
-
$testimonials = get_transient( 'jetpack-testimonial-count-cache' );
|
413 |
-
|
414 |
-
if ( false === $testimonials ) {
|
415 |
-
$testimonials = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
416 |
-
|
417 |
-
if ( ! empty( $testimonials ) ) {
|
418 |
-
set_transient( 'jetpack-testimonial-count-cache', $testimonials, 60 * 60 * 12 );
|
419 |
-
}
|
420 |
-
}
|
421 |
-
|
422 |
-
return $testimonials;
|
423 |
-
}
|
424 |
-
|
425 |
-
/**
|
426 |
-
* Adds a submenu link to the Customizer.
|
427 |
-
*/
|
428 |
-
function add_customize_page() {
|
429 |
-
add_submenu_page(
|
430 |
-
'edit.php?post_type=' . self::CUSTOM_POST_TYPE,
|
431 |
-
esc_html__( 'Customize Testimonials Archive', 'essential-content-types' ),
|
432 |
-
esc_html__( 'Customize', 'essential-content-types' ),
|
433 |
-
'edit_theme_options',
|
434 |
-
add_query_arg(
|
435 |
-
array(
|
436 |
-
'url' => urlencode( home_url( '/testimonial/' ) ),
|
437 |
-
'autofocus[section]' => 'jetpack_testimonials',
|
438 |
-
),
|
439 |
-
'customize.php'
|
440 |
-
)
|
441 |
-
);
|
442 |
-
}
|
443 |
-
|
444 |
-
/**
|
445 |
-
* Adds testimonial section to the Customizer.
|
446 |
-
*/
|
447 |
-
function customize_register( $wp_customize ) {
|
448 |
-
essential_content_testimonial_custom_control_classes();
|
449 |
-
|
450 |
-
$wp_customize->add_panel(
|
451 |
-
'ect_plugin_options',
|
452 |
-
array(
|
453 |
-
'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
|
454 |
-
'priority' => 1,
|
455 |
-
)
|
456 |
-
);
|
457 |
-
|
458 |
-
$wp_customize->add_section(
|
459 |
-
'jetpack_testimonials',
|
460 |
-
array(
|
461 |
-
'title' => esc_html__( 'Testimonials', 'essential-content-types' ),
|
462 |
-
'theme_supports' => self::CUSTOM_POST_TYPE,
|
463 |
-
'priority' => 130,
|
464 |
-
'panel' => 'ect_plugin_options',
|
465 |
-
)
|
466 |
-
);
|
467 |
-
|
468 |
-
$wp_customize->add_setting(
|
469 |
-
'jetpack_testimonial_title',
|
470 |
-
array(
|
471 |
-
'default' => esc_html__( 'Testimonials', 'essential-content-types' ),
|
472 |
-
'type' => 'option',
|
473 |
-
'sanitize_callback' => 'sanitize_text_field',
|
474 |
-
'sanitize_js_callback' => 'sanitize_text_field',
|
475 |
-
)
|
476 |
-
);
|
477 |
-
$wp_customize->add_control(
|
478 |
-
'jetpack_testimonial_title',
|
479 |
-
array(
|
480 |
-
'section' => 'jetpack_testimonials',
|
481 |
-
'label' => esc_html__( 'Testimonial Archive Title', 'essential-content-types' ),
|
482 |
-
'type' => 'text',
|
483 |
-
)
|
484 |
-
);
|
485 |
-
|
486 |
-
$wp_customize->add_setting(
|
487 |
-
'jetpack_testimonial_content',
|
488 |
-
array(
|
489 |
-
'default' => '',
|
490 |
-
'type' => 'option',
|
491 |
-
'sanitize_callback' => 'wp_kses_post',
|
492 |
-
'sanitize_js_callback' => 'wp_kses_post',
|
493 |
-
)
|
494 |
-
);
|
495 |
-
$wp_customize->add_control(
|
496 |
-
new Essential_Content_Jetpack_Testimonial_Textarea_Control(
|
497 |
-
$wp_customize,
|
498 |
-
'jetpack_testimonial_content',
|
499 |
-
array(
|
500 |
-
'section' => 'jetpack_testimonials',
|
501 |
-
'label' => esc_html__( 'Testimonial Archive Content', 'essential-content-types' ),
|
502 |
-
'type' => 'textarea',
|
503 |
-
)
|
504 |
-
)
|
505 |
-
);
|
506 |
-
|
507 |
-
$wp_customize->add_setting(
|
508 |
-
'jetpack_testimonial_featured_image',
|
509 |
-
array(
|
510 |
-
'default' => '',
|
511 |
-
'type' => 'option',
|
512 |
-
'sanitize_callback' => 'attachment_url_to_postid',
|
513 |
-
'sanitize_js_callback' => 'attachment_url_to_postid',
|
514 |
-
'theme_supports' => 'post-thumbnails',
|
515 |
-
)
|
516 |
-
);
|
517 |
-
$wp_customize->add_control(
|
518 |
-
new WP_Customize_Image_Control(
|
519 |
-
$wp_customize,
|
520 |
-
'jetpack_testimonial_featured_image',
|
521 |
-
array(
|
522 |
-
'section' => 'jetpack_testimonials',
|
523 |
-
'label' => esc_html__( 'Testimonial Archive Featured Image', 'essential-content-types' ),
|
524 |
-
)
|
525 |
-
)
|
526 |
-
);
|
527 |
-
|
528 |
-
// The featured image control doesn't display properly in the Customizer unless we coerce
|
529 |
-
// it back into a URL sooner, since that's what WP_Customize_Upload_Control::to_json() expects
|
530 |
-
if ( is_admin() ) {
|
531 |
-
add_filter( 'theme_mod_jetpack_testimonials', array( $this, 'coerce_testimonial_image_to_url' ) );
|
532 |
-
}
|
533 |
-
}
|
534 |
-
|
535 |
-
public function coerce_testimonial_image_to_url( $opt ) {
|
536 |
-
if ( ! $opt || ! is_array( $opt ) ) {
|
537 |
-
return $opt;
|
538 |
-
}
|
539 |
-
if ( ! isset( $opt['featured-image'] ) || ! is_scalar( $opt['featured-image'] ) ) {
|
540 |
-
return $opt;
|
541 |
-
}
|
542 |
-
$url = wp_get_attachment_url( $opt['featured-image'] );
|
543 |
-
if ( $url ) {
|
544 |
-
$opt['featured-image'] = $url;
|
545 |
-
}
|
546 |
-
return $opt;
|
547 |
-
}
|
548 |
-
|
549 |
-
/**
|
550 |
-
* Our [testimonial] shortcode.
|
551 |
-
* Prints Testimonial data styled to look good on *any* theme.
|
552 |
-
*
|
553 |
-
* @return jetpack_testimonial_shortcode_html
|
554 |
-
*/
|
555 |
-
static function jetpack_testimonial_shortcode( $atts ) {
|
556 |
-
// Default attributes
|
557 |
-
$atts = shortcode_atts(
|
558 |
-
array(
|
559 |
-
'display_content' => true,
|
560 |
-
'image' => true,
|
561 |
-
'columns' => 1,
|
562 |
-
'showposts' => -1,
|
563 |
-
'order' => 'asc',
|
564 |
-
'orderby' => 'date',
|
565 |
-
),
|
566 |
-
$atts,
|
567 |
-
'testimonial'
|
568 |
-
);
|
569 |
-
|
570 |
-
// A little sanitization
|
571 |
-
if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
|
572 |
-
$atts['display_content'] = false;
|
573 |
-
}
|
574 |
-
|
575 |
-
if ( $atts['image'] && 'true' != $atts['image'] ) {
|
576 |
-
$atts['image'] = false;
|
577 |
-
}
|
578 |
-
|
579 |
-
// Check if column value is set to valid numbers or else set default value as 1
|
580 |
-
if ( 1 == $atts['columns'] || 2 == $atts['columns'] ) {
|
581 |
-
$atts['columns'] = absint( $atts['columns'] );
|
582 |
-
} else {
|
583 |
-
$atts['columns'] = 1;
|
584 |
-
}
|
585 |
-
|
586 |
-
$atts['showposts'] = intval( $atts['showposts'] );
|
587 |
-
|
588 |
-
if ( $atts['order'] ) {
|
589 |
-
$atts['order'] = urldecode( $atts['order'] );
|
590 |
-
$atts['order'] = strtoupper( $atts['order'] );
|
591 |
-
if ( 'DESC' != $atts['order'] ) {
|
592 |
-
$atts['order'] = 'ASC';
|
593 |
-
}
|
594 |
-
}
|
595 |
-
|
596 |
-
if ( $atts['orderby'] ) {
|
597 |
-
$atts['orderby'] = urldecode( $atts['orderby'] );
|
598 |
-
$atts['orderby'] = strtolower( $atts['orderby'] );
|
599 |
-
$allowed_keys = array( 'author', 'date', 'title', 'rand' );
|
600 |
-
|
601 |
-
$parsed = array();
|
602 |
-
foreach ( explode( ',', $atts['orderby'] ) as $testimonial_index_number => $orderby ) {
|
603 |
-
if ( ! in_array( $orderby, $allowed_keys ) ) {
|
604 |
-
continue;
|
605 |
-
}
|
606 |
-
$parsed[] = $orderby;
|
607 |
-
}
|
608 |
-
|
609 |
-
if ( empty( $parsed ) ) {
|
610 |
-
unset( $atts['orderby'] );
|
611 |
-
} else {
|
612 |
-
$atts['orderby'] = implode( ' ', $parsed );
|
613 |
-
}
|
614 |
-
}
|
615 |
-
|
616 |
-
// enqueue shortcode styles when shortcode is used
|
617 |
-
wp_enqueue_style( 'jetpack-testimonial-style', plugins_url( 'css/testimonial-shortcode.css', __FILE__ ), array(), '20140326' );
|
618 |
-
|
619 |
-
return self::jetpack_testimonial_shortcode_html( $atts );
|
620 |
-
}
|
621 |
-
|
622 |
-
/**
|
623 |
-
* The Testimonial shortcode loop.
|
624 |
-
*
|
625 |
-
* @todo add theme color styles
|
626 |
-
* @return html
|
627 |
-
*/
|
628 |
-
|
629 |
-
static function jetpack_testimonial_shortcode_html( $atts ) {
|
630 |
-
|
631 |
-
// Default query arguments
|
632 |
-
$defaults = array(
|
633 |
-
'order' => $atts['order'],
|
634 |
-
'orderby' => $atts['orderby'],
|
635 |
-
'posts_per_page' => $atts['showposts'],
|
636 |
-
);
|
637 |
-
|
638 |
-
$args = wp_parse_args( $atts, $defaults );
|
639 |
-
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
640 |
-
$query = new WP_Query( $args );
|
641 |
-
|
642 |
-
ob_start();
|
643 |
-
|
644 |
-
// If we have posts, create the html
|
645 |
-
// with testimonial markup
|
646 |
-
if ( $query->have_posts() ) {
|
647 |
-
|
648 |
-
/**
|
649 |
-
* Hook: ect_before_testimonial_loop.
|
650 |
-
*
|
651 |
-
* @hooked
|
652 |
-
*/
|
653 |
-
$layout = ect_get_layout();
|
654 |
-
do_action( 'ect_before_testimonial_loop', $layout[ $atts['columns'] ] );
|
655 |
-
?>
|
656 |
-
<?php
|
657 |
-
while ( $query->have_posts() ) {
|
658 |
-
|
659 |
-
$query->the_post();
|
660 |
-
ect_get_template_part( 'content', 'testimonial', $atts );
|
661 |
-
|
662 |
-
}
|
663 |
-
wp_reset_postdata();
|
664 |
-
?>
|
665 |
-
<?php
|
666 |
-
|
667 |
-
/**
|
668 |
-
* Hook: ect_after_testimonial_loop.
|
669 |
-
*
|
670 |
-
* @hooked
|
671 |
-
*/
|
672 |
-
do_action( 'ect_after_testimonial_loop' );
|
673 |
-
|
674 |
-
} else {
|
675 |
-
/**
|
676 |
-
* Hook: ect_no_testimonial_found.
|
677 |
-
*
|
678 |
-
* @hooked ect_no_testimonial_found
|
679 |
-
*/
|
680 |
-
do_action( 'ect_no_testimonial_found' );
|
681 |
-
}
|
682 |
-
|
683 |
-
$html = ob_get_clean();
|
684 |
-
|
685 |
-
// If there is a [testimonials] within a [testimonials], remove the shortcode
|
686 |
-
if ( has_shortcode( $html, 'testimonials' ) ) {
|
687 |
-
remove_shortcode( 'testimonials' );
|
688 |
-
}
|
689 |
-
|
690 |
-
// Return the HTML block
|
691 |
-
return $html;
|
692 |
-
}
|
693 |
-
}
|
694 |
-
add_action( 'init', array( 'Essential_Content_Jetpack_Testimonial', 'init' ) );
|
695 |
-
|
696 |
-
|
697 |
-
function essential_content_testimonial_custom_control_classes() {
|
698 |
-
class Essential_Content_Jetpack_Testimonial_Title_Control extends WP_Customize_Control {
|
699 |
-
public static function sanitize_content( $value ) {
|
700 |
-
if ( '' != $value ) {
|
701 |
-
$value = trim( convert_chars( wptexturize( $value ) ) );
|
702 |
-
}
|
703 |
-
|
704 |
-
return $value;
|
705 |
-
}
|
706 |
-
}
|
707 |
-
|
708 |
-
class Essential_Content_Jetpack_Testimonial_Textarea_Control extends WP_Customize_Control {
|
709 |
-
public $type = 'textarea';
|
710 |
-
|
711 |
-
public function render_content() {
|
712 |
-
?>
|
713 |
-
<label>
|
714 |
-
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
|
715 |
-
<textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
|
716 |
-
</label>
|
717 |
-
<?php
|
718 |
-
}
|
719 |
-
|
720 |
-
public static function sanitize_content( $value ) {
|
721 |
-
if ( ! empty( $value ) ) {
|
722 |
-
/** This filter is already documented in core. wp-includes/post-template.php */
|
723 |
-
$value = apply_filters( 'the_content', $value );
|
724 |
-
}
|
725 |
-
|
726 |
-
$value = preg_replace( '@<div id="jp-post-flair"([^>]+)?>(.+)?</div>@is', '', $value ); // Strip WPCOM and Jetpack post flair if included in content
|
727 |
-
|
728 |
-
return $value;
|
729 |
-
}
|
730 |
-
}
|
731 |
-
}
|
732 |
-
|
733 |
-
/**
|
734 |
-
* Add Testimonial support
|
735 |
-
*/
|
736 |
-
function essential_content_testimonial_support() {
|
737 |
-
/*
|
738 |
-
* Adding theme support for Jetpack Testimonial CPT.
|
739 |
-
*/
|
740 |
-
add_theme_support( 'jetpack-testimonial' );
|
741 |
-
}
|
742 |
-
add_action( 'after_setup_theme', 'essential_content_testimonial_support' );
|
743 |
-
|
744 |
-
|
745 |
-
/**
|
746 |
-
* Class to Renders and save metabox options
|
747 |
-
*
|
748 |
-
*/
|
749 |
-
class Essential_Content_Jetpack_Testimonial_Metabox {
|
750 |
-
private $meta_box;
|
751 |
-
|
752 |
-
private $fields;
|
753 |
-
|
754 |
-
/**
|
755 |
-
* Constructor
|
756 |
-
*
|
757 |
-
*
|
758 |
-
* @access public
|
759 |
-
*
|
760 |
-
*/
|
761 |
-
public function __construct( $meta_box_id, $meta_box_title, $post_type ) {
|
762 |
-
|
763 |
-
$this->meta_box = array(
|
764 |
-
'id' => $meta_box_id,
|
765 |
-
'title' => $meta_box_title,
|
766 |
-
'post_type' => $post_type,
|
767 |
-
);
|
768 |
-
|
769 |
-
$this->fields = array(
|
770 |
-
'ect-testimonials',
|
771 |
-
);
|
772 |
-
|
773 |
-
// Add metaboxes
|
774 |
-
add_action( 'add_meta_boxes', array( $this, 'add' ) );
|
775 |
-
|
776 |
-
add_action( 'save_post', array( $this, 'save' ) );
|
777 |
-
}
|
778 |
-
|
779 |
-
/**
|
780 |
-
* Add Meta Box for multiple post types.
|
781 |
-
*
|
782 |
-
*
|
783 |
-
* @access public
|
784 |
-
*/
|
785 |
-
public function add( $postType ) {
|
786 |
-
if ( in_array( $postType, $this->meta_box['post_type'] ) ) {
|
787 |
-
add_meta_box( $this->meta_box['id'], $this->meta_box['title'], array( $this, 'show' ), null, 'side', 'high' );
|
788 |
-
}
|
789 |
-
}
|
790 |
-
|
791 |
-
/**
|
792 |
-
* Renders metabox
|
793 |
-
*
|
794 |
-
*
|
795 |
-
* @access public
|
796 |
-
*/
|
797 |
-
public function show() {
|
798 |
-
global $post;
|
799 |
-
|
800 |
-
// Use nonce for verification
|
801 |
-
wp_nonce_field( basename( __FILE__ ), 'ect_custom_meta_box_nonce' );
|
802 |
-
|
803 |
-
$position = get_post_meta( $post->ID, 'ect_testimonial_position', true );
|
804 |
-
|
805 |
-
// Begin the form
|
806 |
-
?>
|
807 |
-
<p>
|
808 |
-
<label for="ect_testimonial_position"><?php esc_html_e( 'Position', 'essential-content-types' ); ?></label>
|
809 |
-
<input type="text" class="widefat ect-testimonial-position" name="ect_testimonial_position" value="<?php echo esc_attr( $position ); ?>" />
|
810 |
-
</p>
|
811 |
-
<?php
|
812 |
-
}
|
813 |
-
|
814 |
-
/**
|
815 |
-
* Save custom metabox data
|
816 |
-
*
|
817 |
-
* @action save_post
|
818 |
-
*
|
819 |
-
* @access public
|
820 |
-
*/
|
821 |
-
public function save( $post_id ) {
|
822 |
-
global $post_type;
|
823 |
-
|
824 |
-
$post_type_object = get_post_type_object( $post_type );
|
825 |
-
|
826 |
-
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) // Check Autosave
|
827 |
-
|| ( ! isset( $_POST['post_ID'] ) || $post_id != $_POST['post_ID'] ) // Check Revision
|
828 |
-
|| ( ! in_array( $post_type, $this->meta_box['post_type'] ) ) // Check if current post type is supported.
|
829 |
-
|| ( ! check_admin_referer( basename( __FILE__ ), 'ect_custom_meta_box_nonce' ) ) // Check nonce - Security
|
830 |
-
|| ( ! current_user_can( $post_type_object->cap->edit_post, $post_id ) ) ) { // Check permission
|
831 |
-
return $post_id;
|
832 |
-
}
|
833 |
-
|
834 |
-
if ( ! update_post_meta( $post_id, 'ect_testimonial_position', sanitize_text_field( $_POST['ect_testimonial_position'] ) ) ) {
|
835 |
-
add_post_meta( $post_id, 'ect_testimonial_position', sanitize_text_field( $_POST['ect_testimonial_position'] ), true );
|
836 |
-
}
|
837 |
-
}
|
838 |
-
}
|
839 |
-
|
840 |
-
$ect_metabox = new Essential_Content_Jetpack_Testimonial_Metabox(
|
841 |
-
'ect-options', //metabox id
|
842 |
-
esc_html__( 'Testmonial Options', 'essential-content-types' ), //metabox title
|
843 |
-
array( 'jetpack-testimonial' ) //metabox post types
|
844 |
-
);
|
845 |
-
|
846 |
-
|
847 |
-
if ( ! function_exists( 'essential_content_get_testimonial_thumbnail_link' ) ) :
|
848 |
-
/**
|
849 |
-
* Display the featured image if it's available
|
850 |
-
*
|
851 |
-
* @return html
|
852 |
-
*/
|
853 |
-
function essential_content_get_testimonial_thumbnail_link( $post_id, $size ) {
|
854 |
-
if ( has_post_thumbnail( $post_id ) ) {
|
855 |
-
/**
|
856 |
-
* Change the Testimonial thumbnail size.
|
857 |
-
*
|
858 |
-
* @module custom-content-types
|
859 |
-
*
|
860 |
-
* @since 3.4.0
|
861 |
-
*
|
862 |
-
* @param string|array $var Either a registered size keyword or size array.
|
863 |
-
*/
|
864 |
-
//return '<a class="testimonial-featured-image testimonial-thumbnail post-thumbnail" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'testimonial_thumbnail_size', $size ) ) . '</a>';
|
865 |
-
return '<div class="testimonial-featured-image testimonial-thumbnail post-thumbnail">' . get_the_post_thumbnail( $post_id, apply_filters( 'testimonial_thumbnail_size', $size ) ) . '</div>';
|
866 |
-
}
|
867 |
-
}
|
868 |
-
endif;
|
869 |
-
|
870 |
-
|
871 |
-
if ( ! function_exists( 'essential_content_no_testimonial_found' ) ) :
|
872 |
-
/**
|
873 |
-
* No items found text
|
874 |
-
*
|
875 |
-
* @return html
|
876 |
-
*/
|
877 |
-
function essential_content_no_testimonial_found() {
|
878 |
-
echo '<p><em>' . esc_html__( 'Your Testimonial Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . '</em></p>';
|
879 |
-
}
|
880 |
-
add_action( 'ect_no_testimonial_found', 'essential_content_no_testimonial_found', 10 );
|
881 |
-
endif;
|
882 |
-
|
883 |
-
|
884 |
-
if ( ! function_exists( 'essential_content_testimonial_section_open' ) ) :
|
885 |
-
/**
|
886 |
-
* Open section
|
887 |
-
*
|
888 |
-
* @return html
|
889 |
-
*/
|
890 |
-
function essential_content_testimonial_section_open( $layout = null ) {
|
891 |
-
echo '<div class="ect-testimonial-content-section ect-section ' . $layout . '">';
|
892 |
-
echo '<div class="ect-wrapper">';
|
893 |
-
}
|
894 |
-
endif;
|
895 |
-
add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_section_open', 10, 1 );
|
896 |
-
|
897 |
-
|
898 |
-
if ( ! function_exists( 'essential_content_testimonial_loop_start' ) ) :
|
899 |
-
/**
|
900 |
-
* open wrapper before loop
|
901 |
-
*
|
902 |
-
*/
|
903 |
-
function essential_content_testimonial_loop_start( $layout = null ) {
|
904 |
-
echo '<div class="section-content-wrapper testimonial-content-wrapper">';
|
905 |
-
}
|
906 |
-
endif;
|
907 |
-
add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_loop_start', 30 );
|
908 |
-
|
909 |
-
|
910 |
-
if ( ! function_exists( 'essential_content_testimonial_slider_open' ) ) :
|
911 |
-
function essential_content_testimonial_slider_open() {
|
912 |
-
?>
|
913 |
-
<div class="cycle-slideshow"
|
914 |
-
data-cycle-log="false"
|
915 |
-
data-cycle-pause-on-hover="true"
|
916 |
-
data-cycle-swipe="true"
|
917 |
-
data-cycle-auto-height=container
|
918 |
-
data-cycle-loader=false
|
919 |
-
data-cycle-slides=".testimonial_slider_wrap"
|
920 |
-
data-cycle-pager=".testimonial-slider-pager"
|
921 |
-
data-cycle-prev=".testimonial-slider-prev"
|
922 |
-
data-cycle-next=".testimonial-slider-next"
|
923 |
-
>
|
924 |
-
|
925 |
-
<div class="controller">
|
926 |
-
<!-- prev/next links -->
|
927 |
-
<button class="cycle-prev testimonial-slider-prev" aria-label="Previous">
|
928 |
-
<span class="screen-reader-text"><?php esc_html_e( 'Previous Slide', 'essential-content-types-pro' ); ?></span><?php echo essential_content_get_svg( array( 'icon' => 'angle-down' ) ); ?>
|
929 |
-
</button>
|
930 |
-
|
931 |
-
<!-- empty element for pager links -->
|
932 |
-
<div class="cycle-pager testimonial-slider-pager"></div>
|
933 |
-
|
934 |
-
<button class="cycle-next testimonial-slider-next" aria-label="Next">
|
935 |
-
<span class="screen-reader-text"><?php esc_html_e( 'Next Slide', 'essential-content-types-pro' ); ?></span><?php echo essential_content_get_svg( array( 'icon' => 'angle-down' ) ); ?>
|
936 |
-
</button>
|
937 |
-
</div><!-- .controller -->
|
938 |
-
|
939 |
-
<div class="testimonial_slider_wrap">
|
940 |
-
|
941 |
-
<?php
|
942 |
-
}
|
943 |
-
endif;
|
944 |
-
//add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_slider_open', 40 );
|
945 |
-
|
946 |
-
|
947 |
-
if ( ! function_exists( 'essential_content_testimonial_slider_close' ) ) :
|
948 |
-
function essential_content_testimonial_slider_close() {
|
949 |
-
echo '</div><!-- .testimonial_slider_wrap -->';
|
950 |
-
echo '</div><!-- .cycle-slideshow -->';
|
951 |
-
}
|
952 |
-
endif;
|
953 |
-
//add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_slider_close', 10 );
|
954 |
-
|
955 |
-
|
956 |
-
if ( ! function_exists( 'essential_content_testimonial_loop_end' ) ) :
|
957 |
-
/**
|
958 |
-
* close wrapper after loop
|
959 |
-
*
|
960 |
-
*/
|
961 |
-
function essential_content_testimonial_loop_end() {
|
962 |
-
echo '</div><!-- .testimonial-content-wrapper -->';
|
963 |
-
}
|
964 |
-
endif;
|
965 |
-
add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_loop_end', 20 );
|
966 |
-
|
967 |
-
|
968 |
-
if ( ! function_exists( 'essential_content_testimonial_section_close' ) ) :
|
969 |
-
/**
|
970 |
-
* Close section
|
971 |
-
*
|
972 |
-
* @return html
|
973 |
-
*/
|
974 |
-
function essential_content_testimonial_section_close() {
|
975 |
-
echo '</div><!-- .ect-wrapper -->';
|
976 |
-
echo '</div><!-- .ect-section -->';
|
977 |
-
}
|
978 |
-
endif;
|
979 |
-
add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_section_close', 30 );
|
980 |
-
|
981 |
-
|
982 |
-
if ( ! function_exists( 'essential_content_get_svg' ) ) :
|
983 |
-
/**
|
984 |
-
* Return SVG markup.
|
985 |
-
*
|
986 |
-
* @param array $args {
|
987 |
-
* Parameters needed to display an SVG.
|
988 |
-
*
|
989 |
-
* @type string $icon Required SVG icon filename.
|
990 |
-
* @type string $title Optional SVG title.
|
991 |
-
* @type string $desc Optional SVG description.
|
992 |
-
* }
|
993 |
-
* @return string SVG markup.
|
994 |
-
*/
|
995 |
-
function essential_content_get_svg( $args = array() ) {
|
996 |
-
// Make sure $args are an array.
|
997 |
-
if ( empty( $args ) ) {
|
998 |
-
return __( 'Please define default parameters in the form of an array.', 'starter-pro' );
|
999 |
-
}
|
1000 |
-
|
1001 |
-
// Define an icon.
|
1002 |
-
if ( false === array_key_exists( 'icon', $args ) ) {
|
1003 |
-
return __( 'Please define an SVG icon filename.', 'starter-pro' );
|
1004 |
-
}
|
1005 |
-
|
1006 |
-
// Set defaults.
|
1007 |
-
$defaults = array(
|
1008 |
-
'icon' => '',
|
1009 |
-
'title' => '',
|
1010 |
-
'desc' => '',
|
1011 |
-
'fallback' => false,
|
1012 |
-
);
|
1013 |
-
|
1014 |
-
// Parse args.
|
1015 |
-
$args = wp_parse_args( $args, $defaults );
|
1016 |
-
|
1017 |
-
// Set aria hidden.
|
1018 |
-
$aria_hidden = ' aria-hidden="true"';
|
1019 |
-
|
1020 |
-
// Set ARIA.
|
1021 |
-
$aria_labelledby = '';
|
1022 |
-
|
1023 |
-
/*
|
1024 |
-
* Starter doesn't use the SVG title or description attributes; non-decorative icons are described with .screen-reader-text.
|
1025 |
-
*
|
1026 |
-
* However, child themes can use the title and description to add information to non-decorative SVG icons to improve accessibility.
|
1027 |
-
*
|
1028 |
-
* Example 1 with title: <?php echo starter_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ) ) ); ?>
|
1029 |
-
*
|
1030 |
-
* Example 2 with title and description: <?php echo starter_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ), 'desc' => __( 'This is the description', 'textdomain' ) ) ); ?>
|
1031 |
-
*
|
1032 |
-
* See https://www.paciellogroup.com/blog/2013/12/using-aria-enhance-svg-accessibility/.
|
1033 |
-
*/
|
1034 |
-
if ( $args['title'] ) {
|
1035 |
-
$aria_hidden = '';
|
1036 |
-
$unique_id = uniqid();
|
1037 |
-
$aria_labelledby = ' aria-labelledby="title-' . $unique_id . '"';
|
1038 |
-
|
1039 |
-
if ( $args['desc'] ) {
|
1040 |
-
$aria_labelledby = ' aria-labelledby="title-' . $unique_id . ' desc-' . $unique_id . '"';
|
1041 |
-
}
|
1042 |
-
}
|
1043 |
-
|
1044 |
-
// Begin SVG markup.
|
1045 |
-
$svg = '<svg class="icon icon-' . esc_attr( $args['icon'] ) . '"' . $aria_hidden . $aria_labelledby . ' role="img">';
|
1046 |
-
|
1047 |
-
// Display the title.
|
1048 |
-
if ( $args['title'] ) {
|
1049 |
-
$svg .= '<title id="title-' . $unique_id . '">' . esc_html( $args['title'] ) . '</title>';
|
1050 |
-
|
1051 |
-
// Display the desc only if the title is already set.
|
1052 |
-
if ( $args['desc'] ) {
|
1053 |
-
$svg .= '<desc id="desc-' . $unique_id . '">' . esc_html( $args['desc'] ) . '</desc>';
|
1054 |
-
}
|
1055 |
-
}
|
1056 |
-
|
1057 |
-
/*
|
1058 |
-
* Display the icon.
|
1059 |
-
*
|
1060 |
-
* The whitespace around `<use>` is intentional - it is a work around to a keyboard navigation bug in Safari 10.
|
1061 |
-
*
|
1062 |
-
* See https://core.trac.wordpress.org/ticket/38387.
|
1063 |
-
*/
|
1064 |
-
$svg .= ' <use href="#icon-' . esc_html( $args['icon'] ) . '" xlink:href="#icon-' . esc_html( $args['icon'] ) . '"></use> ';
|
1065 |
-
|
1066 |
-
// Add some markup to use as a fallback for browsers that do not support SVGs.
|
1067 |
-
if ( $args['fallback'] ) {
|
1068 |
-
$svg .= '<span class="svg-fallback icon-' . esc_attr( $args['icon'] ) . '"></span>';
|
1069 |
-
}
|
1070 |
-
|
1071 |
-
$svg .= '</svg>';
|
1072 |
-
|
1073 |
-
return $svg;
|
1074 |
-
}
|
1075 |
-
endif;
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Support JetPack Testimonial
|
5 |
+
*/
|
6 |
+
class Essential_Content_Jetpack_Testimonial {
|
7 |
+
const CUSTOM_POST_TYPE = 'jetpack-testimonial';
|
8 |
+
const OPTION_NAME = 'jetpack_testimonial';
|
9 |
+
const OPTION_READING_SETTING = 'jetpack_testimonial_posts_per_page';
|
10 |
+
|
11 |
+
public $version = ESSENTIAL_CONTENT_TYPES_VERSION;
|
12 |
+
|
13 |
+
static function init() {
|
14 |
+
static $instance = false;
|
15 |
+
|
16 |
+
if ( ! $instance ) {
|
17 |
+
$instance = new Essential_Content_Jetpack_Testimonial;
|
18 |
+
}
|
19 |
+
|
20 |
+
return $instance;
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Conditionally hook into WordPress.
|
25 |
+
*
|
26 |
+
* Setup user option for enabling CPT.
|
27 |
+
* If user has CPT enabled, show in admin.
|
28 |
+
*/
|
29 |
+
function __construct() {
|
30 |
+
// Make sure the post types are loaded for imports
|
31 |
+
add_action( 'import_start', array( $this, 'register_post_types' ) );
|
32 |
+
|
33 |
+
// If called via REST API, we need to register later in lifecycle
|
34 |
+
add_action( 'restapi_theme_init', array( $this, 'maybe_register_cpt' ) );
|
35 |
+
|
36 |
+
// Add to REST API post type whitelist
|
37 |
+
add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_cpt_rest_api_type' ) );
|
38 |
+
|
39 |
+
$this->maybe_register_cpt();
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Registers the custom post types and adds action/filter handlers, but
|
44 |
+
* only if the site supports it
|
45 |
+
*/
|
46 |
+
function maybe_register_cpt() {
|
47 |
+
// Add an option to enable the CPT
|
48 |
+
add_action( 'admin_init', array( $this, 'settings_api_init' ) );
|
49 |
+
|
50 |
+
// Check on theme switch if theme supports CPT and setting is disabled
|
51 |
+
add_action( 'after_switch_theme', array( $this, 'activation_post_type_support' ) );
|
52 |
+
|
53 |
+
$setting = 1;
|
54 |
+
|
55 |
+
if ( class_exists( 'Jetpack_Options' ) ) {
|
56 |
+
$setting = Jetpack_Options::get_option_and_ensure_autoload( self::OPTION_NAME, '0' );
|
57 |
+
}
|
58 |
+
|
59 |
+
// Bail early if Testimonial option is not set and the theme doesn't declare support
|
60 |
+
if ( empty( $setting ) && ! $this->site_supports_custom_post_type() ) {
|
61 |
+
return;
|
62 |
+
}
|
63 |
+
|
64 |
+
// Enable Omnisearch for CPT.
|
65 |
+
if ( class_exists( 'Jetpack_Omnisearch_Posts' ) ) {
|
66 |
+
new Jetpack_Omnisearch_Posts( self::CUSTOM_POST_TYPE );
|
67 |
+
}
|
68 |
+
|
69 |
+
// CPT magic
|
70 |
+
$this->register_post_types();
|
71 |
+
add_action( sprintf( 'add_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
72 |
+
add_action( sprintf( 'update_option_%s', self::OPTION_NAME ), array( $this, 'flush_rules_on_enable' ), 10 );
|
73 |
+
add_action( sprintf( 'publish_%s', self::CUSTOM_POST_TYPE ), array( $this, 'flush_rules_on_first_testimonial' ) );
|
74 |
+
add_action( 'after_switch_theme', array( $this, 'flush_rules_on_switch' ) );
|
75 |
+
|
76 |
+
// Admin Customization
|
77 |
+
add_filter( 'enter_title_here', array( $this, 'change_default_title' ) );
|
78 |
+
add_filter( sprintf( 'manage_%s_posts_columns', self::CUSTOM_POST_TYPE ), array( $this, 'edit_title_column_label' ) );
|
79 |
+
add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
|
80 |
+
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
81 |
+
|
82 |
+
// Only add the 'Customize' sub-menu if the theme supports it.
|
83 |
+
$num_testimonials = self::count_testimonials();
|
84 |
+
if ( ! empty( $num_testimonials ) && current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
85 |
+
add_action( 'admin_menu', array( $this, 'add_customize_page' ) );
|
86 |
+
}
|
87 |
+
|
88 |
+
// Add to Jetpack XML sitemap
|
89 |
+
add_filter( 'jetpack_sitemap_post_types', array( $this, 'add_to_sitemap' ) );
|
90 |
+
|
91 |
+
// Adjust CPT archive and custom taxonomies to obey CPT reading setting
|
92 |
+
add_filter( 'pre_get_posts', array( $this, 'query_reading_setting' ), 20 );
|
93 |
+
add_filter( 'infinite_scroll_settings', array( $this, 'infinite_scroll_click_posts_per_page' ) );
|
94 |
+
|
95 |
+
// Register [jetpack_testimonials] always and
|
96 |
+
// register [testimonials] if [testimonials] isn't already set
|
97 |
+
add_shortcode( 'jetpack_testimonials', array( $this, 'jetpack_testimonial_shortcode' ) );
|
98 |
+
|
99 |
+
if ( ! shortcode_exists( 'testimonials' ) ) {
|
100 |
+
add_shortcode( 'testimonials', array( $this, 'jetpack_testimonial_shortcode' ) );
|
101 |
+
}
|
102 |
+
|
103 |
+
// If CPT was enabled programatically and no CPT items exist when user switches away, disable
|
104 |
+
if ( $setting && $this->site_supports_custom_post_type() ) {
|
105 |
+
add_action( 'switch_theme', array( $this, 'deactivation_post_type_support' ) );
|
106 |
+
}
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Add a checkbox field in 'Settings' > 'Writing'
|
111 |
+
* for enabling CPT functionality.
|
112 |
+
*
|
113 |
+
* @return null
|
114 |
+
*/
|
115 |
+
function settings_api_init() {
|
116 |
+
add_settings_field(
|
117 |
+
self::OPTION_NAME,
|
118 |
+
'<span class="cpt-options">' . __( 'Testimonials', 'essential-content-types' ) . '</span>',
|
119 |
+
array( $this, 'setting_html' ),
|
120 |
+
'writing',
|
121 |
+
'jetpack_cpt_section'
|
122 |
+
);
|
123 |
+
|
124 |
+
register_setting(
|
125 |
+
'writing',
|
126 |
+
self::OPTION_NAME,
|
127 |
+
'intval'
|
128 |
+
);
|
129 |
+
|
130 |
+
// Check if CPT is enabled first so that intval doesn't get set to NULL on re-registering
|
131 |
+
if ( $this->site_supports_custom_post_type() ) {
|
132 |
+
register_setting(
|
133 |
+
'writing',
|
134 |
+
self::OPTION_READING_SETTING,
|
135 |
+
'intval'
|
136 |
+
);
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* HTML code to display a checkbox true/false option
|
142 |
+
* for the CPT setting.
|
143 |
+
*
|
144 |
+
* @return html
|
145 |
+
*/
|
146 |
+
function setting_html() {
|
147 |
+
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) : ?>
|
148 |
+
<p><?php printf( __( 'Your theme supports Testimonials', 'essential-content-types' ) ); ?></p>
|
149 |
+
<?php else : ?>
|
150 |
+
<label for="<?php echo esc_attr( self::OPTION_NAME ); ?>">
|
151 |
+
<input name="<?php echo esc_attr( self::OPTION_NAME ); ?>" id="<?php echo esc_attr( self::OPTION_NAME ); ?>" <?php echo checked( get_option( self::OPTION_NAME, '0' ), true, false ); ?> type="checkbox" value="1" />
|
152 |
+
<?php esc_html_e( 'Enable Testimonials for this site.', 'essential-content-types' ); ?>
|
153 |
+
<a target="_blank" href="http://en.support.wordpress.com/testimonials/"><?php esc_html_e( 'Learn More', 'essential-content-types' ); ?></a>
|
154 |
+
</label>
|
155 |
+
<?php
|
156 |
+
endif;
|
157 |
+
|
158 |
+
if ( $this->site_supports_custom_post_type() ) :
|
159 |
+
printf(
|
160 |
+
'<p><label for="%1$s">%2$s</label></p>',
|
161 |
+
esc_attr( self::OPTION_READING_SETTING ),
|
162 |
+
/* translators: %1$s is replaced with an input field for numbers */
|
163 |
+
sprintf(
|
164 |
+
__( 'Testimonial pages display at most %1$s testimonials', 'essential-content-types' ),
|
165 |
+
sprintf(
|
166 |
+
'<input name="%1$s" id="%1$s" type="number" step="1" min="1" value="%2$s" class="small-text" />',
|
167 |
+
esc_attr( self::OPTION_READING_SETTING ),
|
168 |
+
esc_attr( get_option( self::OPTION_READING_SETTING, '10' ) )
|
169 |
+
)
|
170 |
+
)
|
171 |
+
);
|
172 |
+
endif;
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Should this Custom Post Type be made available?
|
177 |
+
*/
|
178 |
+
function site_supports_custom_post_type() {
|
179 |
+
// If the current theme requests it.
|
180 |
+
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) || get_option( self::OPTION_NAME, '0' ) ) {
|
181 |
+
return true;
|
182 |
+
}
|
183 |
+
|
184 |
+
// Otherwise, say no unless something wants to filter us to say yes.
|
185 |
+
/** This action is documented in modules/custom-post-types/nova.php */
|
186 |
+
return (bool) apply_filters( 'jetpack_enable_cpt', false, self::CUSTOM_POST_TYPE );
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Add to REST API post type whitelist
|
191 |
+
*/
|
192 |
+
function allow_cpt_rest_api_type( $post_types ) {
|
193 |
+
$post_types[] = self::CUSTOM_POST_TYPE;
|
194 |
+
|
195 |
+
return $post_types;
|
196 |
+
}
|
197 |
+
|
198 |
+
|
199 |
+
/*
|
200 |
+
* Flush permalinks when CPT option is turned on/off
|
201 |
+
*/
|
202 |
+
function flush_rules_on_enable() {
|
203 |
+
flush_rewrite_rules();
|
204 |
+
}
|
205 |
+
|
206 |
+
/*
|
207 |
+
* Count published testimonials and flush permalinks when first testimonial is published
|
208 |
+
*/
|
209 |
+
function flush_rules_on_first_testimonial() {
|
210 |
+
$testimonials = get_transient( 'jetpack-testimonial-count-cache' );
|
211 |
+
|
212 |
+
if ( false === $testimonials ) {
|
213 |
+
flush_rewrite_rules();
|
214 |
+
$testimonials = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
215 |
+
|
216 |
+
if ( ! empty( $testimonials ) ) {
|
217 |
+
set_transient( 'jetpack-testimonial-count-cache', $testimonials, HOUR_IN_SECONDS * 12 );
|
218 |
+
}
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
/*
|
223 |
+
* Flush permalinks when CPT supported theme is activated
|
224 |
+
*/
|
225 |
+
function flush_rules_on_switch() {
|
226 |
+
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
227 |
+
flush_rewrite_rules();
|
228 |
+
}
|
229 |
+
}
|
230 |
+
|
231 |
+
/**
|
232 |
+
* On plugin/theme activation, check if current theme supports CPT
|
233 |
+
*/
|
234 |
+
static function activation_post_type_support() {
|
235 |
+
if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
|
236 |
+
update_option( self::OPTION_NAME, '1' );
|
237 |
+
}
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* On theme switch, check if CPT item exists and disable if not
|
242 |
+
*/
|
243 |
+
function deactivation_post_type_support() {
|
244 |
+
$testimonials = get_posts(
|
245 |
+
array(
|
246 |
+
'fields' => 'ids',
|
247 |
+
'posts_per_page' => 1,
|
248 |
+
'post_type' => self::CUSTOM_POST_TYPE,
|
249 |
+
'suppress_filters' => false,
|
250 |
+
)
|
251 |
+
);
|
252 |
+
|
253 |
+
if ( empty( $testimonials ) ) {
|
254 |
+
update_option( self::OPTION_NAME, '0' );
|
255 |
+
}
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Register Post Type
|
260 |
+
*/
|
261 |
+
function register_post_types() {
|
262 |
+
if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
|
263 |
+
return;
|
264 |
+
}
|
265 |
+
|
266 |
+
$args = array(
|
267 |
+
'description' => __( 'Customer Testimonials', 'essential-content-types' ),
|
268 |
+
'labels' => array(
|
269 |
+
'name' => esc_html__( 'Testimonials', 'essential-content-types' ),
|
270 |
+
'singular_name' => esc_html__( 'Testimonial', 'essential-content-types' ),
|
271 |
+
'menu_name' => esc_html__( 'Testimonials', 'essential-content-types' ),
|
272 |
+
'all_items' => esc_html__( 'All Testimonials', 'essential-content-types' ),
|
273 |
+
'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
|
274 |
+
'add_new_item' => esc_html__( 'Add New Testimonial', 'essential-content-types' ),
|
275 |
+
'edit_item' => esc_html__( 'Edit Testimonial', 'essential-content-types' ),
|
276 |
+
'new_item' => esc_html__( 'New Testimonial', 'essential-content-types' ),
|
277 |
+
'view_item' => esc_html__( 'View Testimonial', 'essential-content-types' ),
|
278 |
+
'search_items' => esc_html__( 'Search Testimonials', 'essential-content-types' ),
|
279 |
+
'not_found' => esc_html__( 'No Testimonials found', 'essential-content-types' ),
|
280 |
+
'not_found_in_trash' => esc_html__( 'No Testimonials found in Trash', 'essential-content-types' ),
|
281 |
+
'filter_items_list' => esc_html__( 'Filter Testimonials list', 'essential-content-types' ),
|
282 |
+
'items_list_navigation' => esc_html__( 'Testimonial list navigation', 'essential-content-types' ),
|
283 |
+
'items_list' => esc_html__( 'Testimonials list', 'essential-content-types' ),
|
284 |
+
),
|
285 |
+
'supports' => array(
|
286 |
+
'title',
|
287 |
+
'editor',
|
288 |
+
'excerpt',
|
289 |
+
'thumbnail',
|
290 |
+
'page-attributes',
|
291 |
+
'revisions',
|
292 |
+
),
|
293 |
+
'rewrite' => array(
|
294 |
+
'slug' => 'testimonial',
|
295 |
+
'with_front' => false,
|
296 |
+
'feeds' => false,
|
297 |
+
'pages' => true,
|
298 |
+
),
|
299 |
+
'public' => true,
|
300 |
+
'show_ui' => true,
|
301 |
+
'menu_position' => 20, // below Pages
|
302 |
+
'menu_icon' => 'dashicons-testimonial',
|
303 |
+
'capability_type' => 'page',
|
304 |
+
'map_meta_cap' => true,
|
305 |
+
'has_archive' => true,
|
306 |
+
'query_var' => 'testimonial',
|
307 |
+
'show_in_rest' => true,
|
308 |
+
);
|
309 |
+
|
310 |
+
$description = get_option( 'jetpack_testimonial_content' );
|
311 |
+
if ( '' !== $description ) {
|
312 |
+
$args['description'] = $description;
|
313 |
+
}
|
314 |
+
|
315 |
+
register_post_type( self::CUSTOM_POST_TYPE, $args );
|
316 |
+
}
|
317 |
+
|
318 |
+
/**
|
319 |
+
* Update messages for the Testimonial admin.
|
320 |
+
*/
|
321 |
+
function updated_messages( $messages ) {
|
322 |
+
global $post;
|
323 |
+
|
324 |
+
$messages[ self::CUSTOM_POST_TYPE ] = array(
|
325 |
+
0 => '', // Unused. Messages start at index 1.
|
326 |
+
1 => sprintf( __( 'Testimonial updated. <a href="%s">View testimonial</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
327 |
+
2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
|
328 |
+
3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
|
329 |
+
4 => esc_html__( 'Testimonial updated.', 'essential-content-types' ),
|
330 |
+
/* translators: %s: date and time of the revision */
|
331 |
+
5 => isset( $_GET['revision'] ) ? sprintf( esc_html__( 'Testimonial restored to revision from %s', 'essential-content-types' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
|
332 |
+
6 => sprintf( __( 'Testimonial published. <a href="%s">View testimonial</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
|
333 |
+
7 => esc_html__( 'Testimonial saved.', 'essential-content-types' ),
|
334 |
+
8 => sprintf( __( 'Testimonial submitted. <a target="_blank" href="%s">Preview testimonial</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
335 |
+
9 => sprintf(
|
336 |
+
__( 'Testimonial scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview testimonial</a>', 'essential-content-types' ),
|
337 |
+
// translators: Publish box date format, see http://php.net/date
|
338 |
+
date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ),
|
339 |
+
esc_url( get_permalink( $post->ID ) )
|
340 |
+
),
|
341 |
+
10 => sprintf( __( 'Testimonial draft updated. <a target="_blank" href="%s">Preview testimonial</a>', 'essential-content-types' ), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
|
342 |
+
);
|
343 |
+
|
344 |
+
return $messages;
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Change ‘Enter Title Here’ text for the Testimonial.
|
349 |
+
*/
|
350 |
+
function change_default_title( $title ) {
|
351 |
+
$screen = get_current_screen();
|
352 |
+
|
353 |
+
if ( self::CUSTOM_POST_TYPE == $screen->post_type ) {
|
354 |
+
$title = esc_html__( "Enter the customer's name here", 'essential-content-types' );
|
355 |
+
}
|
356 |
+
|
357 |
+
return $title;
|
358 |
+
}
|
359 |
+
|
360 |
+
/**
|
361 |
+
* Change ‘Title’ column label on all Testimonials page.
|
362 |
+
*/
|
363 |
+
function edit_title_column_label( $columns ) {
|
364 |
+
$columns['title'] = esc_html__( 'Customer Name', 'essential-content-types' );
|
365 |
+
|
366 |
+
return $columns;
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* Follow CPT reading setting on CPT archive page
|
371 |
+
*/
|
372 |
+
function query_reading_setting( $query ) {
|
373 |
+
if ( ! is_admin()
|
374 |
+
&& $query->is_main_query()
|
375 |
+
&& $query->is_post_type_archive( self::CUSTOM_POST_TYPE )
|
376 |
+
) {
|
377 |
+
$post_per_page = ( null != get_option( 'posts_per_page' ) ) ? get_option( 'posts_per_page' ) : '10';
|
378 |
+
$query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
|
379 |
+
}
|
380 |
+
}
|
381 |
+
|
382 |
+
/*
|
383 |
+
* If Infinite Scroll is set to 'click', use our custom reading setting instead of core's `posts_per_page`.
|
384 |
+
*/
|
385 |
+
function infinite_scroll_click_posts_per_page( $settings ) {
|
386 |
+
global $wp_query;
|
387 |
+
|
388 |
+
if ( ! is_admin() && true === $settings['click_handle'] && $wp_query->is_post_type_archive( self::CUSTOM_POST_TYPE ) ) {
|
389 |
+
$settings['posts_per_page'] = get_option( self::OPTION_READING_SETTING, $settings['posts_per_page'] );
|
390 |
+
}
|
391 |
+
|
392 |
+
return $settings;
|
393 |
+
}
|
394 |
+
|
395 |
+
/**
|
396 |
+
* Add CPT to Dotcom sitemap
|
397 |
+
*/
|
398 |
+
function add_to_sitemap( $post_types ) {
|
399 |
+
$post_types[] = self::CUSTOM_POST_TYPE;
|
400 |
+
|
401 |
+
return $post_types;
|
402 |
+
}
|
403 |
+
|
404 |
+
function set_testimonial_option() {
|
405 |
+
$testimonials = wp_count_posts( self::CUSTOM_POST_TYPE );
|
406 |
+
$published_testimonials = $testimonials->publish;
|
407 |
+
|
408 |
+
update_option( self::OPTION_NAME, $published_testimonials );
|
409 |
+
}
|
410 |
+
|
411 |
+
function count_testimonials() {
|
412 |
+
$testimonials = get_transient( 'jetpack-testimonial-count-cache' );
|
413 |
+
|
414 |
+
if ( false === $testimonials ) {
|
415 |
+
$testimonials = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
|
416 |
+
|
417 |
+
if ( ! empty( $testimonials ) ) {
|
418 |
+
set_transient( 'jetpack-testimonial-count-cache', $testimonials, 60 * 60 * 12 );
|
419 |
+
}
|
420 |
+
}
|
421 |
+
|
422 |
+
return $testimonials;
|
423 |
+
}
|
424 |
+
|
425 |
+
/**
|
426 |
+
* Adds a submenu link to the Customizer.
|
427 |
+
*/
|
428 |
+
function add_customize_page() {
|
429 |
+
add_submenu_page(
|
430 |
+
'edit.php?post_type=' . self::CUSTOM_POST_TYPE,
|
431 |
+
esc_html__( 'Customize Testimonials Archive', 'essential-content-types' ),
|
432 |
+
esc_html__( 'Customize', 'essential-content-types' ),
|
433 |
+
'edit_theme_options',
|
434 |
+
add_query_arg(
|
435 |
+
array(
|
436 |
+
'url' => urlencode( home_url( '/testimonial/' ) ),
|
437 |
+
'autofocus[section]' => 'jetpack_testimonials',
|
438 |
+
),
|
439 |
+
'customize.php'
|
440 |
+
)
|
441 |
+
);
|
442 |
+
}
|
443 |
+
|
444 |
+
/**
|
445 |
+
* Adds testimonial section to the Customizer.
|
446 |
+
*/
|
447 |
+
function customize_register( $wp_customize ) {
|
448 |
+
essential_content_testimonial_custom_control_classes();
|
449 |
+
|
450 |
+
$wp_customize->add_panel(
|
451 |
+
'ect_plugin_options',
|
452 |
+
array(
|
453 |
+
'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
|
454 |
+
'priority' => 1,
|
455 |
+
)
|
456 |
+
);
|
457 |
+
|
458 |
+
$wp_customize->add_section(
|
459 |
+
'jetpack_testimonials',
|
460 |
+
array(
|
461 |
+
'title' => esc_html__( 'Testimonials', 'essential-content-types' ),
|
462 |
+
'theme_supports' => self::CUSTOM_POST_TYPE,
|
463 |
+
'priority' => 130,
|
464 |
+
'panel' => 'ect_plugin_options',
|
465 |
+
)
|
466 |
+
);
|
467 |
+
|
468 |
+
$wp_customize->add_setting(
|
469 |
+
'jetpack_testimonial_title',
|
470 |
+
array(
|
471 |
+
'default' => esc_html__( 'Testimonials', 'essential-content-types' ),
|
472 |
+
'type' => 'option',
|
473 |
+
'sanitize_callback' => 'sanitize_text_field',
|
474 |
+
'sanitize_js_callback' => 'sanitize_text_field',
|
475 |
+
)
|
476 |
+
);
|
477 |
+
$wp_customize->add_control(
|
478 |
+
'jetpack_testimonial_title',
|
479 |
+
array(
|
480 |
+
'section' => 'jetpack_testimonials',
|
481 |
+
'label' => esc_html__( 'Testimonial Archive Title', 'essential-content-types' ),
|
482 |
+
'type' => 'text',
|
483 |
+
)
|
484 |
+
);
|
485 |
+
|
486 |
+
$wp_customize->add_setting(
|
487 |
+
'jetpack_testimonial_content',
|
488 |
+
array(
|
489 |
+
'default' => '',
|
490 |
+
'type' => 'option',
|
491 |
+
'sanitize_callback' => 'wp_kses_post',
|
492 |
+
'sanitize_js_callback' => 'wp_kses_post',
|
493 |
+
)
|
494 |
+
);
|
495 |
+
$wp_customize->add_control(
|
496 |
+
new Essential_Content_Jetpack_Testimonial_Textarea_Control(
|
497 |
+
$wp_customize,
|
498 |
+
'jetpack_testimonial_content',
|
499 |
+
array(
|
500 |
+
'section' => 'jetpack_testimonials',
|
501 |
+
'label' => esc_html__( 'Testimonial Archive Content', 'essential-content-types' ),
|
502 |
+
'type' => 'textarea',
|
503 |
+
)
|
504 |
+
)
|
505 |
+
);
|
506 |
+
|
507 |
+
$wp_customize->add_setting(
|
508 |
+
'jetpack_testimonial_featured_image',
|
509 |
+
array(
|
510 |
+
'default' => '',
|
511 |
+
'type' => 'option',
|
512 |
+
'sanitize_callback' => 'attachment_url_to_postid',
|
513 |
+
'sanitize_js_callback' => 'attachment_url_to_postid',
|
514 |
+
'theme_supports' => 'post-thumbnails',
|
515 |
+
)
|
516 |
+
);
|
517 |
+
$wp_customize->add_control(
|
518 |
+
new WP_Customize_Image_Control(
|
519 |
+
$wp_customize,
|
520 |
+
'jetpack_testimonial_featured_image',
|
521 |
+
array(
|
522 |
+
'section' => 'jetpack_testimonials',
|
523 |
+
'label' => esc_html__( 'Testimonial Archive Featured Image', 'essential-content-types' ),
|
524 |
+
)
|
525 |
+
)
|
526 |
+
);
|
527 |
+
|
528 |
+
// The featured image control doesn't display properly in the Customizer unless we coerce
|
529 |
+
// it back into a URL sooner, since that's what WP_Customize_Upload_Control::to_json() expects
|
530 |
+
if ( is_admin() ) {
|
531 |
+
add_filter( 'theme_mod_jetpack_testimonials', array( $this, 'coerce_testimonial_image_to_url' ) );
|
532 |
+
}
|
533 |
+
}
|
534 |
+
|
535 |
+
public function coerce_testimonial_image_to_url( $opt ) {
|
536 |
+
if ( ! $opt || ! is_array( $opt ) ) {
|
537 |
+
return $opt;
|
538 |
+
}
|
539 |
+
if ( ! isset( $opt['featured-image'] ) || ! is_scalar( $opt['featured-image'] ) ) {
|
540 |
+
return $opt;
|
541 |
+
}
|
542 |
+
$url = wp_get_attachment_url( $opt['featured-image'] );
|
543 |
+
if ( $url ) {
|
544 |
+
$opt['featured-image'] = $url;
|
545 |
+
}
|
546 |
+
return $opt;
|
547 |
+
}
|
548 |
+
|
549 |
+
/**
|
550 |
+
* Our [testimonial] shortcode.
|
551 |
+
* Prints Testimonial data styled to look good on *any* theme.
|
552 |
+
*
|
553 |
+
* @return jetpack_testimonial_shortcode_html
|
554 |
+
*/
|
555 |
+
static function jetpack_testimonial_shortcode( $atts ) {
|
556 |
+
// Default attributes
|
557 |
+
$atts = shortcode_atts(
|
558 |
+
array(
|
559 |
+
'display_content' => true,
|
560 |
+
'image' => true,
|
561 |
+
'columns' => 1,
|
562 |
+
'showposts' => -1,
|
563 |
+
'order' => 'asc',
|
564 |
+
'orderby' => 'date',
|
565 |
+
),
|
566 |
+
$atts,
|
567 |
+
'testimonial'
|
568 |
+
);
|
569 |
+
|
570 |
+
// A little sanitization
|
571 |
+
if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
|
572 |
+
$atts['display_content'] = false;
|
573 |
+
}
|
574 |
+
|
575 |
+
if ( $atts['image'] && 'true' != $atts['image'] ) {
|
576 |
+
$atts['image'] = false;
|
577 |
+
}
|
578 |
+
|
579 |
+
// Check if column value is set to valid numbers or else set default value as 1
|
580 |
+
if ( 1 == $atts['columns'] || 2 == $atts['columns'] ) {
|
581 |
+
$atts['columns'] = absint( $atts['columns'] );
|
582 |
+
} else {
|
583 |
+
$atts['columns'] = 1;
|
584 |
+
}
|
585 |
+
|
586 |
+
$atts['showposts'] = intval( $atts['showposts'] );
|
587 |
+
|
588 |
+
if ( $atts['order'] ) {
|
589 |
+
$atts['order'] = urldecode( $atts['order'] );
|
590 |
+
$atts['order'] = strtoupper( $atts['order'] );
|
591 |
+
if ( 'DESC' != $atts['order'] ) {
|
592 |
+
$atts['order'] = 'ASC';
|
593 |
+
}
|
594 |
+
}
|
595 |
+
|
596 |
+
if ( $atts['orderby'] ) {
|
597 |
+
$atts['orderby'] = urldecode( $atts['orderby'] );
|
598 |
+
$atts['orderby'] = strtolower( $atts['orderby'] );
|
599 |
+
$allowed_keys = array( 'author', 'date', 'title', 'rand' );
|
600 |
+
|
601 |
+
$parsed = array();
|
602 |
+
foreach ( explode( ',', $atts['orderby'] ) as $testimonial_index_number => $orderby ) {
|
603 |
+
if ( ! in_array( $orderby, $allowed_keys ) ) {
|
604 |
+
continue;
|
605 |
+
}
|
606 |
+
$parsed[] = $orderby;
|
607 |
+
}
|
608 |
+
|
609 |
+
if ( empty( $parsed ) ) {
|
610 |
+
unset( $atts['orderby'] );
|
611 |
+
} else {
|
612 |
+
$atts['orderby'] = implode( ' ', $parsed );
|
613 |
+
}
|
614 |
+
}
|
615 |
+
|
616 |
+
// enqueue shortcode styles when shortcode is used
|
617 |
+
wp_enqueue_style( 'jetpack-testimonial-style', plugins_url( 'css/testimonial-shortcode.css', __FILE__ ), array(), '20140326' );
|
618 |
+
|
619 |
+
return self::jetpack_testimonial_shortcode_html( $atts );
|
620 |
+
}
|
621 |
+
|
622 |
+
/**
|
623 |
+
* The Testimonial shortcode loop.
|
624 |
+
*
|
625 |
+
* @todo add theme color styles
|
626 |
+
* @return html
|
627 |
+
*/
|
628 |
+
|
629 |
+
static function jetpack_testimonial_shortcode_html( $atts ) {
|
630 |
+
|
631 |
+
// Default query arguments
|
632 |
+
$defaults = array(
|
633 |
+
'order' => $atts['order'],
|
634 |
+
'orderby' => $atts['orderby'],
|
635 |
+
'posts_per_page' => $atts['showposts'],
|
636 |
+
);
|
637 |
+
|
638 |
+
$args = wp_parse_args( $atts, $defaults );
|
639 |
+
$args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
|
640 |
+
$query = new WP_Query( $args );
|
641 |
+
|
642 |
+
ob_start();
|
643 |
+
|
644 |
+
// If we have posts, create the html
|
645 |
+
// with testimonial markup
|
646 |
+
if ( $query->have_posts() ) {
|
647 |
+
|
648 |
+
/**
|
649 |
+
* Hook: ect_before_testimonial_loop.
|
650 |
+
*
|
651 |
+
* @hooked
|
652 |
+
*/
|
653 |
+
$layout = ect_get_layout();
|
654 |
+
do_action( 'ect_before_testimonial_loop', $layout[ $atts['columns'] ] );
|
655 |
+
?>
|
656 |
+
<?php
|
657 |
+
while ( $query->have_posts() ) {
|
658 |
+
|
659 |
+
$query->the_post();
|
660 |
+
ect_get_template_part( 'content', 'testimonial', $atts );
|
661 |
+
|
662 |
+
}
|
663 |
+
wp_reset_postdata();
|
664 |
+
?>
|
665 |
+
<?php
|
666 |
+
|
667 |
+
/**
|
668 |
+
* Hook: ect_after_testimonial_loop.
|
669 |
+
*
|
670 |
+
* @hooked
|
671 |
+
*/
|
672 |
+
do_action( 'ect_after_testimonial_loop' );
|
673 |
+
|
674 |
+
} else {
|
675 |
+
/**
|
676 |
+
* Hook: ect_no_testimonial_found.
|
677 |
+
*
|
678 |
+
* @hooked ect_no_testimonial_found
|
679 |
+
*/
|
680 |
+
do_action( 'ect_no_testimonial_found' );
|
681 |
+
}
|
682 |
+
|
683 |
+
$html = ob_get_clean();
|
684 |
+
|
685 |
+
// If there is a [testimonials] within a [testimonials], remove the shortcode
|
686 |
+
if ( has_shortcode( $html, 'testimonials' ) ) {
|
687 |
+
remove_shortcode( 'testimonials' );
|
688 |
+
}
|
689 |
+
|
690 |
+
// Return the HTML block
|
691 |
+
return $html;
|
692 |
+
}
|
693 |
+
}
|
694 |
+
add_action( 'init', array( 'Essential_Content_Jetpack_Testimonial', 'init' ) );
|
695 |
+
|
696 |
+
|
697 |
+
function essential_content_testimonial_custom_control_classes() {
|
698 |
+
class Essential_Content_Jetpack_Testimonial_Title_Control extends WP_Customize_Control {
|
699 |
+
public static function sanitize_content( $value ) {
|
700 |
+
if ( '' != $value ) {
|
701 |
+
$value = trim( convert_chars( wptexturize( $value ) ) );
|
702 |
+
}
|
703 |
+
|
704 |
+
return $value;
|
705 |
+
}
|
706 |
+
}
|
707 |
+
|
708 |
+
class Essential_Content_Jetpack_Testimonial_Textarea_Control extends WP_Customize_Control {
|
709 |
+
public $type = 'textarea';
|
710 |
+
|
711 |
+
public function render_content() {
|
712 |
+
?>
|
713 |
+
<label>
|
714 |
+
<span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
|
715 |
+
<textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
|
716 |
+
</label>
|
717 |
+
<?php
|
718 |
+
}
|
719 |
+
|
720 |
+
public static function sanitize_content( $value ) {
|
721 |
+
if ( ! empty( $value ) ) {
|
722 |
+
/** This filter is already documented in core. wp-includes/post-template.php */
|
723 |
+
$value = apply_filters( 'the_content', $value );
|
724 |
+
}
|
725 |
+
|
726 |
+
$value = preg_replace( '@<div id="jp-post-flair"([^>]+)?>(.+)?</div>@is', '', $value ); // Strip WPCOM and Jetpack post flair if included in content
|
727 |
+
|
728 |
+
return $value;
|
729 |
+
}
|
730 |
+
}
|
731 |
+
}
|
732 |
+
|
733 |
+
/**
|
734 |
+
* Add Testimonial support
|
735 |
+
*/
|
736 |
+
function essential_content_testimonial_support() {
|
737 |
+
/*
|
738 |
+
* Adding theme support for Jetpack Testimonial CPT.
|
739 |
+
*/
|
740 |
+
add_theme_support( 'jetpack-testimonial' );
|
741 |
+
}
|
742 |
+
add_action( 'after_setup_theme', 'essential_content_testimonial_support' );
|
743 |
+
|
744 |
+
|
745 |
+
/**
|
746 |
+
* Class to Renders and save metabox options
|
747 |
+
*
|
748 |
+
*/
|
749 |
+
class Essential_Content_Jetpack_Testimonial_Metabox {
|
750 |
+
private $meta_box;
|
751 |
+
|
752 |
+
private $fields;
|
753 |
+
|
754 |
+
/**
|
755 |
+
* Constructor
|
756 |
+
*
|
757 |
+
*
|
758 |
+
* @access public
|
759 |
+
*
|
760 |
+
*/
|
761 |
+
public function __construct( $meta_box_id, $meta_box_title, $post_type ) {
|
762 |
+
|
763 |
+
$this->meta_box = array(
|
764 |
+
'id' => $meta_box_id,
|
765 |
+
'title' => $meta_box_title,
|
766 |
+
'post_type' => $post_type,
|
767 |
+
);
|
768 |
+
|
769 |
+
$this->fields = array(
|
770 |
+
'ect-testimonials',
|
771 |
+
);
|
772 |
+
|
773 |
+
// Add metaboxes
|
774 |
+
add_action( 'add_meta_boxes', array( $this, 'add' ) );
|
775 |
+
|
776 |
+
add_action( 'save_post', array( $this, 'save' ) );
|
777 |
+
}
|
778 |
+
|
779 |
+
/**
|
780 |
+
* Add Meta Box for multiple post types.
|
781 |
+
*
|
782 |
+
*
|
783 |
+
* @access public
|
784 |
+
*/
|
785 |
+
public function add( $postType ) {
|
786 |
+
if ( in_array( $postType, $this->meta_box['post_type'] ) ) {
|
787 |
+
add_meta_box( $this->meta_box['id'], $this->meta_box['title'], array( $this, 'show' ), null, 'side', 'high' );
|
788 |
+
}
|
789 |
+
}
|
790 |
+
|
791 |
+
/**
|
792 |
+
* Renders metabox
|
793 |
+
*
|
794 |
+
*
|
795 |
+
* @access public
|
796 |
+
*/
|
797 |
+
public function show() {
|
798 |
+
global $post;
|
799 |
+
|
800 |
+
// Use nonce for verification
|
801 |
+
wp_nonce_field( basename( __FILE__ ), 'ect_custom_meta_box_nonce' );
|
802 |
+
|
803 |
+
$position = get_post_meta( $post->ID, 'ect_testimonial_position', true );
|
804 |
+
|
805 |
+
// Begin the form
|
806 |
+
?>
|
807 |
+
<p>
|
808 |
+
<label for="ect_testimonial_position"><?php esc_html_e( 'Position', 'essential-content-types' ); ?></label>
|
809 |
+
<input type="text" class="widefat ect-testimonial-position" name="ect_testimonial_position" value="<?php echo esc_attr( $position ); ?>" />
|
810 |
+
</p>
|
811 |
+
<?php
|
812 |
+
}
|
813 |
+
|
814 |
+
/**
|
815 |
+
* Save custom metabox data
|
816 |
+
*
|
817 |
+
* @action save_post
|
818 |
+
*
|
819 |
+
* @access public
|
820 |
+
*/
|
821 |
+
public function save( $post_id ) {
|
822 |
+
global $post_type;
|
823 |
+
|
824 |
+
$post_type_object = get_post_type_object( $post_type );
|
825 |
+
|
826 |
+
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) // Check Autosave
|
827 |
+
|| ( ! isset( $_POST['post_ID'] ) || $post_id != $_POST['post_ID'] ) // Check Revision
|
828 |
+
|| ( ! in_array( $post_type, $this->meta_box['post_type'] ) ) // Check if current post type is supported.
|
829 |
+
|| ( ! check_admin_referer( basename( __FILE__ ), 'ect_custom_meta_box_nonce' ) ) // Check nonce - Security
|
830 |
+
|| ( ! current_user_can( $post_type_object->cap->edit_post, $post_id ) ) ) { // Check permission
|
831 |
+
return $post_id;
|
832 |
+
}
|
833 |
+
|
834 |
+
if ( ! update_post_meta( $post_id, 'ect_testimonial_position', sanitize_text_field( $_POST['ect_testimonial_position'] ) ) ) {
|
835 |
+
add_post_meta( $post_id, 'ect_testimonial_position', sanitize_text_field( $_POST['ect_testimonial_position'] ), true );
|
836 |
+
}
|
837 |
+
}
|
838 |
+
}
|
839 |
+
|
840 |
+
$ect_metabox = new Essential_Content_Jetpack_Testimonial_Metabox(
|
841 |
+
'ect-options', //metabox id
|
842 |
+
esc_html__( 'Testmonial Options', 'essential-content-types' ), //metabox title
|
843 |
+
array( 'jetpack-testimonial' ) //metabox post types
|
844 |
+
);
|
845 |
+
|
846 |
+
|
847 |
+
if ( ! function_exists( 'essential_content_get_testimonial_thumbnail_link' ) ) :
|
848 |
+
/**
|
849 |
+
* Display the featured image if it's available
|
850 |
+
*
|
851 |
+
* @return html
|
852 |
+
*/
|
853 |
+
function essential_content_get_testimonial_thumbnail_link( $post_id, $size ) {
|
854 |
+
if ( has_post_thumbnail( $post_id ) ) {
|
855 |
+
/**
|
856 |
+
* Change the Testimonial thumbnail size.
|
857 |
+
*
|
858 |
+
* @module custom-content-types
|
859 |
+
*
|
860 |
+
* @since 3.4.0
|
861 |
+
*
|
862 |
+
* @param string|array $var Either a registered size keyword or size array.
|
863 |
+
*/
|
864 |
+
//return '<a class="testimonial-featured-image testimonial-thumbnail post-thumbnail" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'testimonial_thumbnail_size', $size ) ) . '</a>';
|
865 |
+
return '<div class="testimonial-featured-image testimonial-thumbnail post-thumbnail">' . get_the_post_thumbnail( $post_id, apply_filters( 'testimonial_thumbnail_size', $size ) ) . '</div>';
|
866 |
+
}
|
867 |
+
}
|
868 |
+
endif;
|
869 |
+
|
870 |
+
|
871 |
+
if ( ! function_exists( 'essential_content_no_testimonial_found' ) ) :
|
872 |
+
/**
|
873 |
+
* No items found text
|
874 |
+
*
|
875 |
+
* @return html
|
876 |
+
*/
|
877 |
+
function essential_content_no_testimonial_found() {
|
878 |
+
echo '<p><em>' . esc_html__( 'Your Testimonial Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types-pro' ) . '</em></p>';
|
879 |
+
}
|
880 |
+
add_action( 'ect_no_testimonial_found', 'essential_content_no_testimonial_found', 10 );
|
881 |
+
endif;
|
882 |
+
|
883 |
+
|
884 |
+
if ( ! function_exists( 'essential_content_testimonial_section_open' ) ) :
|
885 |
+
/**
|
886 |
+
* Open section
|
887 |
+
*
|
888 |
+
* @return html
|
889 |
+
*/
|
890 |
+
function essential_content_testimonial_section_open( $layout = null ) {
|
891 |
+
echo '<div class="ect-testimonial-content-section ect-section ' . $layout . '">';
|
892 |
+
echo '<div class="ect-wrapper">';
|
893 |
+
}
|
894 |
+
endif;
|
895 |
+
add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_section_open', 10, 1 );
|
896 |
+
|
897 |
+
|
898 |
+
if ( ! function_exists( 'essential_content_testimonial_loop_start' ) ) :
|
899 |
+
/**
|
900 |
+
* open wrapper before loop
|
901 |
+
*
|
902 |
+
*/
|
903 |
+
function essential_content_testimonial_loop_start( $layout = null ) {
|
904 |
+
echo '<div class="section-content-wrapper testimonial-content-wrapper">';
|
905 |
+
}
|
906 |
+
endif;
|
907 |
+
add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_loop_start', 30 );
|
908 |
+
|
909 |
+
|
910 |
+
if ( ! function_exists( 'essential_content_testimonial_slider_open' ) ) :
|
911 |
+
function essential_content_testimonial_slider_open() {
|
912 |
+
?>
|
913 |
+
<div class="cycle-slideshow"
|
914 |
+
data-cycle-log="false"
|
915 |
+
data-cycle-pause-on-hover="true"
|
916 |
+
data-cycle-swipe="true"
|
917 |
+
data-cycle-auto-height=container
|
918 |
+
data-cycle-loader=false
|
919 |
+
data-cycle-slides=".testimonial_slider_wrap"
|
920 |
+
data-cycle-pager=".testimonial-slider-pager"
|
921 |
+
data-cycle-prev=".testimonial-slider-prev"
|
922 |
+
data-cycle-next=".testimonial-slider-next"
|
923 |
+
>
|
924 |
+
|
925 |
+
<div class="controller">
|
926 |
+
<!-- prev/next links -->
|
927 |
+
<button class="cycle-prev testimonial-slider-prev" aria-label="Previous">
|
928 |
+
<span class="screen-reader-text"><?php esc_html_e( 'Previous Slide', 'essential-content-types-pro' ); ?></span><?php echo essential_content_get_svg( array( 'icon' => 'angle-down' ) ); ?>
|
929 |
+
</button>
|
930 |
+
|
931 |
+
<!-- empty element for pager links -->
|
932 |
+
<div class="cycle-pager testimonial-slider-pager"></div>
|
933 |
+
|
934 |
+
<button class="cycle-next testimonial-slider-next" aria-label="Next">
|
935 |
+
<span class="screen-reader-text"><?php esc_html_e( 'Next Slide', 'essential-content-types-pro' ); ?></span><?php echo essential_content_get_svg( array( 'icon' => 'angle-down' ) ); ?>
|
936 |
+
</button>
|
937 |
+
</div><!-- .controller -->
|
938 |
+
|
939 |
+
<div class="testimonial_slider_wrap">
|
940 |
+
|
941 |
+
<?php
|
942 |
+
}
|
943 |
+
endif;
|
944 |
+
//add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_slider_open', 40 );
|
945 |
+
|
946 |
+
|
947 |
+
if ( ! function_exists( 'essential_content_testimonial_slider_close' ) ) :
|
948 |
+
function essential_content_testimonial_slider_close() {
|
949 |
+
echo '</div><!-- .testimonial_slider_wrap -->';
|
950 |
+
echo '</div><!-- .cycle-slideshow -->';
|
951 |
+
}
|
952 |
+
endif;
|
953 |
+
//add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_slider_close', 10 );
|
954 |
+
|
955 |
+
|
956 |
+
if ( ! function_exists( 'essential_content_testimonial_loop_end' ) ) :
|
957 |
+
/**
|
958 |
+
* close wrapper after loop
|
959 |
+
*
|
960 |
+
*/
|
961 |
+
function essential_content_testimonial_loop_end() {
|
962 |
+
echo '</div><!-- .testimonial-content-wrapper -->';
|
963 |
+
}
|
964 |
+
endif;
|
965 |
+
add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_loop_end', 20 );
|
966 |
+
|
967 |
+
|
968 |
+
if ( ! function_exists( 'essential_content_testimonial_section_close' ) ) :
|
969 |
+
/**
|
970 |
+
* Close section
|
971 |
+
*
|
972 |
+
* @return html
|
973 |
+
*/
|
974 |
+
function essential_content_testimonial_section_close() {
|
975 |
+
echo '</div><!-- .ect-wrapper -->';
|
976 |
+
echo '</div><!-- .ect-section -->';
|
977 |
+
}
|
978 |
+
endif;
|
979 |
+
add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_section_close', 30 );
|
980 |
+
|
981 |
+
|
982 |
+
if ( ! function_exists( 'essential_content_get_svg' ) ) :
|
983 |
+
/**
|
984 |
+
* Return SVG markup.
|
985 |
+
*
|
986 |
+
* @param array $args {
|
987 |
+
* Parameters needed to display an SVG.
|
988 |
+
*
|
989 |
+
* @type string $icon Required SVG icon filename.
|
990 |
+
* @type string $title Optional SVG title.
|
991 |
+
* @type string $desc Optional SVG description.
|
992 |
+
* }
|
993 |
+
* @return string SVG markup.
|
994 |
+
*/
|
995 |
+
function essential_content_get_svg( $args = array() ) {
|
996 |
+
// Make sure $args are an array.
|
997 |
+
if ( empty( $args ) ) {
|
998 |
+
return __( 'Please define default parameters in the form of an array.', 'starter-pro' );
|
999 |
+
}
|
1000 |
+
|
1001 |
+
// Define an icon.
|
1002 |
+
if ( false === array_key_exists( 'icon', $args ) ) {
|
1003 |
+
return __( 'Please define an SVG icon filename.', 'starter-pro' );
|
1004 |
+
}
|
1005 |
+
|
1006 |
+
// Set defaults.
|
1007 |
+
$defaults = array(
|
1008 |
+
'icon' => '',
|
1009 |
+
'title' => '',
|
1010 |
+
'desc' => '',
|
1011 |
+
'fallback' => false,
|
1012 |
+
);
|
1013 |
+
|
1014 |
+
// Parse args.
|
1015 |
+
$args = wp_parse_args( $args, $defaults );
|
1016 |
+
|
1017 |
+
// Set aria hidden.
|
1018 |
+
$aria_hidden = ' aria-hidden="true"';
|
1019 |
+
|
1020 |
+
// Set ARIA.
|
1021 |
+
$aria_labelledby = '';
|
1022 |
+
|
1023 |
+
/*
|
1024 |
+
* Starter doesn't use the SVG title or description attributes; non-decorative icons are described with .screen-reader-text.
|
1025 |
+
*
|
1026 |
+
* However, child themes can use the title and description to add information to non-decorative SVG icons to improve accessibility.
|
1027 |
+
*
|
1028 |
+
* Example 1 with title: <?php echo starter_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ) ) ); ?>
|
1029 |
+
*
|
1030 |
+
* Example 2 with title and description: <?php echo starter_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ), 'desc' => __( 'This is the description', 'textdomain' ) ) ); ?>
|
1031 |
+
*
|
1032 |
+
* See https://www.paciellogroup.com/blog/2013/12/using-aria-enhance-svg-accessibility/.
|
1033 |
+
*/
|
1034 |
+
if ( $args['title'] ) {
|
1035 |
+
$aria_hidden = '';
|
1036 |
+
$unique_id = uniqid();
|
1037 |
+
$aria_labelledby = ' aria-labelledby="title-' . $unique_id . '"';
|
1038 |
+
|
1039 |
+
if ( $args['desc'] ) {
|
1040 |
+
$aria_labelledby = ' aria-labelledby="title-' . $unique_id . ' desc-' . $unique_id . '"';
|
1041 |
+
}
|
1042 |
+
}
|
1043 |
+
|
1044 |
+
// Begin SVG markup.
|
1045 |
+
$svg = '<svg class="icon icon-' . esc_attr( $args['icon'] ) . '"' . $aria_hidden . $aria_labelledby . ' role="img">';
|
1046 |
+
|
1047 |
+
// Display the title.
|
1048 |
+
if ( $args['title'] ) {
|
1049 |
+
$svg .= '<title id="title-' . $unique_id . '">' . esc_html( $args['title'] ) . '</title>';
|
1050 |
+
|
1051 |
+
// Display the desc only if the title is already set.
|
1052 |
+
if ( $args['desc'] ) {
|
1053 |
+
$svg .= '<desc id="desc-' . $unique_id . '">' . esc_html( $args['desc'] ) . '</desc>';
|
1054 |
+
}
|
1055 |
+
}
|
1056 |
+
|
1057 |
+
/*
|
1058 |
+
* Display the icon.
|
1059 |
+
*
|
1060 |
+
* The whitespace around `<use>` is intentional - it is a work around to a keyboard navigation bug in Safari 10.
|
1061 |
+
*
|
1062 |
+
* See https://core.trac.wordpress.org/ticket/38387.
|
1063 |
+
*/
|
1064 |
+
$svg .= ' <use href="#icon-' . esc_html( $args['icon'] ) . '" xlink:href="#icon-' . esc_html( $args['icon'] ) . '"></use> ';
|
1065 |
+
|
1066 |
+
// Add some markup to use as a fallback for browsers that do not support SVGs.
|
1067 |
+
if ( $args['fallback'] ) {
|
1068 |
+
$svg .= '<span class="svg-fallback icon-' . esc_attr( $args['icon'] ) . '"></span>';
|
1069 |
+
}
|
1070 |
+
|
1071 |
+
$svg .= '</svg>';
|
1072 |
+
|
1073 |
+
return $svg;
|
1074 |
+
}
|
1075 |
+
endif;
|
admin/css/food-menu-shortcode.css
CHANGED
@@ -1,160 +1,160 @@
|
|
1 |
-
/*--------------------------------------------------------------
|
2 |
-
# Food Menu
|
3 |
-
--------------------------------------------------------------*/
|
4 |
-
|
5 |
-
/*--------------------------------------------------------------
|
6 |
-
# Element
|
7 |
-
--------------------------------------------------------------*/
|
8 |
-
html {
|
9 |
-
-webkit-box-sizing: border-box;
|
10 |
-
-moz-box-sizing: border-box;
|
11 |
-
box-sizing: border-box;
|
12 |
-
}
|
13 |
-
|
14 |
-
*,
|
15 |
-
*:before,
|
16 |
-
*:after {
|
17 |
-
/* Inherit box-sizing to make it easier to change the property for components that leverage other behavior; see http://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */
|
18 |
-
-webkit-box-sizing: inherit;
|
19 |
-
-moz-box-sizing: inherit;
|
20 |
-
box-sizing: inherit;
|
21 |
-
}
|
22 |
-
|
23 |
-
.menu-content-wrapper {
|
24 |
-
max-width: 1080px;
|
25 |
-
margin: 0 auto;
|
26 |
-
}
|
27 |
-
|
28 |
-
.menu-content-wrapper .ui-nav-collapse {
|
29 |
-
margin: 0;
|
30 |
-
margin-bottom: 21px;
|
31 |
-
}
|
32 |
-
|
33 |
-
|
34 |
-
.menu-content-wrapper .ui-nav-collapse,
|
35 |
-
.menu-content-wrapper .ui-tabs-anchor {
|
36 |
-
display: block;
|
37 |
-
font-size: 20px;
|
38 |
-
font-size: 1.25rem;
|
39 |
-
font-weight: 500;
|
40 |
-
text-transform: capitalize;
|
41 |
-
}
|
42 |
-
|
43 |
-
.menu-content-wrapper .tabs-nav,
|
44 |
-
.menu-content-wrapper .ui-tabs-panel {
|
45 |
-
display: none;
|
46 |
-
}
|
47 |
-
|
48 |
-
.menu-content-wrapper .ui-tabs-panel.active-tab {
|
49 |
-
display: block;
|
50 |
-
}
|
51 |
-
|
52 |
-
.menu-content-wrapper .hentry {
|
53 |
-
margin-bottom: 21px;
|
54 |
-
}
|
55 |
-
|
56 |
-
.menu-content-wrapper .hentry-inner {
|
57 |
-
border-bottom: 3px solid #eee;
|
58 |
-
padding-bottom: 21px;
|
59 |
-
}
|
60 |
-
|
61 |
-
.menu-content-wrapper .entry-container {
|
62 |
-
display: table;
|
63 |
-
position: relative;
|
64 |
-
table-layout: fixed;
|
65 |
-
width: 100%;
|
66 |
-
}
|
67 |
-
|
68 |
-
.menu-content-wrapper .entry-description, .entry-price {
|
69 |
-
display: table-cell;
|
70 |
-
vertical-align: top;
|
71 |
-
}
|
72 |
-
|
73 |
-
.menu-content-wrapper .entry-description {
|
74 |
-
width: 70%;
|
75 |
-
}
|
76 |
-
|
77 |
-
.entry-price {
|
78 |
-
padding-top: 4px;
|
79 |
-
width: 30%;
|
80 |
-
text-align: right;
|
81 |
-
}
|
82 |
-
|
83 |
-
.menu-group-header {
|
84 |
-
display: none;
|
85 |
-
}
|
86 |
-
|
87 |
-
/*--------------------------------------------------------------
|
88 |
-
# >= 667px
|
89 |
-
--------------------------------------------------------------*/
|
90 |
-
|
91 |
-
@media screen and (min-width: 41.6875em) {
|
92 |
-
|
93 |
-
/*menu-content-wrapper*/
|
94 |
-
.menu-content-wrapper .tabs-nav {
|
95 |
-
display: block;
|
96 |
-
margin-bottom: 35px;
|
97 |
-
}
|
98 |
-
|
99 |
-
.menu-content-wrapper .ui-tabs-nav {
|
100 |
-
margin: 0;
|
101 |
-
padding: 0;
|
102 |
-
text-align: center;
|
103 |
-
}
|
104 |
-
|
105 |
-
.menu-content-wrapper .ui-tabs-nav li {
|
106 |
-
display: inline-block;
|
107 |
-
list-style: none;
|
108 |
-
}
|
109 |
-
|
110 |
-
.menu-content-wrapper .ui-tabs-anchor {
|
111 |
-
display: inline-block;
|
112 |
-
padding: 14px 25px;
|
113 |
-
}
|
114 |
-
|
115 |
-
.menu-content-wrapper .ui-nav-collapse {
|
116 |
-
display: none;
|
117 |
-
}
|
118 |
-
|
119 |
-
.menu-content-wrapper .hentry-inner {
|
120 |
-
padding-bottom: 28px;
|
121 |
-
}
|
122 |
-
|
123 |
-
.entry-price {
|
124 |
-
font-size: 18px;
|
125 |
-
font-size: 1.125rem;
|
126 |
-
}
|
127 |
-
}
|
128 |
-
|
129 |
-
.menu-content-wrapper a {
|
130 |
-
text-decoration: none;
|
131 |
-
}
|
132 |
-
|
133 |
-
.menu-content-wrapper .entry-title,
|
134 |
-
.menu-content-wrapper .entry-header {
|
135 |
-
margin-bottom: 0;
|
136 |
-
padding: 0;
|
137 |
-
}
|
138 |
-
|
139 |
-
.menu-content-wrapper .entry-title {
|
140 |
-
margin-bottom: 7px;
|
141 |
-
}
|
142 |
-
|
143 |
-
body.ect-post .content-area .singular-content-wrap .menu-content-wrapper .entry-content {
|
144 |
-
padding-top: 0;
|
145 |
-
margin-top: 21px;
|
146 |
-
}
|
147 |
-
|
148 |
-
.ect-post .menu-content-wrapper .more-button {
|
149 |
-
text-align: left;
|
150 |
-
}
|
151 |
-
|
152 |
-
.ect-post .singular-content-wrap .entry-content .entry-header,
|
153 |
-
.ect-post .entry-content,
|
154 |
-
.ect-post .ect-menu .menu-content-wrapper .entry-header {
|
155 |
-
text-align: left;
|
156 |
-
}
|
157 |
-
|
158 |
-
.ect-post .menu-content-wrapper .ect_food_menu_item .entry-header .entry-title {
|
159 |
-
font-size: 24px;
|
160 |
}
|
1 |
+
/*--------------------------------------------------------------
|
2 |
+
# Food Menu
|
3 |
+
--------------------------------------------------------------*/
|
4 |
+
|
5 |
+
/*--------------------------------------------------------------
|
6 |
+
# Element
|
7 |
+
--------------------------------------------------------------*/
|
8 |
+
html {
|
9 |
+
-webkit-box-sizing: border-box;
|
10 |
+
-moz-box-sizing: border-box;
|
11 |
+
box-sizing: border-box;
|
12 |
+
}
|
13 |
+
|
14 |
+
*,
|
15 |
+
*:before,
|
16 |
+
*:after {
|
17 |
+
/* Inherit box-sizing to make it easier to change the property for components that leverage other behavior; see http://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */
|
18 |
+
-webkit-box-sizing: inherit;
|
19 |
+
-moz-box-sizing: inherit;
|
20 |
+
box-sizing: inherit;
|
21 |
+
}
|
22 |
+
|
23 |
+
.menu-content-wrapper {
|
24 |
+
max-width: 1080px;
|
25 |
+
margin: 0 auto;
|
26 |
+
}
|
27 |
+
|
28 |
+
.menu-content-wrapper .ui-nav-collapse {
|
29 |
+
margin: 0;
|
30 |
+
margin-bottom: 21px;
|
31 |
+
}
|
32 |
+
|
33 |
+
|
34 |
+
.menu-content-wrapper .ui-nav-collapse,
|
35 |
+
.menu-content-wrapper .ui-tabs-anchor {
|
36 |
+
display: block;
|
37 |
+
font-size: 20px;
|
38 |
+
font-size: 1.25rem;
|
39 |
+
font-weight: 500;
|
40 |
+
text-transform: capitalize;
|
41 |
+
}
|
42 |
+
|
43 |
+
.menu-content-wrapper .tabs-nav,
|
44 |
+
.menu-content-wrapper .ui-tabs-panel {
|
45 |
+
display: none;
|
46 |
+
}
|
47 |
+
|
48 |
+
.menu-content-wrapper .ui-tabs-panel.active-tab {
|
49 |
+
display: block;
|
50 |
+
}
|
51 |
+
|
52 |
+
.menu-content-wrapper .hentry {
|
53 |
+
margin-bottom: 21px;
|
54 |
+
}
|
55 |
+
|
56 |
+
.menu-content-wrapper .hentry-inner {
|
57 |
+
border-bottom: 3px solid #eee;
|
58 |
+
padding-bottom: 21px;
|
59 |
+
}
|
60 |
+
|
61 |
+
.menu-content-wrapper .entry-container {
|
62 |
+
display: table;
|
63 |
+
position: relative;
|
64 |
+
table-layout: fixed;
|
65 |
+
width: 100%;
|
66 |
+
}
|
67 |
+
|
68 |
+
.menu-content-wrapper .entry-description, .entry-price {
|
69 |
+
display: table-cell;
|
70 |
+
vertical-align: top;
|
71 |
+
}
|
72 |
+
|
73 |
+
.menu-content-wrapper .entry-description {
|
74 |
+
width: 70%;
|
75 |
+
}
|
76 |
+
|
77 |
+
.entry-price {
|
78 |
+
padding-top: 4px;
|
79 |
+
width: 30%;
|
80 |
+
text-align: right;
|
81 |
+
}
|
82 |
+
|
83 |
+
.menu-group-header {
|
84 |
+
display: none;
|
85 |
+
}
|
86 |
+
|
87 |
+
/*--------------------------------------------------------------
|
88 |
+
# >= 667px
|
89 |
+
--------------------------------------------------------------*/
|
90 |
+
|
91 |
+
@media screen and (min-width: 41.6875em) {
|
92 |
+
|
93 |
+
/*menu-content-wrapper*/
|
94 |
+
.menu-content-wrapper .tabs-nav {
|
95 |
+
display: block;
|
96 |
+
margin-bottom: 35px;
|
97 |
+
}
|
98 |
+
|
99 |
+
.menu-content-wrapper .ui-tabs-nav {
|
100 |
+
margin: 0;
|
101 |
+
padding: 0;
|
102 |
+
text-align: center;
|
103 |
+
}
|
104 |
+
|
105 |
+
.menu-content-wrapper .ui-tabs-nav li {
|
106 |
+
display: inline-block;
|
107 |
+
list-style: none;
|
108 |
+
}
|
109 |
+
|
110 |
+
.menu-content-wrapper .ui-tabs-anchor {
|
111 |
+
display: inline-block;
|
112 |
+
padding: 14px 25px;
|
113 |
+
}
|
114 |
+
|
115 |
+
.menu-content-wrapper .ui-nav-collapse {
|
116 |
+
display: none;
|
117 |
+
}
|
118 |
+
|
119 |
+
.menu-content-wrapper .hentry-inner {
|
120 |
+
padding-bottom: 28px;
|
121 |
+
}
|
122 |
+
|
123 |
+
.entry-price {
|
124 |
+
font-size: 18px;
|
125 |
+
font-size: 1.125rem;
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
.menu-content-wrapper a {
|
130 |
+
text-decoration: none;
|
131 |
+
}
|
132 |
+
|
133 |
+
.menu-content-wrapper .entry-title,
|
134 |
+
.menu-content-wrapper .entry-header {
|
135 |
+
margin-bottom: 0;
|
136 |
+
padding: 0;
|
137 |
+
}
|
138 |
+
|
139 |
+
.menu-content-wrapper .entry-title {
|
140 |
+
margin-bottom: 7px;
|
141 |
+
}
|
142 |
+
|
143 |
+
body.ect-post .content-area .singular-content-wrap .menu-content-wrapper .entry-content {
|
144 |
+
padding-top: 0;
|
145 |
+
margin-top: 21px;
|
146 |
+
}
|
147 |
+
|
148 |
+
.ect-post .menu-content-wrapper .more-button {
|
149 |
+
text-align: left;
|
150 |
+
}
|
151 |
+
|
152 |
+
.ect-post .singular-content-wrap .entry-content .entry-header,
|
153 |
+
.ect-post .entry-content,
|
154 |
+
.ect-post .ect-menu .menu-content-wrapper .entry-header {
|
155 |
+
text-align: left;
|
156 |
+
}
|
157 |
+
|
158 |
+
.ect-post .menu-content-wrapper .ect_food_menu_item .entry-header .entry-title {
|
159 |
+
font-size: 24px;
|
160 |
}
|
ect-templates/content-menu.php
CHANGED
@@ -1,36 +1,36 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly
|
5 |
-
}
|
6 |
-
|
7 |
-
?>
|
8 |
-
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
|
9 |
-
<div class="hentry-inner">
|
10 |
-
<?php
|
11 |
-
// Check if has thumbnail
|
12 |
-
if ( has_post_thumbnail( get_the_ID() ) ) :
|
13 |
-
?>
|
14 |
-
<div class="food-menu-thumbnail post-thumbnail">
|
15 |
-
<a href="<?php echo get_the_permalink(); ?>">
|
16 |
-
<?php echo get_the_post_thumbnail( get_the_ID(), array( 50, 50 ) ); ?>
|
17 |
-
</a>
|
18 |
-
</div>
|
19 |
-
<?php endif; ?>
|
20 |
-
<div class="entry-container">
|
21 |
-
<div class="entry-description">
|
22 |
-
<header class="entry-header">
|
23 |
-
<?php the_title( '<h2 class="entry-title"><a href="' . get_the_permalink() . '">', '</a></h2>' ); ?>
|
24 |
-
</header>
|
25 |
-
|
26 |
-
<div class="entry-content">
|
27 |
-
<?php the_excerpt(); ?>
|
28 |
-
</div>
|
29 |
-
</div>
|
30 |
-
|
31 |
-
<div class="entry-price">
|
32 |
-
<p class="item-price"><?php echo esc_html( get_post_meta( get_the_ID(), 'ect_food_price', true ) ); ?></p>
|
33 |
-
</div>
|
34 |
-
</div>
|
35 |
-
</div><!-- .hentry-inner -->
|
36 |
-
</article><!-- .hentry -->
|
1 |
+
<?php
|
2 |
+
|
3 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
+
exit; // Exit if accessed directly
|
5 |
+
}
|
6 |
+
|
7 |
+
?>
|
8 |
+
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
|
9 |
+
<div class="hentry-inner">
|
10 |
+
<?php
|
11 |
+
// Check if has thumbnail
|
12 |
+
if ( has_post_thumbnail( get_the_ID() ) ) :
|
13 |
+
?>
|
14 |
+
<div class="food-menu-thumbnail post-thumbnail">
|
15 |
+
<a href="<?php echo get_the_permalink(); ?>">
|
16 |
+
<?php echo get_the_post_thumbnail( get_the_ID(), array( 50, 50 ) ); ?>
|
17 |
+
</a>
|
18 |
+
</div>
|
19 |
+
<?php endif; ?>
|
20 |
+
<div class="entry-container">
|
21 |
+
<div class="entry-description">
|
22 |
+
<header class="entry-header">
|
23 |
+
<?php the_title( '<h2 class="entry-title"><a href="' . get_the_permalink() . '">', '</a></h2>' ); ?>
|
24 |
+
</header>
|
25 |
+
|
26 |
+
<div class="entry-content">
|
27 |
+
<?php the_excerpt(); ?>
|
28 |
+
</div>
|
29 |
+
</div>
|
30 |
+
|
31 |
+
<div class="entry-price">
|
32 |
+
<p class="item-price"><?php echo esc_html( get_post_meta( get_the_ID(), 'ect_food_price', true ) ); ?></p>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
</div><!-- .hentry-inner -->
|
36 |
+
</article><!-- .hentry -->
|
ect-templates/ect-menu.php
CHANGED
@@ -1,108 +1,108 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* The template for displaying food_menu items
|
4 |
-
*
|
5 |
-
* @package Foodie_World
|
6 |
-
*/
|
7 |
-
?>
|
8 |
-
|
9 |
-
<?php
|
10 |
-
$cat_list = array();
|
11 |
-
|
12 |
-
$menu_categories = essential_content_food_menu_get_menus();
|
13 |
-
|
14 |
-
foreach ( $menu_categories as $category ) {
|
15 |
-
if ( false != $atts['include_type'] ) {
|
16 |
-
if ( in_array( $category->slug, $atts['include_type'] ) ) {
|
17 |
-
$cat_list[] = $category->term_id;
|
18 |
-
}
|
19 |
-
} else {
|
20 |
-
$cat_list[] = $category->term_id;
|
21 |
-
}
|
22 |
-
}
|
23 |
-
?>
|
24 |
-
<div id="tabs" class="tabs">
|
25 |
-
<div class="tabs-nav">
|
26 |
-
<ul class="ui-tabs-nav menu-tabs-nav">
|
27 |
-
<?php
|
28 |
-
$taxonomy = 'ect_food_menu';
|
29 |
-
|
30 |
-
$i = 0;
|
31 |
-
foreach ( $cat_list as $cat ) :
|
32 |
-
$term_obj = get_term_by( 'id', absint( $cat ), $taxonomy );
|
33 |
-
if ( $term_obj ) {
|
34 |
-
$term_name = $cat_name[] = $term_obj->name;
|
35 |
-
|
36 |
-
$class = 'ui-tabs-tab menu-tabs-tab';
|
37 |
-
|
38 |
-
if ( 0 === $i ) {
|
39 |
-
$class .= ' ui-state-active';
|
40 |
-
}
|
41 |
-
|
42 |
-
?>
|
43 |
-
<li class="<?php echo $class; ?>"><a href="#tab-<?php echo esc_attr( $i + 1 ); ?>" class="ui-tabs-anchor"><?php echo esc_html( $term_obj->name ); ?></a></li>
|
44 |
-
<?php
|
45 |
-
}
|
46 |
-
$i++;
|
47 |
-
endforeach;
|
48 |
-
?>
|
49 |
-
</ul>
|
50 |
-
</div><!-- .tabs-nav -->
|
51 |
-
|
52 |
-
<?php
|
53 |
-
$i = 0;
|
54 |
-
foreach ( $cat_list as $cat ) :
|
55 |
-
if ( isset( $cat_name ) ) {
|
56 |
-
?>
|
57 |
-
|
58 |
-
<div class="ui-tabs-panel-wrap">
|
59 |
-
<h4 class="menu-nav-collapse ui-nav-collapse<?php echo ( 0 === $i ) ? ' ui-state-active' : ''; ?>"><a href="#tab-<?php echo esc_attr( $i + 1 ); ?>" class="ui-tabs-anchor"><?php echo esc_html( $cat_name[ $i ] ); ?></a></h4>
|
60 |
-
<div id="tab-<?php echo esc_attr( $i + 1 ); ?>" class="menu-tabs-panel ui-tabs-panel<?php echo ( 0 === $i ) ? ' active-tab' : ''; ?>">
|
61 |
-
<?php
|
62 |
-
|
63 |
-
$args = array();
|
64 |
-
$args['post_type'] = Essential_Content_Food_Menu::MENU_ITEM_POST_TYPE;
|
65 |
-
|
66 |
-
$tax_query = array(
|
67 |
-
array(
|
68 |
-
'taxonomy' => Essential_Content_Food_Menu::MENU_TAX,
|
69 |
-
'terms' => absint( $cat ),
|
70 |
-
'field' => 'term_id',
|
71 |
-
),
|
72 |
-
);
|
73 |
-
|
74 |
-
$args['tax_query'] = $tax_query;
|
75 |
-
|
76 |
-
if ( false != $atts['include_tag'] ) {
|
77 |
-
array_push(
|
78 |
-
$args['tax_query'],
|
79 |
-
array(
|
80 |
-
'taxonomy' => Essential_Content_Food_Menu::MENU_ITEM_LABEL_TAX,
|
81 |
-
'field' => 'slug',
|
82 |
-
'terms' => $atts['include_tag'],
|
83 |
-
)
|
84 |
-
);
|
85 |
-
}
|
86 |
-
|
87 |
-
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
88 |
-
$args['tax_query']['relation'] = 'AND';
|
89 |
-
}
|
90 |
-
|
91 |
-
$loop = new WP_Query( $args );
|
92 |
-
if ( $loop->have_posts() ) :
|
93 |
-
while ( $loop->have_posts() ) :
|
94 |
-
$loop->the_post();
|
95 |
-
ect_get_template_part( 'content', 'menu', $atts );
|
96 |
-
endwhile;
|
97 |
-
endif;
|
98 |
-
wp_reset_postdata();
|
99 |
-
?>
|
100 |
-
</div><!-- #tab-1 -->
|
101 |
-
</div><!-- .ui-tabs-panel-wrap -->
|
102 |
-
|
103 |
-
<?php
|
104 |
-
}
|
105 |
-
$i++;
|
106 |
-
endforeach;
|
107 |
-
?>
|
108 |
-
</div><!-- .tabs -->
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The template for displaying food_menu items
|
4 |
+
*
|
5 |
+
* @package Foodie_World
|
6 |
+
*/
|
7 |
+
?>
|
8 |
+
|
9 |
+
<?php
|
10 |
+
$cat_list = array();
|
11 |
+
|
12 |
+
$menu_categories = essential_content_food_menu_get_menus();
|
13 |
+
|
14 |
+
foreach ( $menu_categories as $category ) {
|
15 |
+
if ( false != $atts['include_type'] ) {
|
16 |
+
if ( in_array( $category->slug, $atts['include_type'] ) ) {
|
17 |
+
$cat_list[] = $category->term_id;
|
18 |
+
}
|
19 |
+
} else {
|
20 |
+
$cat_list[] = $category->term_id;
|
21 |
+
}
|
22 |
+
}
|
23 |
+
?>
|
24 |
+
<div id="tabs" class="tabs">
|
25 |
+
<div class="tabs-nav">
|
26 |
+
<ul class="ui-tabs-nav menu-tabs-nav">
|
27 |
+
<?php
|
28 |
+
$taxonomy = 'ect_food_menu';
|
29 |
+
|
30 |
+
$i = 0;
|
31 |
+
foreach ( $cat_list as $cat ) :
|
32 |
+
$term_obj = get_term_by( 'id', absint( $cat ), $taxonomy );
|
33 |
+
if ( $term_obj ) {
|
34 |
+
$term_name = $cat_name[] = $term_obj->name;
|
35 |
+
|
36 |
+
$class = 'ui-tabs-tab menu-tabs-tab';
|
37 |
+
|
38 |
+
if ( 0 === $i ) {
|
39 |
+
$class .= ' ui-state-active';
|
40 |
+
}
|
41 |
+
|
42 |
+
?>
|
43 |
+
<li class="<?php echo $class; ?>"><a href="#tab-<?php echo esc_attr( $i + 1 ); ?>" class="ui-tabs-anchor"><?php echo esc_html( $term_obj->name ); ?></a></li>
|
44 |
+
<?php
|
45 |
+
}
|
46 |
+
$i++;
|
47 |
+
endforeach;
|
48 |
+
?>
|
49 |
+
</ul>
|
50 |
+
</div><!-- .tabs-nav -->
|
51 |
+
|
52 |
+
<?php
|
53 |
+
$i = 0;
|
54 |
+
foreach ( $cat_list as $cat ) :
|
55 |
+
if ( isset( $cat_name ) ) {
|
56 |
+
?>
|
57 |
+
|
58 |
+
<div class="ui-tabs-panel-wrap">
|
59 |
+
<h4 class="menu-nav-collapse ui-nav-collapse<?php echo ( 0 === $i ) ? ' ui-state-active' : ''; ?>"><a href="#tab-<?php echo esc_attr( $i + 1 ); ?>" class="ui-tabs-anchor"><?php echo esc_html( $cat_name[ $i ] ); ?></a></h4>
|
60 |
+
<div id="tab-<?php echo esc_attr( $i + 1 ); ?>" class="menu-tabs-panel ui-tabs-panel<?php echo ( 0 === $i ) ? ' active-tab' : ''; ?>">
|
61 |
+
<?php
|
62 |
+
|
63 |
+
$args = array();
|
64 |
+
$args['post_type'] = Essential_Content_Food_Menu::MENU_ITEM_POST_TYPE;
|
65 |
+
|
66 |
+
$tax_query = array(
|
67 |
+
array(
|
68 |
+
'taxonomy' => Essential_Content_Food_Menu::MENU_TAX,
|
69 |
+
'terms' => absint( $cat ),
|
70 |
+
'field' => 'term_id',
|
71 |
+
),
|
72 |
+
);
|
73 |
+
|
74 |
+
$args['tax_query'] = $tax_query;
|
75 |
+
|
76 |
+
if ( false != $atts['include_tag'] ) {
|
77 |
+
array_push(
|
78 |
+
$args['tax_query'],
|
79 |
+
array(
|
80 |
+
'taxonomy' => Essential_Content_Food_Menu::MENU_ITEM_LABEL_TAX,
|
81 |
+
'field' => 'slug',
|
82 |
+
'terms' => $atts['include_tag'],
|
83 |
+
)
|
84 |
+
);
|
85 |
+
}
|
86 |
+
|
87 |
+
if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
|
88 |
+
$args['tax_query']['relation'] = 'AND';
|
89 |
+
}
|
90 |
+
|
91 |
+
$loop = new WP_Query( $args );
|
92 |
+
if ( $loop->have_posts() ) :
|
93 |
+
while ( $loop->have_posts() ) :
|
94 |
+
$loop->the_post();
|
95 |
+
ect_get_template_part( 'content', 'menu', $atts );
|
96 |
+
endwhile;
|
97 |
+
endif;
|
98 |
+
wp_reset_postdata();
|
99 |
+
?>
|
100 |
+
</div><!-- #tab-1 -->
|
101 |
+
</div><!-- .ui-tabs-panel-wrap -->
|
102 |
+
|
103 |
+
<?php
|
104 |
+
}
|
105 |
+
$i++;
|
106 |
+
endforeach;
|
107 |
+
?>
|
108 |
+
</div><!-- .tabs -->
|
essential-content-types.php
CHANGED
@@ -1,273 +1,273 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* The plugin bootstrap file
|
5 |
-
*
|
6 |
-
* This file is read by WordPress to generate the plugin information in the plugin
|
7 |
-
* admin area. This file also includes all of the dependencies used by the plugin,
|
8 |
-
* registers the activation and deactivation functions, and defines a function
|
9 |
-
* that starts the plugin.
|
10 |
-
*
|
11 |
-
* @link https://catchplugins.com
|
12 |
-
* @since 1.0.0
|
13 |
-
* @package Essential_Content_Types
|
14 |
-
*
|
15 |
-
* @wordpress-plugin
|
16 |
-
* Plugin Name: Essential Content Types
|
17 |
-
* Plugin URI: https://catchplugins.com/plugins/essential-content-types/
|
18 |
-
* Description: Essential Content Types allows you to feature the impressive content through different content/post types on your website just the way you want it. These content/post types are missed by the themes in WordPress Theme Directory as the feature falls more towards the plugins’ territory.
|
19 |
-
* Version: 1.8.
|
20 |
-
* Author: Catch Plugins
|
21 |
-
* Author URI: https://catchplugins.com
|
22 |
-
* License: GPL-3.0+
|
23 |
-
* License URI: http://www.gnu.org/licenses/gpl-3.0.txt
|
24 |
-
* Text Domain: essential-content-types
|
25 |
-
* Domain Path: /languages
|
26 |
-
*/
|
27 |
-
|
28 |
-
// If this file is called directly, abort.
|
29 |
-
if ( ! defined( 'WPINC' ) ) {
|
30 |
-
die;
|
31 |
-
}
|
32 |
-
|
33 |
-
// Define Version
|
34 |
-
define( 'ESSENTIAL_CONTENT_TYPES_VERSION', '1.8.
|
35 |
-
|
36 |
-
/**
|
37 |
-
* The code that runs during plugin activation.
|
38 |
-
* This action is documented in includes/class-essential-content-types-activator.php
|
39 |
-
*/
|
40 |
-
// The URL of the directory that contains the plugin
|
41 |
-
if ( ! defined( 'ESSENTIAL_CONTENT_TYPES_URL' ) ) {
|
42 |
-
define( 'ESSENTIAL_CONTENT_TYPES_URL', plugin_dir_url( __FILE__ ) );
|
43 |
-
}
|
44 |
-
|
45 |
-
|
46 |
-
// The absolute path of the directory that contains the file
|
47 |
-
if ( ! defined( 'ESSENTIAL_CONTENT_TYPES_PATH' ) ) {
|
48 |
-
define( 'ESSENTIAL_CONTENT_TYPES_PATH', plugin_dir_path( __FILE__ ) );
|
49 |
-
}
|
50 |
-
|
51 |
-
|
52 |
-
// Gets the path to a plugin file or directory, relative to the plugins directory, without the leading and trailing slashes.
|
53 |
-
if ( ! defined( 'ESSENTIAL_CONTENT_TYPES_BASENAME' ) ) {
|
54 |
-
define( 'ESSENTIAL_CONTENT_TYPES_BASENAME', plugin_basename( __FILE__ ) );
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Make plugin available for translation
|
59 |
-
* Translations can be filed in the /languages/ directory
|
60 |
-
*/
|
61 |
-
function activate_essential_content_types() {
|
62 |
-
$required = 'essential-content-types-pro/essential-content-types-pro.php';
|
63 |
-
if ( is_plugin_active( $required ) ) {
|
64 |
-
$message = esc_html__( 'Sorry, Pro plugin is already active. No need to activate Free version. %1$s« Return to Plugins%2$s.', 'essential-content-types' );
|
65 |
-
$message = sprintf( $message, '<br><a href="' . esc_url( admin_url( 'plugins.php' ) ) . '">', '</a>' );
|
66 |
-
wp_die( $message );
|
67 |
-
}
|
68 |
-
require_once plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types-activator.php';
|
69 |
-
Essential_Content_Types_Activator::activate();
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* The code that runs during plugin deactivation.
|
74 |
-
* This action is documented in includes/class-essential-content-types-deactivator.php
|
75 |
-
*/
|
76 |
-
function deactivate_essential_content_types() {
|
77 |
-
require_once plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types-deactivator.php';
|
78 |
-
Essential_Content_Types_Deactivator::deactivate();
|
79 |
-
}
|
80 |
-
|
81 |
-
register_activation_hook( __FILE__, 'activate_essential_content_types' );
|
82 |
-
register_deactivation_hook( __FILE__, 'deactivate_essential_content_types' );
|
83 |
-
|
84 |
-
/**
|
85 |
-
* The core plugin class that is used to define internationalization,
|
86 |
-
* admin-specific hooks, and public-facing site hooks.
|
87 |
-
*/
|
88 |
-
require plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types.php';
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Begins execution of the plugin.
|
92 |
-
*
|
93 |
-
* Since everything within the plugin is registered via hooks,
|
94 |
-
* then kicking off the plugin from this point in the file does
|
95 |
-
* not affect the page life cycle.
|
96 |
-
*
|
97 |
-
* @since 1.0.0
|
98 |
-
*/
|
99 |
-
function run_essential_content_types() {
|
100 |
-
|
101 |
-
$plugin = new Essential_Content_Types();
|
102 |
-
$plugin->run();
|
103 |
-
|
104 |
-
}
|
105 |
-
run_essential_content_types();
|
106 |
-
|
107 |
-
|
108 |
-
if ( ! function_exists( 'ect_get_layout' ) ) :
|
109 |
-
function ect_get_layout() {
|
110 |
-
$layout = array(
|
111 |
-
'1' => 'layout-one',
|
112 |
-
'2' => 'layout-two',
|
113 |
-
'3' => 'layout-three',
|
114 |
-
'4' => 'layout-four',
|
115 |
-
'5' => 'layout-five',
|
116 |
-
'6' => 'layout-six',
|
117 |
-
);
|
118 |
-
return $layout;
|
119 |
-
}
|
120 |
-
endif;
|
121 |
-
|
122 |
-
|
123 |
-
if ( ! function_exists( 'ect_plugin_path' ) ) :
|
124 |
-
/**
|
125 |
-
* Get the plugin path.
|
126 |
-
*
|
127 |
-
* @return string
|
128 |
-
*/
|
129 |
-
function ect_plugin_path() {
|
130 |
-
return untrailingslashit( plugin_dir_path( __FILE__ ) );
|
131 |
-
}
|
132 |
-
endif;
|
133 |
-
|
134 |
-
|
135 |
-
if ( ! function_exists( 'ect_template_path' ) ) :
|
136 |
-
/**
|
137 |
-
* Get the template path.
|
138 |
-
*
|
139 |
-
* @return string
|
140 |
-
*/
|
141 |
-
function ect_template_path() {
|
142 |
-
return apply_filters( 'ect_template_path', 'ect-templates/' );
|
143 |
-
}
|
144 |
-
endif;
|
145 |
-
|
146 |
-
|
147 |
-
if ( ! function_exists( 'ect_get_template_part' ) ) :
|
148 |
-
/**
|
149 |
-
* Get template part (for templates like the shop-loop).
|
150 |
-
*
|
151 |
-
*
|
152 |
-
* @access public
|
153 |
-
* @param mixed $slug Template slug.
|
154 |
-
* @param string $name Template name (default: '').
|
155 |
-
* @param array $atts Options to pass into template.
|
156 |
-
*/
|
157 |
-
function ect_get_template_part( $slug, $name = '', $atts ) {
|
158 |
-
|
159 |
-
$template = '';
|
160 |
-
set_query_var( 'atts', $atts );
|
161 |
-
|
162 |
-
// Look in yourtheme/slug-name.php and yourtheme/ect-templates/slug-name.php.
|
163 |
-
if ( $name ) {
|
164 |
-
$template = locate_template( array( "{$slug}-{$name}.php", ect_template_path() . "{$slug}-{$name}.php" ) );
|
165 |
-
}
|
166 |
-
|
167 |
-
// Get default slug-name.php.
|
168 |
-
if ( empty( $template ) && $name && file_exists( ect_plugin_path() . '/' . ect_template_path() . "{$slug}-{$name}.php" ) ) {
|
169 |
-
$template = ect_plugin_path() . '/' . ect_template_path() . "{$slug}-{$name}.php";
|
170 |
-
}
|
171 |
-
|
172 |
-
// If template file doesn't exist, look in yourtheme/slug.php and yourtheme/ect-templates/slug.php.
|
173 |
-
if ( ! $template ) {
|
174 |
-
$template = locate_template( array( "{$slug}.php", ect_template_path() . "{$slug}.php" ) );
|
175 |
-
}
|
176 |
-
|
177 |
-
// Allow 3rd party plugins to filter template file from their plugin.
|
178 |
-
$template = apply_filters( 'ect_get_template_part', $template, $slug, $name );
|
179 |
-
|
180 |
-
if ( $template ) {
|
181 |
-
load_template( $template, false, 'atts' );
|
182 |
-
}
|
183 |
-
}
|
184 |
-
endif;
|
185 |
-
|
186 |
-
function ect_body_classes( $classes ) {
|
187 |
-
$classes[] = 'ect-post';
|
188 |
-
return $classes;
|
189 |
-
}
|
190 |
-
add_filter( 'body_class', 'ect_body_classes' );
|
191 |
-
/* CTP tabs removal options */
|
192 |
-
require plugin_dir_path( __FILE__ ) . '/includes/ctp-tabs-removal.php';
|
193 |
-
|
194 |
-
$ctp_options = ctp_get_options();
|
195 |
-
if ( 1 == $ctp_options['theme_plugin_tabs'] ) {
|
196 |
-
/* Adds Catch Themes tab in Add theme page and Themes by Catch Themes in Customizer's change theme option. */
|
197 |
-
if ( ! class_exists( 'CatchThemesThemePlugin' ) && ! function_exists( 'add_our_plugins_tab' ) ) {
|
198 |
-
require plugin_dir_path( __FILE__ ) . '/includes/CatchThemesThemePlugin.php';
|
199 |
-
}
|
200 |
-
}
|
201 |
-
|
202 |
-
/* Modify ECT Post type archive title for default values */
|
203 |
-
function ect_check_archive_title(){
|
204 |
-
global $wp_query;
|
205 |
-
$post_type = false;
|
206 |
-
if ( isset( $wp_query->query['post_type'] ) ) {
|
207 |
-
$post_type = $wp_query->query['post_type'];
|
208 |
-
}
|
209 |
-
|
210 |
-
$ect_post_types = array(
|
211 |
-
'featured-content',
|
212 |
-
'jetpack-portfolio',
|
213 |
-
'jetpack-testimonial',
|
214 |
-
'ect-service',
|
215 |
-
);
|
216 |
-
|
217 |
-
if( $post_type !== false || in_array($post_type, $ect_post_types, true)) {
|
218 |
-
add_filter( 'get_the_archive_title', 'ect_modify_archive_title', 10, 1 );
|
219 |
-
}
|
220 |
-
}
|
221 |
-
|
222 |
-
add_action('
|
223 |
-
|
224 |
-
/* set default title if options not found */
|
225 |
-
function ect_modify_archive_title( $title ) {
|
226 |
-
$title_label = '<span class="some-class">%1$s</span>%2$s';
|
227 |
-
$type = ect_get_archive_post_type();
|
228 |
-
|
229 |
-
$default_title = array(
|
230 |
-
'ect_service_title' => esc_html( 'Services', 'essential-content-types' ),
|
231 |
-
'jetpack_testimonial_title' => esc_html( 'Testimonial', 'essential-content-types' ),
|
232 |
-
'jetpack_portfolio_title' => esc_html( 'Portfolio', 'essential-content-types' ),
|
233 |
-
'featured_content_title' => esc_html( 'Featured Content', 'essential-content-types' ),
|
234 |
-
);
|
235 |
-
|
236 |
-
$archive_title = get_option( $type, $default_title[ $type ] );
|
237 |
-
|
238 |
-
if ( '' !== $archive_title ) {
|
239 |
-
return trim(
|
240 |
-
sprintf(
|
241 |
-
$title_label,
|
242 |
-
esc_html_x( 'Archives: ', 'Archive title label.', 'archive-title' ),
|
243 |
-
$archive_title
|
244 |
-
)
|
245 |
-
);
|
246 |
-
} else {
|
247 |
-
return trim(
|
248 |
-
sprintf(
|
249 |
-
$title_label,
|
250 |
-
esc_html_x( 'Archives: ', 'Archive title label.', 'archive-title' ),
|
251 |
-
post_type_archive_title( '', false )
|
252 |
-
)
|
253 |
-
);
|
254 |
-
}
|
255 |
-
|
256 |
-
}
|
257 |
-
|
258 |
-
function ect_get_archive_post_type() {
|
259 |
-
|
260 |
-
global $wp_query;
|
261 |
-
if ( isset( $wp_query->query['post_type'] ) ) {
|
262 |
-
$post_type = $wp_query->query['post_type'];
|
263 |
-
}
|
264 |
-
|
265 |
-
$type = array(
|
266 |
-
'featured-content' => 'featured_content_title',
|
267 |
-
'jetpack-portfolio' => 'jetpack_portfolio_title',
|
268 |
-
'jetpack-testimonial' => 'jetpack_testimonial_title',
|
269 |
-
'ect-service' => 'ect_service_title',
|
270 |
-
);
|
271 |
-
|
272 |
-
return $type[ $post_type ];
|
273 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* The plugin bootstrap file
|
5 |
+
*
|
6 |
+
* This file is read by WordPress to generate the plugin information in the plugin
|
7 |
+
* admin area. This file also includes all of the dependencies used by the plugin,
|
8 |
+
* registers the activation and deactivation functions, and defines a function
|
9 |
+
* that starts the plugin.
|
10 |
+
*
|
11 |
+
* @link https://catchplugins.com
|
12 |
+
* @since 1.0.0
|
13 |
+
* @package Essential_Content_Types
|
14 |
+
*
|
15 |
+
* @wordpress-plugin
|
16 |
+
* Plugin Name: Essential Content Types
|
17 |
+
* Plugin URI: https://catchplugins.com/plugins/essential-content-types/
|
18 |
+
* Description: Essential Content Types allows you to feature the impressive content through different content/post types on your website just the way you want it. These content/post types are missed by the themes in WordPress Theme Directory as the feature falls more towards the plugins’ territory.
|
19 |
+
* Version: 1.8.6
|
20 |
+
* Author: Catch Plugins
|
21 |
+
* Author URI: https://catchplugins.com
|
22 |
+
* License: GPL-3.0+
|
23 |
+
* License URI: http://www.gnu.org/licenses/gpl-3.0.txt
|
24 |
+
* Text Domain: essential-content-types
|
25 |
+
* Domain Path: /languages
|
26 |
+
*/
|
27 |
+
|
28 |
+
// If this file is called directly, abort.
|
29 |
+
if ( ! defined( 'WPINC' ) ) {
|
30 |
+
die;
|
31 |
+
}
|
32 |
+
|
33 |
+
// Define Version
|
34 |
+
define( 'ESSENTIAL_CONTENT_TYPES_VERSION', '1.8.6' );
|
35 |
+
|
36 |
+
/**
|
37 |
+
* The code that runs during plugin activation.
|
38 |
+
* This action is documented in includes/class-essential-content-types-activator.php
|
39 |
+
*/
|
40 |
+
// The URL of the directory that contains the plugin
|
41 |
+
if ( ! defined( 'ESSENTIAL_CONTENT_TYPES_URL' ) ) {
|
42 |
+
define( 'ESSENTIAL_CONTENT_TYPES_URL', plugin_dir_url( __FILE__ ) );
|
43 |
+
}
|
44 |
+
|
45 |
+
|
46 |
+
// The absolute path of the directory that contains the file
|
47 |
+
if ( ! defined( 'ESSENTIAL_CONTENT_TYPES_PATH' ) ) {
|
48 |
+
define( 'ESSENTIAL_CONTENT_TYPES_PATH', plugin_dir_path( __FILE__ ) );
|
49 |
+
}
|
50 |
+
|
51 |
+
|
52 |
+
// Gets the path to a plugin file or directory, relative to the plugins directory, without the leading and trailing slashes.
|
53 |
+
if ( ! defined( 'ESSENTIAL_CONTENT_TYPES_BASENAME' ) ) {
|
54 |
+
define( 'ESSENTIAL_CONTENT_TYPES_BASENAME', plugin_basename( __FILE__ ) );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Make plugin available for translation
|
59 |
+
* Translations can be filed in the /languages/ directory
|
60 |
+
*/
|
61 |
+
function activate_essential_content_types() {
|
62 |
+
$required = 'essential-content-types-pro/essential-content-types-pro.php';
|
63 |
+
if ( is_plugin_active( $required ) ) {
|
64 |
+
$message = esc_html__( 'Sorry, Pro plugin is already active. No need to activate Free version. %1$s« Return to Plugins%2$s.', 'essential-content-types' );
|
65 |
+
$message = sprintf( $message, '<br><a href="' . esc_url( admin_url( 'plugins.php' ) ) . '">', '</a>' );
|
66 |
+
wp_die( $message );
|
67 |
+
}
|
68 |
+
require_once plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types-activator.php';
|
69 |
+
Essential_Content_Types_Activator::activate();
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* The code that runs during plugin deactivation.
|
74 |
+
* This action is documented in includes/class-essential-content-types-deactivator.php
|
75 |
+
*/
|
76 |
+
function deactivate_essential_content_types() {
|
77 |
+
require_once plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types-deactivator.php';
|
78 |
+
Essential_Content_Types_Deactivator::deactivate();
|
79 |
+
}
|
80 |
+
|
81 |
+
register_activation_hook( __FILE__, 'activate_essential_content_types' );
|
82 |
+
register_deactivation_hook( __FILE__, 'deactivate_essential_content_types' );
|
83 |
+
|
84 |
+
/**
|
85 |
+
* The core plugin class that is used to define internationalization,
|
86 |
+
* admin-specific hooks, and public-facing site hooks.
|
87 |
+
*/
|
88 |
+
require plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types.php';
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Begins execution of the plugin.
|
92 |
+
*
|
93 |
+
* Since everything within the plugin is registered via hooks,
|
94 |
+
* then kicking off the plugin from this point in the file does
|
95 |
+
* not affect the page life cycle.
|
96 |
+
*
|
97 |
+
* @since 1.0.0
|
98 |
+
*/
|
99 |
+
function run_essential_content_types() {
|
100 |
+
|
101 |
+
$plugin = new Essential_Content_Types();
|
102 |
+
$plugin->run();
|
103 |
+
|
104 |
+
}
|
105 |
+
run_essential_content_types();
|
106 |
+
|
107 |
+
|
108 |
+
if ( ! function_exists( 'ect_get_layout' ) ) :
|
109 |
+
function ect_get_layout() {
|
110 |
+
$layout = array(
|
111 |
+
'1' => 'layout-one',
|
112 |
+
'2' => 'layout-two',
|
113 |
+
'3' => 'layout-three',
|
114 |
+
'4' => 'layout-four',
|
115 |
+
'5' => 'layout-five',
|
116 |
+
'6' => 'layout-six',
|
117 |
+
);
|
118 |
+
return $layout;
|
119 |
+
}
|
120 |
+
endif;
|
121 |
+
|
122 |
+
|
123 |
+
if ( ! function_exists( 'ect_plugin_path' ) ) :
|
124 |
+
/**
|
125 |
+
* Get the plugin path.
|
126 |
+
*
|
127 |
+
* @return string
|
128 |
+
*/
|
129 |
+
function ect_plugin_path() {
|
130 |
+
return untrailingslashit( plugin_dir_path( __FILE__ ) );
|
131 |
+
}
|
132 |
+
endif;
|
133 |
+
|
134 |
+
|
135 |
+
if ( ! function_exists( 'ect_template_path' ) ) :
|
136 |
+
/**
|
137 |
+
* Get the template path.
|
138 |
+
*
|
139 |
+
* @return string
|
140 |
+
*/
|
141 |
+
function ect_template_path() {
|
142 |
+
return apply_filters( 'ect_template_path', 'ect-templates/' );
|
143 |
+
}
|
144 |
+
endif;
|
145 |
+
|
146 |
+
|
147 |
+
if ( ! function_exists( 'ect_get_template_part' ) ) :
|
148 |
+
/**
|
149 |
+
* Get template part (for templates like the shop-loop).
|
150 |
+
*
|
151 |
+
*
|
152 |
+
* @access public
|
153 |
+
* @param mixed $slug Template slug.
|
154 |
+
* @param string $name Template name (default: '').
|
155 |
+
* @param array $atts Options to pass into template.
|
156 |
+
*/
|
157 |
+
function ect_get_template_part( $slug, $name = '', $atts = '' ) {
|
158 |
+
|
159 |
+
$template = '';
|
160 |
+
set_query_var( 'atts', $atts );
|
161 |
+
|
162 |
+
// Look in yourtheme/slug-name.php and yourtheme/ect-templates/slug-name.php.
|
163 |
+
if ( $name ) {
|
164 |
+
$template = locate_template( array( "{$slug}-{$name}.php", ect_template_path() . "{$slug}-{$name}.php" ) );
|
165 |
+
}
|
166 |
+
|
167 |
+
// Get default slug-name.php.
|
168 |
+
if ( empty( $template ) && $name && file_exists( ect_plugin_path() . '/' . ect_template_path() . "{$slug}-{$name}.php" ) ) {
|
169 |
+
$template = ect_plugin_path() . '/' . ect_template_path() . "{$slug}-{$name}.php";
|
170 |
+
}
|
171 |
+
|
172 |
+
// If template file doesn't exist, look in yourtheme/slug.php and yourtheme/ect-templates/slug.php.
|
173 |
+
if ( ! $template ) {
|
174 |
+
$template = locate_template( array( "{$slug}.php", ect_template_path() . "{$slug}.php" ) );
|
175 |
+
}
|
176 |
+
|
177 |
+
// Allow 3rd party plugins to filter template file from their plugin.
|
178 |
+
$template = apply_filters( 'ect_get_template_part', $template, $slug, $name );
|
179 |
+
|
180 |
+
if ( $template ) {
|
181 |
+
load_template( $template, false, 'atts' );
|
182 |
+
}
|
183 |
+
}
|
184 |
+
endif;
|
185 |
+
|
186 |
+
function ect_body_classes( $classes ) {
|
187 |
+
$classes[] = 'ect-post';
|
188 |
+
return $classes;
|
189 |
+
}
|
190 |
+
add_filter( 'body_class', 'ect_body_classes' );
|
191 |
+
/* CTP tabs removal options */
|
192 |
+
require plugin_dir_path( __FILE__ ) . '/includes/ctp-tabs-removal.php';
|
193 |
+
|
194 |
+
$ctp_options = ctp_get_options();
|
195 |
+
if ( 1 == $ctp_options['theme_plugin_tabs'] ) {
|
196 |
+
/* Adds Catch Themes tab in Add theme page and Themes by Catch Themes in Customizer's change theme option. */
|
197 |
+
if ( ! class_exists( 'CatchThemesThemePlugin' ) && ! function_exists( 'add_our_plugins_tab' ) ) {
|
198 |
+
require plugin_dir_path( __FILE__ ) . '/includes/CatchThemesThemePlugin.php';
|
199 |
+
}
|
200 |
+
}
|
201 |
+
|
202 |
+
/* Modify ECT Post type archive title for default values */
|
203 |
+
function ect_check_archive_title() {
|
204 |
+
global $wp_query;
|
205 |
+
$post_type = false;
|
206 |
+
if ( isset( $wp_query->query['post_type'] ) ) {
|
207 |
+
$post_type = $wp_query->query['post_type'];
|
208 |
+
}
|
209 |
+
|
210 |
+
$ect_post_types = array(
|
211 |
+
'featured-content',
|
212 |
+
'jetpack-portfolio',
|
213 |
+
'jetpack-testimonial',
|
214 |
+
'ect-service',
|
215 |
+
);
|
216 |
+
|
217 |
+
if ( $post_type !== false || in_array( $post_type, $ect_post_types, true ) ) {
|
218 |
+
add_filter( 'get_the_archive_title', 'ect_modify_archive_title', 10, 1 );
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
add_action( 'wp_head', 'ect_check_archive_title' );
|
223 |
+
|
224 |
+
/* set default title if options not found */
|
225 |
+
function ect_modify_archive_title( $title ) {
|
226 |
+
$title_label = '<span class="some-class">%1$s</span>%2$s';
|
227 |
+
$type = ect_get_archive_post_type();
|
228 |
+
|
229 |
+
$default_title = array(
|
230 |
+
'ect_service_title' => esc_html( 'Services', 'essential-content-types' ),
|
231 |
+
'jetpack_testimonial_title' => esc_html( 'Testimonial', 'essential-content-types' ),
|
232 |
+
'jetpack_portfolio_title' => esc_html( 'Portfolio', 'essential-content-types' ),
|
233 |
+
'featured_content_title' => esc_html( 'Featured Content', 'essential-content-types' ),
|
234 |
+
);
|
235 |
+
|
236 |
+
$archive_title = get_option( $type, $default_title[ $type ] );
|
237 |
+
|
238 |
+
if ( '' !== $archive_title ) {
|
239 |
+
return trim(
|
240 |
+
sprintf(
|
241 |
+
$title_label,
|
242 |
+
esc_html_x( 'Archives: ', 'Archive title label.', 'archive-title' ),
|
243 |
+
$archive_title
|
244 |
+
)
|
245 |
+
);
|
246 |
+
} else {
|
247 |
+
return trim(
|
248 |
+
sprintf(
|
249 |
+
$title_label,
|
250 |
+
esc_html_x( 'Archives: ', 'Archive title label.', 'archive-title' ),
|
251 |
+
post_type_archive_title( '', false )
|
252 |
+
)
|
253 |
+
);
|
254 |
+
}
|
255 |
+
|
256 |
+
}
|
257 |
+
|
258 |
+
function ect_get_archive_post_type() {
|
259 |
+
|
260 |
+
global $wp_query;
|
261 |
+
if ( isset( $wp_query->query['post_type'] ) ) {
|
262 |
+
$post_type = $wp_query->query['post_type'];
|
263 |
+
}
|
264 |
+
|
265 |
+
$type = array(
|
266 |
+
'featured-content' => 'featured_content_title',
|
267 |
+
'jetpack-portfolio' => 'jetpack_portfolio_title',
|
268 |
+
'jetpack-testimonial' => 'jetpack_testimonial_title',
|
269 |
+
'ect-service' => 'ect_service_title',
|
270 |
+
);
|
271 |
+
|
272 |
+
return $type[ $post_type ];
|
273 |
+
}
|
includes/CatchThemesThemePlugin.php
CHANGED
@@ -1,484 +1,484 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class CatchThemesThemePlugin {
|
4 |
-
public function __construct() {
|
5 |
-
remove_action( 'wp_ajax_query-themes', array( $this, 'wp_ajax_query_themes' ), 1 );
|
6 |
-
add_action( 'wp_ajax_query-themes', array( $this, 'wp_ajax_custom_query_themes' ), 1 );
|
7 |
-
|
8 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'our_themes_script' ) );
|
9 |
-
|
10 |
-
if ( ! is_multisite() ) {
|
11 |
-
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
12 |
-
}
|
13 |
-
|
14 |
-
global $wp_customize;
|
15 |
-
remove_action( 'wp_ajax_customize_load_themes', array( $wp_customize, 'handle_load_themes_request' ) );
|
16 |
-
add_action( 'wp_ajax_customize_load_themes', array( $this, 'handle_load_themes_request' ) );
|
17 |
-
|
18 |
-
add_filter( 'install_plugins_tabs', array( $this, 'add_our_plugins_tab' ), 1 );
|
19 |
-
add_filter( 'install_plugins_table_api_args_catchplugins', array( $this, 'catchplugins' ), 1 );
|
20 |
-
add_action( 'install_plugins_catchplugins', array( $this, 'plugins_table' ) );
|
21 |
-
}
|
22 |
-
|
23 |
-
/* Adds Catch Themes tab in Add Theme page to show all themes by Catch Themes in wordpress.org
|
24 |
-
* taken from wp-admin/includes/ajax-action.php wp_ajax_query_themes().
|
25 |
-
* Ajax handler for getting themes from themes_api().
|
26 |
-
*
|
27 |
-
* @since 3.9.0
|
28 |
-
*
|
29 |
-
* @global array $themes_allowedtags
|
30 |
-
* @global array $theme_field_defaults
|
31 |
-
*/
|
32 |
-
public function wp_ajax_custom_query_themes() {
|
33 |
-
global $themes_allowedtags, $theme_field_defaults;
|
34 |
-
|
35 |
-
if ( ! current_user_can( 'install_themes' ) ) {
|
36 |
-
wp_send_json_error();
|
37 |
-
}
|
38 |
-
|
39 |
-
$args = wp_parse_args(
|
40 |
-
wp_unslash( $_REQUEST['request'] ),
|
41 |
-
array(
|
42 |
-
'per_page' => 20,
|
43 |
-
'fields' => array_merge(
|
44 |
-
(array) $theme_field_defaults,
|
45 |
-
array(
|
46 |
-
'reviews_url' => true, // Explicitly request the reviews URL to be linked from the Add Themes screen.
|
47 |
-
)
|
48 |
-
),
|
49 |
-
)
|
50 |
-
);
|
51 |
-
|
52 |
-
if ( isset( $args['browse'] ) && 'catchthemes' === $args['browse'] && ! isset( $args['user'] ) ) {
|
53 |
-
$args['author'] = 'catchthemes';
|
54 |
-
unset( $args['browse'] );
|
55 |
-
}
|
56 |
-
|
57 |
-
if ( isset( $args['browse'] ) && 'favorites' === $args['browse'] && ! isset( $args['user'] ) ) {
|
58 |
-
$user = get_user_option( 'wporg_favorites' );
|
59 |
-
if ( $user ) {
|
60 |
-
$args['user'] = $user;
|
61 |
-
}
|
62 |
-
}
|
63 |
-
|
64 |
-
$old_filter = isset( $args['browse'] ) ? $args['browse'] : 'search';
|
65 |
-
|
66 |
-
/** This filter is documented in wp-admin/includes/class-wp-theme-install-list-table.php */
|
67 |
-
$args = apply_filters( 'install_themes_table_api_args_' . $old_filter, $args );
|
68 |
-
|
69 |
-
$api = themes_api( 'query_themes', $args );
|
70 |
-
|
71 |
-
if ( is_wp_error( $api ) ) {
|
72 |
-
wp_send_json_error();
|
73 |
-
}
|
74 |
-
|
75 |
-
$update_php = network_admin_url( 'update.php?action=install-theme' );
|
76 |
-
foreach ( $api->themes as &$theme ) {
|
77 |
-
$theme->install_url = add_query_arg(
|
78 |
-
array(
|
79 |
-
'theme' => $theme->slug,
|
80 |
-
'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ),
|
81 |
-
),
|
82 |
-
$update_php
|
83 |
-
);
|
84 |
-
|
85 |
-
if ( current_user_can( 'switch_themes' ) ) {
|
86 |
-
if ( is_multisite() ) {
|
87 |
-
$theme->activate_url = add_query_arg(
|
88 |
-
array(
|
89 |
-
'action' => 'enable',
|
90 |
-
'_wpnonce' => wp_create_nonce( 'enable-theme_' . $theme->slug ),
|
91 |
-
'theme' => $theme->slug,
|
92 |
-
),
|
93 |
-
network_admin_url( 'themes.php' )
|
94 |
-
);
|
95 |
-
} else {
|
96 |
-
$theme->activate_url = add_query_arg(
|
97 |
-
array(
|
98 |
-
'action' => 'activate',
|
99 |
-
'_wpnonce' => wp_create_nonce( 'switch-theme_' . $theme->slug ),
|
100 |
-
'stylesheet' => $theme->slug,
|
101 |
-
),
|
102 |
-
admin_url( 'themes.php' )
|
103 |
-
);
|
104 |
-
}
|
105 |
-
}
|
106 |
-
|
107 |
-
if ( ! is_multisite() && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
|
108 |
-
$theme->customize_url = add_query_arg(
|
109 |
-
array(
|
110 |
-
'return' => urlencode( network_admin_url( 'theme-install.php', 'relative' ) ),
|
111 |
-
),
|
112 |
-
wp_customize_url( $theme->slug )
|
113 |
-
);
|
114 |
-
}
|
115 |
-
|
116 |
-
$theme->name = wp_kses( $theme->name, $themes_allowedtags );
|
117 |
-
$theme->author = wp_kses( $theme->author['display_name'], $themes_allowedtags );
|
118 |
-
$theme->version = wp_kses( $theme->version, $themes_allowedtags );
|
119 |
-
$theme->description = wp_kses( $theme->description, $themes_allowedtags );
|
120 |
-
|
121 |
-
$theme->stars = wp_star_rating(
|
122 |
-
array(
|
123 |
-
'rating' => $theme->rating,
|
124 |
-
'type' => 'percent',
|
125 |
-
'number' => $theme->num_ratings,
|
126 |
-
'echo' => false,
|
127 |
-
)
|
128 |
-
);
|
129 |
-
|
130 |
-
$theme->num_ratings = number_format_i18n( $theme->num_ratings );
|
131 |
-
$theme->preview_url = set_url_scheme( $theme->preview_url );
|
132 |
-
$theme->compatible_wp = is_wp_version_compatible( $theme->requires );
|
133 |
-
$theme->compatible_php = is_php_version_compatible( $theme->requires_php );
|
134 |
-
|
135 |
-
}
|
136 |
-
|
137 |
-
wp_send_json_success( $api );
|
138 |
-
}
|
139 |
-
|
140 |
-
public function our_themes_script( $hook_suffix ) {
|
141 |
-
|
142 |
-
if ( 'theme-install.php' === $hook_suffix ) {
|
143 |
-
wp_enqueue_script( 'our-themes-script', plugin_dir_url( __FILE__ ) . '../js/our-themes.js', array( 'jquery' ), '2018-05-16' );
|
144 |
-
}
|
145 |
-
}
|
146 |
-
|
147 |
-
/* Add Catch Themes Section in Theme in Customizer */
|
148 |
-
public function customize_register( $wp_customize ) {
|
149 |
-
$wp_customize->add_section(
|
150 |
-
new WP_Customize_Themes_Section(
|
151 |
-
$wp_customize,
|
152 |
-
'catchthemes',
|
153 |
-
array(
|
154 |
-
'title' => __( 'Themes by CatchThemes', 'catch-themes-demo-import' ),
|
155 |
-
'action' => 'catchthemes',
|
156 |
-
'capability' => 'install_themes',
|
157 |
-
'panel' => 'themes',
|
158 |
-
'priority' => 6,
|
159 |
-
)
|
160 |
-
)
|
161 |
-
);
|
162 |
-
}
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
/**
|
168 |
-
* Load themes into the theme browsing/installation UI.
|
169 |
-
* taken from wp-includes/cllass-wp-customize-manager.php
|
170 |
-
* @since 4.9.0
|
171 |
-
*/
|
172 |
-
public function handle_load_themes_request() {
|
173 |
-
check_ajax_referer( 'switch_themes', 'nonce' );
|
174 |
-
if ( ! current_user_can( 'switch_themes' ) ) {
|
175 |
-
wp_die( -1 );
|
176 |
-
}
|
177 |
-
|
178 |
-
if ( empty( $_POST['theme_action'] ) ) {
|
179 |
-
wp_send_json_error( 'missing_theme_action' );
|
180 |
-
}
|
181 |
-
$theme_action = sanitize_key( $_POST['theme_action'] );
|
182 |
-
$themes = array();
|
183 |
-
$args = array();
|
184 |
-
|
185 |
-
// Define query filters based on user input.
|
186 |
-
if ( ! array_key_exists( 'search', $_POST ) ) {
|
187 |
-
$args['search'] = '';
|
188 |
-
} else {
|
189 |
-
$args['search'] = sanitize_text_field( wp_unslash( $_POST['search'] ) );
|
190 |
-
}
|
191 |
-
|
192 |
-
if ( ! array_key_exists( 'tags', $_POST ) ) {
|
193 |
-
$args['tag'] = '';
|
194 |
-
} else {
|
195 |
-
$args['tag'] = array_map( 'sanitize_text_field', wp_unslash( (array) $_POST['tags'] ) );
|
196 |
-
}
|
197 |
-
|
198 |
-
if ( ! array_key_exists( 'page', $_POST ) ) {
|
199 |
-
$args['page'] = 1;
|
200 |
-
} else {
|
201 |
-
$args['page'] = absint( $_POST['page'] );
|
202 |
-
}
|
203 |
-
|
204 |
-
require_once ABSPATH . 'wp-admin/includes/theme.php';
|
205 |
-
|
206 |
-
if ( 'installed' === $theme_action ) {
|
207 |
-
|
208 |
-
// Load all installed themes from wp_prepare_themes_for_js().
|
209 |
-
$themes = array( 'themes' => wp_prepare_themes_for_js() );
|
210 |
-
foreach ( $themes['themes'] as &$theme ) {
|
211 |
-
$theme['type'] = 'installed';
|
212 |
-
$theme['active'] = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme['id'] );
|
213 |
-
}
|
214 |
-
} elseif ( 'catchthemes' === $theme_action ) {
|
215 |
-
|
216 |
-
// Load WordPress.org themes from the .org API and normalize data to match installed theme objects.
|
217 |
-
if ( ! current_user_can( 'install_themes' ) ) {
|
218 |
-
wp_die( -1 );
|
219 |
-
}
|
220 |
-
|
221 |
-
// Arguments for all queries.
|
222 |
-
$wporg_args = array(
|
223 |
-
'per_page' => 100,
|
224 |
-
'fields' => array(
|
225 |
-
'reviews_url' => true, // Explicitly request the reviews URL to be linked from the customizer.
|
226 |
-
),
|
227 |
-
);
|
228 |
-
|
229 |
-
$args = array_merge( $wporg_args, $args );
|
230 |
-
|
231 |
-
if ( '' === $args['search'] && '' === $args['tag'] ) {
|
232 |
-
$args['browse'] = 'new'; // Sort by latest themes by default.
|
233 |
-
}
|
234 |
-
|
235 |
-
$args['author'] = 'catchthemes';
|
236 |
-
|
237 |
-
// Load themes from the .org API.
|
238 |
-
$themes = themes_api( 'query_themes', $args );
|
239 |
-
if ( is_wp_error( $themes ) ) {
|
240 |
-
wp_send_json_error();
|
241 |
-
}
|
242 |
-
|
243 |
-
// This list matches the allowed tags in wp-admin/includes/theme-install.php.
|
244 |
-
$themes_allowedtags = array_fill_keys(
|
245 |
-
array( 'a', 'abbr', 'acronym', 'code', 'pre', 'em', 'strong', 'div', 'p', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'img' ),
|
246 |
-
array()
|
247 |
-
);
|
248 |
-
$themes_allowedtags['a'] = array_fill_keys( array( 'href', 'title', 'target' ), true );
|
249 |
-
$themes_allowedtags['acronym']['title'] = true;
|
250 |
-
$themes_allowedtags['abbr']['title'] = true;
|
251 |
-
$themes_allowedtags['img'] = array_fill_keys( array( 'src', 'class', 'alt' ), true );
|
252 |
-
|
253 |
-
// Prepare a list of installed themes to check against before the loop.
|
254 |
-
$installed_themes = array();
|
255 |
-
$wp_themes = wp_get_themes();
|
256 |
-
foreach ( $wp_themes as $theme ) {
|
257 |
-
$installed_themes[] = $theme->get_stylesheet();
|
258 |
-
}
|
259 |
-
$update_php = network_admin_url( 'update.php?action=install-theme' );
|
260 |
-
|
261 |
-
// Set up properties for themes available on WordPress.org.
|
262 |
-
foreach ( $themes->themes as &$theme ) {
|
263 |
-
$theme->install_url = add_query_arg(
|
264 |
-
array(
|
265 |
-
'theme' => $theme->slug,
|
266 |
-
'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ),
|
267 |
-
),
|
268 |
-
$update_php
|
269 |
-
);
|
270 |
-
|
271 |
-
$theme->name = wp_kses( $theme->name, $themes_allowedtags );
|
272 |
-
$theme->version = wp_kses( $theme->version, $themes_allowedtags );
|
273 |
-
$theme->description = wp_kses( $theme->description, $themes_allowedtags );
|
274 |
-
$theme->stars = wp_star_rating(
|
275 |
-
array(
|
276 |
-
'rating' => $theme->rating,
|
277 |
-
'type' => 'percent',
|
278 |
-
'number' => $theme->num_ratings,
|
279 |
-
'echo' => false,
|
280 |
-
)
|
281 |
-
);
|
282 |
-
$theme->num_ratings = number_format_i18n( $theme->num_ratings );
|
283 |
-
$theme->preview_url = set_url_scheme( $theme->preview_url );
|
284 |
-
|
285 |
-
// Handle themes that are already installed as installed themes.
|
286 |
-
if ( in_array( $theme->slug, $installed_themes, true ) ) {
|
287 |
-
$theme->type = 'installed';
|
288 |
-
} else {
|
289 |
-
$theme->type = $theme_action;
|
290 |
-
}
|
291 |
-
|
292 |
-
// Set active based on customized theme.
|
293 |
-
$theme->active = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme->slug );
|
294 |
-
|
295 |
-
// Map available theme properties to installed theme properties.
|
296 |
-
$theme->id = $theme->slug;
|
297 |
-
$theme->screenshot = array( $theme->screenshot_url );
|
298 |
-
$theme->authorAndUri = wp_kses( $theme->author['display_name'], $themes_allowedtags );
|
299 |
-
$theme->compatibleWP = is_wp_version_compatible( $theme->requires ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
300 |
-
$theme->compatiblePHP = is_php_version_compatible( $theme->requires_php ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
301 |
-
|
302 |
-
if ( isset( $theme->parent ) ) {
|
303 |
-
$theme->parent = $theme->parent['slug'];
|
304 |
-
} else {
|
305 |
-
$theme->parent = false;
|
306 |
-
}
|
307 |
-
unset( $theme->slug );
|
308 |
-
unset( $theme->screenshot_url );
|
309 |
-
unset( $theme->author );
|
310 |
-
} // End foreach().
|
311 |
-
} elseif ( 'wporg' === $theme_action ) {
|
312 |
-
|
313 |
-
// Load WordPress.org themes from the .org API and normalize data to match installed theme objects.
|
314 |
-
if ( ! current_user_can( 'install_themes' ) ) {
|
315 |
-
wp_die( -1 );
|
316 |
-
}
|
317 |
-
|
318 |
-
// Arguments for all queries.
|
319 |
-
$wporg_args = array(
|
320 |
-
'per_page' => 100,
|
321 |
-
'fields' => array(
|
322 |
-
'reviews_url' => true, // Explicitly request the reviews URL to be linked from the customizer.
|
323 |
-
),
|
324 |
-
);
|
325 |
-
|
326 |
-
$args = array_merge( $wporg_args, $args );
|
327 |
-
|
328 |
-
if ( '' === $args['search'] && '' === $args['tag'] ) {
|
329 |
-
$args['browse'] = 'new'; // Sort by latest themes by default.
|
330 |
-
}
|
331 |
-
|
332 |
-
// Load themes from the .org API.
|
333 |
-
$themes = themes_api( 'query_themes', $args );
|
334 |
-
if ( is_wp_error( $themes ) ) {
|
335 |
-
wp_send_json_error();
|
336 |
-
}
|
337 |
-
|
338 |
-
// This list matches the allowed tags in wp-admin/includes/theme-install.php.
|
339 |
-
$themes_allowedtags = array_fill_keys(
|
340 |
-
array( 'a', 'abbr', 'acronym', 'code', 'pre', 'em', 'strong', 'div', 'p', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'img' ),
|
341 |
-
array()
|
342 |
-
);
|
343 |
-
$themes_allowedtags['a'] = array_fill_keys( array( 'href', 'title', 'target' ), true );
|
344 |
-
$themes_allowedtags['acronym']['title'] = true;
|
345 |
-
$themes_allowedtags['abbr']['title'] = true;
|
346 |
-
$themes_allowedtags['img'] = array_fill_keys( array( 'src', 'class', 'alt' ), true );
|
347 |
-
|
348 |
-
// Prepare a list of installed themes to check against before the loop.
|
349 |
-
$installed_themes = array();
|
350 |
-
$wp_themes = wp_get_themes();
|
351 |
-
foreach ( $wp_themes as $theme ) {
|
352 |
-
$installed_themes[] = $theme->get_stylesheet();
|
353 |
-
}
|
354 |
-
$update_php = network_admin_url( 'update.php?action=install-theme' );
|
355 |
-
|
356 |
-
// Set up properties for themes available on WordPress.org.
|
357 |
-
foreach ( $themes->themes as &$theme ) {
|
358 |
-
$theme->install_url = add_query_arg(
|
359 |
-
array(
|
360 |
-
'theme' => $theme->slug,
|
361 |
-
'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ),
|
362 |
-
),
|
363 |
-
$update_php
|
364 |
-
);
|
365 |
-
|
366 |
-
$theme->name = wp_kses( $theme->name, $themes_allowedtags );
|
367 |
-
$theme->version = wp_kses( $theme->version, $themes_allowedtags );
|
368 |
-
$theme->description = wp_kses( $theme->description, $themes_allowedtags );
|
369 |
-
$theme->stars = wp_star_rating(
|
370 |
-
array(
|
371 |
-
'rating' => $theme->rating,
|
372 |
-
'type' => 'percent',
|
373 |
-
'number' => $theme->num_ratings,
|
374 |
-
'echo' => false,
|
375 |
-
)
|
376 |
-
);
|
377 |
-
$theme->num_ratings = number_format_i18n( $theme->num_ratings );
|
378 |
-
$theme->preview_url = set_url_scheme( $theme->preview_url );
|
379 |
-
|
380 |
-
// Handle themes that are already installed as installed themes.
|
381 |
-
if ( in_array( $theme->slug, $installed_themes, true ) ) {
|
382 |
-
$theme->type = 'installed';
|
383 |
-
} else {
|
384 |
-
$theme->type = $theme_action;
|
385 |
-
}
|
386 |
-
|
387 |
-
// Set active based on customized theme.
|
388 |
-
$theme->active = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme->slug );
|
389 |
-
|
390 |
-
// Map available theme properties to installed theme properties.
|
391 |
-
$theme->id = $theme->slug;
|
392 |
-
$theme->screenshot = array( $theme->screenshot_url );
|
393 |
-
$theme->authorAndUri = wp_kses( $theme->author['display_name'], $themes_allowedtags );
|
394 |
-
$theme->compatibleWP = is_wp_version_compatible( $theme->requires ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
395 |
-
$theme->compatiblePHP = is_php_version_compatible( $theme->requires_php ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
396 |
-
|
397 |
-
if ( isset( $theme->parent ) ) {
|
398 |
-
$theme->parent = $theme->parent['slug'];
|
399 |
-
} else {
|
400 |
-
$theme->parent = false;
|
401 |
-
}
|
402 |
-
unset( $theme->slug );
|
403 |
-
unset( $theme->screenshot_url );
|
404 |
-
unset( $theme->author );
|
405 |
-
} // End foreach().
|
406 |
-
} // End if().
|
407 |
-
|
408 |
-
/**
|
409 |
-
* Filters the theme data loaded in the customizer.
|
410 |
-
*
|
411 |
-
* This allows theme data to be loading from an external source,
|
412 |
-
* or modification of data loaded from `wp_prepare_themes_for_js()`
|
413 |
-
* or WordPress.org via `themes_api()`.
|
414 |
-
*
|
415 |
-
* @since 4.9.0
|
416 |
-
*
|
417 |
-
* @see wp_prepare_themes_for_js()
|
418 |
-
* @see themes_api()
|
419 |
-
* @see WP_Customize_Manager::__construct()
|
420 |
-
*
|
421 |
-
* @param array $themes Nested array of theme data.
|
422 |
-
* @param array $args List of arguments, such as page, search term, and tags to query for.
|
423 |
-
* @param WP_Customize_Manager $manager Instance of Customize manager.
|
424 |
-
*/
|
425 |
-
$themes = apply_filters( 'customize_load_themes', $themes, $args, $wp_customize );
|
426 |
-
|
427 |
-
wp_send_json_success( $themes );
|
428 |
-
}
|
429 |
-
|
430 |
-
/* Plugins */
|
431 |
-
/* Adds Catch Plugins tab in Add Plugin page to show all plugins by Catch Plugins in wordpress.org */
|
432 |
-
public function add_our_plugins_tab( $tabs ) {
|
433 |
-
// Add our filter here
|
434 |
-
$tabs['catchplugins'] = _x( 'Catch Plugins', 'Plugin Installer' );
|
435 |
-
|
436 |
-
return $tabs;
|
437 |
-
}
|
438 |
-
|
439 |
-
public function catchplugins() {
|
440 |
-
/* From CORE Start */
|
441 |
-
global $paged, $tab;
|
442 |
-
wp_reset_vars( array( 'tab' ) );
|
443 |
-
|
444 |
-
$defined_class = new WP_Plugin_Install_List_Table();
|
445 |
-
$paged = $defined_class->get_pagenum();
|
446 |
-
|
447 |
-
$per_page = 30;
|
448 |
-
//$installed_plugins = catch_get_installed_plugins();
|
449 |
-
|
450 |
-
$args = array(
|
451 |
-
'page' => $paged,
|
452 |
-
'per_page' => $per_page,
|
453 |
-
'fields' => array(
|
454 |
-
'last_updated' => true,
|
455 |
-
'icons' => true,
|
456 |
-
'active_installs' => true,
|
457 |
-
),
|
458 |
-
// Send the locale and installed plugin slugs to the API so it can provide context-sensitive results.
|
459 |
-
'locale' => get_user_locale(),
|
460 |
-
//'installed_plugins' => array_keys( $installed_plugins ),
|
461 |
-
);
|
462 |
-
/* From CORE End */
|
463 |
-
|
464 |
-
// Add author filter for our plugins
|
465 |
-
$args['author'] = 'catchplugins';
|
466 |
-
|
467 |
-
return $args;
|
468 |
-
}
|
469 |
-
|
470 |
-
public function plugins_table() {
|
471 |
-
global $wp_list_table;
|
472 |
-
printf(
|
473 |
-
'<p class="catch-plugins-list">' . __( 'You can use any of our free plugins or premium plugins from <a href="%s" target="_blank">Catch Plugins</a>' ) . '.</p>',
|
474 |
-
'https://catchplugins.com/'
|
475 |
-
);
|
476 |
-
?>
|
477 |
-
<form id="plugin-filter" method="post">
|
478 |
-
<?php $wp_list_table->display(); ?>
|
479 |
-
</form>
|
480 |
-
<?php
|
481 |
-
}
|
482 |
-
}
|
483 |
-
|
484 |
-
$catchthemes_theme_plugin = new CatchThemesThemePlugin();
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class CatchThemesThemePlugin {
|
4 |
+
public function __construct() {
|
5 |
+
remove_action( 'wp_ajax_query-themes', array( $this, 'wp_ajax_query_themes' ), 1 );
|
6 |
+
add_action( 'wp_ajax_query-themes', array( $this, 'wp_ajax_custom_query_themes' ), 1 );
|
7 |
+
|
8 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'our_themes_script' ) );
|
9 |
+
|
10 |
+
if ( ! is_multisite() ) {
|
11 |
+
add_action( 'customize_register', array( $this, 'customize_register' ) );
|
12 |
+
}
|
13 |
+
|
14 |
+
global $wp_customize;
|
15 |
+
remove_action( 'wp_ajax_customize_load_themes', array( $wp_customize, 'handle_load_themes_request' ) );
|
16 |
+
add_action( 'wp_ajax_customize_load_themes', array( $this, 'handle_load_themes_request' ) );
|
17 |
+
|
18 |
+
add_filter( 'install_plugins_tabs', array( $this, 'add_our_plugins_tab' ), 1 );
|
19 |
+
add_filter( 'install_plugins_table_api_args_catchplugins', array( $this, 'catchplugins' ), 1 );
|
20 |
+
add_action( 'install_plugins_catchplugins', array( $this, 'plugins_table' ) );
|
21 |
+
}
|
22 |
+
|
23 |
+
/* Adds Catch Themes tab in Add Theme page to show all themes by Catch Themes in wordpress.org
|
24 |
+
* taken from wp-admin/includes/ajax-action.php wp_ajax_query_themes().
|
25 |
+
* Ajax handler for getting themes from themes_api().
|
26 |
+
*
|
27 |
+
* @since 3.9.0
|
28 |
+
*
|
29 |
+
* @global array $themes_allowedtags
|
30 |
+
* @global array $theme_field_defaults
|
31 |
+
*/
|
32 |
+
public function wp_ajax_custom_query_themes() {
|
33 |
+
global $themes_allowedtags, $theme_field_defaults;
|
34 |
+
|
35 |
+
if ( ! current_user_can( 'install_themes' ) ) {
|
36 |
+
wp_send_json_error();
|
37 |
+
}
|
38 |
+
|
39 |
+
$args = wp_parse_args(
|
40 |
+
wp_unslash( $_REQUEST['request'] ),
|
41 |
+
array(
|
42 |
+
'per_page' => 20,
|
43 |
+
'fields' => array_merge(
|
44 |
+
(array) $theme_field_defaults,
|
45 |
+
array(
|
46 |
+
'reviews_url' => true, // Explicitly request the reviews URL to be linked from the Add Themes screen.
|
47 |
+
)
|
48 |
+
),
|
49 |
+
)
|
50 |
+
);
|
51 |
+
|
52 |
+
if ( isset( $args['browse'] ) && 'catchthemes' === $args['browse'] && ! isset( $args['user'] ) ) {
|
53 |
+
$args['author'] = 'catchthemes';
|
54 |
+
unset( $args['browse'] );
|
55 |
+
}
|
56 |
+
|
57 |
+
if ( isset( $args['browse'] ) && 'favorites' === $args['browse'] && ! isset( $args['user'] ) ) {
|
58 |
+
$user = get_user_option( 'wporg_favorites' );
|
59 |
+
if ( $user ) {
|
60 |
+
$args['user'] = $user;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
$old_filter = isset( $args['browse'] ) ? $args['browse'] : 'search';
|
65 |
+
|
66 |
+
/** This filter is documented in wp-admin/includes/class-wp-theme-install-list-table.php */
|
67 |
+
$args = apply_filters( 'install_themes_table_api_args_' . $old_filter, $args );
|
68 |
+
|
69 |
+
$api = themes_api( 'query_themes', $args );
|
70 |
+
|
71 |
+
if ( is_wp_error( $api ) ) {
|
72 |
+
wp_send_json_error();
|
73 |
+
}
|
74 |
+
|
75 |
+
$update_php = network_admin_url( 'update.php?action=install-theme' );
|
76 |
+
foreach ( $api->themes as &$theme ) {
|
77 |
+
$theme->install_url = add_query_arg(
|
78 |
+
array(
|
79 |
+
'theme' => $theme->slug,
|
80 |
+
'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ),
|
81 |
+
),
|
82 |
+
$update_php
|
83 |
+
);
|
84 |
+
|
85 |
+
if ( current_user_can( 'switch_themes' ) ) {
|
86 |
+
if ( is_multisite() ) {
|
87 |
+
$theme->activate_url = add_query_arg(
|
88 |
+
array(
|
89 |
+
'action' => 'enable',
|
90 |
+
'_wpnonce' => wp_create_nonce( 'enable-theme_' . $theme->slug ),
|
91 |
+
'theme' => $theme->slug,
|
92 |
+
),
|
93 |
+
network_admin_url( 'themes.php' )
|
94 |
+
);
|
95 |
+
} else {
|
96 |
+
$theme->activate_url = add_query_arg(
|
97 |
+
array(
|
98 |
+
'action' => 'activate',
|
99 |
+
'_wpnonce' => wp_create_nonce( 'switch-theme_' . $theme->slug ),
|
100 |
+
'stylesheet' => $theme->slug,
|
101 |
+
),
|
102 |
+
admin_url( 'themes.php' )
|
103 |
+
);
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
if ( ! is_multisite() && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
|
108 |
+
$theme->customize_url = add_query_arg(
|
109 |
+
array(
|
110 |
+
'return' => urlencode( network_admin_url( 'theme-install.php', 'relative' ) ),
|
111 |
+
),
|
112 |
+
wp_customize_url( $theme->slug )
|
113 |
+
);
|
114 |
+
}
|
115 |
+
|
116 |
+
$theme->name = wp_kses( $theme->name, $themes_allowedtags );
|
117 |
+
$theme->author = wp_kses( $theme->author['display_name'], $themes_allowedtags );
|
118 |
+
$theme->version = wp_kses( $theme->version, $themes_allowedtags );
|
119 |
+
$theme->description = wp_kses( $theme->description, $themes_allowedtags );
|
120 |
+
|
121 |
+
$theme->stars = wp_star_rating(
|
122 |
+
array(
|
123 |
+
'rating' => $theme->rating,
|
124 |
+
'type' => 'percent',
|
125 |
+
'number' => $theme->num_ratings,
|
126 |
+
'echo' => false,
|
127 |
+
)
|
128 |
+
);
|
129 |
+
|
130 |
+
$theme->num_ratings = number_format_i18n( $theme->num_ratings );
|
131 |
+
$theme->preview_url = set_url_scheme( $theme->preview_url );
|
132 |
+
$theme->compatible_wp = is_wp_version_compatible( $theme->requires );
|
133 |
+
$theme->compatible_php = is_php_version_compatible( $theme->requires_php );
|
134 |
+
|
135 |
+
}
|
136 |
+
|
137 |
+
wp_send_json_success( $api );
|
138 |
+
}
|
139 |
+
|
140 |
+
public function our_themes_script( $hook_suffix ) {
|
141 |
+
|
142 |
+
if ( 'theme-install.php' === $hook_suffix ) {
|
143 |
+
wp_enqueue_script( 'our-themes-script', plugin_dir_url( __FILE__ ) . '../js/our-themes.js', array( 'jquery' ), '2018-05-16' );
|
144 |
+
}
|
145 |
+
}
|
146 |
+
|
147 |
+
/* Add Catch Themes Section in Theme in Customizer */
|
148 |
+
public function customize_register( $wp_customize ) {
|
149 |
+
$wp_customize->add_section(
|
150 |
+
new WP_Customize_Themes_Section(
|
151 |
+
$wp_customize,
|
152 |
+
'catchthemes',
|
153 |
+
array(
|
154 |
+
'title' => __( 'Themes by CatchThemes', 'catch-themes-demo-import' ),
|
155 |
+
'action' => 'catchthemes',
|
156 |
+
'capability' => 'install_themes',
|
157 |
+
'panel' => 'themes',
|
158 |
+
'priority' => 6,
|
159 |
+
)
|
160 |
+
)
|
161 |
+
);
|
162 |
+
}
|
163 |
+
|
164 |
+
|
165 |
+
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Load themes into the theme browsing/installation UI.
|
169 |
+
* taken from wp-includes/cllass-wp-customize-manager.php
|
170 |
+
* @since 4.9.0
|
171 |
+
*/
|
172 |
+
public function handle_load_themes_request() {
|
173 |
+
check_ajax_referer( 'switch_themes', 'nonce' );
|
174 |
+
if ( ! current_user_can( 'switch_themes' ) ) {
|
175 |
+
wp_die( -1 );
|
176 |
+
}
|
177 |
+
|
178 |
+
if ( empty( $_POST['theme_action'] ) ) {
|
179 |
+
wp_send_json_error( 'missing_theme_action' );
|
180 |
+
}
|
181 |
+
$theme_action = sanitize_key( $_POST['theme_action'] );
|
182 |
+
$themes = array();
|
183 |
+
$args = array();
|
184 |
+
|
185 |
+
// Define query filters based on user input.
|
186 |
+
if ( ! array_key_exists( 'search', $_POST ) ) {
|
187 |
+
$args['search'] = '';
|
188 |
+
} else {
|
189 |
+
$args['search'] = sanitize_text_field( wp_unslash( $_POST['search'] ) );
|
190 |
+
}
|
191 |
+
|
192 |
+
if ( ! array_key_exists( 'tags', $_POST ) ) {
|
193 |
+
$args['tag'] = '';
|
194 |
+
} else {
|
195 |
+
$args['tag'] = array_map( 'sanitize_text_field', wp_unslash( (array) $_POST['tags'] ) );
|
196 |
+
}
|
197 |
+
|
198 |
+
if ( ! array_key_exists( 'page', $_POST ) ) {
|
199 |
+
$args['page'] = 1;
|
200 |
+
} else {
|
201 |
+
$args['page'] = absint( $_POST['page'] );
|
202 |
+
}
|
203 |
+
|
204 |
+
require_once ABSPATH . 'wp-admin/includes/theme.php';
|
205 |
+
|
206 |
+
if ( 'installed' === $theme_action ) {
|
207 |
+
|
208 |
+
// Load all installed themes from wp_prepare_themes_for_js().
|
209 |
+
$themes = array( 'themes' => wp_prepare_themes_for_js() );
|
210 |
+
foreach ( $themes['themes'] as &$theme ) {
|
211 |
+
$theme['type'] = 'installed';
|
212 |
+
$theme['active'] = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme['id'] );
|
213 |
+
}
|
214 |
+
} elseif ( 'catchthemes' === $theme_action ) {
|
215 |
+
|
216 |
+
// Load WordPress.org themes from the .org API and normalize data to match installed theme objects.
|
217 |
+
if ( ! current_user_can( 'install_themes' ) ) {
|
218 |
+
wp_die( -1 );
|
219 |
+
}
|
220 |
+
|
221 |
+
// Arguments for all queries.
|
222 |
+
$wporg_args = array(
|
223 |
+
'per_page' => 100,
|
224 |
+
'fields' => array(
|
225 |
+
'reviews_url' => true, // Explicitly request the reviews URL to be linked from the customizer.
|
226 |
+
),
|
227 |
+
);
|
228 |
+
|
229 |
+
$args = array_merge( $wporg_args, $args );
|
230 |
+
|
231 |
+
if ( '' === $args['search'] && '' === $args['tag'] ) {
|
232 |
+
$args['browse'] = 'new'; // Sort by latest themes by default.
|
233 |
+
}
|
234 |
+
|
235 |
+
$args['author'] = 'catchthemes';
|
236 |
+
|
237 |
+
// Load themes from the .org API.
|
238 |
+
$themes = themes_api( 'query_themes', $args );
|
239 |
+
if ( is_wp_error( $themes ) ) {
|
240 |
+
wp_send_json_error();
|
241 |
+
}
|
242 |
+
|
243 |
+
// This list matches the allowed tags in wp-admin/includes/theme-install.php.
|
244 |
+
$themes_allowedtags = array_fill_keys(
|
245 |
+
array( 'a', 'abbr', 'acronym', 'code', 'pre', 'em', 'strong', 'div', 'p', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'img' ),
|
246 |
+
array()
|
247 |
+
);
|
248 |
+
$themes_allowedtags['a'] = array_fill_keys( array( 'href', 'title', 'target' ), true );
|
249 |
+
$themes_allowedtags['acronym']['title'] = true;
|
250 |
+
$themes_allowedtags['abbr']['title'] = true;
|
251 |
+
$themes_allowedtags['img'] = array_fill_keys( array( 'src', 'class', 'alt' ), true );
|
252 |
+
|
253 |
+
// Prepare a list of installed themes to check against before the loop.
|
254 |
+
$installed_themes = array();
|
255 |
+
$wp_themes = wp_get_themes();
|
256 |
+
foreach ( $wp_themes as $theme ) {
|
257 |
+
$installed_themes[] = $theme->get_stylesheet();
|
258 |
+
}
|
259 |
+
$update_php = network_admin_url( 'update.php?action=install-theme' );
|
260 |
+
|
261 |
+
// Set up properties for themes available on WordPress.org.
|
262 |
+
foreach ( $themes->themes as &$theme ) {
|
263 |
+
$theme->install_url = add_query_arg(
|
264 |
+
array(
|
265 |
+
'theme' => $theme->slug,
|
266 |
+
'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ),
|
267 |
+
),
|
268 |
+
$update_php
|
269 |
+
);
|
270 |
+
|
271 |
+
$theme->name = wp_kses( $theme->name, $themes_allowedtags );
|
272 |
+
$theme->version = wp_kses( $theme->version, $themes_allowedtags );
|
273 |
+
$theme->description = wp_kses( $theme->description, $themes_allowedtags );
|
274 |
+
$theme->stars = wp_star_rating(
|
275 |
+
array(
|
276 |
+
'rating' => $theme->rating,
|
277 |
+
'type' => 'percent',
|
278 |
+
'number' => $theme->num_ratings,
|
279 |
+
'echo' => false,
|
280 |
+
)
|
281 |
+
);
|
282 |
+
$theme->num_ratings = number_format_i18n( $theme->num_ratings );
|
283 |
+
$theme->preview_url = set_url_scheme( $theme->preview_url );
|
284 |
+
|
285 |
+
// Handle themes that are already installed as installed themes.
|
286 |
+
if ( in_array( $theme->slug, $installed_themes, true ) ) {
|
287 |
+
$theme->type = 'installed';
|
288 |
+
} else {
|
289 |
+
$theme->type = $theme_action;
|
290 |
+
}
|
291 |
+
|
292 |
+
// Set active based on customized theme.
|
293 |
+
$theme->active = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme->slug );
|
294 |
+
|
295 |
+
// Map available theme properties to installed theme properties.
|
296 |
+
$theme->id = $theme->slug;
|
297 |
+
$theme->screenshot = array( $theme->screenshot_url );
|
298 |
+
$theme->authorAndUri = wp_kses( $theme->author['display_name'], $themes_allowedtags );
|
299 |
+
$theme->compatibleWP = is_wp_version_compatible( $theme->requires ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
300 |
+
$theme->compatiblePHP = is_php_version_compatible( $theme->requires_php ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
301 |
+
|
302 |
+
if ( isset( $theme->parent ) ) {
|
303 |
+
$theme->parent = $theme->parent['slug'];
|
304 |
+
} else {
|
305 |
+
$theme->parent = false;
|
306 |
+
}
|
307 |
+
unset( $theme->slug );
|
308 |
+
unset( $theme->screenshot_url );
|
309 |
+
unset( $theme->author );
|
310 |
+
} // End foreach().
|
311 |
+
} elseif ( 'wporg' === $theme_action ) {
|
312 |
+
|
313 |
+
// Load WordPress.org themes from the .org API and normalize data to match installed theme objects.
|
314 |
+
if ( ! current_user_can( 'install_themes' ) ) {
|
315 |
+
wp_die( -1 );
|
316 |
+
}
|
317 |
+
|
318 |
+
// Arguments for all queries.
|
319 |
+
$wporg_args = array(
|
320 |
+
'per_page' => 100,
|
321 |
+
'fields' => array(
|
322 |
+
'reviews_url' => true, // Explicitly request the reviews URL to be linked from the customizer.
|
323 |
+
),
|
324 |
+
);
|
325 |
+
|
326 |
+
$args = array_merge( $wporg_args, $args );
|
327 |
+
|
328 |
+
if ( '' === $args['search'] && '' === $args['tag'] ) {
|
329 |
+
$args['browse'] = 'new'; // Sort by latest themes by default.
|
330 |
+
}
|
331 |
+
|
332 |
+
// Load themes from the .org API.
|
333 |
+
$themes = themes_api( 'query_themes', $args );
|
334 |
+
if ( is_wp_error( $themes ) ) {
|
335 |
+
wp_send_json_error();
|
336 |
+
}
|
337 |
+
|
338 |
+
// This list matches the allowed tags in wp-admin/includes/theme-install.php.
|
339 |
+
$themes_allowedtags = array_fill_keys(
|
340 |
+
array( 'a', 'abbr', 'acronym', 'code', 'pre', 'em', 'strong', 'div', 'p', 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'img' ),
|
341 |
+
array()
|
342 |
+
);
|
343 |
+
$themes_allowedtags['a'] = array_fill_keys( array( 'href', 'title', 'target' ), true );
|
344 |
+
$themes_allowedtags['acronym']['title'] = true;
|
345 |
+
$themes_allowedtags['abbr']['title'] = true;
|
346 |
+
$themes_allowedtags['img'] = array_fill_keys( array( 'src', 'class', 'alt' ), true );
|
347 |
+
|
348 |
+
// Prepare a list of installed themes to check against before the loop.
|
349 |
+
$installed_themes = array();
|
350 |
+
$wp_themes = wp_get_themes();
|
351 |
+
foreach ( $wp_themes as $theme ) {
|
352 |
+
$installed_themes[] = $theme->get_stylesheet();
|
353 |
+
}
|
354 |
+
$update_php = network_admin_url( 'update.php?action=install-theme' );
|
355 |
+
|
356 |
+
// Set up properties for themes available on WordPress.org.
|
357 |
+
foreach ( $themes->themes as &$theme ) {
|
358 |
+
$theme->install_url = add_query_arg(
|
359 |
+
array(
|
360 |
+
'theme' => $theme->slug,
|
361 |
+
'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ),
|
362 |
+
),
|
363 |
+
$update_php
|
364 |
+
);
|
365 |
+
|
366 |
+
$theme->name = wp_kses( $theme->name, $themes_allowedtags );
|
367 |
+
$theme->version = wp_kses( $theme->version, $themes_allowedtags );
|
368 |
+
$theme->description = wp_kses( $theme->description, $themes_allowedtags );
|
369 |
+
$theme->stars = wp_star_rating(
|
370 |
+
array(
|
371 |
+
'rating' => $theme->rating,
|
372 |
+
'type' => 'percent',
|
373 |
+
'number' => $theme->num_ratings,
|
374 |
+
'echo' => false,
|
375 |
+
)
|
376 |
+
);
|
377 |
+
$theme->num_ratings = number_format_i18n( $theme->num_ratings );
|
378 |
+
$theme->preview_url = set_url_scheme( $theme->preview_url );
|
379 |
+
|
380 |
+
// Handle themes that are already installed as installed themes.
|
381 |
+
if ( in_array( $theme->slug, $installed_themes, true ) ) {
|
382 |
+
$theme->type = 'installed';
|
383 |
+
} else {
|
384 |
+
$theme->type = $theme_action;
|
385 |
+
}
|
386 |
+
|
387 |
+
// Set active based on customized theme.
|
388 |
+
$theme->active = ( isset( $_POST['customized_theme'] ) && $_POST['customized_theme'] === $theme->slug );
|
389 |
+
|
390 |
+
// Map available theme properties to installed theme properties.
|
391 |
+
$theme->id = $theme->slug;
|
392 |
+
$theme->screenshot = array( $theme->screenshot_url );
|
393 |
+
$theme->authorAndUri = wp_kses( $theme->author['display_name'], $themes_allowedtags );
|
394 |
+
$theme->compatibleWP = is_wp_version_compatible( $theme->requires ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
395 |
+
$theme->compatiblePHP = is_php_version_compatible( $theme->requires_php ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
396 |
+
|
397 |
+
if ( isset( $theme->parent ) ) {
|
398 |
+
$theme->parent = $theme->parent['slug'];
|
399 |
+
} else {
|
400 |
+
$theme->parent = false;
|
401 |
+
}
|
402 |
+
unset( $theme->slug );
|
403 |
+
unset( $theme->screenshot_url );
|
404 |
+
unset( $theme->author );
|
405 |
+
} // End foreach().
|
406 |
+
} // End if().
|
407 |
+
|
408 |
+
/**
|
409 |
+
* Filters the theme data loaded in the customizer.
|
410 |
+
*
|
411 |
+
* This allows theme data to be loading from an external source,
|
412 |
+
* or modification of data loaded from `wp_prepare_themes_for_js()`
|
413 |
+
* or WordPress.org via `themes_api()`.
|
414 |
+
*
|
415 |
+
* @since 4.9.0
|
416 |
+
*
|
417 |
+
* @see wp_prepare_themes_for_js()
|
418 |
+
* @see themes_api()
|
419 |
+
* @see WP_Customize_Manager::__construct()
|
420 |
+
*
|
421 |
+
* @param array $themes Nested array of theme data.
|
422 |
+
* @param array $args List of arguments, such as page, search term, and tags to query for.
|
423 |
+
* @param WP_Customize_Manager $manager Instance of Customize manager.
|
424 |
+
*/
|
425 |
+
$themes = apply_filters( 'customize_load_themes', $themes, $args, $wp_customize );
|
426 |
+
|
427 |
+
wp_send_json_success( $themes );
|
428 |
+
}
|
429 |
+
|
430 |
+
/* Plugins */
|
431 |
+
/* Adds Catch Plugins tab in Add Plugin page to show all plugins by Catch Plugins in wordpress.org */
|
432 |
+
public function add_our_plugins_tab( $tabs ) {
|
433 |
+
// Add our filter here
|
434 |
+
$tabs['catchplugins'] = _x( 'Catch Plugins', 'Plugin Installer' );
|
435 |
+
|
436 |
+
return $tabs;
|
437 |
+
}
|
438 |
+
|
439 |
+
public function catchplugins() {
|
440 |
+
/* From CORE Start */
|
441 |
+
global $paged, $tab;
|
442 |
+
wp_reset_vars( array( 'tab' ) );
|
443 |
+
|
444 |
+
$defined_class = new WP_Plugin_Install_List_Table();
|
445 |
+
$paged = $defined_class->get_pagenum();
|
446 |
+
|
447 |
+
$per_page = 30;
|
448 |
+
//$installed_plugins = catch_get_installed_plugins();
|
449 |
+
|
450 |
+
$args = array(
|
451 |
+
'page' => $paged,
|
452 |
+
'per_page' => $per_page,
|
453 |
+
'fields' => array(
|
454 |
+
'last_updated' => true,
|
455 |
+
'icons' => true,
|
456 |
+
'active_installs' => true,
|
457 |
+
),
|
458 |
+
// Send the locale and installed plugin slugs to the API so it can provide context-sensitive results.
|
459 |
+
'locale' => get_user_locale(),
|
460 |
+
//'installed_plugins' => array_keys( $installed_plugins ),
|
461 |
+
);
|
462 |
+
/* From CORE End */
|
463 |
+
|
464 |
+
// Add author filter for our plugins
|
465 |
+
$args['author'] = 'catchplugins';
|
466 |
+
|
467 |
+
return $args;
|
468 |
+
}
|
469 |
+
|
470 |
+
public function plugins_table() {
|
471 |
+
global $wp_list_table;
|
472 |
+
printf(
|
473 |
+
'<p class="catch-plugins-list">' . __( 'You can use any of our free plugins or premium plugins from <a href="%s" target="_blank">Catch Plugins</a>' ) . '.</p>',
|
474 |
+
'https://catchplugins.com/'
|
475 |
+
);
|
476 |
+
?>
|
477 |
+
<form id="plugin-filter" method="post">
|
478 |
+
<?php $wp_list_table->display(); ?>
|
479 |
+
</form>
|
480 |
+
<?php
|
481 |
+
}
|
482 |
+
}
|
483 |
+
|
484 |
+
$catchthemes_theme_plugin = new CatchThemesThemePlugin();
|
languages/essential-content-types-fr_FR.mo
CHANGED
Binary file
|
languages/essential-content-types-fr_FR.po
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
-
# Copyright (C) 2018-
|
2 |
# This file is distributed under the GNU General Public License v2 or later.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
"Project-Id-Version: Essential Content Types\n"
|
6 |
"Report-Msgid-Bugs-To: https://wordpress.org/tags/_s\n"
|
7 |
-
"POT-Creation-Date:
|
8 |
-
"PO-Revision-Date:
|
9 |
"Last-Translator: Charles Girardin <girardin.charles.57@gmail.com>\n"
|
10 |
"Language-Team: Catch Plugins <info@catchplugins.com>\n"
|
11 |
"Language: fr_FR\n"
|
@@ -13,7 +13,7 @@ msgstr ""
|
|
13 |
"Content-Type: text/plain; charset=UTF-8\n"
|
14 |
"Content-Transfer-Encoding: 8bit\n"
|
15 |
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
16 |
-
"X-Generator: Poedit 2.4.
|
17 |
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;esc_attr_e;esc_attr__;_nx;_x;"
|
18 |
"esc_html_e;esc_html__;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;_n_noop:1,2;"
|
19 |
"__ngettext_noop:1,2;_c,_nc:4c,1,2\n"
|
1 |
+
# Copyright (C) 2018-2021 Catch Plugins
|
2 |
# This file is distributed under the GNU General Public License v2 or later.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
"Project-Id-Version: Essential Content Types\n"
|
6 |
"Report-Msgid-Bugs-To: https://wordpress.org/tags/_s\n"
|
7 |
+
"POT-Creation-Date: 2021-08-05 10:15-0700\n"
|
8 |
+
"PO-Revision-Date: 2021-08-05 10:15-0700\n"
|
9 |
"Last-Translator: Charles Girardin <girardin.charles.57@gmail.com>\n"
|
10 |
"Language-Team: Catch Plugins <info@catchplugins.com>\n"
|
11 |
"Language: fr_FR\n"
|
13 |
"Content-Type: text/plain; charset=UTF-8\n"
|
14 |
"Content-Transfer-Encoding: 8bit\n"
|
15 |
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
16 |
+
"X-Generator: Poedit 2.4.3\n"
|
17 |
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;esc_attr_e;esc_attr__;_nx;_x;"
|
18 |
"esc_html_e;esc_html__;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;_n_noop:1,2;"
|
19 |
"__ngettext_noop:1,2;_c,_nc:4c,1,2\n"
|
languages/essential-content-types.pot
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
-
# Copyright (C) 2018-
|
2 |
# This file is distributed under the GNU General Public License v2 or later.
|
3 |
#, fuzzy
|
4 |
msgid ""
|
5 |
msgstr ""
|
6 |
"Project-Id-Version: Essential Content Types\n"
|
7 |
"Report-Msgid-Bugs-To: https://wordpress.org/tags/_s\n"
|
8 |
-
"POT-Creation-Date:
|
9 |
"PO-Revision-Date: 2016-12-12 09:23-0500\n"
|
10 |
"Last-Translator: Sakin Shrestha <info@catchplugins.com>\n"
|
11 |
"Language-Team: Catch Plugins <info@catchplugins.com>\n"
|
@@ -14,7 +14,7 @@ msgstr ""
|
|
14 |
"Content-Type: text/plain; charset=UTF-8\n"
|
15 |
"Content-Transfer-Encoding: 8bit\n"
|
16 |
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
17 |
-
"X-Generator: Poedit 2.4.
|
18 |
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;esc_attr_e;esc_attr__;_nx;_x;"
|
19 |
"esc_html_e;esc_html__;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;_n_noop:1,2;"
|
20 |
"__ngettext_noop:1,2;_c,_nc:4c,1,2\n"
|
1 |
+
# Copyright (C) 2018-2021 Catch Plugins
|
2 |
# This file is distributed under the GNU General Public License v2 or later.
|
3 |
#, fuzzy
|
4 |
msgid ""
|
5 |
msgstr ""
|
6 |
"Project-Id-Version: Essential Content Types\n"
|
7 |
"Report-Msgid-Bugs-To: https://wordpress.org/tags/_s\n"
|
8 |
+
"POT-Creation-Date: 2021-08-05 10:15-0700\n"
|
9 |
"PO-Revision-Date: 2016-12-12 09:23-0500\n"
|
10 |
"Last-Translator: Sakin Shrestha <info@catchplugins.com>\n"
|
11 |
"Language-Team: Catch Plugins <info@catchplugins.com>\n"
|
14 |
"Content-Type: text/plain; charset=UTF-8\n"
|
15 |
"Content-Transfer-Encoding: 8bit\n"
|
16 |
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
17 |
+
"X-Generator: Poedit 2.4.3\n"
|
18 |
"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;esc_attr_e;esc_attr__;_nx;_x;"
|
19 |
"esc_html_e;esc_html__;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;_n_noop:1,2;"
|
20 |
"__ngettext_noop:1,2;_c,_nc:4c,1,2\n"
|