Essential Content Types - Version 1.8.4

Version Description

(Released: December 07, 2020) = * Bug Fixed: ECT archive title and description via customizer * Compatibility check up to version 5.6

Download this release

Release Info

Developer catchthemes
Plugin Icon Essential Content Types
Version 1.8.4
Comparing to
See all releases

Code changes from version 1.8.3 to 1.8.4

README.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: catchplugins, catchthemes, sakinshrestha, pratikshrestha, maheshma
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.5
7
  Stable tag: trunk
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
@@ -200,10 +200,15 @@ Not so easy way (via FTP) :
200
  5. Customizer: Services Archive Options
201
 
202
  == Changelog ==
203
- = 1.8.3 (Released: September 21, 2020) ==
 
 
 
 
 
204
  * Bug Fixed: Check if thumbnail exists on templates
205
 
206
- = 1.8.2 (Released: Aug 19, 2020) ==
207
  * Bug Fixed: Issue in add new theme page
208
 
209
  = 1.8.1 (Released: May 07, 2020) =
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.6
7
  Stable tag: trunk
8
  License: GPLv3 or later
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
200
  5. Customizer: Services Archive Options
201
 
202
  == Changelog ==
203
+
204
+ = 1.8.4 (Released: December 07, 2020) =
205
+ * Bug Fixed: ECT archive title and description via customizer
206
+ * Compatibility check up to version 5.6
207
+
208
+ = 1.8.3 (Released: September 21, 2020) =
209
  * Bug Fixed: Check if thumbnail exists on templates
210
 
211
+ = 1.8.2 (Released: Aug 19, 2020) =
212
  * Bug Fixed: Issue in add new theme page
213
 
214
  = 1.8.1 (Released: May 07, 2020) =
admin/class-featured-content.php CHANGED
@@ -1,725 +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
- register_post_type( self::CUSTOM_POST_TYPE, 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
- register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
146
- 'hierarchical' => true,
147
- 'labels' => array(
148
- 'name' => esc_html__( 'Content Types', 'essential-content-types' ),
149
- 'singular_name' => esc_html__( 'Content Type', 'essential-content-types' ),
150
- 'menu_name' => esc_html__( 'Content Types', 'essential-content-types' ),
151
- 'all_items' => esc_html__( 'All Content Types', 'essential-content-types' ),
152
- 'edit_item' => esc_html__( 'Edit Content Type', 'essential-content-types' ),
153
- 'view_item' => esc_html__( 'View Content Type', 'essential-content-types' ),
154
- 'update_item' => esc_html__( 'Update Content Type', 'essential-content-types' ),
155
- 'add_new_item' => esc_html__( 'Add New Content Type', 'essential-content-types' ),
156
- 'new_item_name' => esc_html__( 'New Content Type Name', 'essential-content-types' ),
157
- 'parent_item' => esc_html__( 'Parent Content Type', 'essential-content-types' ),
158
- 'parent_item_colon' => esc_html__( 'Parent Content Type:', 'essential-content-types' ),
159
- 'search_items' => esc_html__( 'Search Content Types', 'essential-content-types' ),
160
- 'items_list_navigation' => esc_html__( 'Content type list navigation', 'essential-content-types' ),
161
- 'items_list' => esc_html__( 'Content type list', 'essential-content-types' ),
162
- ),
163
- 'public' => true,
164
- 'show_ui' => true,
165
- 'show_in_nav_menus' => true,
166
- 'show_in_rest' => true,
167
- 'show_admin_column' => true,
168
- 'query_var' => true,
169
- 'rewrite' => array( 'slug' => 'content-type' ),
170
- ) );
171
-
172
- register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
173
- 'hierarchical' => false,
174
- 'labels' => array(
175
- 'name' => esc_html__( 'Content Tags', 'essential-content-types' ),
176
- 'singular_name' => esc_html__( 'Content Tag', 'essential-content-types' ),
177
- 'menu_name' => esc_html__( 'Content Tags', 'essential-content-types' ),
178
- 'all_items' => esc_html__( 'All Content Tags', 'essential-content-types' ),
179
- 'edit_item' => esc_html__( 'Edit Content Tag', 'essential-content-types' ),
180
- 'view_item' => esc_html__( 'View Content Tag', 'essential-content-types' ),
181
- 'update_item' => esc_html__( 'Update Content Tag', 'essential-content-types' ),
182
- 'add_new_item' => esc_html__( 'Add New Content Tag', 'essential-content-types' ),
183
- 'new_item_name' => esc_html__( 'New Content Tag Name', 'essential-content-types' ),
184
- 'search_items' => esc_html__( 'Search Content Tags', 'essential-content-types' ),
185
- 'popular_items' => esc_html__( 'Popular Content Tags', 'essential-content-types' ),
186
- 'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
187
- 'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
188
- 'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
189
- 'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
190
- 'items_list_navigation' => esc_html__( 'Content tag list navigation', 'essential-content-types' ),
191
- 'items_list' => esc_html__( 'Content tag list', 'essential-content-types' ),
192
- ),
193
- 'public' => true,
194
- 'show_ui' => true,
195
- 'show_in_nav_menus' => true,
196
- 'show_in_rest' => true,
197
- 'show_admin_column' => true,
198
- 'query_var' => true,
199
- 'rewrite' => array( 'slug' => 'content-tag' ),
200
- ) );
201
- }
202
-
203
- /**
204
- * Update messages for the Featured Content admin.
205
- */
206
- function updated_messages( $messages ) {
207
- global $post;
208
-
209
- $messages[self::CUSTOM_POST_TYPE] = array(
210
- 0 => '', // Unused. Messages start at index 1.
211
- 1 => sprintf( __( 'Content updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
212
- 2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
213
- 3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
214
- 4 => esc_html__( 'Content updated.', 'essential-content-types' ),
215
- /* translators: %s: date and time of the revision */
216
- 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,
217
- 6 => sprintf( __( 'Content published. <a href="%s">View content</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
218
- 7 => esc_html__( 'Content saved.', 'essential-content-types' ),
219
- 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 ) ) ) ),
220
- 9 => sprintf( __( 'Content scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview content</a>', 'essential-content-types' ),
221
- // translators: Publish box date format, see http://php.net/date
222
- date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
223
- 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 ) ) ) ),
224
- );
225
-
226
- return $messages;
227
- }
228
-
229
- /**
230
- * Change ‘Title’ column label
231
- * Add Featured Image column
232
- */
233
- function edit_admin_columns( $columns ) {
234
- // change 'Title' to 'Content'
235
- $columns['title'] = __( 'Content', 'essential-content-types' );
236
- if ( current_theme_supports( 'post-thumbnails' ) ) {
237
- // add featured image before 'Content'
238
- $columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
239
- }
240
-
241
- return $columns;
242
- }
243
-
244
- /**
245
- * Add featured image to column
246
- */
247
- function image_column( $column, $post_id ) {
248
- global $post;
249
- switch ( $column ) {
250
- case 'thumbnail':
251
- echo get_the_post_thumbnail( $post_id, 'featured-content-admin-thumb' );
252
- break;
253
- }
254
- }
255
-
256
- /**
257
- * Adjust image column width
258
- */
259
- function enqueue_admin_styles( $hook ) {
260
- $screen = get_current_screen();
261
-
262
- if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
263
- 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; } }' );
264
- }
265
- }
266
-
267
- /**
268
- * Adds featured_content section to the Customizer.
269
- */
270
- function customize_register( $wp_customize ) {
271
- $wp_customize->add_panel( 'ect_plugin_options', array(
272
- 'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
273
- 'priority' => 1,
274
- ) );
275
-
276
- $wp_customize->add_section( 'ect_featured_content', array(
277
- 'title' => esc_html__( 'Featured Content', 'essential-content-types' ),
278
- 'panel' => 'ect_plugin_options',
279
- ) );
280
-
281
- $wp_customize->add_setting( 'featured_content_title', array(
282
- 'default' => esc_html__( 'Contents', 'essential-content-types' ),
283
- 'type' => 'option',
284
- 'sanitize_callback' => 'sanitize_text_field',
285
- 'sanitize_js_callback' => 'sanitize_text_field',
286
- ) );
287
-
288
- $wp_customize->add_control( 'featured_content_title', array(
289
- 'section' => 'ect_featured_content',
290
- 'label' => esc_html__( 'Featured Content Archive Title', 'essential-content-types' ),
291
- 'type' => 'text',
292
- ) );
293
-
294
- $wp_customize->add_setting( 'featured_content_content', array(
295
- 'default' => '',
296
- 'type' => 'option',
297
- 'sanitize_callback' => 'wp_kses_post',
298
- 'sanitize_js_callback' => 'wp_kses_post',
299
- ) );
300
-
301
- $wp_customize->add_control( 'featured_content_content', array(
302
- 'section' => 'ect_featured_content',
303
- 'label' => esc_html__( 'Featured Content Archive Content', 'essential-content-types' ),
304
- 'type' => 'textarea',
305
- ) );
306
-
307
- $wp_customize->add_setting( 'featured_content_featured_image', array(
308
- 'default' => '',
309
- 'type' => 'option',
310
- 'sanitize_callback' => 'attachment_url_to_postid',
311
- 'sanitize_js_callback' => 'attachment_url_to_postid',
312
- 'theme_supports' => 'post-thumbnails',
313
- ) );
314
-
315
- $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'featured_content_featured_image', array(
316
- 'section' => 'ect_featured_content',
317
- 'label' => esc_html__( 'Featured Content Archive Featured Image', 'essential-content-types' ),
318
- ) ) );
319
- }
320
-
321
- /**
322
- * Follow CPT reading setting on CPT archive and taxonomy pages
323
- */
324
- function query_reading_setting( $query ) {
325
- if ( ! is_admin() &&
326
- $query->is_main_query() &&
327
- ( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
328
- ) {
329
- $post_per_page = ( null != get_option('posts_per_page') ) ? get_option('posts_per_page') : '10';
330
- $query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
331
- }
332
- }
333
-
334
- /**
335
- * Add to REST API post type whitelist
336
- */
337
- function allow_featured_content_rest_api_type( $post_types ) {
338
- $post_types[] = self::CUSTOM_POST_TYPE;
339
-
340
- return $post_types;
341
- }
342
-
343
- /**
344
- * Our [featured_content] shortcode.
345
- * Prints Featured Content data styled to look good on *any* theme.
346
- *
347
- * @return featured_content_shortcode_html
348
- */
349
- static function featured_content_shortcode( $atts ) {
350
- // Default attributes
351
- $atts = shortcode_atts( array(
352
- 'image' => true,
353
- 'display_types' => true,
354
- 'display_tags' => true,
355
- 'display_content' => true,
356
- 'display_author' => false,
357
- 'show_filter' => false,
358
- 'include_type' => false,
359
- 'include_tag' => false,
360
- 'columns' => 2,
361
- 'showposts' => -1,
362
- 'order' => 'asc',
363
- 'orderby' => 'date',
364
- ), $atts, 'featured_content' );
365
-
366
- // A little sanitization
367
- if ( $atts['image'] && 'true' != $atts['image'] ) {
368
- $atts['image'] = false;
369
- }
370
-
371
- if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
372
- $atts['display_types'] = false;
373
- }
374
-
375
- if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
376
- $atts['display_tags'] = false;
377
- }
378
-
379
- if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
380
- $atts['display_author'] = false;
381
- }
382
-
383
- if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
384
- $atts['display_content'] = false;
385
- }
386
-
387
- if ( $atts['include_type'] ) {
388
- $atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
389
- }
390
-
391
- if ( $atts['include_tag'] ) {
392
- $atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
393
- }
394
-
395
- // Check if column value is set to valid numbers or else set default value as 2
396
- if( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
397
- $atts['columns'] = absint( $atts['columns'] );
398
- } else {
399
- $atts['columns'] = 2;
400
- }
401
-
402
- $atts['showposts'] = intval( $atts['showposts'] );
403
-
404
-
405
- if ( $atts['order'] ) {
406
- $atts['order'] = urldecode( $atts['order'] );
407
- $atts['order'] = strtoupper( $atts['order'] );
408
- if ( 'DESC' != $atts['order'] ) {
409
- $atts['order'] = 'ASC';
410
- }
411
- }
412
-
413
- if ( $atts['orderby'] ) {
414
- $atts['orderby'] = urldecode( $atts['orderby'] );
415
- $atts['orderby'] = strtolower( $atts['orderby'] );
416
- $allowed_keys = array( 'author', 'date', 'title', 'rand' );
417
-
418
- $parsed = array();
419
- foreach ( explode( ',', $atts['orderby'] ) as $featured_content_index_number => $orderby ) {
420
- if ( ! in_array( $orderby, $allowed_keys ) ) {
421
- continue;
422
- }
423
- $parsed[] = $orderby;
424
- }
425
-
426
- if ( empty( $parsed ) ) {
427
- unset( $atts['orderby'] );
428
- } else {
429
- $atts['orderby'] = implode( ' ', $parsed );
430
- }
431
- }
432
-
433
- // enqueue shortcode styles when shortcode is used
434
- wp_enqueue_style( 'featured-content-style', plugins_url( 'css/featured-content-shortcode.css', __FILE__ ), array(), '20140326' );
435
-
436
- return self::featured_content_shortcode_html( $atts );
437
- }
438
-
439
- /**
440
- * Query to retrieve entries from the Featured Content post_type.
441
- *
442
- * @return object
443
- */
444
- static function featured_content_query( $atts ) {
445
- // Default query arguments
446
- $default = array(
447
- 'order' => $atts['order'],
448
- 'orderby' => $atts['orderby'],
449
- 'posts_per_page' => $atts['showposts'],
450
- );
451
-
452
- $args = wp_parse_args( $atts, $default );
453
- $args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
454
-
455
- if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
456
- $args['tax_query'] = array();
457
- }
458
-
459
- // If 'include_type' has been set use it on the main query
460
- if ( false != $atts['include_type'] ) {
461
- array_push( $args['tax_query'], array(
462
- 'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
463
- 'field' => 'slug',
464
- 'terms' => $atts['include_type'],
465
- ) );
466
- }
467
-
468
- // If 'include_tag' has been set use it on the main query
469
- if ( false != $atts['include_tag'] ) {
470
- array_push( $args['tax_query'], array(
471
- 'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
472
- 'field' => 'slug',
473
- 'terms' => $atts['include_tag'],
474
- ) );
475
- }
476
-
477
- if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
478
- $args['tax_query']['relation'] = 'AND';
479
- }
480
-
481
- // Run the query and return
482
- $query = new WP_Query( $args );
483
- return $query;
484
- }
485
-
486
- /**
487
- * The Featured Content shortcode loop.
488
- *
489
- * @todo add theme color styles
490
- * @return html
491
- */
492
- static function featured_content_shortcode_html( $atts ) {
493
-
494
- $query = self::featured_content_query( $atts );
495
-
496
- ob_start();
497
-
498
- // If we have posts, create the html
499
- // with featured-content markup
500
- if ( $query->have_posts() ) {
501
-
502
- /**
503
- * Hook: ect_before_featured_content_loop.
504
- *
505
- * @hooked ect_featured_content_section_open
506
- */
507
- $layout = ect_get_layout();
508
- do_action( 'ect_before_featured_content_loop', $layout[$atts['columns']] );
509
-
510
- ?>
511
- <?php
512
- while ( $query->have_posts() ) {
513
- $query->the_post();
514
- ect_get_template_part( 'content', 'featured-content', $atts );
515
- }
516
- wp_reset_postdata();
517
- ?>
518
- <?php
519
-
520
- /**
521
- * Hook: ect_after_featured_content_loop.
522
- *
523
- * @hooked essential_content_pro_featured_content_section_close
524
- */
525
- do_action( 'ect_after_featured_content_loop' );
526
-
527
- } else {
528
- /**
529
- * Hook: ect_no_articles_found.
530
- *
531
- * @hooked ect_no_articles_found
532
- */
533
- do_action( 'ect_no_featured_content_found' );
534
- }
535
-
536
- $html = ob_get_clean();
537
-
538
- // If there is a [featured-content] within a [featured-content], remove the shortcode
539
- if ( has_shortcode( $html, 'featured-content' ) ){
540
- remove_shortcode( 'featured-content' );
541
- }
542
-
543
- // Return the HTML block
544
- return $html;
545
- }
546
-
547
- /**
548
- * Displays the content type that a content belongs to.
549
- *
550
- * @return html
551
- */
552
- static function get_content_type( $post_id ) {
553
- $content_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
554
-
555
- // If no types, return empty string
556
- if ( empty( $content_types ) || is_wp_error( $content_types ) ) {
557
- return;
558
- }
559
-
560
- $html = '<div class="content-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
561
- $types = array();
562
- // Loop thorugh all the types
563
- foreach ( $content_types as $content_type ) {
564
- $content_type_link = get_term_link( $content_type, self::CUSTOM_TAXONOMY_TYPE );
565
-
566
- if ( is_wp_error( $content_type_link ) ) {
567
- return $content_type_link;
568
- }
569
-
570
- $types[] = '<a href="' . esc_url( $content_type_link ) . '" rel="tag">' . esc_html( $content_type->name ) . '</a>';
571
- }
572
- $html .= ' '.implode( ', ', $types );
573
- $html .= '</div>';
574
-
575
- return $html;
576
- }
577
-
578
- /**
579
- * Displays the content tags that a content belongs to.
580
- *
581
- * @return html
582
- */
583
- static function get_content_tags( $post_id ) {
584
- $content_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
585
-
586
- // If no tags, return empty string
587
- if ( empty( $content_tags ) || is_wp_error( $content_tags ) ) {
588
- return false;
589
- }
590
-
591
- $html = '<div class="content-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
592
- $tags = array();
593
- // Loop thorugh all the tags
594
- foreach ( $content_tags as $content_tag ) {
595
- $content_tag_link = get_term_link( $content_tag, self::CUSTOM_TAXONOMY_TYPE );
596
-
597
- if ( is_wp_error( $content_tag_link ) ) {
598
- return $content_tag_link;
599
- }
600
-
601
- $tags[] = '<a href="' . esc_url( $content_tag_link ) . '" rel="tag">' . esc_html( $content_tag->name ) . '</a>';
602
- }
603
- $html .= ' '. implode( ', ', $tags );
604
- $html .= '</div>';
605
-
606
- return $html;
607
- }
608
-
609
- /**
610
- * Displays the author of the current featured_content content.
611
- *
612
- * @return html
613
- */
614
- static function get_content_author() {
615
- $html = '<div class="content-author">';
616
- /* translators: %1$s is link to author posts, %2$s is author display name */
617
- $html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
618
- esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
619
- esc_html( get_the_author() )
620
- );
621
- $html .= '</div>';
622
-
623
- return $html;
624
- }
625
- }
626
- add_action( 'init', array( 'Essential_Content_Featured_Content', 'init' ) );
627
-
628
- /**
629
- * Add Featured Content support
630
- */
631
- function essential_content_featured_content_support() {
632
- /*
633
- * Adding theme support for Jetpack Featured Content CPT.
634
- */
635
- add_image_size( 'ect-featured-content', 640, 640, true );
636
- }
637
- add_action( 'after_setup_theme', 'essential_content_featured_content_support' );
638
-
639
-
640
- if( ! function_exists( 'essential_content_get_featured_content_thumbnail_link' ) ):
641
- /**
642
- * Display the featured image if it's available
643
- *
644
- * @return html
645
- */
646
- function essential_content_get_featured_content_thumbnail_link( $post_id, $size ) {
647
- if ( has_post_thumbnail( $post_id ) ) {
648
- /**
649
- * Change the Featured Content thumbnail size.
650
- *
651
- * @module custom-content-types
652
- *
653
- * @since 3.4.0
654
- *
655
- * @param string|array $var Either a registered size keyword or size array.
656
- */
657
- 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>';
658
- }
659
- }
660
- endif;
661
-
662
-
663
- if( ! function_exists('essential_content_no_featured_content_found') ):
664
- /**
665
- * No items found text
666
- *
667
- * @return html
668
- */
669
- function essential_content_no_featured_content_found(){
670
- 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>";
671
- }
672
- add_action( 'ect_no_featured_content_found', 'essential_content_no_featured_content_found', 10 );
673
- endif;
674
-
675
-
676
- if( ! function_exists( 'essential_content_featured_content_section_open' ) ):
677
- /**
678
- * Open section
679
- *
680
- * @return html
681
- */
682
- function essential_content_featured_content_section_open( $layout ) {
683
- echo '<div class="ect-featured-content ect-section ' . $layout . '">';
684
- echo '<div class="ect-wrapper">';
685
- }
686
- endif;
687
- add_action( 'ect_before_featured_content_loop', 'essential_content_featured_content_section_open', 10, 1 );
688
-
689
-
690
- if( ! function_exists( 'essential_content_featured_content_loop_start' ) ):
691
- /**
692
- * open wrapper before loop
693
- *
694
- */
695
- function essential_content_featured_content_loop_start( $layout = null ){
696
- echo '<div class="section-content-wrapper featured-content-wrapper ' . $layout . '">';
697
- }
698
- endif;
699
- add_action( 'ect_before_featured_content_loop', 'essential_content_featured_content_loop_start', 30 );
700
-
701
-
702
- if( ! function_exists( 'ect_featured_content_loop_end' ) ):
703
- /**
704
- * close wrapper after loop
705
- *
706
- */
707
- function essential_content_featured_content_loop_end(){
708
- echo '</div><!-- .featured-content-wrapper -->';
709
- }
710
- endif;
711
- add_action( 'ect_after_featured_content_loop', 'essential_content_featured_content_loop_end', 10 );
712
-
713
-
714
- if( ! function_exists( 'ect_featured_content_section_close' ) ):
715
- /**
716
- * Close section
717
- *
718
- * @return html
719
- */
720
- function essential_content_featured_content_section_close() {
721
- echo '</div><!-- .ect-wrapper -->';
722
- echo '</div><!-- .ect-section -->';
723
- }
724
- endif;
725
- 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-portfolio.php CHANGED
@@ -1,875 +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
- register_post_type( self::CUSTOM_POST_TYPE, 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
- register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
274
- 'hierarchical' => true,
275
- 'labels' => array(
276
- 'name' => esc_html__( 'Project Types', 'essential-content-types' ),
277
- 'singular_name' => esc_html__( 'Project Type', 'essential-content-types' ),
278
- 'menu_name' => esc_html__( 'Project Types', 'essential-content-types' ),
279
- 'all_items' => esc_html__( 'All Project Types', 'essential-content-types' ),
280
- 'edit_item' => esc_html__( 'Edit Project Type', 'essential-content-types' ),
281
- 'view_item' => esc_html__( 'View Project Type', 'essential-content-types' ),
282
- 'update_item' => esc_html__( 'Update Project Type', 'essential-content-types' ),
283
- 'add_new_item' => esc_html__( 'Add New Project Type', 'essential-content-types' ),
284
- 'new_item_name' => esc_html__( 'New Project Type Name', 'essential-content-types' ),
285
- 'parent_item' => esc_html__( 'Parent Project Type', 'essential-content-types' ),
286
- 'parent_item_colon' => esc_html__( 'Parent Project Type:', 'essential-content-types' ),
287
- 'search_items' => esc_html__( 'Search Project Types', 'essential-content-types' ),
288
- 'items_list_navigation' => esc_html__( 'Project type list navigation', 'essential-content-types' ),
289
- 'items_list' => esc_html__( 'Project type list', 'essential-content-types' ),
290
- ),
291
- 'public' => true,
292
- 'show_ui' => true,
293
- 'show_in_nav_menus' => true,
294
- 'show_in_rest' => true,
295
- 'show_admin_column' => true,
296
- 'query_var' => true,
297
- 'rewrite' => array( 'slug' => 'project-type' ),
298
- ) );
299
-
300
- register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
301
- 'hierarchical' => false,
302
- 'labels' => array(
303
- 'name' => esc_html__( 'Project Tags', 'essential-content-types' ),
304
- 'singular_name' => esc_html__( 'Project Tag', 'essential-content-types' ),
305
- 'menu_name' => esc_html__( 'Project Tags', 'essential-content-types' ),
306
- 'all_items' => esc_html__( 'All Project Tags', 'essential-content-types' ),
307
- 'edit_item' => esc_html__( 'Edit Project Tag', 'essential-content-types' ),
308
- 'view_item' => esc_html__( 'View Project Tag', 'essential-content-types' ),
309
- 'update_item' => esc_html__( 'Update Project Tag', 'essential-content-types' ),
310
- 'add_new_item' => esc_html__( 'Add New Project Tag', 'essential-content-types' ),
311
- 'new_item_name' => esc_html__( 'New Project Tag Name', 'essential-content-types' ),
312
- 'search_items' => esc_html__( 'Search Project Tags', 'essential-content-types' ),
313
- 'popular_items' => esc_html__( 'Popular Project Tags', 'essential-content-types' ),
314
- 'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
315
- 'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
316
- 'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
317
- 'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
318
- 'items_list_navigation' => esc_html__( 'Project tag list navigation', 'essential-content-types' ),
319
- 'items_list' => esc_html__( 'Project tag list', 'essential-content-types' ),
320
- ),
321
- 'public' => true,
322
- 'show_ui' => true,
323
- 'show_in_nav_menus' => true,
324
- 'show_in_rest' => true,
325
- 'show_admin_column' => true,
326
- 'query_var' => true,
327
- 'rewrite' => array( 'slug' => 'project-tag' ),
328
- ) );
329
- }
330
-
331
- /**
332
- * Update messages for the Portfolio admin.
333
- */
334
- function updated_messages( $messages ) {
335
- global $post;
336
-
337
- $messages[self::CUSTOM_POST_TYPE] = array(
338
- 0 => '', // Unused. Messages start at index 1.
339
- 1 => sprintf( __( 'Project updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
340
- 2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
341
- 3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
342
- 4 => esc_html__( 'Project updated.', 'essential-content-types' ),
343
- /* translators: %s: date and time of the revision */
344
- 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,
345
- 6 => sprintf( __( 'Project published. <a href="%s">View project</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
346
- 7 => esc_html__( 'Project saved.', 'essential-content-types' ),
347
- 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 ) ) ) ),
348
- 9 => sprintf( __( 'Project scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview project</a>', 'essential-content-types' ),
349
- // translators: Publish box date format, see http://php.net/date
350
- date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
351
- 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 ) ) ) ),
352
- );
353
-
354
- return $messages;
355
- }
356
-
357
- /**
358
- * Change ‘Title’ column label
359
- * Add Featured Image column
360
- */
361
- function edit_admin_columns( $columns ) {
362
- // change 'Title' to 'Project'
363
- $columns['title'] = __( 'Project', 'essential-content-types' );
364
- if ( current_theme_supports( 'post-thumbnails' ) ) {
365
- // add featured image before 'Project'
366
- $columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
367
- }
368
-
369
- return $columns;
370
- }
371
-
372
- /**
373
- * Add featured image to column
374
- */
375
- function image_column( $column, $post_id ) {
376
- global $post;
377
- switch ( $column ) {
378
- case 'thumbnail':
379
- echo get_the_post_thumbnail( $post_id, 'jetpack-portfolio-admin-thumb' );
380
- break;
381
- }
382
- }
383
-
384
- /**
385
- * Adjust image column width
386
- */
387
- function enqueue_admin_styles( $hook ) {
388
- $screen = get_current_screen();
389
-
390
- if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
391
- 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; } }' );
392
- }
393
- }
394
-
395
- /**
396
- * Adds portfolio section to the Customizer.
397
- */
398
- function customize_register( $wp_customize ) {
399
- $options = get_theme_support( self::CUSTOM_POST_TYPE );
400
-
401
- 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'] ) ) {
402
- return;
403
- }
404
-
405
- $wp_customize->add_panel( 'ect_plugin_options', array(
406
- 'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
407
- 'priority' => 1,
408
- ) );
409
-
410
- $wp_customize->add_section( 'jetpack_portfolio', array(
411
- 'title' => esc_html__( 'Portfolio', 'essential-content-types' ),
412
- 'theme_supports' => self::CUSTOM_POST_TYPE,
413
- 'priority' => 130,
414
- 'panel' => 'ect_plugin_options',
415
- ) );
416
-
417
- if ( isset( $options[0]['title'] ) && true === $options[0]['title'] ) {
418
- $wp_customize->add_setting( 'jetpack_portfolio_title', array(
419
- 'default' => esc_html__( 'Projects', 'essential-content-types' ),
420
- 'type' => 'option',
421
- 'sanitize_callback' => 'sanitize_text_field',
422
- 'sanitize_js_callback' => 'sanitize_text_field',
423
- ) );
424
-
425
- $wp_customize->add_control( 'jetpack_portfolio_title', array(
426
- 'section' => 'jetpack_portfolio',
427
- 'label' => esc_html__( 'Portfolio Archive Title', 'essential-content-types' ),
428
- 'type' => 'text',
429
- ) );
430
- }
431
-
432
- if ( isset( $options[0]['content'] ) && true === $options[0]['content'] ) {
433
- $wp_customize->add_setting( 'jetpack_portfolio_content', array(
434
- 'default' => '',
435
- 'type' => 'option',
436
- 'sanitize_callback' => 'wp_kses_post',
437
- 'sanitize_js_callback' => 'wp_kses_post',
438
- ) );
439
-
440
- $wp_customize->add_control( 'jetpack_portfolio_content', array(
441
- 'section' => 'jetpack_portfolio',
442
- 'label' => esc_html__( 'Portfolio Archive Content', 'essential-content-types' ),
443
- 'type' => 'textarea',
444
- ) );
445
- }
446
-
447
- if ( isset( $options[0]['featured-image'] ) && true === $options[0]['featured-image'] ) {
448
- $wp_customize->add_setting( 'jetpack_portfolio_featured_image', array(
449
- 'default' => '',
450
- 'type' => 'option',
451
- 'sanitize_callback' => 'attachment_url_to_postid',
452
- 'sanitize_js_callback' => 'attachment_url_to_postid',
453
- 'theme_supports' => 'post-thumbnails',
454
- ) );
455
-
456
- $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'jetpack_portfolio_featured_image', array(
457
- 'section' => 'jetpack_portfolio',
458
- 'label' => esc_html__( 'Portfolio Archive Featured Image', 'essential-content-types' ),
459
- ) ) );
460
- }
461
- }
462
-
463
- /**
464
- * Follow CPT reading setting on CPT archive and taxonomy pages
465
- */
466
- function query_reading_setting( $query ) {
467
- if ( ! is_admin() &&
468
- $query->is_main_query() &&
469
- ( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
470
- ) {
471
- $post_per_page = ( null != get_option('posts_per_page') ) ? get_option('posts_per_page') : '10';
472
- $query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
473
- }
474
- }
475
-
476
- /**
477
- * Add to REST API post type whitelist
478
- */
479
- function allow_portfolio_rest_api_type( $post_types ) {
480
- $post_types[] = self::CUSTOM_POST_TYPE;
481
-
482
- return $post_types;
483
- }
484
-
485
- /**
486
- * Our [portfolio] shortcode.
487
- * Prints Portfolio data styled to look good on *any* theme.
488
- *
489
- * @return portfolio_shortcode_html
490
- */
491
- static function portfolio_shortcode( $atts ) {
492
- // Default attributes
493
- $atts = shortcode_atts( array(
494
- 'display_types' => true,
495
- 'display_tags' => true,
496
- 'display_content' => true,
497
- 'display_author' => false,
498
- 'show_filter' => false,
499
- 'include_type' => false,
500
- 'include_tag' => false,
501
- 'columns' => 2,
502
- 'showposts' => -1,
503
- 'order' => 'asc',
504
- 'orderby' => 'date',
505
- ), $atts, 'portfolio' );
506
-
507
- // A little sanitization
508
- if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
509
- $atts['display_types'] = false;
510
- }
511
-
512
- if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
513
- $atts['display_tags'] = false;
514
- }
515
-
516
- if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
517
- $atts['display_author'] = false;
518
- }
519
-
520
- if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
521
- $atts['display_content'] = false;
522
- }
523
-
524
- if ( $atts['include_type'] ) {
525
- $atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
526
- }
527
-
528
- if ( $atts['include_tag'] ) {
529
- $atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
530
- }
531
-
532
- // Check if column value is set to valid numbers or else set default value as 2
533
- if( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
534
- $atts['columns'] = absint( $atts['columns'] );
535
- } else {
536
- $atts['columns'] = 2;
537
- }
538
-
539
- $atts['showposts'] = intval( $atts['showposts'] );
540
-
541
-
542
- if ( $atts['order'] ) {
543
- $atts['order'] = urldecode( $atts['order'] );
544
- $atts['order'] = strtoupper( $atts['order'] );
545
- if ( 'DESC' != $atts['order'] ) {
546
- $atts['order'] = 'ASC';
547
- }
548
- }
549
-
550
- if ( $atts['orderby'] ) {
551
- $atts['orderby'] = urldecode( $atts['orderby'] );
552
- $atts['orderby'] = strtolower( $atts['orderby'] );
553
- $allowed_keys = array( 'author', 'date', 'title', 'rand' );
554
-
555
- $parsed = array();
556
- foreach ( explode( ',', $atts['orderby'] ) as $portfolio_index_number => $orderby ) {
557
- if ( ! in_array( $orderby, $allowed_keys ) ) {
558
- continue;
559
- }
560
- $parsed[] = $orderby;
561
- }
562
-
563
- if ( empty( $parsed ) ) {
564
- unset( $atts['orderby'] );
565
- } else {
566
- $atts['orderby'] = implode( ' ', $parsed );
567
- }
568
- }
569
-
570
- // enqueue shortcode styles when shortcode is used
571
- wp_enqueue_style( 'jetpack-portfolio-style', plugins_url( 'css/portfolio-shortcode.css', __FILE__ ), array(), '20140326' );
572
-
573
- return self::portfolio_shortcode_html( $atts );
574
- }
575
-
576
- /**
577
- * Query to retrieve entries from the Portfolio post_type.
578
- *
579
- * @return object
580
- */
581
- static function portfolio_query( $atts ) {
582
- // Default query arguments
583
- $default = array(
584
- 'order' => $atts['order'],
585
- 'orderby' => $atts['orderby'],
586
- 'posts_per_page' => $atts['showposts'],
587
- );
588
-
589
- $args = wp_parse_args( $atts, $default );
590
- $args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
591
-
592
- if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
593
- $args['tax_query'] = array();
594
- }
595
-
596
- // If 'include_type' has been set use it on the main query
597
- if ( false != $atts['include_type'] ) {
598
- array_push( $args['tax_query'], array(
599
- 'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
600
- 'field' => 'slug',
601
- 'terms' => $atts['include_type'],
602
- ) );
603
- }
604
-
605
- // If 'include_tag' has been set use it on the main query
606
- if ( false != $atts['include_tag'] ) {
607
- array_push( $args['tax_query'], array(
608
- 'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
609
- 'field' => 'slug',
610
- 'terms' => $atts['include_tag'],
611
- ) );
612
- }
613
-
614
- if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
615
- $args['tax_query']['relation'] = 'AND';
616
- }
617
-
618
- // Run the query and return
619
- $query = new WP_Query( $args );
620
- return $query;
621
- }
622
-
623
- /**
624
- * The Portfolio shortcode loop.
625
- *
626
- * @todo add theme color styles
627
- * @return html
628
- */
629
-
630
- static function portfolio_shortcode_html( $atts ) {
631
-
632
- $query = self::portfolio_query( $atts );
633
-
634
- ob_start();
635
-
636
- // If we have posts, create the html
637
- // with hportfolio markup
638
- if ( $query->have_posts() ) {
639
-
640
-
641
- /**
642
- * Hook: ect_before_portfolio_loop.
643
- *
644
- * @hooked ect_portfolio_section
645
- */
646
- $layout = ect_get_layout();
647
- do_action( 'ect_before_portfolio_loop', $layout[$atts['columns']] );
648
- ?>
649
- <?php
650
- //ect_portfolio_loop_start( $layout[$atts['columns']] );
651
- while ( $query->have_posts() ) {
652
- $query->the_post();
653
- ect_get_template_part( 'content', 'portfolio', $atts );
654
- /**
655
- * Hook: ect_portfolio_loop.
656
- *
657
- * @hooked
658
- */
659
- }
660
- wp_reset_postdata();
661
- //ect_portfolio_loop_end();
662
- ?>
663
- <?php
664
-
665
- /**
666
- * Hook: ect_after_portfolio_loop.
667
- *
668
- * @hooked
669
- */
670
- do_action( 'ect_after_portfolio_loop' );
671
-
672
- } else {
673
- /**
674
- * Hook: ect_no_portfolio_found.
675
- *
676
- * @hooked ect_no_portfolio_found
677
- */
678
- do_action( 'ect_no_portfolio_found' );
679
- }
680
-
681
- $html = ob_get_clean();
682
-
683
- // If there is a [portfolio] within a [portfolio], remove the shortcode
684
- if ( has_shortcode( $html, 'portfolio' ) ){
685
- remove_shortcode( 'portfolio' );
686
- }
687
-
688
- // Return the HTML block
689
- return $html;
690
- }
691
-
692
- /**
693
- * Displays the project type that a project belongs to.
694
- *
695
- * @return html
696
- */
697
- static function get_project_type( $post_id ) {
698
- $project_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
699
-
700
- // If no types, return empty string
701
- if ( empty( $project_types ) || is_wp_error( $project_types ) ) {
702
- return;
703
- }
704
-
705
- $html = '<div class="project-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
706
- $types = array();
707
- // Loop thorugh all the types
708
- foreach ( $project_types as $project_type ) {
709
- $project_type_link = get_term_link( $project_type, self::CUSTOM_TAXONOMY_TYPE );
710
-
711
- if ( is_wp_error( $project_type_link ) ) {
712
- return $project_type_link;
713
- }
714
-
715
- $types[] = '<a href="' . esc_url( $project_type_link ) . '" rel="tag">' . esc_html( $project_type->name ) . '</a>';
716
- }
717
- $html .= ' '.implode( ', ', $types );
718
- $html .= '</div>';
719
-
720
- return $html;
721
- }
722
-
723
- /**
724
- * Displays the project tags that a project belongs to.
725
- *
726
- * @return html
727
- */
728
- static function get_project_tags( $post_id ) {
729
- $project_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
730
-
731
- // If no tags, return empty string
732
- if ( empty( $project_tags ) || is_wp_error( $project_tags ) ) {
733
- return false;
734
- }
735
-
736
- $html = '<div class="project-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
737
- $tags = array();
738
- // Loop thorugh all the tags
739
- foreach ( $project_tags as $project_tag ) {
740
- $project_tag_link = get_term_link( $project_tag, self::CUSTOM_TAXONOMY_TYPE );
741
-
742
- if ( is_wp_error( $project_tag_link ) ) {
743
- return $project_tag_link;
744
- }
745
-
746
- $tags[] = '<a href="' . esc_url( $project_tag_link ) . '" rel="tag">' . esc_html( $project_tag->name ) . '</a>';
747
- }
748
- $html .= ' '. implode( ', ', $tags );
749
- $html .= '</div>';
750
-
751
- return $html;
752
- }
753
-
754
- /**
755
- * Displays the author of the current portfolio project.
756
- *
757
- * @return html
758
- */
759
- static function get_project_author() {
760
- $html = '<div class="project-author">';
761
- /* translators: %1$s is link to author posts, %2$s is author display name */
762
- $html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
763
- esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
764
- esc_html( get_the_author() )
765
- );
766
- $html .= '</div>';
767
-
768
- return $html;
769
- }
770
- }
771
- add_action( 'init', array( 'Essential_Content_Jetpack_Portfolio', 'init' ) );
772
-
773
- /**
774
- * Add Portfolio support
775
- */
776
- function essential_content_portfolio_support() {
777
- /*
778
- * Adding theme support for Jetpack Portfolio CPT.
779
- */
780
- add_theme_support( 'jetpack-portfolio', array(
781
- 'title' => true,
782
- 'content' => true,
783
- 'featured-image' => true,
784
- ) );
785
- add_image_size( 'ect-jetpack-portfolio-featured', 640, 640, true );
786
- }
787
- add_action( 'after_setup_theme', 'essential_content_portfolio_support' );
788
-
789
-
790
- if( ! function_exists( 'essential_content_get_portfolio_thumbnail_link' ) ):
791
- /**
792
- * Display the featured image if it's available
793
- *
794
- * @return html
795
- */
796
- function essential_content_get_portfolio_thumbnail_link( $post_id ) {
797
- if ( has_post_thumbnail( $post_id ) ) {
798
- /**
799
- * Change the Portfolio thumbnail size.
800
- *
801
- * @module custom-content-types
802
- *
803
- * @since 3.4.0
804
- *
805
- * @param string|array $var Either a registered size keyword or size array.
806
- */
807
- 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>';
808
- }
809
- }
810
- endif;
811
-
812
-
813
- if( ! function_exists( 'essential_content_no_portfolio_found' ) ):
814
- /**
815
- * No items found text
816
- *
817
- * @return html
818
- */
819
- function essential_content_no_portfolio_found() {
820
- 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>";
821
- }
822
- endif;
823
- add_action( 'ect_no_portfolio_found', 'essential_content_no_portfolio_found', 10 );
824
-
825
-
826
- if( ! function_exists( 'essential_content_portfolio_section_open' ) ):
827
- /**
828
- * Open section
829
- *
830
- * @return html
831
- */
832
- function essential_content_portfolio_section_open( $layout ) {
833
- echo '<div class="ect-portfolio ect-section">';
834
- echo '<div class="ect-wrapper">';
835
- }
836
- endif;
837
- add_action( 'ect_before_portfolio_loop', 'essential_content_portfolio_section_open', 10, 1 );
838
-
839
-
840
- if( ! function_exists( 'essential_content_portfolio_loop_start' ) ):
841
- /**
842
- * open wrapper before loop
843
- *
844
- */
845
- function essential_content_portfolio_loop_start( $layout = null ){
846
- echo '<div class="section-content-wrapper portfolio-content-wrapper ' . $layout . '">';
847
- }
848
- endif;
849
- add_action( 'ect_before_portfolio_loop', 'essential_content_portfolio_loop_start', 30 );
850
-
851
-
852
- if( ! function_exists( 'essential_content_portfolio_loop_end' ) ):
853
- /**
854
- * close wrapper after loop
855
- *
856
- */
857
- function essential_content_portfolio_loop_end(){
858
- echo '</div><!-- .portfolio-content-wrapper -->';
859
- }
860
- endif;
861
- add_action( 'ect_after_portfolio_loop', 'essential_content_portfolio_loop_end', 10 );
862
-
863
-
864
- if( ! function_exists( 'essential_content_portfolio_section_close' ) ):
865
- /**
866
- * Close section
867
- *
868
- * @return html
869
- */
870
- function essential_content_portfolio_section_close() {
871
- echo '</div><!-- .ect-wrapper -->';
872
- echo '</div><!-- .ect-section -->';
873
- }
874
- endif;
 
 
 
 
 
 
 
875
  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,729 +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
- register_post_type( self::CUSTOM_POST_TYPE, 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
- register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
146
- 'hierarchical' => true,
147
- 'labels' => array(
148
- 'name' => esc_html__( 'Service Types', 'essential-content-types' ),
149
- 'singular_name' => esc_html__( 'Service Type', 'essential-content-types' ),
150
- 'menu_name' => esc_html__( 'Service Types', 'essential-content-types' ),
151
- 'all_items' => esc_html__( 'All Service Types', 'essential-content-types' ),
152
- 'edit_item' => esc_html__( 'Edit Service Type', 'essential-content-types' ),
153
- 'view_item' => esc_html__( 'View Service Type', 'essential-content-types' ),
154
- 'update_item' => esc_html__( 'Update Service Type', 'essential-content-types' ),
155
- 'add_new_item' => esc_html__( 'Add New Service Type', 'essential-content-types' ),
156
- 'new_item_name' => esc_html__( 'New Service Type Name', 'essential-content-types' ),
157
- 'parent_item' => esc_html__( 'Parent Service Type', 'essential-content-types' ),
158
- 'parent_item_colon' => esc_html__( 'Parent Service Type:', 'essential-content-types' ),
159
- 'search_items' => esc_html__( 'Search Service Types', 'essential-content-types' ),
160
- 'items_list_navigation' => esc_html__( 'Service type list navigation', 'essential-content-types' ),
161
- 'items_list' => esc_html__( 'Service type list', 'essential-content-types' ),
162
- ),
163
- 'public' => true,
164
- 'show_ui' => true,
165
- 'show_in_nav_menus' => true,
166
- 'show_in_rest' => true,
167
- 'show_admin_column' => true,
168
- 'query_var' => true,
169
- 'rewrite' => array( 'slug' => 'service-type' ),
170
- ) );
171
-
172
- register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
173
- 'hierarchical' => false,
174
- 'labels' => array(
175
- 'name' => esc_html__( 'Service Tags', 'essential-content-types' ),
176
- 'singular_name' => esc_html__( 'Service Tag', 'essential-content-types' ),
177
- 'menu_name' => esc_html__( 'Service Tags', 'essential-content-types' ),
178
- 'all_items' => esc_html__( 'All Service Tags', 'essential-content-types' ),
179
- 'edit_item' => esc_html__( 'Edit Service Tag', 'essential-content-types' ),
180
- 'view_item' => esc_html__( 'View Service Tag', 'essential-content-types' ),
181
- 'update_item' => esc_html__( 'Update Service Tag', 'essential-content-types' ),
182
- 'add_new_item' => esc_html__( 'Add New Service Tag', 'essential-content-types' ),
183
- 'new_item_name' => esc_html__( 'New Service Tag Name', 'essential-content-types' ),
184
- 'search_items' => esc_html__( 'Search Service Tags', 'essential-content-types' ),
185
- 'popular_items' => esc_html__( 'Popular Service Tags', 'essential-content-types' ),
186
- 'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
187
- 'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
188
- 'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
189
- 'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
190
- 'items_list_navigation' => esc_html__( 'Service tag list navigation', 'essential-content-types' ),
191
- 'items_list' => esc_html__( 'Service tag list', 'essential-content-types' ),
192
- ),
193
- 'public' => true,
194
- 'show_ui' => true,
195
- 'show_in_nav_menus' => true,
196
- 'show_in_rest' => true,
197
- 'show_admin_column' => true,
198
- 'query_var' => true,
199
- 'rewrite' => array( 'slug' => 'service-tag' ),
200
- ) );
201
- }
202
-
203
- /**
204
- * Update messages for the Services admin.
205
- */
206
- function updated_messages( $messages ) {
207
- global $post;
208
-
209
- $messages[self::CUSTOM_POST_TYPE] = array(
210
- 0 => '', // Unused. Messages start at index 1.
211
- 1 => sprintf( __( 'Service updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
212
- 2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
213
- 3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
214
- 4 => esc_html__( 'Service updated.', 'essential-content-types' ),
215
- /* translators: %s: date and time of the revision */
216
- 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,
217
- 6 => sprintf( __( 'Service published. <a href="%s">View content</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
218
- 7 => esc_html__( 'Service saved.', 'essential-content-types' ),
219
- 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 ) ) ) ),
220
- 9 => sprintf( __( 'Service scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview service</a>', 'essential-content-types' ),
221
- // translators: Publish box date format, see http://php.net/date
222
- date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
223
- 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 ) ) ) ),
224
- );
225
-
226
- return $messages;
227
- }
228
-
229
- /**
230
- * Change ‘Title’ column label
231
- * Add Featured Image column
232
- */
233
- function edit_admin_columns( $columns ) {
234
- // change 'Title' to 'Content'
235
- $columns['title'] = __( 'Service', 'essential-content-types' );
236
- if ( current_theme_supports( 'post-thumbnails' ) ) {
237
- // add featured image before 'Content'
238
- $columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
239
- }
240
-
241
- return $columns;
242
- }
243
-
244
- /**
245
- * Add featured image to column
246
- */
247
- function image_column( $column, $post_id ) {
248
- global $post;
249
- switch ( $column ) {
250
- case 'thumbnail':
251
- echo get_the_post_thumbnail( $post_id, 'service-admin-thumb' );
252
- break;
253
- }
254
- }
255
-
256
- /**
257
- * Adjust image column width
258
- */
259
- function enqueue_admin_styles( $hook ) {
260
- $screen = get_current_screen();
261
-
262
- if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
263
- 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; } }' );
264
- }
265
- }
266
-
267
- /**
268
- * Adds service section to the Customizer.
269
- */
270
- function customize_register( $wp_customize ) {
271
- $wp_customize->add_panel( 'ect_plugin_options', array(
272
- 'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
273
- 'priority' => 1,
274
- ) );
275
-
276
- $wp_customize->add_section( 'ect_service', array(
277
- 'title' => esc_html__( 'Services', 'essential-content-types' ),
278
- 'priority' => 130,
279
- 'panel' => 'ect_plugin_options',
280
- ) );
281
-
282
- $wp_customize->add_setting( 'ect_service_title', array(
283
- 'default' => esc_html__( 'Services', 'essential-content-types' ),
284
- 'type' => 'option',
285
- 'sanitize_callback' => 'sanitize_text_field',
286
- 'sanitize_js_callback' => 'sanitize_text_field',
287
- ) );
288
-
289
- $wp_customize->add_control( 'ect_service_title', array(
290
- 'section' => 'ect_service',
291
- 'label' => esc_html__( 'Service Archive Title', 'essential-content-types' ),
292
- 'type' => 'text',
293
- ) );
294
-
295
- $wp_customize->add_setting( 'ect_service_content', array(
296
- 'default' => '',
297
- 'type' => 'option',
298
- 'sanitize_callback' => 'wp_kses_post',
299
- 'sanitize_js_callback' => 'wp_kses_post',
300
- ) );
301
-
302
- $wp_customize->add_control( 'ect_service_content', array(
303
- 'section' => 'ect_service',
304
- 'label' => esc_html__( 'Service Archive Content', 'essential-content-types' ),
305
- 'type' => 'textarea',
306
- ) );
307
-
308
- $wp_customize->add_setting( 'ect_service_featured_image', array(
309
- 'default' => '',
310
- 'type' => 'option',
311
- 'sanitize_callback' => 'attachment_url_to_postid',
312
- 'sanitize_js_callback' => 'attachment_url_to_postid',
313
- 'theme_supports' => 'post-thumbnails',
314
- ) );
315
-
316
- $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'ect_service_featured_image', array(
317
- 'section' => 'ect_service',
318
- 'label' => esc_html__( 'Service Archive Featured Image', 'essential-content-types' ),
319
- ) ) );
320
- }
321
-
322
- /**
323
- * Follow CPT reading setting on CPT archive and taxonomy pages
324
- */
325
- function query_reading_setting( $query ) {
326
- if ( ! is_admin() &&
327
- $query->is_main_query() &&
328
- ( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
329
- ) {
330
- $post_per_page = ( null != get_option('posts_per_page') ) ? get_option('posts_per_page') : '10';
331
- $query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
332
- }
333
- }
334
-
335
- /**
336
- * Add to REST API post type whitelist
337
- */
338
- function allow_service_rest_api_type( $post_types ) {
339
- $post_types[] = self::CUSTOM_POST_TYPE;
340
-
341
- return $post_types;
342
- }
343
-
344
- /**
345
- * Our [services] shortcode.
346
- * Prints Service data styled to look good on *any* theme.
347
- *
348
- * @return service_shortcode_html
349
- */
350
- static function service_shortcode( $atts ) {
351
- // Default attributes
352
- $atts = shortcode_atts( array(
353
- 'image' => true,
354
- 'display_types' => true,
355
- 'display_tags' => true,
356
- 'display_content' => true,
357
- 'display_author' => false,
358
- 'show_filter' => false,
359
- 'include_type' => false,
360
- 'include_tag' => false,
361
- 'columns' => 2,
362
- 'showposts' => -1,
363
- 'order' => 'asc',
364
- 'orderby' => 'date',
365
- ), $atts, 'services' );
366
-
367
- // A little sanitization
368
- if ( $atts['image'] && 'true' != $atts['image'] ) {
369
- $atts['image'] = false;
370
- }
371
-
372
- if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
373
- $atts['display_types'] = false;
374
- }
375
-
376
- if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
377
- $atts['display_tags'] = false;
378
- }
379
-
380
- if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
381
- $atts['display_author'] = false;
382
- }
383
-
384
- if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
385
- $atts['display_content'] = false;
386
- }
387
-
388
- if ( $atts['include_type'] ) {
389
- $atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
390
- }
391
-
392
- if ( $atts['include_tag'] ) {
393
- $atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
394
- }
395
-
396
- // Check if column value is set to valid numbers or else set default value as 2
397
- if( 1 <= $atts['columns'] && 6 >= $atts['columns'] ) {
398
- $atts['columns'] = absint( $atts['columns'] );
399
- } else {
400
- $atts['columns'] = 2;
401
- }
402
-
403
- $atts['showposts'] = intval( $atts['showposts'] );
404
-
405
-
406
- if ( $atts['order'] ) {
407
- $atts['order'] = urldecode( $atts['order'] );
408
- $atts['order'] = strtoupper( $atts['order'] );
409
- if ( 'DESC' != $atts['order'] ) {
410
- $atts['order'] = 'ASC';
411
- }
412
- }
413
-
414
- if ( $atts['orderby'] ) {
415
- $atts['orderby'] = urldecode( $atts['orderby'] );
416
- $atts['orderby'] = strtolower( $atts['orderby'] );
417
- $allowed_keys = array( 'author', 'date', 'title', 'rand' );
418
-
419
- $parsed = array();
420
- foreach ( explode( ',', $atts['orderby'] ) as $service_index_number => $orderby ) {
421
- if ( ! in_array( $orderby, $allowed_keys ) ) {
422
- continue;
423
- }
424
- $parsed[] = $orderby;
425
- }
426
-
427
- if ( empty( $parsed ) ) {
428
- unset( $atts['orderby'] );
429
- } else {
430
- $atts['orderby'] = implode( ' ', $parsed );
431
- }
432
- }
433
-
434
- // enqueue shortcode styles when shortcode is used
435
- wp_enqueue_style( 'service-style', plugins_url( 'css/service-shortcode.css', __FILE__ ), array(), '20140326' );
436
-
437
- return self::service_shortcode_html( $atts );
438
- }
439
-
440
- /**
441
- * Query to retrieve entries from the Service post_type.
442
- *
443
- * @return object
444
- */
445
- static function service_query( $atts ) {
446
- // Default query arguments
447
- $default = array(
448
- 'order' => $atts['order'],
449
- 'orderby' => $atts['orderby'],
450
- 'posts_per_page' => $atts['showposts'],
451
- );
452
-
453
- $args = wp_parse_args( $atts, $default );
454
- $args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
455
-
456
- if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
457
- $args['tax_query'] = array();
458
- }
459
-
460
- // If 'include_type' has been set use it on the main query
461
- if ( false != $atts['include_type'] ) {
462
- array_push( $args['tax_query'], array(
463
- 'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
464
- 'field' => 'slug',
465
- 'terms' => $atts['include_type'],
466
- ) );
467
- }
468
-
469
- // If 'include_tag' has been set use it on the main query
470
- if ( false != $atts['include_tag'] ) {
471
- array_push( $args['tax_query'], array(
472
- 'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
473
- 'field' => 'slug',
474
- 'terms' => $atts['include_tag'],
475
- ) );
476
- }
477
-
478
- if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
479
- $args['tax_query']['relation'] = 'AND';
480
- }
481
-
482
- // Run the query and return
483
- $query = new WP_Query( $args );
484
- return $query;
485
- }
486
-
487
- /**
488
- * The Service shortcode loop.
489
- *
490
- * @todo add theme color styles
491
- * @return html
492
- */
493
-
494
- static function service_shortcode_html( $atts ) {
495
-
496
- $query = self::service_query( $atts );
497
- $atts['service_index_number'] = 0;
498
-
499
- ob_start();
500
-
501
- // If we have posts, create the html
502
- // with service markup
503
- if ( $query->have_posts() ) {
504
-
505
- /**
506
- * Hook: ect_before_service_loop.
507
- *
508
- * @hooked
509
- */
510
- $layout = ect_get_layout();
511
- do_action( 'ect_before_service_loop', $layout[$atts['columns']] );
512
-
513
- ?>
514
- <?php
515
- while ( $query->have_posts() ) {
516
- $query->the_post();
517
- ect_get_template_part( 'content', 'service', $atts );
518
- /**
519
- * Hook: ect_service_loop.
520
- *
521
- * @hooked
522
- */
523
- }
524
- wp_reset_postdata();
525
- ?>
526
- <?php
527
-
528
- /**
529
- * Hook: ect_after_service_loop.
530
- *
531
- * @hooked
532
- */
533
- do_action( 'ect_after_service_loop' );
534
-
535
- } else {
536
- /**
537
- * Hook: ect_no_service_found.
538
- *
539
- * @hooked ect_no_service_found
540
- */
541
- do_action( 'ect_no_service_found' );
542
- }
543
-
544
- $html = ob_get_clean();
545
-
546
- // If there is a [services] within a [services], remove the shortcode
547
- if ( has_shortcode( $html, 'services' ) ){
548
- remove_shortcode( 'services' );
549
- }
550
-
551
- // Return the HTML block
552
- return $html;
553
- }
554
-
555
- /**
556
- * Displays the content type that a content belongs to.
557
- *
558
- * @return html
559
- */
560
- static function get_content_type( $post_id ) {
561
- $content_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
562
-
563
- // If no types, return empty string
564
- if ( empty( $content_types ) || is_wp_error( $content_types ) ) {
565
- return;
566
- }
567
-
568
- $html = '<div class="content-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
569
- $types = array();
570
- // Loop thorugh all the types
571
- foreach ( $content_types as $content_type ) {
572
- $content_type_link = get_term_link( $content_type, self::CUSTOM_TAXONOMY_TYPE );
573
-
574
- if ( is_wp_error( $content_type_link ) ) {
575
- return $content_type_link;
576
- }
577
-
578
- $types[] = '<a href="' . esc_url( $content_type_link ) . '" rel="tag">' . esc_html( $content_type->name ) . '</a>';
579
- }
580
- $html .= ' '.implode( ', ', $types );
581
- $html .= '</div>';
582
-
583
- return $html;
584
- }
585
-
586
- /**
587
- * Displays the content tags that a content belongs to.
588
- *
589
- * @return html
590
- */
591
- static function get_content_tags( $post_id ) {
592
- $content_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
593
-
594
- // If no tags, return empty string
595
- if ( empty( $content_tags ) || is_wp_error( $content_tags ) ) {
596
- return false;
597
- }
598
-
599
- $html = '<div class="content-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
600
- $tags = array();
601
- // Loop thorugh all the tags
602
- foreach ( $content_tags as $content_tag ) {
603
- $content_tag_link = get_term_link( $content_tag, self::CUSTOM_TAXONOMY_TYPE );
604
-
605
- if ( is_wp_error( $content_tag_link ) ) {
606
- return $content_tag_link;
607
- }
608
-
609
- $tags[] = '<a href="' . esc_url( $content_tag_link ) . '" rel="tag">' . esc_html( $content_tag->name ) . '</a>';
610
- }
611
- $html .= ' '. implode( ', ', $tags );
612
- $html .= '</div>';
613
-
614
- return $html;
615
- }
616
-
617
- /**
618
- * Displays the author of the current service content.
619
- *
620
- * @return html
621
- */
622
- static function get_content_author() {
623
- $html = '<div class="content-author">';
624
- /* translators: %1$s is link to author posts, %2$s is author display name */
625
- $html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
626
- esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
627
- esc_html( get_the_author() )
628
- );
629
- $html .= '</div>';
630
-
631
- return $html;
632
- }
633
- }
634
- add_action( 'init', array( 'Essential_Content_Service', 'init' ) );
635
-
636
-
637
- /**
638
- * Add Service support
639
- */
640
- function essential_content_service_support() {
641
- /*
642
- * Adding theme support for Jetpack Service CPT.
643
- */
644
- add_image_size( 'ect-service', 640, 640, true );
645
- }
646
- add_action( 'after_setup_theme', 'essential_content_service_support' );
647
-
648
-
649
- if( ! function_exists( 'essential_content_get_service_thumbnail_link' ) ):
650
- function essential_content_get_service_thumbnail_link( $post_id, $size ) {
651
- if ( has_post_thumbnail( $post_id ) ) {
652
- /**
653
- * Change the Service thumbnail size.
654
- *
655
- * @module custom-content-types
656
- *
657
- * @since 3.4.0
658
- *
659
- * @param string|array $var Either a registered size keyword or size array.
660
- */
661
- 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>';
662
- }
663
- }
664
- endif;
665
-
666
-
667
- if( ! function_exists( 'essential_content_no_service_found' ) ):
668
- /**
669
- * No items found text
670
- *
671
- * @return html
672
- */
673
- function essential_content_no_service_found() {
674
- 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>";
675
- }
676
- add_action( 'ect_no_service_found', 'essential_content_no_service_found', 10 );
677
- endif;
678
-
679
-
680
- if( ! function_exists( 'essential_content_service_section_open' ) ):
681
- /**
682
- * Open section
683
- *
684
- * @return html
685
- */
686
- function essential_content_service_section_open( $layout ) {
687
- echo '<div class="ect-service ect-section">';
688
- echo '<div class="ect-wrapper">';
689
- }
690
- endif;
691
- add_action( 'ect_before_service_loop', 'essential_content_service_section_open', 10, 1 );
692
-
693
-
694
- if( ! function_exists( 'essential_content_service_loop_start' ) ):
695
- /**
696
- * open wrapper before loop
697
- *
698
- */
699
- function essential_content_service_loop_start( $layout = null ){
700
- echo '<div class="section-content-wrapper service-content-wrapper ' . $layout . '">';
701
- }
702
- endif;
703
- add_action( 'ect_before_service_loop', 'essential_content_service_loop_start', 30 );
704
-
705
-
706
- if( ! function_exists( 'essential_content_service_loop_end' ) ):
707
- /**
708
- * close wrapper after loop
709
- *
710
- */
711
- function essential_content_service_loop_end(){
712
- echo '</div><!-- .service-content-wrapper -->';
713
- }
714
- endif;
715
- add_action( 'ect_after_service_loop', 'essential_content_service_loop_end', 10 );
716
-
717
-
718
- if( ! function_exists( 'essential_content_service_section_close' ) ):
719
- /**
720
- * Close section
721
- *
722
- * @return html
723
- */
724
- function essential_content_service_section_close() {
725
- echo '</div><!-- .ect-wrapper -->';
726
- echo '</div><!-- .ect-section -->';
727
- }
728
- endif;
 
 
 
 
 
 
 
729
  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,1016 +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 endif;
156
-
157
- if ( $this->site_supports_custom_post_type() ) :
158
- printf( '<p><label for="%1$s">%2$s</label></p>',
159
- esc_attr( self::OPTION_READING_SETTING ),
160
- /* translators: %1$s is replaced with an input field for numbers */
161
- sprintf( __( 'Testimonial pages display at most %1$s testimonials', 'essential-content-types' ),
162
- sprintf( '<input name="%1$s" id="%1$s" type="number" step="1" min="1" value="%2$s" class="small-text" />',
163
- esc_attr( self::OPTION_READING_SETTING ),
164
- esc_attr( get_option( self::OPTION_READING_SETTING, '10' ) )
165
- )
166
- )
167
- );
168
- endif;
169
- }
170
-
171
- /**
172
- * Should this Custom Post Type be made available?
173
- */
174
- function site_supports_custom_post_type() {
175
- // If the current theme requests it.
176
- if ( current_theme_supports( self::CUSTOM_POST_TYPE ) || get_option( self::OPTION_NAME, '0' ) ) {
177
- return true;
178
- }
179
-
180
- // Otherwise, say no unless something wants to filter us to say yes.
181
- /** This action is documented in modules/custom-post-types/nova.php */
182
- return (bool) apply_filters( 'jetpack_enable_cpt', false, self::CUSTOM_POST_TYPE );
183
- }
184
-
185
- /**
186
- * Add to REST API post type whitelist
187
- */
188
- function allow_cpt_rest_api_type( $post_types ) {
189
- $post_types[] = self::CUSTOM_POST_TYPE;
190
-
191
- return $post_types;
192
- }
193
-
194
-
195
- /*
196
- * Flush permalinks when CPT option is turned on/off
197
- */
198
- function flush_rules_on_enable() {
199
- flush_rewrite_rules();
200
- }
201
-
202
- /*
203
- * Count published testimonials and flush permalinks when first testimonial is published
204
- */
205
- function flush_rules_on_first_testimonial() {
206
- $testimonials = get_transient( 'jetpack-testimonial-count-cache' );
207
-
208
- if ( false === $testimonials ) {
209
- flush_rewrite_rules();
210
- $testimonials = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
211
-
212
- if ( ! empty( $testimonials ) ) {
213
- set_transient( 'jetpack-testimonial-count-cache', $testimonials, HOUR_IN_SECONDS * 12 );
214
- }
215
- }
216
- }
217
-
218
- /*
219
- * Flush permalinks when CPT supported theme is activated
220
- */
221
- function flush_rules_on_switch() {
222
- if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
223
- flush_rewrite_rules();
224
- }
225
- }
226
-
227
- /**
228
- * On plugin/theme activation, check if current theme supports CPT
229
- */
230
- static function activation_post_type_support() {
231
- if ( current_theme_supports( self::CUSTOM_POST_TYPE ) ) {
232
- update_option( self::OPTION_NAME, '1' );
233
- }
234
- }
235
-
236
- /**
237
- * On theme switch, check if CPT item exists and disable if not
238
- */
239
- function deactivation_post_type_support() {
240
- $testimonials = get_posts( array(
241
- 'fields' => 'ids',
242
- 'posts_per_page' => 1,
243
- 'post_type' => self::CUSTOM_POST_TYPE,
244
- 'suppress_filters' => false
245
- ) );
246
-
247
- if ( empty( $testimonials ) ) {
248
- update_option( self::OPTION_NAME, '0' );
249
- }
250
- }
251
-
252
- /**
253
- * Register Post Type
254
- */
255
- function register_post_types() {
256
- if ( post_type_exists( self::CUSTOM_POST_TYPE ) ) {
257
- return;
258
- }
259
-
260
- register_post_type( self::CUSTOM_POST_TYPE, array(
261
- 'description' => __( 'Customer Testimonials', 'essential-content-types' ),
262
- 'labels' => array(
263
- 'name' => esc_html__( 'Testimonials', 'essential-content-types' ),
264
- 'singular_name' => esc_html__( 'Testimonial', 'essential-content-types' ),
265
- 'menu_name' => esc_html__( 'Testimonials', 'essential-content-types' ),
266
- 'all_items' => esc_html__( 'All Testimonials', 'essential-content-types' ),
267
- 'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
268
- 'add_new_item' => esc_html__( 'Add New Testimonial', 'essential-content-types' ),
269
- 'edit_item' => esc_html__( 'Edit Testimonial', 'essential-content-types' ),
270
- 'new_item' => esc_html__( 'New Testimonial', 'essential-content-types' ),
271
- 'view_item' => esc_html__( 'View Testimonial', 'essential-content-types' ),
272
- 'search_items' => esc_html__( 'Search Testimonials', 'essential-content-types' ),
273
- 'not_found' => esc_html__( 'No Testimonials found', 'essential-content-types' ),
274
- 'not_found_in_trash' => esc_html__( 'No Testimonials found in Trash', 'essential-content-types' ),
275
- 'filter_items_list' => esc_html__( 'Filter Testimonials list', 'essential-content-types' ),
276
- 'items_list_navigation' => esc_html__( 'Testimonial list navigation', 'essential-content-types' ),
277
- 'items_list' => esc_html__( 'Testimonials list', 'essential-content-types' ),
278
- ),
279
- 'supports' => array(
280
- 'title',
281
- 'editor',
282
- 'excerpt',
283
- 'thumbnail',
284
- 'page-attributes',
285
- 'revisions',
286
- ),
287
- 'rewrite' => array(
288
- 'slug' => 'testimonial',
289
- 'with_front' => false,
290
- 'feeds' => false,
291
- 'pages' => true,
292
- ),
293
- 'public' => true,
294
- 'show_ui' => true,
295
- 'menu_position' => 20, // below Pages
296
- 'menu_icon' => 'dashicons-testimonial',
297
- 'capability_type' => 'page',
298
- 'map_meta_cap' => true,
299
- 'has_archive' => true,
300
- 'query_var' => 'testimonial',
301
- 'show_in_rest' => true,
302
- ) );
303
- }
304
-
305
- /**
306
- * Update messages for the Testimonial admin.
307
- */
308
- function updated_messages( $messages ) {
309
- global $post;
310
-
311
- $messages[ self::CUSTOM_POST_TYPE ] = array(
312
- 0 => '', // Unused. Messages start at index 1.
313
- 1 => sprintf( __( 'Testimonial updated. <a href="%s">View testimonial</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
314
- 2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
315
- 3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
316
- 4 => esc_html__( 'Testimonial updated.', 'essential-content-types' ),
317
- /* translators: %s: date and time of the revision */
318
- 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,
319
- 6 => sprintf( __( 'Testimonial published. <a href="%s">View testimonial</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
320
- 7 => esc_html__( 'Testimonial saved.', 'essential-content-types' ),
321
- 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 ) ) ) ),
322
- 9 => sprintf( __( 'Testimonial scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview testimonial</a>', 'essential-content-types' ),
323
- // translators: Publish box date format, see http://php.net/date
324
- date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
325
- 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 ) ) ) ),
326
- );
327
-
328
- return $messages;
329
- }
330
-
331
- /**
332
- * Change ‘Enter Title Here’ text for the Testimonial.
333
- */
334
- function change_default_title( $title ) {
335
- $screen = get_current_screen();
336
-
337
- if ( self::CUSTOM_POST_TYPE == $screen->post_type )
338
- $title = esc_html__( "Enter the customer's name here", 'essential-content-types' );
339
-
340
- return $title;
341
- }
342
-
343
- /**
344
- * Change ‘Title’ column label on all Testimonials page.
345
- */
346
- function edit_title_column_label( $columns ) {
347
- $columns['title'] = esc_html__( 'Customer Name', 'essential-content-types' );
348
-
349
- return $columns;
350
- }
351
-
352
- /**
353
- * Follow CPT reading setting on CPT archive page
354
- */
355
- function query_reading_setting( $query ) {
356
- if ( ! is_admin()
357
- && $query->is_main_query()
358
- && $query->is_post_type_archive( self::CUSTOM_POST_TYPE )
359
- ) {
360
- $post_per_page = ( null != get_option('posts_per_page') ) ? get_option('posts_per_page') : '10';
361
- $query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, $post_per_page ) );
362
- }
363
- }
364
-
365
- /*
366
- * If Infinite Scroll is set to 'click', use our custom reading setting instead of core's `posts_per_page`.
367
- */
368
- function infinite_scroll_click_posts_per_page( $settings ) {
369
- global $wp_query;
370
-
371
- if ( ! is_admin() && true === $settings['click_handle'] && $wp_query->is_post_type_archive( self::CUSTOM_POST_TYPE ) ) {
372
- $settings['posts_per_page'] = get_option( self::OPTION_READING_SETTING, $settings['posts_per_page'] );
373
- }
374
-
375
- return $settings;
376
- }
377
-
378
- /**
379
- * Add CPT to Dotcom sitemap
380
- */
381
- function add_to_sitemap( $post_types ) {
382
- $post_types[] = self::CUSTOM_POST_TYPE;
383
-
384
- return $post_types;
385
- }
386
-
387
- function set_testimonial_option() {
388
- $testimonials = wp_count_posts( self::CUSTOM_POST_TYPE );
389
- $published_testimonials = $testimonials->publish;
390
-
391
- update_option( self::OPTION_NAME, $published_testimonials );
392
- }
393
-
394
- function count_testimonials() {
395
- $testimonials = get_transient( 'jetpack-testimonial-count-cache' );
396
-
397
- if ( false === $testimonials ) {
398
- $testimonials = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
399
-
400
- if ( ! empty( $testimonials ) ) {
401
- set_transient( 'jetpack-testimonial-count-cache', $testimonials, 60*60*12 );
402
- }
403
- }
404
-
405
- return $testimonials;
406
- }
407
-
408
- /**
409
- * Adds a submenu link to the Customizer.
410
- */
411
- function add_customize_page() {
412
- add_submenu_page(
413
- 'edit.php?post_type=' . self::CUSTOM_POST_TYPE,
414
- esc_html__( 'Customize Testimonials Archive', 'essential-content-types' ),
415
- esc_html__( 'Customize', 'essential-content-types' ),
416
- 'edit_theme_options',
417
- add_query_arg( array(
418
- 'url' => urlencode( home_url( '/testimonial/' ) ),
419
- 'autofocus[section]' => 'jetpack_testimonials'
420
- ), 'customize.php' )
421
- );
422
- }
423
-
424
- /**
425
- * Adds testimonial section to the Customizer.
426
- */
427
- function customize_register( $wp_customize ) {
428
- essential_content_testimonial_custom_control_classes();
429
-
430
- $wp_customize->add_panel( 'ect_plugin_options', array(
431
- 'title' => esc_html__( 'Essential Content Types Plugin Options', 'essential-content-types' ),
432
- 'priority' => 1,
433
- ) );
434
-
435
- $wp_customize->add_section( 'jetpack_testimonials', array(
436
- 'title' => esc_html__( 'Testimonials', 'essential-content-types' ),
437
- 'theme_supports' => self::CUSTOM_POST_TYPE,
438
- 'priority' => 130,
439
- 'panel' => 'ect_plugin_options',
440
- ) );
441
-
442
- $wp_customize->add_setting( 'jetpack_testimonials[page-title]', array(
443
- 'default' => esc_html__( 'Testimonials', 'essential-content-types' ),
444
- 'sanitize_callback' => array( 'Essential_Content_Jetpack_Testimonial_Title_Control', 'sanitize_content' ),
445
- 'sanitize_js_callback' => array( 'Essential_Content_Jetpack_Testimonial_Title_Control', 'sanitize_content' ),
446
- ) );
447
- $wp_customize->add_control( 'jetpack_testimonials[page-title]', array(
448
- 'section' => 'jetpack_testimonials',
449
- 'label' => esc_html__( 'Testimonial Archive Title', 'essential-content-types' ),
450
- 'type' => 'text',
451
- ) );
452
-
453
- $wp_customize->add_setting( 'jetpack_testimonials[page-content]', array(
454
- 'default' => '',
455
- 'sanitize_callback' => array( 'Essential_Content_Jetpack_Testimonial_Textarea_Control', 'sanitize_content' ),
456
- 'sanitize_js_callback' => array( 'Essential_Content_Jetpack_Testimonial_Textarea_Control', 'sanitize_content' ),
457
- ) );
458
- $wp_customize->add_control( new Essential_Content_Jetpack_Testimonial_Textarea_Control( $wp_customize, 'jetpack_testimonials[page-content]', array(
459
- 'section' => 'jetpack_testimonials',
460
- 'settings' => 'jetpack_testimonials[page-content]',
461
- 'label' => esc_html__( 'Testimonial Archive Content', 'essential-content-types' ),
462
- ) ) );
463
-
464
- $wp_customize->add_setting( 'jetpack_testimonials[featured-image]', array(
465
- 'default' => '',
466
- 'sanitize_callback' => 'attachment_url_to_postid',
467
- 'sanitize_js_callback' => 'attachment_url_to_postid',
468
- 'theme_supports' => 'post-thumbnails',
469
- ) );
470
- $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'jetpack_testimonials[featured-image]', array(
471
- 'section' => 'jetpack_testimonials',
472
- 'label' => esc_html__( 'Testimonial Archive Featured Image', 'essential-content-types' ),
473
- ) ) );
474
-
475
- // The featured image control doesn't display properly in the Customizer unless we coerce
476
- // it back into a URL sooner, since that's what WP_Customize_Upload_Control::to_json() expects
477
- if ( is_admin() ) {
478
- add_filter( 'theme_mod_jetpack_testimonials', array( $this, 'coerce_testimonial_image_to_url' ) );
479
- }
480
- }
481
-
482
- public function coerce_testimonial_image_to_url( $opt ) {
483
- if ( ! $opt || ! is_array( $opt ) ) {
484
- return $opt;
485
- }
486
- if ( ! isset( $opt['featured-image'] ) || ! is_scalar( $opt['featured-image'] ) ) {
487
- return $opt;
488
- }
489
- $url = wp_get_attachment_url( $opt['featured-image'] );
490
- if ( $url ) {
491
- $opt['featured-image'] = $url;
492
- }
493
- return $opt;
494
- }
495
-
496
- /**
497
- * Our [testimonial] shortcode.
498
- * Prints Testimonial data styled to look good on *any* theme.
499
- *
500
- * @return jetpack_testimonial_shortcode_html
501
- */
502
- static function jetpack_testimonial_shortcode( $atts ) {
503
- // Default attributes
504
- $atts = shortcode_atts( array(
505
- 'display_content' => true,
506
- 'image' => true,
507
- 'columns' => 1,
508
- 'showposts' => -1,
509
- 'order' => 'asc',
510
- 'orderby' => 'date',
511
- ), $atts, 'testimonial' );
512
-
513
- // A little sanitization
514
- if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
515
- $atts['display_content'] = false;
516
- }
517
-
518
- if ( $atts['image'] && 'true' != $atts['image'] ) {
519
- $atts['image'] = false;
520
- }
521
-
522
- // Check if column value is set to valid numbers or else set default value as 1
523
- if( 1 == $atts['columns'] || 2 == $atts['columns'] ) {
524
- $atts['columns'] = absint( $atts['columns'] );
525
- } else {
526
- $atts['columns'] = 1;
527
- }
528
-
529
- $atts['showposts'] = intval( $atts['showposts'] );
530
-
531
- if ( $atts['order'] ) {
532
- $atts['order'] = urldecode( $atts['order'] );
533
- $atts['order'] = strtoupper( $atts['order'] );
534
- if ( 'DESC' != $atts['order'] ) {
535
- $atts['order'] = 'ASC';
536
- }
537
- }
538
-
539
- if ( $atts['orderby'] ) {
540
- $atts['orderby'] = urldecode( $atts['orderby'] );
541
- $atts['orderby'] = strtolower( $atts['orderby'] );
542
- $allowed_keys = array('author', 'date', 'title', 'rand');
543
-
544
- $parsed = array();
545
- foreach ( explode( ',', $atts['orderby'] ) as $testimonial_index_number => $orderby ) {
546
- if ( ! in_array( $orderby, $allowed_keys ) ) {
547
- continue;
548
- }
549
- $parsed[] = $orderby;
550
- }
551
-
552
- if ( empty( $parsed ) ) {
553
- unset($atts['orderby']);
554
- } else {
555
- $atts['orderby'] = implode( ' ', $parsed );
556
- }
557
- }
558
-
559
- // enqueue shortcode styles when shortcode is used
560
- wp_enqueue_style( 'jetpack-testimonial-style', plugins_url( 'css/testimonial-shortcode.css', __FILE__ ), array(), '20140326' );
561
-
562
- return self::jetpack_testimonial_shortcode_html( $atts );
563
- }
564
-
565
- /**
566
- * The Testimonial shortcode loop.
567
- *
568
- * @todo add theme color styles
569
- * @return html
570
- */
571
-
572
- static function jetpack_testimonial_shortcode_html( $atts ) {
573
-
574
- // Default query arguments
575
- $defaults = array(
576
- 'order' => $atts['order'],
577
- 'orderby' => $atts['orderby'],
578
- 'posts_per_page' => $atts['showposts'],
579
- );
580
-
581
- $args = wp_parse_args( $atts, $defaults );
582
- $args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
583
- $query = new WP_Query( $args );
584
-
585
- ob_start();
586
-
587
- // If we have posts, create the html
588
- // with testimonial markup
589
- if ( $query->have_posts() ) {
590
-
591
-
592
- /**
593
- * Hook: ect_before_testimonial_loop.
594
- *
595
- * @hooked
596
- */
597
- $layout = ect_get_layout();
598
- do_action( 'ect_before_testimonial_loop', $layout[$atts['columns']] );
599
- ?>
600
- <?php
601
- while ( $query->have_posts() ) {
602
-
603
- $query->the_post();
604
- ect_get_template_part( 'content', 'testimonial', $atts );
605
-
606
- }
607
- wp_reset_postdata();
608
- ?>
609
- <?php
610
-
611
- /**
612
- * Hook: ect_after_testimonial_loop.
613
- *
614
- * @hooked
615
- */
616
- do_action( 'ect_after_testimonial_loop' );
617
-
618
- } else {
619
- /**
620
- * Hook: ect_no_testimonial_found.
621
- *
622
- * @hooked ect_no_testimonial_found
623
- */
624
- do_action( 'ect_no_testimonial_found' );
625
- }
626
-
627
- $html = ob_get_clean();
628
-
629
- // If there is a [testimonials] within a [testimonials], remove the shortcode
630
- if ( has_shortcode( $html, 'testimonials' ) ){
631
- remove_shortcode( 'testimonials' );
632
- }
633
-
634
- // Return the HTML block
635
- return $html;
636
- }
637
- }
638
- add_action( 'init', array( 'Essential_Content_Jetpack_Testimonial', 'init' ) );
639
-
640
-
641
- function essential_content_testimonial_custom_control_classes() {
642
- class Essential_Content_Jetpack_Testimonial_Title_Control extends WP_Customize_Control {
643
- public static function sanitize_content( $value ) {
644
- if ( '' != $value )
645
- $value = trim( convert_chars( wptexturize( $value ) ) );
646
-
647
- return $value;
648
- }
649
- }
650
-
651
- class Essential_Content_Jetpack_Testimonial_Textarea_Control extends WP_Customize_Control {
652
- public $type = 'textarea';
653
-
654
- public function render_content() {
655
- ?>
656
- <label>
657
- <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
658
- <textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
659
- </label>
660
- <?php
661
- }
662
-
663
- public static function sanitize_content( $value ) {
664
- if ( ! empty( $value ) )
665
- /** This filter is already documented in core. wp-includes/post-template.php */
666
- $value = apply_filters( 'the_content', $value );
667
-
668
- $value = preg_replace( '@<div id="jp-post-flair"([^>]+)?>(.+)?</div>@is', '', $value ); // Strip WPCOM and Jetpack post flair if included in content
669
-
670
- return $value;
671
- }
672
- }
673
- }
674
-
675
- /**
676
- * Add Testimonial support
677
- */
678
- function essential_content_testimonial_support() {
679
- /*
680
- * Adding theme support for Jetpack Testimonial CPT.
681
- */
682
- add_theme_support( 'jetpack-testimonial' );
683
- }
684
- add_action( 'after_setup_theme', 'essential_content_testimonial_support' );
685
-
686
-
687
- /**
688
- * Class to Renders and save metabox options
689
- *
690
- */
691
- class Essential_Content_Jetpack_Testimonial_Metabox {
692
- private $meta_box;
693
-
694
- private $fields;
695
-
696
- /**
697
- * Constructor
698
- *
699
- *
700
- * @access public
701
- *
702
- */
703
- public function __construct( $meta_box_id, $meta_box_title, $post_type ) {
704
-
705
- $this->meta_box = array (
706
- 'id' => $meta_box_id,
707
- 'title' => $meta_box_title,
708
- 'post_type' => $post_type,
709
- );
710
-
711
- $this->fields = array(
712
- 'ect-testimonials',
713
- );
714
-
715
-
716
- // Add metaboxes
717
- add_action( 'add_meta_boxes', array( $this, 'add' ) );
718
-
719
- add_action( 'save_post', array( $this, 'save' ) );
720
- }
721
-
722
- /**
723
- * Add Meta Box for multiple post types.
724
- *
725
- *
726
- * @access public
727
- */
728
- public function add($postType) {
729
- if( in_array( $postType, $this->meta_box['post_type'] ) ) {
730
- add_meta_box( $this->meta_box['id'], $this->meta_box['title'], array( $this, 'show' ), null, 'side', 'high' );
731
- }
732
- }
733
-
734
- /**
735
- * Renders metabox
736
- *
737
- *
738
- * @access public
739
- */
740
- public function show() {
741
- global $post;
742
-
743
- // Use nonce for verification
744
- wp_nonce_field( basename( __FILE__ ), 'ect_custom_meta_box_nonce' );
745
-
746
- $position = get_post_meta( $post->ID, 'ect_testimonial_position', true );
747
-
748
- // Begin the form ?>
749
- <p>
750
- <label for="ect_testimonial_position"><?php esc_html_e( 'Position', 'essential-content-types' ); ?></label>
751
- <input type="text" class="widefat ect-testimonial-position" name="ect_testimonial_position" value="<?php echo esc_attr( $position ); ?>" />
752
- </p>
753
- <?php
754
- }
755
-
756
- /**
757
- * Save custom metabox data
758
- *
759
- * @action save_post
760
- *
761
- * @access public
762
- */
763
- public function save( $post_id ) {
764
- global $post_type;
765
-
766
- $post_type_object = get_post_type_object( $post_type );
767
-
768
- if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) // Check Autosave
769
- || ( ! isset( $_POST['post_ID'] ) || $post_id != $_POST['post_ID'] ) // Check Revision
770
- || ( ! in_array( $post_type, $this->meta_box['post_type'] ) ) // Check if current post type is supported.
771
- || ( ! check_admin_referer( basename( __FILE__ ), 'ect_custom_meta_box_nonce') ) // Check nonce - Security
772
- || ( ! current_user_can( $post_type_object->cap->edit_post, $post_id ) ) ) // Check permission
773
- {
774
- return $post_id;
775
- }
776
-
777
- if ( ! update_post_meta ( $post_id, 'ect_testimonial_position', sanitize_text_field( $_POST['ect_testimonial_position'] ) ) ) {
778
- add_post_meta( $post_id, 'ect_testimonial_position', sanitize_text_field( $_POST['ect_testimonial_position'] ), true );
779
- }
780
- }
781
- }
782
-
783
- $ect_metabox = new Essential_Content_Jetpack_Testimonial_Metabox(
784
- 'ect-options', //metabox id
785
- esc_html__( 'Testmonial Options', 'essential-content-types' ), //metabox title
786
- array( 'jetpack-testimonial' ) //metabox post types
787
- );
788
-
789
-
790
- if( ! function_exists( 'essential_content_get_testimonial_thumbnail_link' ) ):
791
- /**
792
- * Display the featured image if it's available
793
- *
794
- * @return html
795
- */
796
- function essential_content_get_testimonial_thumbnail_link( $post_id, $size ) {
797
- if ( has_post_thumbnail( $post_id ) ) {
798
- /**
799
- * Change the Testimonial thumbnail size.
800
- *
801
- * @module custom-content-types
802
- *
803
- * @since 3.4.0
804
- *
805
- * @param string|array $var Either a registered size keyword or size array.
806
- */
807
- //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>';
808
- return '<div class="testimonial-featured-image testimonial-thumbnail post-thumbnail">' . get_the_post_thumbnail( $post_id, apply_filters( 'testimonial_thumbnail_size', $size ) ) . '</div>';
809
- }
810
- }
811
- endif;
812
-
813
-
814
- if( ! function_exists( 'essential_content_no_testimonial_found' ) ):
815
- /**
816
- * No items found text
817
- *
818
- * @return html
819
- */
820
- function essential_content_no_testimonial_found() {
821
- 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>";
822
- }
823
- add_action( 'ect_no_testimonial_found', 'essential_content_no_testimonial_found', 10 );
824
- endif;
825
-
826
-
827
- if( ! function_exists( 'essential_content_testimonial_section_open' ) ):
828
- /**
829
- * Open section
830
- *
831
- * @return html
832
- */
833
- function essential_content_testimonial_section_open( $layout = null ) {
834
- echo '<div class="ect-testimonial-content-section ect-section ' . $layout . '">';
835
- echo '<div class="ect-wrapper">';
836
- }
837
- endif;
838
- add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_section_open', 10, 1 );
839
-
840
-
841
- if( ! function_exists( 'essential_content_testimonial_loop_start' ) ):
842
- /**
843
- * open wrapper before loop
844
- *
845
- */
846
- function essential_content_testimonial_loop_start( $layout = null ){
847
- echo '<div class="section-content-wrapper testimonial-content-wrapper">';
848
- }
849
- endif;
850
- add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_loop_start', 30 );
851
-
852
-
853
- if( ! function_exists( 'essential_content_testimonial_slider_open' ) ):
854
- function essential_content_testimonial_slider_open() { ?>
855
- <div class="cycle-slideshow"
856
- data-cycle-log="false"
857
- data-cycle-pause-on-hover="true"
858
- data-cycle-swipe="true"
859
- data-cycle-auto-height=container
860
- data-cycle-loader=false
861
- data-cycle-slides=".testimonial_slider_wrap"
862
- data-cycle-pager=".testimonial-slider-pager"
863
- data-cycle-prev=".testimonial-slider-prev"
864
- data-cycle-next=".testimonial-slider-next"
865
- >
866
-
867
- <div class="controller">
868
- <!-- prev/next links -->
869
- <button class="cycle-prev testimonial-slider-prev" aria-label="Previous">
870
- <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' ) ); ?>
871
- </button>
872
-
873
- <!-- empty element for pager links -->
874
- <div class="cycle-pager testimonial-slider-pager"></div>
875
-
876
- <button class="cycle-next testimonial-slider-next" aria-label="Next">
877
- <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' ) ); ?>
878
- </button>
879
- </div><!-- .controller -->
880
-
881
- <div class="testimonial_slider_wrap">
882
-
883
- <?php }
884
- endif;
885
- //add_action( 'ect_before_testimonial_loop', 'essential_content_testimonial_slider_open', 40 );
886
-
887
-
888
- if( ! function_exists( 'essential_content_testimonial_slider_close' ) ):
889
- function essential_content_testimonial_slider_close() {
890
- echo '</div><!-- .testimonial_slider_wrap -->';
891
- echo '</div><!-- .cycle-slideshow -->';
892
- }
893
- endif;
894
- //add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_slider_close', 10 );
895
-
896
-
897
- if( ! function_exists( 'essential_content_testimonial_loop_end' ) ):
898
- /**
899
- * close wrapper after loop
900
- *
901
- */
902
- function essential_content_testimonial_loop_end(){
903
- echo '</div><!-- .testimonial-content-wrapper -->';
904
- }
905
- endif;
906
- add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_loop_end', 20 );
907
-
908
-
909
- if( ! function_exists( 'essential_content_testimonial_section_close' ) ):
910
- /**
911
- * Close section
912
- *
913
- * @return html
914
- */
915
- function essential_content_testimonial_section_close() {
916
- echo '</div><!-- .ect-wrapper -->';
917
- echo '</div><!-- .ect-section -->';
918
- }
919
- endif;
920
- add_action( 'ect_after_testimonial_loop', 'essential_content_testimonial_section_close', 30 );
921
-
922
-
923
- if( ! function_exists( 'essential_content_get_svg' ) ):
924
- /**
925
- * Return SVG markup.
926
- *
927
- * @param array $args {
928
- * Parameters needed to display an SVG.
929
- *
930
- * @type string $icon Required SVG icon filename.
931
- * @type string $title Optional SVG title.
932
- * @type string $desc Optional SVG description.
933
- * }
934
- * @return string SVG markup.
935
- */
936
- function essential_content_get_svg( $args = array() ) {
937
- // Make sure $args are an array.
938
- if ( empty( $args ) ) {
939
- return __( 'Please define default parameters in the form of an array.', 'starter-pro' );
940
- }
941
-
942
- // Define an icon.
943
- if ( false === array_key_exists( 'icon', $args ) ) {
944
- return __( 'Please define an SVG icon filename.', 'starter-pro' );
945
- }
946
-
947
- // Set defaults.
948
- $defaults = array(
949
- 'icon' => '',
950
- 'title' => '',
951
- 'desc' => '',
952
- 'fallback' => false,
953
- );
954
-
955
- // Parse args.
956
- $args = wp_parse_args( $args, $defaults );
957
-
958
- // Set aria hidden.
959
- $aria_hidden = ' aria-hidden="true"';
960
-
961
- // Set ARIA.
962
- $aria_labelledby = '';
963
-
964
- /*
965
- * Starter doesn't use the SVG title or description attributes; non-decorative icons are described with .screen-reader-text.
966
- *
967
- * However, child themes can use the title and description to add information to non-decorative SVG icons to improve accessibility.
968
- *
969
- * Example 1 with title: <?php echo starter_get_svg( array( 'icon' => 'arrow-right', 'title' => __( 'This is the title', 'textdomain' ) ) ); ?>
970
- *
971
- * 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' ) ) ); ?>
972
- *
973
- * See https://www.paciellogroup.com/blog/2013/12/using-aria-enhance-svg-accessibility/.
974
- */
975
- if ( $args['title'] ) {
976
- $aria_hidden = '';
977
- $unique_id = uniqid();
978
- $aria_labelledby = ' aria-labelledby="title-' . $unique_id . '"';
979
-
980
- if ( $args['desc'] ) {
981
- $aria_labelledby = ' aria-labelledby="title-' . $unique_id . ' desc-' . $unique_id . '"';
982
- }
983
- }
984
-
985
- // Begin SVG markup.
986
- $svg = '<svg class="icon icon-' . esc_attr( $args['icon'] ) . '"' . $aria_hidden . $aria_labelledby . ' role="img">';
987
-
988
- // Display the title.
989
- if ( $args['title'] ) {
990
- $svg .= '<title id="title-' . $unique_id . '">' . esc_html( $args['title'] ) . '</title>';
991
-
992
- // Display the desc only if the title is already set.
993
- if ( $args['desc'] ) {
994
- $svg .= '<desc id="desc-' . $unique_id . '">' . esc_html( $args['desc'] ) . '</desc>';
995
- }
996
- }
997
-
998
- /*
999
- * Display the icon.
1000
- *
1001
- * The whitespace around `<use>` is intentional - it is a work around to a keyboard navigation bug in Safari 10.
1002
- *
1003
- * See https://core.trac.wordpress.org/ticket/38387.
1004
- */
1005
- $svg .= ' <use href="#icon-' . esc_html( $args['icon'] ) . '" xlink:href="#icon-' . esc_html( $args['icon'] ) . '"></use> ';
1006
-
1007
- // Add some markup to use as a fallback for browsers that do not support SVGs.
1008
- if ( $args['fallback'] ) {
1009
- $svg .= '<span class="svg-fallback icon-' . esc_attr( $args['icon'] ) . '"></span>';
1010
- }
1011
-
1012
- $svg .= '</svg>';
1013
-
1014
- return $svg;
1015
- }
1016
- 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;
essential-content-types.php CHANGED
@@ -16,7 +16,7 @@
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.3
20
  * Author: Catch Plugins
21
  * Author URI: https://catchplugins.com
22
  * License: GPL-3.0+
@@ -31,7 +31,7 @@ if ( ! defined( 'WPINC' ) ) {
31
  }
32
 
33
  // Define Version
34
- define( 'ESSENTIAL_CONTENT_TYPES_VERSION', '1.8.3' );
35
 
36
  /**
37
  * The code that runs during plugin activation.
@@ -198,3 +198,49 @@ if ( 1 == $ctp_options['theme_plugin_tabs'] ) {
198
  require plugin_dir_path( __FILE__ ) . '/includes/CatchThemesThemePlugin.php';
199
  }
200
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.4
20
  * Author: Catch Plugins
21
  * Author URI: https://catchplugins.com
22
  * License: GPL-3.0+
31
  }
32
 
33
  // Define Version
34
+ define( 'ESSENTIAL_CONTENT_TYPES_VERSION', '1.8.4' );
35
 
36
  /**
37
  * The code that runs during plugin activation.
198
  require plugin_dir_path( __FILE__ ) . '/includes/CatchThemesThemePlugin.php';
199
  }
200
  }
201
+
202
+ add_filter( 'get_the_archive_title', 'ect_modify_archive_title', 10, 1 );
203
+
204
+ function ect_modify_archive_title( $title ) {
205
+ $title_label = '<span class="some-class">%1$s</span>%2$s';
206
+ $type = ect_get_archive_post_type();
207
+
208
+ $archive_title = get_option( $type );
209
+
210
+ if ( '' !== $archive_title ) {
211
+ return trim(
212
+ sprintf(
213
+ $title_label,
214
+ esc_html_x( 'Archives: ', 'Archive title label.', 'archive-title' ),
215
+ $archive_title
216
+ )
217
+ );
218
+ } else {
219
+ return trim(
220
+ sprintf(
221
+ $title_label,
222
+ esc_html_x( 'Archives: ', 'Archive title label.', 'archive-title' ),
223
+ post_type_archive_title( '', false )
224
+ )
225
+ );
226
+ }
227
+
228
+ }
229
+
230
+ function ect_get_archive_post_type() {
231
+ $post_type = false;
232
+
233
+ global $wp_query;
234
+ if ( isset( $wp_query->query['post_type'] ) ) {
235
+ $post_type = $wp_query->query['post_type'];
236
+ }
237
+
238
+ $type = array(
239
+ 'featured-content' => 'featured_content_title',
240
+ 'jetpack-portfolio' => 'jetpack_portfolio_title',
241
+ 'jetpack-testimonial' => 'jetpack_testimonial_title',
242
+ 'ect-service' => 'ect_service_title',
243
+ );
244
+
245
+ return $type[ $post_type ];
246
+ }
languages/essential-content-types-fr_FR.mo CHANGED
Binary file
languages/essential-content-types-fr_FR.po CHANGED
@@ -4,8 +4,8 @@ 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: 2020-09-21 08:20-0400\n"
8
- "PO-Revision-Date: 2020-09-21 08:20-0400\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,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.1\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"
@@ -51,7 +51,7 @@ msgstr "Contenus en vedette"
51
 
52
  #: ../admin/class-featured-content.php:104
53
  #: ../admin/class-featured-content.php:105
54
- #: ../admin/class-featured-content.php:277
55
  #: ../admin/partials/dashboard-display.php:84
56
  #: ../admin/partials/essential-content-types-admin-display.php:113
57
  #: ../admin/partials/essential-content-types-admin-display.php:289
@@ -63,7 +63,7 @@ msgid "All Contents"
63
  msgstr "Tous les Contenus"
64
 
65
  #: ../admin/class-featured-content.php:107 ../admin/class-portfolio.php:234
66
- #: ../admin/class-service.php:107 ../admin/class-testimonial.php:267
67
  msgid "Add New"
68
  msgstr "Ajouter"
69
 
@@ -107,170 +107,170 @@ msgstr "Navigation dans la liste de contenu"
107
  msgid "Contents list"
108
  msgstr "Liste des contenus"
109
 
110
- #: ../admin/class-featured-content.php:148
111
- #: ../admin/class-featured-content.php:150
112
  msgid "Content Types"
113
  msgstr "Types de contenu"
114
 
115
- #: ../admin/class-featured-content.php:149
116
  msgid "Content Type"
117
  msgstr "Type de contenu"
118
 
119
- #: ../admin/class-featured-content.php:151
120
  msgid "All Content Types"
121
  msgstr "Tous les types de contenu"
122
 
123
- #: ../admin/class-featured-content.php:152
124
  msgid "Edit Content Type"
125
  msgstr "Modifier le type de contenu"
126
 
127
- #: ../admin/class-featured-content.php:153
128
  msgid "View Content Type"
129
  msgstr "Voir le type de contenu"
130
 
131
- #: ../admin/class-featured-content.php:154
132
  msgid "Update Content Type"
133
  msgstr "Mettre à jour le type de contenu"
134
 
135
- #: ../admin/class-featured-content.php:155
136
  msgid "Add New Content Type"
137
  msgstr "Ajouter un nouveau type de contenu"
138
 
139
- #: ../admin/class-featured-content.php:156
140
  msgid "New Content Type Name"
141
  msgstr "Nom du nouveau type de contenu"
142
 
143
- #: ../admin/class-featured-content.php:157
144
  msgid "Parent Content Type"
145
  msgstr "Type de contenu parent"
146
 
147
- #: ../admin/class-featured-content.php:158
148
  msgid "Parent Content Type:"
149
  msgstr "Type de contenu parent:"
150
 
151
- #: ../admin/class-featured-content.php:159
152
  msgid "Search Content Types"
153
  msgstr "Recherche de types de contenu"
154
 
155
- #: ../admin/class-featured-content.php:160
156
  msgid "Content type list navigation"
157
  msgstr "Navigation dans la liste des types de contenu"
158
 
159
- #: ../admin/class-featured-content.php:161
160
  msgid "Content type list"
161
  msgstr "Liste des types de contenu"
162
 
163
- #: ../admin/class-featured-content.php:175
164
- #: ../admin/class-featured-content.php:177
165
  msgid "Content Tags"
166
  msgstr "Balises de contenu"
167
 
168
- #: ../admin/class-featured-content.php:176
169
  msgid "Content Tag"
170
  msgstr "Balise de contenu"
171
 
172
- #: ../admin/class-featured-content.php:178
173
  msgid "All Content Tags"
174
  msgstr "Tous les tags de contenu"
175
 
176
- #: ../admin/class-featured-content.php:179
177
  msgid "Edit Content Tag"
178
  msgstr "Éditer la balise de contenu"
179
 
180
- #: ../admin/class-featured-content.php:180
181
  msgid "View Content Tag"
182
  msgstr "Voir la balise de contenu"
183
 
184
- #: ../admin/class-featured-content.php:181
185
  msgid "Update Content Tag"
186
  msgstr "Mettre à jour la balise de contenu"
187
 
188
- #: ../admin/class-featured-content.php:182
189
  msgid "Add New Content Tag"
190
  msgstr "Ajouter une nouvelle balise de contenu"
191
 
192
- #: ../admin/class-featured-content.php:183
193
  msgid "New Content Tag Name"
194
  msgstr "Nouveau nom de balise de contenu"
195
 
196
- #: ../admin/class-featured-content.php:184
197
  msgid "Search Content Tags"
198
  msgstr "Recherche de balises de contenu"
199
 
200
- #: ../admin/class-featured-content.php:185
201
  msgid "Popular Content Tags"
202
  msgstr "Balises de contenu populaires"
203
 
204
- #: ../admin/class-featured-content.php:186 ../admin/class-portfolio.php:314
205
- #: ../admin/class-service.php:186
206
  msgid "Separate tags with commas"
207
  msgstr "Séparez les étiquettes par des virgules"
208
 
209
- #: ../admin/class-featured-content.php:187 ../admin/class-portfolio.php:315
210
- #: ../admin/class-service.php:187
211
  msgid "Add or remove tags"
212
  msgstr "Ajouter ou retirer des balises"
213
 
214
- #: ../admin/class-featured-content.php:188 ../admin/class-portfolio.php:316
215
- #: ../admin/class-service.php:188
216
  msgid "Choose from the most used tags"
217
  msgstr "Choisir parmi les étiquettes les plus utilisées"
218
 
219
- #: ../admin/class-featured-content.php:189 ../admin/class-portfolio.php:317
220
- #: ../admin/class-service.php:189
221
  msgid "No tags found."
222
  msgstr "Aucune balise trouvée."
223
 
224
- #: ../admin/class-featured-content.php:190
225
  msgid "Content tag list navigation"
226
  msgstr "Navigation dans la liste des balises de contenu"
227
 
228
- #: ../admin/class-featured-content.php:191
229
  msgid "Content tag list"
230
  msgstr "Liste des balises de contenu"
231
 
232
- #: ../admin/class-featured-content.php:211
233
  #, php-format
234
  msgid "Content updated. <a href=\"%s\">View item</a>"
235
  msgstr "Contenu mis à jour. <a href=\"%s\">Voir l'article</a>"
236
 
237
- #: ../admin/class-featured-content.php:212 ../admin/class-food-menu.php:269
238
- #: ../admin/class-portfolio.php:340 ../admin/class-service.php:212
239
- #: ../admin/class-testimonial.php:314
240
  msgid "Custom field updated."
241
  msgstr "Champ personnalisé mis à jour."
242
 
243
- #: ../admin/class-featured-content.php:213 ../admin/class-food-menu.php:270
244
- #: ../admin/class-portfolio.php:341 ../admin/class-service.php:213
245
- #: ../admin/class-testimonial.php:315
246
  msgid "Custom field deleted."
247
  msgstr "Champ personnalisé supprimé."
248
 
249
- #: ../admin/class-featured-content.php:214
250
  msgid "Content updated."
251
  msgstr "Contenu mis à jour."
252
 
253
- #: ../admin/class-featured-content.php:216
254
  #, php-format
255
  msgid "Content restored to revision from %s"
256
  msgstr "Le contenu est ramené à la révision de %s"
257
 
258
- #: ../admin/class-featured-content.php:217
259
  #, php-format
260
  msgid "Content published. <a href=\"%s\">View content</a>"
261
  msgstr "Contenu publié. <a href=\"%s\">Voir le contenu</a>"
262
 
263
- #: ../admin/class-featured-content.php:218
264
  msgid "Content saved."
265
  msgstr "Contenu enregistré."
266
 
267
- #: ../admin/class-featured-content.php:219
268
  #, php-format
269
  msgid "Content submitted. <a target=\"_blank\" href=\"%s\">Preview content</a>"
270
  msgstr ""
271
  "Contenu soumis. <a target=\"_blank\" href=\"%s\">Prévisualiser le contenu</a>"
272
 
273
- #: ../admin/class-featured-content.php:220
274
  #, php-format
275
  msgid ""
276
  "Content scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
@@ -279,13 +279,13 @@ msgstr ""
279
  "Contenu prévu pour : <strong>%1$s</strong>. <a target=\"_blank\" href=\"%2$s"
280
  "\">Prévisualiser le contenu</a>"
281
 
282
- #: ../admin/class-featured-content.php:222 ../admin/class-food-menu.php:284
283
- #: ../admin/class-portfolio.php:350 ../admin/class-service.php:222
284
- #: ../admin/class-testimonial.php:324
285
  msgid "M j, Y @ G:i"
286
  msgstr "M j, Y @ G:i"
287
 
288
- #: ../admin/class-featured-content.php:223
289
  #, php-format
290
  msgid ""
291
  "Content item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
@@ -294,48 +294,48 @@ msgstr ""
294
  "Projet de contenu mis à jour. <a target=\"_blank\" href=\"%s\">Prévisualiser "
295
  "le contenu</a>"
296
 
297
- #: ../admin/class-featured-content.php:235
298
  msgid "Content"
299
  msgstr "Contenu"
300
 
301
- #: ../admin/class-featured-content.php:272 ../admin/class-portfolio.php:406
302
- #: ../admin/class-service.php:272 ../admin/class-testimonial.php:431
303
  msgid "Essential Content Types Plugin Options"
304
  msgstr "Options du plugin Types de contenu essentiels"
305
 
306
- #: ../admin/class-featured-content.php:282
307
  msgid "Contents"
308
  msgstr "Contenus"
309
 
310
- #: ../admin/class-featured-content.php:290
311
  msgid "Featured Content Archive Title"
312
  msgstr "Titre du contenu vedette de l'archive"
313
 
314
- #: ../admin/class-featured-content.php:303
315
  msgid "Featured Content Archive Content"
316
  msgstr "Contenu vedette des archives"
317
 
318
- #: ../admin/class-featured-content.php:317
319
  msgid "Featured Content Archive Featured Image"
320
  msgstr "Image en vedette du contenu vedette de l'archive"
321
 
322
- #: ../admin/class-featured-content.php:560 ../admin/class-portfolio.php:705
323
- #: ../admin/class-service.php:568
324
  msgid "Types"
325
  msgstr "Types"
326
 
327
- #: ../admin/class-featured-content.php:591 ../admin/class-portfolio.php:736
328
- #: ../admin/class-service.php:599
329
  msgid "Tags"
330
  msgstr "Tags"
331
 
332
- #: ../admin/class-featured-content.php:617 ../admin/class-portfolio.php:762
333
- #: ../admin/class-service.php:625
334
  #, php-format
335
  msgid "<span>Author:</span> <a href=\"%1$s\">%2$s</a>"
336
  msgstr "<span>Auteur:</span> <a href=\"%1$s\">%2$s</a>"
337
 
338
- #: ../admin/class-featured-content.php:670
339
  msgid ""
340
  "Your Featured Content Archive currently has no entries. You can start "
341
  "creating them on your dashboard."
@@ -714,15 +714,15 @@ msgstr "Les pages de portfolio s'affichent au plus sur %1$s projets"
714
  msgid "Portfolio Items"
715
  msgstr "Eléments du portfolio"
716
 
717
- #: ../admin/class-portfolio.php:230 ../admin/class-portfolio.php:419
718
  msgid "Projects"
719
  msgstr "Projets"
720
 
721
- #: ../admin/class-portfolio.php:231 ../admin/class-portfolio.php:363
722
  msgid "Project"
723
  msgstr "Projet"
724
 
725
- #: ../admin/class-portfolio.php:232 ../admin/class-portfolio.php:411
726
  #: ../admin/partials/essential-content-types-admin-display.php:103
727
  #: ../admin/partials/essential-content-types-admin-display.php:281
728
  msgid "Portfolio"
@@ -772,135 +772,135 @@ msgstr "Navigation de la liste des projets"
772
  msgid "Projects list"
773
  msgstr "Liste des projets"
774
 
775
- #: ../admin/class-portfolio.php:276 ../admin/class-portfolio.php:278
776
  msgid "Project Types"
777
  msgstr "Types de projets"
778
 
779
- #: ../admin/class-portfolio.php:277
780
  msgid "Project Type"
781
  msgstr "Type de projet"
782
 
783
- #: ../admin/class-portfolio.php:279
784
  msgid "All Project Types"
785
  msgstr "Tous les types de projets"
786
 
787
- #: ../admin/class-portfolio.php:280
788
  msgid "Edit Project Type"
789
  msgstr "Modifier le type de projet"
790
 
791
- #: ../admin/class-portfolio.php:281
792
  msgid "View Project Type"
793
  msgstr "Voir le type de projet"
794
 
795
- #: ../admin/class-portfolio.php:282
796
  msgid "Update Project Type"
797
  msgstr "Mettre à jour le type de projet"
798
 
799
- #: ../admin/class-portfolio.php:283
800
  msgid "Add New Project Type"
801
  msgstr "Ajouter un type nouveau projet"
802
 
803
- #: ../admin/class-portfolio.php:284
804
  msgid "New Project Type Name"
805
  msgstr "Nom du nouveau type de projet"
806
 
807
- #: ../admin/class-portfolio.php:285
808
  msgid "Parent Project Type"
809
  msgstr "Type de projet parent"
810
 
811
- #: ../admin/class-portfolio.php:286
812
  msgid "Parent Project Type:"
813
  msgstr "Type de projet parent :"
814
 
815
- #: ../admin/class-portfolio.php:287
816
  msgid "Search Project Types"
817
  msgstr "Rechercher les types de projet"
818
 
819
- #: ../admin/class-portfolio.php:288
820
  msgid "Project type list navigation"
821
  msgstr "Navigation de la liste de type de projet"
822
 
823
- #: ../admin/class-portfolio.php:289
824
  msgid "Project type list"
825
  msgstr "Liste type de projet"
826
 
827
- #: ../admin/class-portfolio.php:303 ../admin/class-portfolio.php:305
828
  msgid "Project Tags"
829
  msgstr "Étiquettes de projet"
830
 
831
- #: ../admin/class-portfolio.php:304
832
  msgid "Project Tag"
833
  msgstr "Étiquette de projet"
834
 
835
- #: ../admin/class-portfolio.php:306
836
  msgid "All Project Tags"
837
  msgstr "Toutes les étiquettes de projet"
838
 
839
- #: ../admin/class-portfolio.php:307
840
  msgid "Edit Project Tag"
841
  msgstr "Modifier la balise de projet"
842
 
843
- #: ../admin/class-portfolio.php:308
844
  msgid "View Project Tag"
845
  msgstr "Voir la balise du projet"
846
 
847
- #: ../admin/class-portfolio.php:309
848
  msgid "Update Project Tag"
849
  msgstr "Mettre à jour une balise de projet"
850
 
851
- #: ../admin/class-portfolio.php:310
852
  msgid "Add New Project Tag"
853
  msgstr "Ajouter une nouvelle balise de projet"
854
 
855
- #: ../admin/class-portfolio.php:311
856
  msgid "New Project Tag Name"
857
  msgstr "Nom de la balise de nouveau projet"
858
 
859
- #: ../admin/class-portfolio.php:312
860
  msgid "Search Project Tags"
861
  msgstr "Rechercher une étiquette de projet"
862
 
863
- #: ../admin/class-portfolio.php:313
864
  msgid "Popular Project Tags"
865
  msgstr "Etiquettes de projet populaires"
866
 
867
- #: ../admin/class-portfolio.php:318
868
  msgid "Project tag list navigation"
869
  msgstr "Navigation des étiquettes de la liste de projet"
870
 
871
- #: ../admin/class-portfolio.php:319
872
  msgid "Project tag list"
873
  msgstr "Liste d'étiquettes de projet"
874
 
875
- #: ../admin/class-portfolio.php:339
876
  #, php-format
877
  msgid "Project updated. <a href=\"%s\">View item</a>"
878
  msgstr "Projet mis à jour. <a href=“%s”>Voir l’élément</a>"
879
 
880
- #: ../admin/class-portfolio.php:342
881
  msgid "Project updated."
882
  msgstr "Projet mis à jour."
883
 
884
- #: ../admin/class-portfolio.php:344
885
  #, php-format
886
  msgid "Project restored to revision from %s"
887
  msgstr "Projet restauré à la révision du %s"
888
 
889
- #: ../admin/class-portfolio.php:345
890
  #, php-format
891
  msgid "Project published. <a href=\"%s\">View project</a>"
892
  msgstr "Projet publié. <a href=\"%s\">Voir le projet</a>"
893
 
894
- #: ../admin/class-portfolio.php:346
895
  msgid "Project saved."
896
  msgstr "Projet enregistré."
897
 
898
- #: ../admin/class-portfolio.php:347
899
  #, php-format
900
  msgid "Project submitted. <a target=\"_blank\" href=\"%s\">Preview project</a>"
901
  msgstr "Projet soumis. <a target=\"_blank\" href=\"%s\">Prévisualiser</a>"
902
 
903
- #: ../admin/class-portfolio.php:348
904
  #, php-format
905
  msgid ""
906
  "Project scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
@@ -909,7 +909,7 @@ msgstr ""
909
  "Projet programmé pour : <strong>%1$s</strong>. <a target=\"_blank\" href="
910
  "\"%2$s\">Prévisualiser le projet</a>"
911
 
912
- #: ../admin/class-portfolio.php:351
913
  #, php-format
914
  msgid ""
915
  "Project item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
@@ -918,19 +918,19 @@ msgstr ""
918
  "Brouillon d'article mis à jour. <a target=\"_blank\" href=\"%s\">Aperçu du "
919
  "projet</a>"
920
 
921
- #: ../admin/class-portfolio.php:427
922
  msgid "Portfolio Archive Title"
923
  msgstr "Titre de l'archive du portfolio"
924
 
925
- #: ../admin/class-portfolio.php:442
926
  msgid "Portfolio Archive Content"
927
  msgstr "Contenu d'archives du portfolio"
928
 
929
- #: ../admin/class-portfolio.php:458
930
  msgid "Portfolio Archive Featured Image"
931
  msgstr "Image à la une de l’archive du Portfolio"
932
 
933
- #: ../admin/class-portfolio.php:820
934
  msgid ""
935
  "Your Portfolio Archive currently has no entries. You can start creating them "
936
  "on your dashboard."
@@ -942,15 +942,15 @@ msgstr ""
942
  msgid "Service Items"
943
  msgstr "Eléments de service"
944
 
945
- #: ../admin/class-service.php:103 ../admin/class-service.php:277
946
- #: ../admin/class-service.php:283 ../admin/partials/dashboard-display.php:112
947
  #: ../admin/partials/essential-content-types-admin-display.php:118
948
  #: ../admin/partials/essential-content-types-admin-display.php:297
949
  msgid "Services"
950
  msgstr "Services"
951
 
952
  #: ../admin/class-service.php:104 ../admin/class-service.php:105
953
- #: ../admin/class-service.php:235
954
  msgid "Service"
955
  msgstr "Service"
956
 
@@ -994,137 +994,137 @@ msgstr "Navigation dans la liste des services"
994
  msgid "Services list"
995
  msgstr "Liste des services"
996
 
997
- #: ../admin/class-service.php:148 ../admin/class-service.php:150
998
  msgid "Service Types"
999
  msgstr "Types de service"
1000
 
1001
- #: ../admin/class-service.php:149
1002
  msgid "Service Type"
1003
  msgstr "Type de service"
1004
 
1005
- #: ../admin/class-service.php:151
1006
  msgid "All Service Types"
1007
  msgstr "Tous les types de services"
1008
 
1009
- #: ../admin/class-service.php:152
1010
  msgid "Edit Service Type"
1011
  msgstr "Modifier type de service"
1012
 
1013
- #: ../admin/class-service.php:153
1014
  msgid "View Service Type"
1015
  msgstr "Voir le type de service"
1016
 
1017
- #: ../admin/class-service.php:154
1018
  msgid "Update Service Type"
1019
  msgstr "Mise à jour du Type de service"
1020
 
1021
- #: ../admin/class-service.php:155
1022
  msgid "Add New Service Type"
1023
  msgstr "Ajouter un nouveau type de service"
1024
 
1025
- #: ../admin/class-service.php:156
1026
  msgid "New Service Type Name"
1027
  msgstr "Nouveau nom du type de service"
1028
 
1029
- #: ../admin/class-service.php:157
1030
  msgid "Parent Service Type"
1031
  msgstr "Type de service parent"
1032
 
1033
- #: ../admin/class-service.php:158
1034
  msgid "Parent Service Type:"
1035
  msgstr "Type de service parent :"
1036
 
1037
- #: ../admin/class-service.php:159
1038
  msgid "Search Service Types"
1039
  msgstr "Recherche de Types de services"
1040
 
1041
- #: ../admin/class-service.php:160
1042
  msgid "Service type list navigation"
1043
  msgstr "Navigation dans la liste des types de services"
1044
 
1045
- #: ../admin/class-service.php:161
1046
  msgid "Service type list"
1047
  msgstr "Liste des types de services"
1048
 
1049
- #: ../admin/class-service.php:175 ../admin/class-service.php:177
1050
  msgid "Service Tags"
1051
  msgstr "Balises de service"
1052
 
1053
- #: ../admin/class-service.php:176
1054
  msgid "Service Tag"
1055
  msgstr "Balise de service"
1056
 
1057
- #: ../admin/class-service.php:178
1058
  msgid "All Service Tags"
1059
  msgstr "Toutes les Balises de service"
1060
 
1061
- #: ../admin/class-service.php:179
1062
  msgid "Edit Service Tag"
1063
  msgstr "Editer la Balise de service"
1064
 
1065
- #: ../admin/class-service.php:180
1066
  msgid "View Service Tag"
1067
  msgstr "Voir la Balise de service"
1068
 
1069
- #: ../admin/class-service.php:181
1070
  msgid "Update Service Tag"
1071
  msgstr "Mettre à jour les mots clés de l'annonce"
1072
 
1073
- #: ../admin/class-service.php:182
1074
  msgid "Add New Service Tag"
1075
  msgstr "Ajouter un nouvelle Balise de service"
1076
 
1077
- #: ../admin/class-service.php:183
1078
  msgid "New Service Tag Name"
1079
  msgstr "Nouveau nom de balise de service"
1080
 
1081
- #: ../admin/class-service.php:184
1082
  msgid "Search Service Tags"
1083
  msgstr "Recherche de Balises de service"
1084
 
1085
- #: ../admin/class-service.php:185
1086
  msgid "Popular Service Tags"
1087
  msgstr "Balises de services populaires"
1088
 
1089
- #: ../admin/class-service.php:190
1090
  msgid "Service tag list navigation"
1091
  msgstr "Navigation dans la liste des balises de service"
1092
 
1093
- #: ../admin/class-service.php:191
1094
  msgid "Service tag list"
1095
  msgstr "Liste des balises de service"
1096
 
1097
- #: ../admin/class-service.php:211
1098
  #, php-format
1099
  msgid "Service updated. <a href=\"%s\">View item</a>"
1100
  msgstr "Service mis à jour. <a href=\"%s\">Voir l'article</a>"
1101
 
1102
- #: ../admin/class-service.php:214
1103
  msgid "Service updated."
1104
  msgstr "Service mis à jour."
1105
 
1106
- #: ../admin/class-service.php:216
1107
  #, php-format
1108
  msgid "Service restored to revision from %s"
1109
  msgstr "Service restauré à la révision de %s"
1110
 
1111
- #: ../admin/class-service.php:217
1112
  #, php-format
1113
  msgid "Service published. <a href=\"%s\">View content</a>"
1114
  msgstr "Service publié. <a href=\"%s\">Voir le contenu</a>"
1115
 
1116
- #: ../admin/class-service.php:218
1117
  msgid "Service saved."
1118
  msgstr "Service enregistré."
1119
 
1120
- #: ../admin/class-service.php:219
1121
  #, php-format
1122
  msgid "Service submitted. <a target=\"_blank\" href=\"%s\">Preview content</a>"
1123
  msgstr ""
1124
  "Service soumis. <a target=\"_blank\" href=\"%s\">Prévisualisation du "
1125
  "contenu</a>"
1126
 
1127
- #: ../admin/class-service.php:220
1128
  #, php-format
1129
  msgid ""
1130
  "Service scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
@@ -1133,7 +1133,7 @@ msgstr ""
1133
  "Prestation plannifiée pour : <strong>%1$s</strong>. <a target=\"_blank\" "
1134
  "href=\"%2$s\">Aperçu</a>"
1135
 
1136
- #: ../admin/class-service.php:223
1137
  #, php-format
1138
  msgid ""
1139
  "Service item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
@@ -1142,19 +1142,19 @@ msgstr ""
1142
  "Projet de service mis à jour. <a target=\"_blank\" href=\"%s"
1143
  "\">Prévisualisation du contenu</a>"
1144
 
1145
- #: ../admin/class-service.php:291
1146
  msgid "Service Archive Title"
1147
  msgstr "Titre des archives de service"
1148
 
1149
- #: ../admin/class-service.php:304
1150
  msgid "Service Archive Content"
1151
  msgstr "Contenu des archives du service"
1152
 
1153
- #: ../admin/class-service.php:318
1154
  msgid "Service Archive Featured Image"
1155
  msgstr "Image à la une de l’archive de service"
1156
 
1157
- #: ../admin/class-service.php:674
1158
  msgid ""
1159
  "Your Service Archive currently has no entries. You can start creating them "
1160
  "on your dashboard."
@@ -1162,9 +1162,9 @@ msgstr ""
1162
  "Les archives de service n'ont actuellement aucune entrée. Vous pouvez "
1163
  "commencer à les créer sur votre tableau de bord."
1164
 
1165
- #: ../admin/class-testimonial.php:118 ../admin/class-testimonial.php:263
1166
- #: ../admin/class-testimonial.php:265 ../admin/class-testimonial.php:436
1167
- #: ../admin/class-testimonial.php:443
1168
  #: ../admin/partials/dashboard-display.php:57
1169
  #: ../admin/partials/essential-content-types-admin-display.php:108
1170
  msgid "Testimonials"
@@ -1178,88 +1178,88 @@ msgstr "Votre thème prend en charge les témoignages"
1178
  msgid "Enable Testimonials for this site."
1179
  msgstr "Activer les témoignages pour ce site."
1180
 
1181
- #: ../admin/class-testimonial.php:161
1182
  #, php-format
1183
  msgid "Testimonial pages display at most %1$s testimonials"
1184
  msgstr "Les pages de témoignages affichent au maximum %1$s témoignages"
1185
 
1186
- #: ../admin/class-testimonial.php:261
1187
  msgid "Customer Testimonials"
1188
  msgstr "Témoignages clients"
1189
 
1190
- #: ../admin/class-testimonial.php:264
1191
  #: ../admin/partials/essential-content-types-admin-display.php:305
1192
  msgid "Testimonial"
1193
  msgstr "Témoignage"
1194
 
1195
- #: ../admin/class-testimonial.php:266
1196
  msgid "All Testimonials"
1197
  msgstr "Tous les témoignages"
1198
 
1199
- #: ../admin/class-testimonial.php:268
1200
  msgid "Add New Testimonial"
1201
  msgstr "Ajouter un nouveau témoignage"
1202
 
1203
- #: ../admin/class-testimonial.php:269
1204
  msgid "Edit Testimonial"
1205
  msgstr "Modifier le témoignage"
1206
 
1207
- #: ../admin/class-testimonial.php:270
1208
  msgid "New Testimonial"
1209
  msgstr "Nouveau témoignage"
1210
 
1211
- #: ../admin/class-testimonial.php:271
1212
  msgid "View Testimonial"
1213
  msgstr "Voir le témoignage"
1214
 
1215
- #: ../admin/class-testimonial.php:272
1216
  msgid "Search Testimonials"
1217
  msgstr "Rechercher des témoignages"
1218
 
1219
- #: ../admin/class-testimonial.php:273
1220
  msgid "No Testimonials found"
1221
  msgstr "Aucun témoignage trouvé"
1222
 
1223
- #: ../admin/class-testimonial.php:274
1224
  msgid "No Testimonials found in Trash"
1225
  msgstr "Aucun témoignage trouvé dans la Corbeille"
1226
 
1227
- #: ../admin/class-testimonial.php:275
1228
  msgid "Filter Testimonials list"
1229
  msgstr "Filtrer les témoignages"
1230
 
1231
- #: ../admin/class-testimonial.php:276
1232
  msgid "Testimonial list navigation"
1233
  msgstr "Navigation dans la liste des témoignages"
1234
 
1235
- #: ../admin/class-testimonial.php:277
1236
  msgid "Testimonials list"
1237
  msgstr "Liste des témoignages"
1238
 
1239
- #: ../admin/class-testimonial.php:313
1240
  #, php-format
1241
  msgid "Testimonial updated. <a href=\"%s\">View testimonial</a>"
1242
  msgstr "Témoignage mis à jour. <a href=\"%s\">Voir le témoignage</a>"
1243
 
1244
- #: ../admin/class-testimonial.php:316
1245
  msgid "Testimonial updated."
1246
  msgstr "Témoignage mis à jour."
1247
 
1248
- #: ../admin/class-testimonial.php:318
1249
  #, php-format
1250
  msgid "Testimonial restored to revision from %s"
1251
  msgstr "Témoignage rétabli à la révision de %s"
1252
 
1253
- #: ../admin/class-testimonial.php:319
1254
  #, php-format
1255
  msgid "Testimonial published. <a href=\"%s\">View testimonial</a>"
1256
  msgstr "Témoignage publié. <a href=\"%s\">Voir témoignage</a>"
1257
 
1258
- #: ../admin/class-testimonial.php:320
1259
  msgid "Testimonial saved."
1260
  msgstr "Témoignage enregistré."
1261
 
1262
- #: ../admin/class-testimonial.php:321
1263
  #, php-format
1264
  msgid ""
1265
  "Testimonial submitted. <a target=\"_blank\" href=\"%s\">Preview testimonial</"
@@ -1268,7 +1268,7 @@ msgstr ""
1268
  "Testimonial submitted. <a target=\"_blank\" href=\"%s\">Preview testimonial</"
1269
  "a>"
1270
 
1271
- #: ../admin/class-testimonial.php:322
1272
  #, php-format
1273
  msgid ""
1274
  "Testimonial scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
@@ -1277,7 +1277,7 @@ msgstr ""
1277
  "Témoignage prévu : <strong>%1$s</strong>. <a target=\"_blank\" href=\"%2$s"
1278
  "\">Aperçu du Témoignage</a>"
1279
 
1280
- #: ../admin/class-testimonial.php:325
1281
  #, php-format
1282
  msgid ""
1283
  "Testimonial draft updated. <a target=\"_blank\" href=\"%s\">Preview "
@@ -1286,43 +1286,43 @@ msgstr ""
1286
  "Projet de témoignage mis à jour. <a target=\"_blank\" href=\"%s\">Aperçu du "
1287
  "Témoignage</a>"
1288
 
1289
- #: ../admin/class-testimonial.php:338
1290
  msgid "Enter the customer's name here"
1291
  msgstr "Entrez le nom du client ici"
1292
 
1293
- #: ../admin/class-testimonial.php:347
1294
  msgid "Customer Name"
1295
  msgstr "Nom du client"
1296
 
1297
- #: ../admin/class-testimonial.php:414
1298
  msgid "Customize Testimonials Archive"
1299
  msgstr "Personnaliser les archives de témoignages"
1300
 
1301
- #: ../admin/class-testimonial.php:415
1302
  msgid "Customize"
1303
  msgstr "Personnaliser"
1304
 
1305
- #: ../admin/class-testimonial.php:449
1306
  msgid "Testimonial Archive Title"
1307
  msgstr "Témoignage Titre de l'archive"
1308
 
1309
- #: ../admin/class-testimonial.php:461
1310
  msgid "Testimonial Archive Content"
1311
  msgstr "Contenu des archives de témoignages"
1312
 
1313
- #: ../admin/class-testimonial.php:472
1314
  msgid "Testimonial Archive Featured Image"
1315
  msgstr "Image à la une de l’archive des témoignages"
1316
 
1317
- #: ../admin/class-testimonial.php:750
1318
  msgid "Position"
1319
  msgstr "Position"
1320
 
1321
- #: ../admin/class-testimonial.php:785
1322
  msgid "Testmonial Options"
1323
  msgstr "Options de témoignage"
1324
 
1325
- #: ../admin/class-testimonial.php:821
1326
  msgid ""
1327
  "Your Testimonial Archive currently has no entries. You can start creating "
1328
  "them on your dashboard."
@@ -1330,19 +1330,19 @@ msgstr ""
1330
  "Vos archives de témoignages n'ont actuellement aucune entrée. Vous pouvez "
1331
  "commencer à les créer sur votre tableau de bord."
1332
 
1333
- #: ../admin/class-testimonial.php:870
1334
  msgid "Previous Slide"
1335
  msgstr "Diapo précédente"
1336
 
1337
- #: ../admin/class-testimonial.php:877
1338
  msgid "Next Slide"
1339
  msgstr "Diapo suivante"
1340
 
1341
- #: ../admin/class-testimonial.php:939
1342
  msgid "Please define default parameters in the form of an array."
1343
  msgstr "Veuillez définir les paramètres par défaut sous la forme d'un tableau."
1344
 
1345
- #: ../admin/class-testimonial.php:944
1346
  msgid "Please define an SVG icon filename."
1347
  msgstr "Veuillez définir un nom pour l’icône SVG."
1348
 
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: 2020-12-07 00:51-0500\n"
8
+ "PO-Revision-Date: 2020-12-07 00:51-0500\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.2\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"
51
 
52
  #: ../admin/class-featured-content.php:104
53
  #: ../admin/class-featured-content.php:105
54
+ #: ../admin/class-featured-content.php:303
55
  #: ../admin/partials/dashboard-display.php:84
56
  #: ../admin/partials/essential-content-types-admin-display.php:113
57
  #: ../admin/partials/essential-content-types-admin-display.php:289
63
  msgstr "Tous les Contenus"
64
 
65
  #: ../admin/class-featured-content.php:107 ../admin/class-portfolio.php:234
66
+ #: ../admin/class-service.php:107 ../admin/class-testimonial.php:273
67
  msgid "Add New"
68
  msgstr "Ajouter"
69
 
107
  msgid "Contents list"
108
  msgstr "Liste des contenus"
109
 
110
+ #: ../admin/class-featured-content.php:161
111
+ #: ../admin/class-featured-content.php:163
112
  msgid "Content Types"
113
  msgstr "Types de contenu"
114
 
115
+ #: ../admin/class-featured-content.php:162
116
  msgid "Content Type"
117
  msgstr "Type de contenu"
118
 
119
+ #: ../admin/class-featured-content.php:164
120
  msgid "All Content Types"
121
  msgstr "Tous les types de contenu"
122
 
123
+ #: ../admin/class-featured-content.php:165
124
  msgid "Edit Content Type"
125
  msgstr "Modifier le type de contenu"
126
 
127
+ #: ../admin/class-featured-content.php:166
128
  msgid "View Content Type"
129
  msgstr "Voir le type de contenu"
130
 
131
+ #: ../admin/class-featured-content.php:167
132
  msgid "Update Content Type"
133
  msgstr "Mettre à jour le type de contenu"
134
 
135
+ #: ../admin/class-featured-content.php:168
136
  msgid "Add New Content Type"
137
  msgstr "Ajouter un nouveau type de contenu"
138
 
139
+ #: ../admin/class-featured-content.php:169
140
  msgid "New Content Type Name"
141
  msgstr "Nom du nouveau type de contenu"
142
 
143
+ #: ../admin/class-featured-content.php:170
144
  msgid "Parent Content Type"
145
  msgstr "Type de contenu parent"
146
 
147
+ #: ../admin/class-featured-content.php:171
148
  msgid "Parent Content Type:"
149
  msgstr "Type de contenu parent:"
150
 
151
+ #: ../admin/class-featured-content.php:172
152
  msgid "Search Content Types"
153
  msgstr "Recherche de types de contenu"
154
 
155
+ #: ../admin/class-featured-content.php:173
156
  msgid "Content type list navigation"
157
  msgstr "Navigation dans la liste des types de contenu"
158
 
159
+ #: ../admin/class-featured-content.php:174
160
  msgid "Content type list"
161
  msgstr "Liste des types de contenu"
162
 
163
+ #: ../admin/class-featured-content.php:192
164
+ #: ../admin/class-featured-content.php:194
165
  msgid "Content Tags"
166
  msgstr "Balises de contenu"
167
 
168
+ #: ../admin/class-featured-content.php:193
169
  msgid "Content Tag"
170
  msgstr "Balise de contenu"
171
 
172
+ #: ../admin/class-featured-content.php:195
173
  msgid "All Content Tags"
174
  msgstr "Tous les tags de contenu"
175
 
176
+ #: ../admin/class-featured-content.php:196
177
  msgid "Edit Content Tag"
178
  msgstr "Éditer la balise de contenu"
179
 
180
+ #: ../admin/class-featured-content.php:197
181
  msgid "View Content Tag"
182
  msgstr "Voir la balise de contenu"
183
 
184
+ #: ../admin/class-featured-content.php:198
185
  msgid "Update Content Tag"
186
  msgstr "Mettre à jour la balise de contenu"
187
 
188
+ #: ../admin/class-featured-content.php:199
189
  msgid "Add New Content Tag"
190
  msgstr "Ajouter une nouvelle balise de contenu"
191
 
192
+ #: ../admin/class-featured-content.php:200
193
  msgid "New Content Tag Name"
194
  msgstr "Nouveau nom de balise de contenu"
195
 
196
+ #: ../admin/class-featured-content.php:201
197
  msgid "Search Content Tags"
198
  msgstr "Recherche de balises de contenu"
199
 
200
+ #: ../admin/class-featured-content.php:202
201
  msgid "Popular Content Tags"
202
  msgstr "Balises de contenu populaires"
203
 
204
+ #: ../admin/class-featured-content.php:203 ../admin/class-portfolio.php:321
205
+ #: ../admin/class-service.php:193
206
  msgid "Separate tags with commas"
207
  msgstr "Séparez les étiquettes par des virgules"
208
 
209
+ #: ../admin/class-featured-content.php:204 ../admin/class-portfolio.php:322
210
+ #: ../admin/class-service.php:194
211
  msgid "Add or remove tags"
212
  msgstr "Ajouter ou retirer des balises"
213
 
214
+ #: ../admin/class-featured-content.php:205 ../admin/class-portfolio.php:323
215
+ #: ../admin/class-service.php:195
216
  msgid "Choose from the most used tags"
217
  msgstr "Choisir parmi les étiquettes les plus utilisées"
218
 
219
+ #: ../admin/class-featured-content.php:206 ../admin/class-portfolio.php:324
220
+ #: ../admin/class-service.php:196
221
  msgid "No tags found."
222
  msgstr "Aucune balise trouvée."
223
 
224
+ #: ../admin/class-featured-content.php:207
225
  msgid "Content tag list navigation"
226
  msgstr "Navigation dans la liste des balises de contenu"
227
 
228
+ #: ../admin/class-featured-content.php:208
229
  msgid "Content tag list"
230
  msgstr "Liste des balises de contenu"
231
 
232
+ #: ../admin/class-featured-content.php:229
233
  #, php-format
234
  msgid "Content updated. <a href=\"%s\">View item</a>"
235
  msgstr "Contenu mis à jour. <a href=\"%s\">Voir l'article</a>"
236
 
237
+ #: ../admin/class-featured-content.php:230 ../admin/class-food-menu.php:269
238
+ #: ../admin/class-portfolio.php:347 ../admin/class-service.php:219
239
+ #: ../admin/class-testimonial.php:327
240
  msgid "Custom field updated."
241
  msgstr "Champ personnalisé mis à jour."
242
 
243
+ #: ../admin/class-featured-content.php:231 ../admin/class-food-menu.php:270
244
+ #: ../admin/class-portfolio.php:348 ../admin/class-service.php:220
245
+ #: ../admin/class-testimonial.php:328
246
  msgid "Custom field deleted."
247
  msgstr "Champ personnalisé supprimé."
248
 
249
+ #: ../admin/class-featured-content.php:232
250
  msgid "Content updated."
251
  msgstr "Contenu mis à jour."
252
 
253
+ #: ../admin/class-featured-content.php:234
254
  #, php-format
255
  msgid "Content restored to revision from %s"
256
  msgstr "Le contenu est ramené à la révision de %s"
257
 
258
+ #: ../admin/class-featured-content.php:235
259
  #, php-format
260
  msgid "Content published. <a href=\"%s\">View content</a>"
261
  msgstr "Contenu publié. <a href=\"%s\">Voir le contenu</a>"
262
 
263
+ #: ../admin/class-featured-content.php:236
264
  msgid "Content saved."
265
  msgstr "Contenu enregistré."
266
 
267
+ #: ../admin/class-featured-content.php:237
268
  #, php-format
269
  msgid "Content submitted. <a target=\"_blank\" href=\"%s\">Preview content</a>"
270
  msgstr ""
271
  "Contenu soumis. <a target=\"_blank\" href=\"%s\">Prévisualiser le contenu</a>"
272
 
273
+ #: ../admin/class-featured-content.php:239
274
  #, php-format
275
  msgid ""
276
  "Content scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
279
  "Contenu prévu pour : <strong>%1$s</strong>. <a target=\"_blank\" href=\"%2$s"
280
  "\">Prévisualiser le contenu</a>"
281
 
282
+ #: ../admin/class-featured-content.php:241 ../admin/class-food-menu.php:284
283
+ #: ../admin/class-portfolio.php:357 ../admin/class-service.php:229
284
+ #: ../admin/class-testimonial.php:338
285
  msgid "M j, Y @ G:i"
286
  msgstr "M j, Y @ G:i"
287
 
288
+ #: ../admin/class-featured-content.php:244
289
  #, php-format
290
  msgid ""
291
  "Content item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
294
  "Projet de contenu mis à jour. <a target=\"_blank\" href=\"%s\">Prévisualiser "
295
  "le contenu</a>"
296
 
297
+ #: ../admin/class-featured-content.php:256
298
  msgid "Content"
299
  msgstr "Contenu"
300
 
301
+ #: ../admin/class-featured-content.php:295 ../admin/class-portfolio.php:413
302
+ #: ../admin/class-service.php:279 ../admin/class-testimonial.php:453
303
  msgid "Essential Content Types Plugin Options"
304
  msgstr "Options du plugin Types de contenu essentiels"
305
 
306
+ #: ../admin/class-featured-content.php:311
307
  msgid "Contents"
308
  msgstr "Contenus"
309
 
310
+ #: ../admin/class-featured-content.php:322
311
  msgid "Featured Content Archive Title"
312
  msgstr "Titre du contenu vedette de l'archive"
313
 
314
+ #: ../admin/class-featured-content.php:341
315
  msgid "Featured Content Archive Content"
316
  msgstr "Contenu vedette des archives"
317
 
318
+ #: ../admin/class-featured-content.php:363
319
  msgid "Featured Content Archive Featured Image"
320
  msgstr "Image en vedette du contenu vedette de l'archive"
321
 
322
+ #: ../admin/class-featured-content.php:618 ../admin/class-portfolio.php:712
323
+ #: ../admin/class-service.php:575
324
  msgid "Types"
325
  msgstr "Types"
326
 
327
+ #: ../admin/class-featured-content.php:649 ../admin/class-portfolio.php:743
328
+ #: ../admin/class-service.php:606
329
  msgid "Tags"
330
  msgstr "Tags"
331
 
332
+ #: ../admin/class-featured-content.php:676 ../admin/class-portfolio.php:769
333
+ #: ../admin/class-service.php:632
334
  #, php-format
335
  msgid "<span>Author:</span> <a href=\"%1$s\">%2$s</a>"
336
  msgstr "<span>Auteur:</span> <a href=\"%1$s\">%2$s</a>"
337
 
338
+ #: ../admin/class-featured-content.php:729
339
  msgid ""
340
  "Your Featured Content Archive currently has no entries. You can start "
341
  "creating them on your dashboard."
714
  msgid "Portfolio Items"
715
  msgstr "Eléments du portfolio"
716
 
717
+ #: ../admin/class-portfolio.php:230 ../admin/class-portfolio.php:426
718
  msgid "Projects"
719
  msgstr "Projets"
720
 
721
+ #: ../admin/class-portfolio.php:231 ../admin/class-portfolio.php:370
722
  msgid "Project"
723
  msgstr "Projet"
724
 
725
+ #: ../admin/class-portfolio.php:232 ../admin/class-portfolio.php:418
726
  #: ../admin/partials/essential-content-types-admin-display.php:103
727
  #: ../admin/partials/essential-content-types-admin-display.php:281
728
  msgid "Portfolio"
772
  msgid "Projects list"
773
  msgstr "Liste des projets"
774
 
775
+ #: ../admin/class-portfolio.php:283 ../admin/class-portfolio.php:285
776
  msgid "Project Types"
777
  msgstr "Types de projets"
778
 
779
+ #: ../admin/class-portfolio.php:284
780
  msgid "Project Type"
781
  msgstr "Type de projet"
782
 
783
+ #: ../admin/class-portfolio.php:286
784
  msgid "All Project Types"
785
  msgstr "Tous les types de projets"
786
 
787
+ #: ../admin/class-portfolio.php:287
788
  msgid "Edit Project Type"
789
  msgstr "Modifier le type de projet"
790
 
791
+ #: ../admin/class-portfolio.php:288
792
  msgid "View Project Type"
793
  msgstr "Voir le type de projet"
794
 
795
+ #: ../admin/class-portfolio.php:289
796
  msgid "Update Project Type"
797
  msgstr "Mettre à jour le type de projet"
798
 
799
+ #: ../admin/class-portfolio.php:290
800
  msgid "Add New Project Type"
801
  msgstr "Ajouter un type nouveau projet"
802
 
803
+ #: ../admin/class-portfolio.php:291
804
  msgid "New Project Type Name"
805
  msgstr "Nom du nouveau type de projet"
806
 
807
+ #: ../admin/class-portfolio.php:292
808
  msgid "Parent Project Type"
809
  msgstr "Type de projet parent"
810
 
811
+ #: ../admin/class-portfolio.php:293
812
  msgid "Parent Project Type:"
813
  msgstr "Type de projet parent :"
814
 
815
+ #: ../admin/class-portfolio.php:294
816
  msgid "Search Project Types"
817
  msgstr "Rechercher les types de projet"
818
 
819
+ #: ../admin/class-portfolio.php:295
820
  msgid "Project type list navigation"
821
  msgstr "Navigation de la liste de type de projet"
822
 
823
+ #: ../admin/class-portfolio.php:296
824
  msgid "Project type list"
825
  msgstr "Liste type de projet"
826
 
827
+ #: ../admin/class-portfolio.php:310 ../admin/class-portfolio.php:312
828
  msgid "Project Tags"
829
  msgstr "Étiquettes de projet"
830
 
831
+ #: ../admin/class-portfolio.php:311
832
  msgid "Project Tag"
833
  msgstr "Étiquette de projet"
834
 
835
+ #: ../admin/class-portfolio.php:313
836
  msgid "All Project Tags"
837
  msgstr "Toutes les étiquettes de projet"
838
 
839
+ #: ../admin/class-portfolio.php:314
840
  msgid "Edit Project Tag"
841
  msgstr "Modifier la balise de projet"
842
 
843
+ #: ../admin/class-portfolio.php:315
844
  msgid "View Project Tag"
845
  msgstr "Voir la balise du projet"
846
 
847
+ #: ../admin/class-portfolio.php:316
848
  msgid "Update Project Tag"
849
  msgstr "Mettre à jour une balise de projet"
850
 
851
+ #: ../admin/class-portfolio.php:317
852
  msgid "Add New Project Tag"
853
  msgstr "Ajouter une nouvelle balise de projet"
854
 
855
+ #: ../admin/class-portfolio.php:318
856
  msgid "New Project Tag Name"
857
  msgstr "Nom de la balise de nouveau projet"
858
 
859
+ #: ../admin/class-portfolio.php:319
860
  msgid "Search Project Tags"
861
  msgstr "Rechercher une étiquette de projet"
862
 
863
+ #: ../admin/class-portfolio.php:320
864
  msgid "Popular Project Tags"
865
  msgstr "Etiquettes de projet populaires"
866
 
867
+ #: ../admin/class-portfolio.php:325
868
  msgid "Project tag list navigation"
869
  msgstr "Navigation des étiquettes de la liste de projet"
870
 
871
+ #: ../admin/class-portfolio.php:326
872
  msgid "Project tag list"
873
  msgstr "Liste d'étiquettes de projet"
874
 
875
+ #: ../admin/class-portfolio.php:346
876
  #, php-format
877
  msgid "Project updated. <a href=\"%s\">View item</a>"
878
  msgstr "Projet mis à jour. <a href=“%s”>Voir l’élément</a>"
879
 
880
+ #: ../admin/class-portfolio.php:349
881
  msgid "Project updated."
882
  msgstr "Projet mis à jour."
883
 
884
+ #: ../admin/class-portfolio.php:351
885
  #, php-format
886
  msgid "Project restored to revision from %s"
887
  msgstr "Projet restauré à la révision du %s"
888
 
889
+ #: ../admin/class-portfolio.php:352
890
  #, php-format
891
  msgid "Project published. <a href=\"%s\">View project</a>"
892
  msgstr "Projet publié. <a href=\"%s\">Voir le projet</a>"
893
 
894
+ #: ../admin/class-portfolio.php:353
895
  msgid "Project saved."
896
  msgstr "Projet enregistré."
897
 
898
+ #: ../admin/class-portfolio.php:354
899
  #, php-format
900
  msgid "Project submitted. <a target=\"_blank\" href=\"%s\">Preview project</a>"
901
  msgstr "Projet soumis. <a target=\"_blank\" href=\"%s\">Prévisualiser</a>"
902
 
903
+ #: ../admin/class-portfolio.php:355
904
  #, php-format
905
  msgid ""
906
  "Project scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
909
  "Projet programmé pour : <strong>%1$s</strong>. <a target=\"_blank\" href="
910
  "\"%2$s\">Prévisualiser le projet</a>"
911
 
912
+ #: ../admin/class-portfolio.php:358
913
  #, php-format
914
  msgid ""
915
  "Project item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
918
  "Brouillon d'article mis à jour. <a target=\"_blank\" href=\"%s\">Aperçu du "
919
  "projet</a>"
920
 
921
+ #: ../admin/class-portfolio.php:434
922
  msgid "Portfolio Archive Title"
923
  msgstr "Titre de l'archive du portfolio"
924
 
925
+ #: ../admin/class-portfolio.php:449
926
  msgid "Portfolio Archive Content"
927
  msgstr "Contenu d'archives du portfolio"
928
 
929
+ #: ../admin/class-portfolio.php:465
930
  msgid "Portfolio Archive Featured Image"
931
  msgstr "Image à la une de l’archive du Portfolio"
932
 
933
+ #: ../admin/class-portfolio.php:827
934
  msgid ""
935
  "Your Portfolio Archive currently has no entries. You can start creating them "
936
  "on your dashboard."
942
  msgid "Service Items"
943
  msgstr "Eléments de service"
944
 
945
+ #: ../admin/class-service.php:103 ../admin/class-service.php:284
946
+ #: ../admin/class-service.php:290 ../admin/partials/dashboard-display.php:112
947
  #: ../admin/partials/essential-content-types-admin-display.php:118
948
  #: ../admin/partials/essential-content-types-admin-display.php:297
949
  msgid "Services"
950
  msgstr "Services"
951
 
952
  #: ../admin/class-service.php:104 ../admin/class-service.php:105
953
+ #: ../admin/class-service.php:242
954
  msgid "Service"
955
  msgstr "Service"
956
 
994
  msgid "Services list"
995
  msgstr "Liste des services"
996
 
997
+ #: ../admin/class-service.php:155 ../admin/class-service.php:157
998
  msgid "Service Types"
999
  msgstr "Types de service"
1000
 
1001
+ #: ../admin/class-service.php:156
1002
  msgid "Service Type"
1003
  msgstr "Type de service"
1004
 
1005
+ #: ../admin/class-service.php:158
1006
  msgid "All Service Types"
1007
  msgstr "Tous les types de services"
1008
 
1009
+ #: ../admin/class-service.php:159
1010
  msgid "Edit Service Type"
1011
  msgstr "Modifier type de service"
1012
 
1013
+ #: ../admin/class-service.php:160
1014
  msgid "View Service Type"
1015
  msgstr "Voir le type de service"
1016
 
1017
+ #: ../admin/class-service.php:161
1018
  msgid "Update Service Type"
1019
  msgstr "Mise à jour du Type de service"
1020
 
1021
+ #: ../admin/class-service.php:162
1022
  msgid "Add New Service Type"
1023
  msgstr "Ajouter un nouveau type de service"
1024
 
1025
+ #: ../admin/class-service.php:163
1026
  msgid "New Service Type Name"
1027
  msgstr "Nouveau nom du type de service"
1028
 
1029
+ #: ../admin/class-service.php:164
1030
  msgid "Parent Service Type"
1031
  msgstr "Type de service parent"
1032
 
1033
+ #: ../admin/class-service.php:165
1034
  msgid "Parent Service Type:"
1035
  msgstr "Type de service parent :"
1036
 
1037
+ #: ../admin/class-service.php:166
1038
  msgid "Search Service Types"
1039
  msgstr "Recherche de Types de services"
1040
 
1041
+ #: ../admin/class-service.php:167
1042
  msgid "Service type list navigation"
1043
  msgstr "Navigation dans la liste des types de services"
1044
 
1045
+ #: ../admin/class-service.php:168
1046
  msgid "Service type list"
1047
  msgstr "Liste des types de services"
1048
 
1049
+ #: ../admin/class-service.php:182 ../admin/class-service.php:184
1050
  msgid "Service Tags"
1051
  msgstr "Balises de service"
1052
 
1053
+ #: ../admin/class-service.php:183
1054
  msgid "Service Tag"
1055
  msgstr "Balise de service"
1056
 
1057
+ #: ../admin/class-service.php:185
1058
  msgid "All Service Tags"
1059
  msgstr "Toutes les Balises de service"
1060
 
1061
+ #: ../admin/class-service.php:186
1062
  msgid "Edit Service Tag"
1063
  msgstr "Editer la Balise de service"
1064
 
1065
+ #: ../admin/class-service.php:187
1066
  msgid "View Service Tag"
1067
  msgstr "Voir la Balise de service"
1068
 
1069
+ #: ../admin/class-service.php:188
1070
  msgid "Update Service Tag"
1071
  msgstr "Mettre à jour les mots clés de l'annonce"
1072
 
1073
+ #: ../admin/class-service.php:189
1074
  msgid "Add New Service Tag"
1075
  msgstr "Ajouter un nouvelle Balise de service"
1076
 
1077
+ #: ../admin/class-service.php:190
1078
  msgid "New Service Tag Name"
1079
  msgstr "Nouveau nom de balise de service"
1080
 
1081
+ #: ../admin/class-service.php:191
1082
  msgid "Search Service Tags"
1083
  msgstr "Recherche de Balises de service"
1084
 
1085
+ #: ../admin/class-service.php:192
1086
  msgid "Popular Service Tags"
1087
  msgstr "Balises de services populaires"
1088
 
1089
+ #: ../admin/class-service.php:197
1090
  msgid "Service tag list navigation"
1091
  msgstr "Navigation dans la liste des balises de service"
1092
 
1093
+ #: ../admin/class-service.php:198
1094
  msgid "Service tag list"
1095
  msgstr "Liste des balises de service"
1096
 
1097
+ #: ../admin/class-service.php:218
1098
  #, php-format
1099
  msgid "Service updated. <a href=\"%s\">View item</a>"
1100
  msgstr "Service mis à jour. <a href=\"%s\">Voir l'article</a>"
1101
 
1102
+ #: ../admin/class-service.php:221
1103
  msgid "Service updated."
1104
  msgstr "Service mis à jour."
1105
 
1106
+ #: ../admin/class-service.php:223
1107
  #, php-format
1108
  msgid "Service restored to revision from %s"
1109
  msgstr "Service restauré à la révision de %s"
1110
 
1111
+ #: ../admin/class-service.php:224
1112
  #, php-format
1113
  msgid "Service published. <a href=\"%s\">View content</a>"
1114
  msgstr "Service publié. <a href=\"%s\">Voir le contenu</a>"
1115
 
1116
+ #: ../admin/class-service.php:225
1117
  msgid "Service saved."
1118
  msgstr "Service enregistré."
1119
 
1120
+ #: ../admin/class-service.php:226
1121
  #, php-format
1122
  msgid "Service submitted. <a target=\"_blank\" href=\"%s\">Preview content</a>"
1123
  msgstr ""
1124
  "Service soumis. <a target=\"_blank\" href=\"%s\">Prévisualisation du "
1125
  "contenu</a>"
1126
 
1127
+ #: ../admin/class-service.php:227
1128
  #, php-format
1129
  msgid ""
1130
  "Service scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
1133
  "Prestation plannifiée pour : <strong>%1$s</strong>. <a target=\"_blank\" "
1134
  "href=\"%2$s\">Aperçu</a>"
1135
 
1136
+ #: ../admin/class-service.php:230
1137
  #, php-format
1138
  msgid ""
1139
  "Service item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
1142
  "Projet de service mis à jour. <a target=\"_blank\" href=\"%s"
1143
  "\">Prévisualisation du contenu</a>"
1144
 
1145
+ #: ../admin/class-service.php:298
1146
  msgid "Service Archive Title"
1147
  msgstr "Titre des archives de service"
1148
 
1149
+ #: ../admin/class-service.php:311
1150
  msgid "Service Archive Content"
1151
  msgstr "Contenu des archives du service"
1152
 
1153
+ #: ../admin/class-service.php:325
1154
  msgid "Service Archive Featured Image"
1155
  msgstr "Image à la une de l’archive de service"
1156
 
1157
+ #: ../admin/class-service.php:681
1158
  msgid ""
1159
  "Your Service Archive currently has no entries. You can start creating them "
1160
  "on your dashboard."
1162
  "Les archives de service n'ont actuellement aucune entrée. Vous pouvez "
1163
  "commencer à les créer sur votre tableau de bord."
1164
 
1165
+ #: ../admin/class-testimonial.php:118 ../admin/class-testimonial.php:269
1166
+ #: ../admin/class-testimonial.php:271 ../admin/class-testimonial.php:461
1167
+ #: ../admin/class-testimonial.php:471
1168
  #: ../admin/partials/dashboard-display.php:57
1169
  #: ../admin/partials/essential-content-types-admin-display.php:108
1170
  msgid "Testimonials"
1178
  msgid "Enable Testimonials for this site."
1179
  msgstr "Activer les témoignages pour ce site."
1180
 
1181
+ #: ../admin/class-testimonial.php:164
1182
  #, php-format
1183
  msgid "Testimonial pages display at most %1$s testimonials"
1184
  msgstr "Les pages de témoignages affichent au maximum %1$s témoignages"
1185
 
1186
+ #: ../admin/class-testimonial.php:267
1187
  msgid "Customer Testimonials"
1188
  msgstr "Témoignages clients"
1189
 
1190
+ #: ../admin/class-testimonial.php:270
1191
  #: ../admin/partials/essential-content-types-admin-display.php:305
1192
  msgid "Testimonial"
1193
  msgstr "Témoignage"
1194
 
1195
+ #: ../admin/class-testimonial.php:272
1196
  msgid "All Testimonials"
1197
  msgstr "Tous les témoignages"
1198
 
1199
+ #: ../admin/class-testimonial.php:274
1200
  msgid "Add New Testimonial"
1201
  msgstr "Ajouter un nouveau témoignage"
1202
 
1203
+ #: ../admin/class-testimonial.php:275
1204
  msgid "Edit Testimonial"
1205
  msgstr "Modifier le témoignage"
1206
 
1207
+ #: ../admin/class-testimonial.php:276
1208
  msgid "New Testimonial"
1209
  msgstr "Nouveau témoignage"
1210
 
1211
+ #: ../admin/class-testimonial.php:277
1212
  msgid "View Testimonial"
1213
  msgstr "Voir le témoignage"
1214
 
1215
+ #: ../admin/class-testimonial.php:278
1216
  msgid "Search Testimonials"
1217
  msgstr "Rechercher des témoignages"
1218
 
1219
+ #: ../admin/class-testimonial.php:279
1220
  msgid "No Testimonials found"
1221
  msgstr "Aucun témoignage trouvé"
1222
 
1223
+ #: ../admin/class-testimonial.php:280
1224
  msgid "No Testimonials found in Trash"
1225
  msgstr "Aucun témoignage trouvé dans la Corbeille"
1226
 
1227
+ #: ../admin/class-testimonial.php:281
1228
  msgid "Filter Testimonials list"
1229
  msgstr "Filtrer les témoignages"
1230
 
1231
+ #: ../admin/class-testimonial.php:282
1232
  msgid "Testimonial list navigation"
1233
  msgstr "Navigation dans la liste des témoignages"
1234
 
1235
+ #: ../admin/class-testimonial.php:283
1236
  msgid "Testimonials list"
1237
  msgstr "Liste des témoignages"
1238
 
1239
+ #: ../admin/class-testimonial.php:326
1240
  #, php-format
1241
  msgid "Testimonial updated. <a href=\"%s\">View testimonial</a>"
1242
  msgstr "Témoignage mis à jour. <a href=\"%s\">Voir le témoignage</a>"
1243
 
1244
+ #: ../admin/class-testimonial.php:329
1245
  msgid "Testimonial updated."
1246
  msgstr "Témoignage mis à jour."
1247
 
1248
+ #: ../admin/class-testimonial.php:331
1249
  #, php-format
1250
  msgid "Testimonial restored to revision from %s"
1251
  msgstr "Témoignage rétabli à la révision de %s"
1252
 
1253
+ #: ../admin/class-testimonial.php:332
1254
  #, php-format
1255
  msgid "Testimonial published. <a href=\"%s\">View testimonial</a>"
1256
  msgstr "Témoignage publié. <a href=\"%s\">Voir témoignage</a>"
1257
 
1258
+ #: ../admin/class-testimonial.php:333
1259
  msgid "Testimonial saved."
1260
  msgstr "Témoignage enregistré."
1261
 
1262
+ #: ../admin/class-testimonial.php:334
1263
  #, php-format
1264
  msgid ""
1265
  "Testimonial submitted. <a target=\"_blank\" href=\"%s\">Preview testimonial</"
1268
  "Testimonial submitted. <a target=\"_blank\" href=\"%s\">Preview testimonial</"
1269
  "a>"
1270
 
1271
+ #: ../admin/class-testimonial.php:336
1272
  #, php-format
1273
  msgid ""
1274
  "Testimonial scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
1277
  "Témoignage prévu : <strong>%1$s</strong>. <a target=\"_blank\" href=\"%2$s"
1278
  "\">Aperçu du Témoignage</a>"
1279
 
1280
+ #: ../admin/class-testimonial.php:341
1281
  #, php-format
1282
  msgid ""
1283
  "Testimonial draft updated. <a target=\"_blank\" href=\"%s\">Preview "
1286
  "Projet de témoignage mis à jour. <a target=\"_blank\" href=\"%s\">Aperçu du "
1287
  "Témoignage</a>"
1288
 
1289
+ #: ../admin/class-testimonial.php:354
1290
  msgid "Enter the customer's name here"
1291
  msgstr "Entrez le nom du client ici"
1292
 
1293
+ #: ../admin/class-testimonial.php:364
1294
  msgid "Customer Name"
1295
  msgstr "Nom du client"
1296
 
1297
+ #: ../admin/class-testimonial.php:431
1298
  msgid "Customize Testimonials Archive"
1299
  msgstr "Personnaliser les archives de témoignages"
1300
 
1301
+ #: ../admin/class-testimonial.php:432
1302
  msgid "Customize"
1303
  msgstr "Personnaliser"
1304
 
1305
+ #: ../admin/class-testimonial.php:481
1306
  msgid "Testimonial Archive Title"
1307
  msgstr "Témoignage Titre de l'archive"
1308
 
1309
+ #: ../admin/class-testimonial.php:501
1310
  msgid "Testimonial Archive Content"
1311
  msgstr "Contenu des archives de témoignages"
1312
 
1313
+ #: ../admin/class-testimonial.php:523
1314
  msgid "Testimonial Archive Featured Image"
1315
  msgstr "Image à la une de l’archive des témoignages"
1316
 
1317
+ #: ../admin/class-testimonial.php:808
1318
  msgid "Position"
1319
  msgstr "Position"
1320
 
1321
+ #: ../admin/class-testimonial.php:842
1322
  msgid "Testmonial Options"
1323
  msgstr "Options de témoignage"
1324
 
1325
+ #: ../admin/class-testimonial.php:878
1326
  msgid ""
1327
  "Your Testimonial Archive currently has no entries. You can start creating "
1328
  "them on your dashboard."
1330
  "Vos archives de témoignages n'ont actuellement aucune entrée. Vous pouvez "
1331
  "commencer à les créer sur votre tableau de bord."
1332
 
1333
+ #: ../admin/class-testimonial.php:928
1334
  msgid "Previous Slide"
1335
  msgstr "Diapo précédente"
1336
 
1337
+ #: ../admin/class-testimonial.php:935
1338
  msgid "Next Slide"
1339
  msgstr "Diapo suivante"
1340
 
1341
+ #: ../admin/class-testimonial.php:998
1342
  msgid "Please define default parameters in the form of an array."
1343
  msgstr "Veuillez définir les paramètres par défaut sous la forme d'un tableau."
1344
 
1345
+ #: ../admin/class-testimonial.php:1003
1346
  msgid "Please define an SVG icon filename."
1347
  msgstr "Veuillez définir un nom pour l’icône SVG."
1348
 
languages/essential-content-types.pot CHANGED
@@ -5,7 +5,7 @@ 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: 2020-09-21 08:20-0400\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,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.1\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"
@@ -52,7 +52,7 @@ msgstr ""
52
 
53
  #: ../admin/class-featured-content.php:104
54
  #: ../admin/class-featured-content.php:105
55
- #: ../admin/class-featured-content.php:277
56
  #: ../admin/partials/dashboard-display.php:84
57
  #: ../admin/partials/essential-content-types-admin-display.php:113
58
  #: ../admin/partials/essential-content-types-admin-display.php:289
@@ -64,7 +64,7 @@ msgid "All Contents"
64
  msgstr ""
65
 
66
  #: ../admin/class-featured-content.php:107 ../admin/class-portfolio.php:234
67
- #: ../admin/class-service.php:107 ../admin/class-testimonial.php:267
68
  msgid "Add New"
69
  msgstr ""
70
 
@@ -108,231 +108,231 @@ msgstr ""
108
  msgid "Contents list"
109
  msgstr ""
110
 
111
- #: ../admin/class-featured-content.php:148
112
- #: ../admin/class-featured-content.php:150
113
  msgid "Content Types"
114
  msgstr ""
115
 
116
- #: ../admin/class-featured-content.php:149
117
  msgid "Content Type"
118
  msgstr ""
119
 
120
- #: ../admin/class-featured-content.php:151
121
  msgid "All Content Types"
122
  msgstr ""
123
 
124
- #: ../admin/class-featured-content.php:152
125
  msgid "Edit Content Type"
126
  msgstr ""
127
 
128
- #: ../admin/class-featured-content.php:153
129
  msgid "View Content Type"
130
  msgstr ""
131
 
132
- #: ../admin/class-featured-content.php:154
133
  msgid "Update Content Type"
134
  msgstr ""
135
 
136
- #: ../admin/class-featured-content.php:155
137
  msgid "Add New Content Type"
138
  msgstr ""
139
 
140
- #: ../admin/class-featured-content.php:156
141
  msgid "New Content Type Name"
142
  msgstr ""
143
 
144
- #: ../admin/class-featured-content.php:157
145
  msgid "Parent Content Type"
146
  msgstr ""
147
 
148
- #: ../admin/class-featured-content.php:158
149
  msgid "Parent Content Type:"
150
  msgstr ""
151
 
152
- #: ../admin/class-featured-content.php:159
153
  msgid "Search Content Types"
154
  msgstr ""
155
 
156
- #: ../admin/class-featured-content.php:160
157
  msgid "Content type list navigation"
158
  msgstr ""
159
 
160
- #: ../admin/class-featured-content.php:161
161
  msgid "Content type list"
162
  msgstr ""
163
 
164
- #: ../admin/class-featured-content.php:175
165
- #: ../admin/class-featured-content.php:177
166
  msgid "Content Tags"
167
  msgstr ""
168
 
169
- #: ../admin/class-featured-content.php:176
170
  msgid "Content Tag"
171
  msgstr ""
172
 
173
- #: ../admin/class-featured-content.php:178
174
  msgid "All Content Tags"
175
  msgstr ""
176
 
177
- #: ../admin/class-featured-content.php:179
178
  msgid "Edit Content Tag"
179
  msgstr ""
180
 
181
- #: ../admin/class-featured-content.php:180
182
  msgid "View Content Tag"
183
  msgstr ""
184
 
185
- #: ../admin/class-featured-content.php:181
186
  msgid "Update Content Tag"
187
  msgstr ""
188
 
189
- #: ../admin/class-featured-content.php:182
190
  msgid "Add New Content Tag"
191
  msgstr ""
192
 
193
- #: ../admin/class-featured-content.php:183
194
  msgid "New Content Tag Name"
195
  msgstr ""
196
 
197
- #: ../admin/class-featured-content.php:184
198
  msgid "Search Content Tags"
199
  msgstr ""
200
 
201
- #: ../admin/class-featured-content.php:185
202
  msgid "Popular Content Tags"
203
  msgstr ""
204
 
205
- #: ../admin/class-featured-content.php:186 ../admin/class-portfolio.php:314
206
- #: ../admin/class-service.php:186
207
  msgid "Separate tags with commas"
208
  msgstr ""
209
 
210
- #: ../admin/class-featured-content.php:187 ../admin/class-portfolio.php:315
211
- #: ../admin/class-service.php:187
212
  msgid "Add or remove tags"
213
  msgstr ""
214
 
215
- #: ../admin/class-featured-content.php:188 ../admin/class-portfolio.php:316
216
- #: ../admin/class-service.php:188
217
  msgid "Choose from the most used tags"
218
  msgstr ""
219
 
220
- #: ../admin/class-featured-content.php:189 ../admin/class-portfolio.php:317
221
- #: ../admin/class-service.php:189
222
  msgid "No tags found."
223
  msgstr ""
224
 
225
- #: ../admin/class-featured-content.php:190
226
  msgid "Content tag list navigation"
227
  msgstr ""
228
 
229
- #: ../admin/class-featured-content.php:191
230
  msgid "Content tag list"
231
  msgstr ""
232
 
233
- #: ../admin/class-featured-content.php:211
234
  #, php-format
235
  msgid "Content updated. <a href=\"%s\">View item</a>"
236
  msgstr ""
237
 
238
- #: ../admin/class-featured-content.php:212 ../admin/class-food-menu.php:269
239
- #: ../admin/class-portfolio.php:340 ../admin/class-service.php:212
240
- #: ../admin/class-testimonial.php:314
241
  msgid "Custom field updated."
242
  msgstr ""
243
 
244
- #: ../admin/class-featured-content.php:213 ../admin/class-food-menu.php:270
245
- #: ../admin/class-portfolio.php:341 ../admin/class-service.php:213
246
- #: ../admin/class-testimonial.php:315
247
  msgid "Custom field deleted."
248
  msgstr ""
249
 
250
- #: ../admin/class-featured-content.php:214
251
  msgid "Content updated."
252
  msgstr ""
253
 
254
- #: ../admin/class-featured-content.php:216
255
  #, php-format
256
  msgid "Content restored to revision from %s"
257
  msgstr ""
258
 
259
- #: ../admin/class-featured-content.php:217
260
  #, php-format
261
  msgid "Content published. <a href=\"%s\">View content</a>"
262
  msgstr ""
263
 
264
- #: ../admin/class-featured-content.php:218
265
  msgid "Content saved."
266
  msgstr ""
267
 
268
- #: ../admin/class-featured-content.php:219
269
  #, php-format
270
  msgid ""
271
  "Content submitted. <a target=\"_blank\" href=\"%s\">Preview content</a>"
272
  msgstr ""
273
 
274
- #: ../admin/class-featured-content.php:220
275
  #, php-format
276
  msgid ""
277
  "Content scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
278
  "\"%2$s\">Preview content</a>"
279
  msgstr ""
280
 
281
- #: ../admin/class-featured-content.php:222 ../admin/class-food-menu.php:284
282
- #: ../admin/class-portfolio.php:350 ../admin/class-service.php:222
283
- #: ../admin/class-testimonial.php:324
284
  msgid "M j, Y @ G:i"
285
  msgstr ""
286
 
287
- #: ../admin/class-featured-content.php:223
288
  #, php-format
289
  msgid ""
290
  "Content item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
291
  "content</a>"
292
  msgstr ""
293
 
294
- #: ../admin/class-featured-content.php:235
295
  msgid "Content"
296
  msgstr ""
297
 
298
- #: ../admin/class-featured-content.php:272 ../admin/class-portfolio.php:406
299
- #: ../admin/class-service.php:272 ../admin/class-testimonial.php:431
300
  msgid "Essential Content Types Plugin Options"
301
  msgstr ""
302
 
303
- #: ../admin/class-featured-content.php:282
304
  msgid "Contents"
305
  msgstr ""
306
 
307
- #: ../admin/class-featured-content.php:290
308
  msgid "Featured Content Archive Title"
309
  msgstr ""
310
 
311
- #: ../admin/class-featured-content.php:303
312
  msgid "Featured Content Archive Content"
313
  msgstr ""
314
 
315
- #: ../admin/class-featured-content.php:317
316
  msgid "Featured Content Archive Featured Image"
317
  msgstr ""
318
 
319
- #: ../admin/class-featured-content.php:560 ../admin/class-portfolio.php:705
320
- #: ../admin/class-service.php:568
321
  msgid "Types"
322
  msgstr ""
323
 
324
- #: ../admin/class-featured-content.php:591 ../admin/class-portfolio.php:736
325
- #: ../admin/class-service.php:599
326
  msgid "Tags"
327
  msgstr ""
328
 
329
- #: ../admin/class-featured-content.php:617 ../admin/class-portfolio.php:762
330
- #: ../admin/class-service.php:625
331
  #, php-format
332
  msgid "<span>Author:</span> <a href=\"%1$s\">%2$s</a>"
333
  msgstr ""
334
 
335
- #: ../admin/class-featured-content.php:670
336
  msgid ""
337
  "Your Featured Content Archive currently has no entries. You can start "
338
  "creating them on your dashboard."
@@ -696,15 +696,15 @@ msgstr ""
696
  msgid "Portfolio Items"
697
  msgstr ""
698
 
699
- #: ../admin/class-portfolio.php:230 ../admin/class-portfolio.php:419
700
  msgid "Projects"
701
  msgstr ""
702
 
703
- #: ../admin/class-portfolio.php:231 ../admin/class-portfolio.php:363
704
  msgid "Project"
705
  msgstr ""
706
 
707
- #: ../admin/class-portfolio.php:232 ../admin/class-portfolio.php:411
708
  #: ../admin/partials/essential-content-types-admin-display.php:103
709
  #: ../admin/partials/essential-content-types-admin-display.php:281
710
  msgid "Portfolio"
@@ -754,162 +754,162 @@ msgstr ""
754
  msgid "Projects list"
755
  msgstr ""
756
 
757
- #: ../admin/class-portfolio.php:276 ../admin/class-portfolio.php:278
758
  msgid "Project Types"
759
  msgstr ""
760
 
761
- #: ../admin/class-portfolio.php:277
762
  msgid "Project Type"
763
  msgstr ""
764
 
765
- #: ../admin/class-portfolio.php:279
766
  msgid "All Project Types"
767
  msgstr ""
768
 
769
- #: ../admin/class-portfolio.php:280
770
  msgid "Edit Project Type"
771
  msgstr ""
772
 
773
- #: ../admin/class-portfolio.php:281
774
  msgid "View Project Type"
775
  msgstr ""
776
 
777
- #: ../admin/class-portfolio.php:282
778
  msgid "Update Project Type"
779
  msgstr ""
780
 
781
- #: ../admin/class-portfolio.php:283
782
  msgid "Add New Project Type"
783
  msgstr ""
784
 
785
- #: ../admin/class-portfolio.php:284
786
  msgid "New Project Type Name"
787
  msgstr ""
788
 
789
- #: ../admin/class-portfolio.php:285
790
  msgid "Parent Project Type"
791
  msgstr ""
792
 
793
- #: ../admin/class-portfolio.php:286
794
  msgid "Parent Project Type:"
795
  msgstr ""
796
 
797
- #: ../admin/class-portfolio.php:287
798
  msgid "Search Project Types"
799
  msgstr ""
800
 
801
- #: ../admin/class-portfolio.php:288
802
  msgid "Project type list navigation"
803
  msgstr ""
804
 
805
- #: ../admin/class-portfolio.php:289
806
  msgid "Project type list"
807
  msgstr ""
808
 
809
- #: ../admin/class-portfolio.php:303 ../admin/class-portfolio.php:305
810
  msgid "Project Tags"
811
  msgstr ""
812
 
813
- #: ../admin/class-portfolio.php:304
814
  msgid "Project Tag"
815
  msgstr ""
816
 
817
- #: ../admin/class-portfolio.php:306
818
  msgid "All Project Tags"
819
  msgstr ""
820
 
821
- #: ../admin/class-portfolio.php:307
822
  msgid "Edit Project Tag"
823
  msgstr ""
824
 
825
- #: ../admin/class-portfolio.php:308
826
  msgid "View Project Tag"
827
  msgstr ""
828
 
829
- #: ../admin/class-portfolio.php:309
830
  msgid "Update Project Tag"
831
  msgstr ""
832
 
833
- #: ../admin/class-portfolio.php:310
834
  msgid "Add New Project Tag"
835
  msgstr ""
836
 
837
- #: ../admin/class-portfolio.php:311
838
  msgid "New Project Tag Name"
839
  msgstr ""
840
 
841
- #: ../admin/class-portfolio.php:312
842
  msgid "Search Project Tags"
843
  msgstr ""
844
 
845
- #: ../admin/class-portfolio.php:313
846
  msgid "Popular Project Tags"
847
  msgstr ""
848
 
849
- #: ../admin/class-portfolio.php:318
850
  msgid "Project tag list navigation"
851
  msgstr ""
852
 
853
- #: ../admin/class-portfolio.php:319
854
  msgid "Project tag list"
855
  msgstr ""
856
 
857
- #: ../admin/class-portfolio.php:339
858
  #, php-format
859
  msgid "Project updated. <a href=\"%s\">View item</a>"
860
  msgstr ""
861
 
862
- #: ../admin/class-portfolio.php:342
863
  msgid "Project updated."
864
  msgstr ""
865
 
866
- #: ../admin/class-portfolio.php:344
867
  #, php-format
868
  msgid "Project restored to revision from %s"
869
  msgstr ""
870
 
871
- #: ../admin/class-portfolio.php:345
872
  #, php-format
873
  msgid "Project published. <a href=\"%s\">View project</a>"
874
  msgstr ""
875
 
876
- #: ../admin/class-portfolio.php:346
877
  msgid "Project saved."
878
  msgstr ""
879
 
880
- #: ../admin/class-portfolio.php:347
881
  #, php-format
882
  msgid ""
883
  "Project submitted. <a target=\"_blank\" href=\"%s\">Preview project</a>"
884
  msgstr ""
885
 
886
- #: ../admin/class-portfolio.php:348
887
  #, php-format
888
  msgid ""
889
  "Project scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
890
  "\"%2$s\">Preview project</a>"
891
  msgstr ""
892
 
893
- #: ../admin/class-portfolio.php:351
894
  #, php-format
895
  msgid ""
896
  "Project item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
897
  "project</a>"
898
  msgstr ""
899
 
900
- #: ../admin/class-portfolio.php:427
901
  msgid "Portfolio Archive Title"
902
  msgstr ""
903
 
904
- #: ../admin/class-portfolio.php:442
905
  msgid "Portfolio Archive Content"
906
  msgstr ""
907
 
908
- #: ../admin/class-portfolio.php:458
909
  msgid "Portfolio Archive Featured Image"
910
  msgstr ""
911
 
912
- #: ../admin/class-portfolio.php:820
913
  msgid ""
914
  "Your Portfolio Archive currently has no entries. You can start creating "
915
  "them on your dashboard."
@@ -919,15 +919,15 @@ msgstr ""
919
  msgid "Service Items"
920
  msgstr ""
921
 
922
- #: ../admin/class-service.php:103 ../admin/class-service.php:277
923
- #: ../admin/class-service.php:283 ../admin/partials/dashboard-display.php:112
924
  #: ../admin/partials/essential-content-types-admin-display.php:118
925
  #: ../admin/partials/essential-content-types-admin-display.php:297
926
  msgid "Services"
927
  msgstr ""
928
 
929
  #: ../admin/class-service.php:104 ../admin/class-service.php:105
930
- #: ../admin/class-service.php:235
931
  msgid "Service"
932
  msgstr ""
933
 
@@ -971,170 +971,170 @@ msgstr ""
971
  msgid "Services list"
972
  msgstr ""
973
 
974
- #: ../admin/class-service.php:148 ../admin/class-service.php:150
975
  msgid "Service Types"
976
  msgstr ""
977
 
978
- #: ../admin/class-service.php:149
979
  msgid "Service Type"
980
  msgstr ""
981
 
982
- #: ../admin/class-service.php:151
983
  msgid "All Service Types"
984
  msgstr ""
985
 
986
- #: ../admin/class-service.php:152
987
  msgid "Edit Service Type"
988
  msgstr ""
989
 
990
- #: ../admin/class-service.php:153
991
  msgid "View Service Type"
992
  msgstr ""
993
 
994
- #: ../admin/class-service.php:154
995
  msgid "Update Service Type"
996
  msgstr ""
997
 
998
- #: ../admin/class-service.php:155
999
  msgid "Add New Service Type"
1000
  msgstr ""
1001
 
1002
- #: ../admin/class-service.php:156
1003
  msgid "New Service Type Name"
1004
  msgstr ""
1005
 
1006
- #: ../admin/class-service.php:157
1007
  msgid "Parent Service Type"
1008
  msgstr ""
1009
 
1010
- #: ../admin/class-service.php:158
1011
  msgid "Parent Service Type:"
1012
  msgstr ""
1013
 
1014
- #: ../admin/class-service.php:159
1015
  msgid "Search Service Types"
1016
  msgstr ""
1017
 
1018
- #: ../admin/class-service.php:160
1019
  msgid "Service type list navigation"
1020
  msgstr ""
1021
 
1022
- #: ../admin/class-service.php:161
1023
  msgid "Service type list"
1024
  msgstr ""
1025
 
1026
- #: ../admin/class-service.php:175 ../admin/class-service.php:177
1027
  msgid "Service Tags"
1028
  msgstr ""
1029
 
1030
- #: ../admin/class-service.php:176
1031
  msgid "Service Tag"
1032
  msgstr ""
1033
 
1034
- #: ../admin/class-service.php:178
1035
  msgid "All Service Tags"
1036
  msgstr ""
1037
 
1038
- #: ../admin/class-service.php:179
1039
  msgid "Edit Service Tag"
1040
  msgstr ""
1041
 
1042
- #: ../admin/class-service.php:180
1043
  msgid "View Service Tag"
1044
  msgstr ""
1045
 
1046
- #: ../admin/class-service.php:181
1047
  msgid "Update Service Tag"
1048
  msgstr ""
1049
 
1050
- #: ../admin/class-service.php:182
1051
  msgid "Add New Service Tag"
1052
  msgstr ""
1053
 
1054
- #: ../admin/class-service.php:183
1055
  msgid "New Service Tag Name"
1056
  msgstr ""
1057
 
1058
- #: ../admin/class-service.php:184
1059
  msgid "Search Service Tags"
1060
  msgstr ""
1061
 
1062
- #: ../admin/class-service.php:185
1063
  msgid "Popular Service Tags"
1064
  msgstr ""
1065
 
1066
- #: ../admin/class-service.php:190
1067
  msgid "Service tag list navigation"
1068
  msgstr ""
1069
 
1070
- #: ../admin/class-service.php:191
1071
  msgid "Service tag list"
1072
  msgstr ""
1073
 
1074
- #: ../admin/class-service.php:211
1075
  #, php-format
1076
  msgid "Service updated. <a href=\"%s\">View item</a>"
1077
  msgstr ""
1078
 
1079
- #: ../admin/class-service.php:214
1080
  msgid "Service updated."
1081
  msgstr ""
1082
 
1083
- #: ../admin/class-service.php:216
1084
  #, php-format
1085
  msgid "Service restored to revision from %s"
1086
  msgstr ""
1087
 
1088
- #: ../admin/class-service.php:217
1089
  #, php-format
1090
  msgid "Service published. <a href=\"%s\">View content</a>"
1091
  msgstr ""
1092
 
1093
- #: ../admin/class-service.php:218
1094
  msgid "Service saved."
1095
  msgstr ""
1096
 
1097
- #: ../admin/class-service.php:219
1098
  #, php-format
1099
  msgid ""
1100
  "Service submitted. <a target=\"_blank\" href=\"%s\">Preview content</a>"
1101
  msgstr ""
1102
 
1103
- #: ../admin/class-service.php:220
1104
  #, php-format
1105
  msgid ""
1106
  "Service scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
1107
  "\"%2$s\">Preview service</a>"
1108
  msgstr ""
1109
 
1110
- #: ../admin/class-service.php:223
1111
  #, php-format
1112
  msgid ""
1113
  "Service item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
1114
  "content</a>"
1115
  msgstr ""
1116
 
1117
- #: ../admin/class-service.php:291
1118
  msgid "Service Archive Title"
1119
  msgstr ""
1120
 
1121
- #: ../admin/class-service.php:304
1122
  msgid "Service Archive Content"
1123
  msgstr ""
1124
 
1125
- #: ../admin/class-service.php:318
1126
  msgid "Service Archive Featured Image"
1127
  msgstr ""
1128
 
1129
- #: ../admin/class-service.php:674
1130
  msgid ""
1131
  "Your Service Archive currently has no entries. You can start creating them "
1132
  "on your dashboard."
1133
  msgstr ""
1134
 
1135
- #: ../admin/class-testimonial.php:118 ../admin/class-testimonial.php:263
1136
- #: ../admin/class-testimonial.php:265 ../admin/class-testimonial.php:436
1137
- #: ../admin/class-testimonial.php:443
1138
  #: ../admin/partials/dashboard-display.php:57
1139
  #: ../admin/partials/essential-content-types-admin-display.php:108
1140
  msgid "Testimonials"
@@ -1148,163 +1148,163 @@ msgstr ""
1148
  msgid "Enable Testimonials for this site."
1149
  msgstr ""
1150
 
1151
- #: ../admin/class-testimonial.php:161
1152
  #, php-format
1153
  msgid "Testimonial pages display at most %1$s testimonials"
1154
  msgstr ""
1155
 
1156
- #: ../admin/class-testimonial.php:261
1157
  msgid "Customer Testimonials"
1158
  msgstr ""
1159
 
1160
- #: ../admin/class-testimonial.php:264
1161
  #: ../admin/partials/essential-content-types-admin-display.php:305
1162
  msgid "Testimonial"
1163
  msgstr ""
1164
 
1165
- #: ../admin/class-testimonial.php:266
1166
  msgid "All Testimonials"
1167
  msgstr ""
1168
 
1169
- #: ../admin/class-testimonial.php:268
1170
  msgid "Add New Testimonial"
1171
  msgstr ""
1172
 
1173
- #: ../admin/class-testimonial.php:269
1174
  msgid "Edit Testimonial"
1175
  msgstr ""
1176
 
1177
- #: ../admin/class-testimonial.php:270
1178
  msgid "New Testimonial"
1179
  msgstr ""
1180
 
1181
- #: ../admin/class-testimonial.php:271
1182
  msgid "View Testimonial"
1183
  msgstr ""
1184
 
1185
- #: ../admin/class-testimonial.php:272
1186
  msgid "Search Testimonials"
1187
  msgstr ""
1188
 
1189
- #: ../admin/class-testimonial.php:273
1190
  msgid "No Testimonials found"
1191
  msgstr ""
1192
 
1193
- #: ../admin/class-testimonial.php:274
1194
  msgid "No Testimonials found in Trash"
1195
  msgstr ""
1196
 
1197
- #: ../admin/class-testimonial.php:275
1198
  msgid "Filter Testimonials list"
1199
  msgstr ""
1200
 
1201
- #: ../admin/class-testimonial.php:276
1202
  msgid "Testimonial list navigation"
1203
  msgstr ""
1204
 
1205
- #: ../admin/class-testimonial.php:277
1206
  msgid "Testimonials list"
1207
  msgstr ""
1208
 
1209
- #: ../admin/class-testimonial.php:313
1210
  #, php-format
1211
  msgid "Testimonial updated. <a href=\"%s\">View testimonial</a>"
1212
  msgstr ""
1213
 
1214
- #: ../admin/class-testimonial.php:316
1215
  msgid "Testimonial updated."
1216
  msgstr ""
1217
 
1218
- #: ../admin/class-testimonial.php:318
1219
  #, php-format
1220
  msgid "Testimonial restored to revision from %s"
1221
  msgstr ""
1222
 
1223
- #: ../admin/class-testimonial.php:319
1224
  #, php-format
1225
  msgid "Testimonial published. <a href=\"%s\">View testimonial</a>"
1226
  msgstr ""
1227
 
1228
- #: ../admin/class-testimonial.php:320
1229
  msgid "Testimonial saved."
1230
  msgstr ""
1231
 
1232
- #: ../admin/class-testimonial.php:321
1233
  #, php-format
1234
  msgid ""
1235
  "Testimonial submitted. <a target=\"_blank\" href=\"%s\">Preview "
1236
  "testimonial</a>"
1237
  msgstr ""
1238
 
1239
- #: ../admin/class-testimonial.php:322
1240
  #, php-format
1241
  msgid ""
1242
  "Testimonial scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
1243
  "\"%2$s\">Preview testimonial</a>"
1244
  msgstr ""
1245
 
1246
- #: ../admin/class-testimonial.php:325
1247
  #, php-format
1248
  msgid ""
1249
  "Testimonial draft updated. <a target=\"_blank\" href=\"%s\">Preview "
1250
  "testimonial</a>"
1251
  msgstr ""
1252
 
1253
- #: ../admin/class-testimonial.php:338
1254
  msgid "Enter the customer's name here"
1255
  msgstr ""
1256
 
1257
- #: ../admin/class-testimonial.php:347
1258
  msgid "Customer Name"
1259
  msgstr ""
1260
 
1261
- #: ../admin/class-testimonial.php:414
1262
  msgid "Customize Testimonials Archive"
1263
  msgstr ""
1264
 
1265
- #: ../admin/class-testimonial.php:415
1266
  msgid "Customize"
1267
  msgstr ""
1268
 
1269
- #: ../admin/class-testimonial.php:449
1270
  msgid "Testimonial Archive Title"
1271
  msgstr ""
1272
 
1273
- #: ../admin/class-testimonial.php:461
1274
  msgid "Testimonial Archive Content"
1275
  msgstr ""
1276
 
1277
- #: ../admin/class-testimonial.php:472
1278
  msgid "Testimonial Archive Featured Image"
1279
  msgstr ""
1280
 
1281
- #: ../admin/class-testimonial.php:750
1282
  msgid "Position"
1283
  msgstr ""
1284
 
1285
- #: ../admin/class-testimonial.php:785
1286
  msgid "Testmonial Options"
1287
  msgstr ""
1288
 
1289
- #: ../admin/class-testimonial.php:821
1290
  msgid ""
1291
  "Your Testimonial Archive currently has no entries. You can start creating "
1292
  "them on your dashboard."
1293
  msgstr ""
1294
 
1295
- #: ../admin/class-testimonial.php:870
1296
  msgid "Previous Slide"
1297
  msgstr ""
1298
 
1299
- #: ../admin/class-testimonial.php:877
1300
  msgid "Next Slide"
1301
  msgstr ""
1302
 
1303
- #: ../admin/class-testimonial.php:939
1304
  msgid "Please define default parameters in the form of an array."
1305
  msgstr ""
1306
 
1307
- #: ../admin/class-testimonial.php:944
1308
  msgid "Please define an SVG icon filename."
1309
  msgstr ""
1310
 
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: 2020-12-07 00:51-0500\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.2\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"
52
 
53
  #: ../admin/class-featured-content.php:104
54
  #: ../admin/class-featured-content.php:105
55
+ #: ../admin/class-featured-content.php:303
56
  #: ../admin/partials/dashboard-display.php:84
57
  #: ../admin/partials/essential-content-types-admin-display.php:113
58
  #: ../admin/partials/essential-content-types-admin-display.php:289
64
  msgstr ""
65
 
66
  #: ../admin/class-featured-content.php:107 ../admin/class-portfolio.php:234
67
+ #: ../admin/class-service.php:107 ../admin/class-testimonial.php:273
68
  msgid "Add New"
69
  msgstr ""
70
 
108
  msgid "Contents list"
109
  msgstr ""
110
 
111
+ #: ../admin/class-featured-content.php:161
112
+ #: ../admin/class-featured-content.php:163
113
  msgid "Content Types"
114
  msgstr ""
115
 
116
+ #: ../admin/class-featured-content.php:162
117
  msgid "Content Type"
118
  msgstr ""
119
 
120
+ #: ../admin/class-featured-content.php:164
121
  msgid "All Content Types"
122
  msgstr ""
123
 
124
+ #: ../admin/class-featured-content.php:165
125
  msgid "Edit Content Type"
126
  msgstr ""
127
 
128
+ #: ../admin/class-featured-content.php:166
129
  msgid "View Content Type"
130
  msgstr ""
131
 
132
+ #: ../admin/class-featured-content.php:167
133
  msgid "Update Content Type"
134
  msgstr ""
135
 
136
+ #: ../admin/class-featured-content.php:168
137
  msgid "Add New Content Type"
138
  msgstr ""
139
 
140
+ #: ../admin/class-featured-content.php:169
141
  msgid "New Content Type Name"
142
  msgstr ""
143
 
144
+ #: ../admin/class-featured-content.php:170
145
  msgid "Parent Content Type"
146
  msgstr ""
147
 
148
+ #: ../admin/class-featured-content.php:171
149
  msgid "Parent Content Type:"
150
  msgstr ""
151
 
152
+ #: ../admin/class-featured-content.php:172
153
  msgid "Search Content Types"
154
  msgstr ""
155
 
156
+ #: ../admin/class-featured-content.php:173
157
  msgid "Content type list navigation"
158
  msgstr ""
159
 
160
+ #: ../admin/class-featured-content.php:174
161
  msgid "Content type list"
162
  msgstr ""
163
 
164
+ #: ../admin/class-featured-content.php:192
165
+ #: ../admin/class-featured-content.php:194
166
  msgid "Content Tags"
167
  msgstr ""
168
 
169
+ #: ../admin/class-featured-content.php:193
170
  msgid "Content Tag"
171
  msgstr ""
172
 
173
+ #: ../admin/class-featured-content.php:195
174
  msgid "All Content Tags"
175
  msgstr ""
176
 
177
+ #: ../admin/class-featured-content.php:196
178
  msgid "Edit Content Tag"
179
  msgstr ""
180
 
181
+ #: ../admin/class-featured-content.php:197
182
  msgid "View Content Tag"
183
  msgstr ""
184
 
185
+ #: ../admin/class-featured-content.php:198
186
  msgid "Update Content Tag"
187
  msgstr ""
188
 
189
+ #: ../admin/class-featured-content.php:199
190
  msgid "Add New Content Tag"
191
  msgstr ""
192
 
193
+ #: ../admin/class-featured-content.php:200
194
  msgid "New Content Tag Name"
195
  msgstr ""
196
 
197
+ #: ../admin/class-featured-content.php:201
198
  msgid "Search Content Tags"
199
  msgstr ""
200
 
201
+ #: ../admin/class-featured-content.php:202
202
  msgid "Popular Content Tags"
203
  msgstr ""
204
 
205
+ #: ../admin/class-featured-content.php:203 ../admin/class-portfolio.php:321
206
+ #: ../admin/class-service.php:193
207
  msgid "Separate tags with commas"
208
  msgstr ""
209
 
210
+ #: ../admin/class-featured-content.php:204 ../admin/class-portfolio.php:322
211
+ #: ../admin/class-service.php:194
212
  msgid "Add or remove tags"
213
  msgstr ""
214
 
215
+ #: ../admin/class-featured-content.php:205 ../admin/class-portfolio.php:323
216
+ #: ../admin/class-service.php:195
217
  msgid "Choose from the most used tags"
218
  msgstr ""
219
 
220
+ #: ../admin/class-featured-content.php:206 ../admin/class-portfolio.php:324
221
+ #: ../admin/class-service.php:196
222
  msgid "No tags found."
223
  msgstr ""
224
 
225
+ #: ../admin/class-featured-content.php:207
226
  msgid "Content tag list navigation"
227
  msgstr ""
228
 
229
+ #: ../admin/class-featured-content.php:208
230
  msgid "Content tag list"
231
  msgstr ""
232
 
233
+ #: ../admin/class-featured-content.php:229
234
  #, php-format
235
  msgid "Content updated. <a href=\"%s\">View item</a>"
236
  msgstr ""
237
 
238
+ #: ../admin/class-featured-content.php:230 ../admin/class-food-menu.php:269
239
+ #: ../admin/class-portfolio.php:347 ../admin/class-service.php:219
240
+ #: ../admin/class-testimonial.php:327
241
  msgid "Custom field updated."
242
  msgstr ""
243
 
244
+ #: ../admin/class-featured-content.php:231 ../admin/class-food-menu.php:270
245
+ #: ../admin/class-portfolio.php:348 ../admin/class-service.php:220
246
+ #: ../admin/class-testimonial.php:328
247
  msgid "Custom field deleted."
248
  msgstr ""
249
 
250
+ #: ../admin/class-featured-content.php:232
251
  msgid "Content updated."
252
  msgstr ""
253
 
254
+ #: ../admin/class-featured-content.php:234
255
  #, php-format
256
  msgid "Content restored to revision from %s"
257
  msgstr ""
258
 
259
+ #: ../admin/class-featured-content.php:235
260
  #, php-format
261
  msgid "Content published. <a href=\"%s\">View content</a>"
262
  msgstr ""
263
 
264
+ #: ../admin/class-featured-content.php:236
265
  msgid "Content saved."
266
  msgstr ""
267
 
268
+ #: ../admin/class-featured-content.php:237
269
  #, php-format
270
  msgid ""
271
  "Content submitted. <a target=\"_blank\" href=\"%s\">Preview content</a>"
272
  msgstr ""
273
 
274
+ #: ../admin/class-featured-content.php:239
275
  #, php-format
276
  msgid ""
277
  "Content scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
278
  "\"%2$s\">Preview content</a>"
279
  msgstr ""
280
 
281
+ #: ../admin/class-featured-content.php:241 ../admin/class-food-menu.php:284
282
+ #: ../admin/class-portfolio.php:357 ../admin/class-service.php:229
283
+ #: ../admin/class-testimonial.php:338
284
  msgid "M j, Y @ G:i"
285
  msgstr ""
286
 
287
+ #: ../admin/class-featured-content.php:244
288
  #, php-format
289
  msgid ""
290
  "Content item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
291
  "content</a>"
292
  msgstr ""
293
 
294
+ #: ../admin/class-featured-content.php:256
295
  msgid "Content"
296
  msgstr ""
297
 
298
+ #: ../admin/class-featured-content.php:295 ../admin/class-portfolio.php:413
299
+ #: ../admin/class-service.php:279 ../admin/class-testimonial.php:453
300
  msgid "Essential Content Types Plugin Options"
301
  msgstr ""
302
 
303
+ #: ../admin/class-featured-content.php:311
304
  msgid "Contents"
305
  msgstr ""
306
 
307
+ #: ../admin/class-featured-content.php:322
308
  msgid "Featured Content Archive Title"
309
  msgstr ""
310
 
311
+ #: ../admin/class-featured-content.php:341
312
  msgid "Featured Content Archive Content"
313
  msgstr ""
314
 
315
+ #: ../admin/class-featured-content.php:363
316
  msgid "Featured Content Archive Featured Image"
317
  msgstr ""
318
 
319
+ #: ../admin/class-featured-content.php:618 ../admin/class-portfolio.php:712
320
+ #: ../admin/class-service.php:575
321
  msgid "Types"
322
  msgstr ""
323
 
324
+ #: ../admin/class-featured-content.php:649 ../admin/class-portfolio.php:743
325
+ #: ../admin/class-service.php:606
326
  msgid "Tags"
327
  msgstr ""
328
 
329
+ #: ../admin/class-featured-content.php:676 ../admin/class-portfolio.php:769
330
+ #: ../admin/class-service.php:632
331
  #, php-format
332
  msgid "<span>Author:</span> <a href=\"%1$s\">%2$s</a>"
333
  msgstr ""
334
 
335
+ #: ../admin/class-featured-content.php:729
336
  msgid ""
337
  "Your Featured Content Archive currently has no entries. You can start "
338
  "creating them on your dashboard."
696
  msgid "Portfolio Items"
697
  msgstr ""
698
 
699
+ #: ../admin/class-portfolio.php:230 ../admin/class-portfolio.php:426
700
  msgid "Projects"
701
  msgstr ""
702
 
703
+ #: ../admin/class-portfolio.php:231 ../admin/class-portfolio.php:370
704
  msgid "Project"
705
  msgstr ""
706
 
707
+ #: ../admin/class-portfolio.php:232 ../admin/class-portfolio.php:418
708
  #: ../admin/partials/essential-content-types-admin-display.php:103
709
  #: ../admin/partials/essential-content-types-admin-display.php:281
710
  msgid "Portfolio"
754
  msgid "Projects list"
755
  msgstr ""
756
 
757
+ #: ../admin/class-portfolio.php:283 ../admin/class-portfolio.php:285
758
  msgid "Project Types"
759
  msgstr ""
760
 
761
+ #: ../admin/class-portfolio.php:284
762
  msgid "Project Type"
763
  msgstr ""
764
 
765
+ #: ../admin/class-portfolio.php:286
766
  msgid "All Project Types"
767
  msgstr ""
768
 
769
+ #: ../admin/class-portfolio.php:287
770
  msgid "Edit Project Type"
771
  msgstr ""
772
 
773
+ #: ../admin/class-portfolio.php:288
774
  msgid "View Project Type"
775
  msgstr ""
776
 
777
+ #: ../admin/class-portfolio.php:289
778
  msgid "Update Project Type"
779
  msgstr ""
780
 
781
+ #: ../admin/class-portfolio.php:290
782
  msgid "Add New Project Type"
783
  msgstr ""
784
 
785
+ #: ../admin/class-portfolio.php:291
786
  msgid "New Project Type Name"
787
  msgstr ""
788
 
789
+ #: ../admin/class-portfolio.php:292
790
  msgid "Parent Project Type"
791
  msgstr ""
792
 
793
+ #: ../admin/class-portfolio.php:293
794
  msgid "Parent Project Type:"
795
  msgstr ""
796
 
797
+ #: ../admin/class-portfolio.php:294
798
  msgid "Search Project Types"
799
  msgstr ""
800
 
801
+ #: ../admin/class-portfolio.php:295
802
  msgid "Project type list navigation"
803
  msgstr ""
804
 
805
+ #: ../admin/class-portfolio.php:296
806
  msgid "Project type list"
807
  msgstr ""
808
 
809
+ #: ../admin/class-portfolio.php:310 ../admin/class-portfolio.php:312
810
  msgid "Project Tags"
811
  msgstr ""
812
 
813
+ #: ../admin/class-portfolio.php:311
814
  msgid "Project Tag"
815
  msgstr ""
816
 
817
+ #: ../admin/class-portfolio.php:313
818
  msgid "All Project Tags"
819
  msgstr ""
820
 
821
+ #: ../admin/class-portfolio.php:314
822
  msgid "Edit Project Tag"
823
  msgstr ""
824
 
825
+ #: ../admin/class-portfolio.php:315
826
  msgid "View Project Tag"
827
  msgstr ""
828
 
829
+ #: ../admin/class-portfolio.php:316
830
  msgid "Update Project Tag"
831
  msgstr ""
832
 
833
+ #: ../admin/class-portfolio.php:317
834
  msgid "Add New Project Tag"
835
  msgstr ""
836
 
837
+ #: ../admin/class-portfolio.php:318
838
  msgid "New Project Tag Name"
839
  msgstr ""
840
 
841
+ #: ../admin/class-portfolio.php:319
842
  msgid "Search Project Tags"
843
  msgstr ""
844
 
845
+ #: ../admin/class-portfolio.php:320
846
  msgid "Popular Project Tags"
847
  msgstr ""
848
 
849
+ #: ../admin/class-portfolio.php:325
850
  msgid "Project tag list navigation"
851
  msgstr ""
852
 
853
+ #: ../admin/class-portfolio.php:326
854
  msgid "Project tag list"
855
  msgstr ""
856
 
857
+ #: ../admin/class-portfolio.php:346
858
  #, php-format
859
  msgid "Project updated. <a href=\"%s\">View item</a>"
860
  msgstr ""
861
 
862
+ #: ../admin/class-portfolio.php:349
863
  msgid "Project updated."
864
  msgstr ""
865
 
866
+ #: ../admin/class-portfolio.php:351
867
  #, php-format
868
  msgid "Project restored to revision from %s"
869
  msgstr ""
870
 
871
+ #: ../admin/class-portfolio.php:352
872
  #, php-format
873
  msgid "Project published. <a href=\"%s\">View project</a>"
874
  msgstr ""
875
 
876
+ #: ../admin/class-portfolio.php:353
877
  msgid "Project saved."
878
  msgstr ""
879
 
880
+ #: ../admin/class-portfolio.php:354
881
  #, php-format
882
  msgid ""
883
  "Project submitted. <a target=\"_blank\" href=\"%s\">Preview project</a>"
884
  msgstr ""
885
 
886
+ #: ../admin/class-portfolio.php:355
887
  #, php-format
888
  msgid ""
889
  "Project scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
890
  "\"%2$s\">Preview project</a>"
891
  msgstr ""
892
 
893
+ #: ../admin/class-portfolio.php:358
894
  #, php-format
895
  msgid ""
896
  "Project item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
897
  "project</a>"
898
  msgstr ""
899
 
900
+ #: ../admin/class-portfolio.php:434
901
  msgid "Portfolio Archive Title"
902
  msgstr ""
903
 
904
+ #: ../admin/class-portfolio.php:449
905
  msgid "Portfolio Archive Content"
906
  msgstr ""
907
 
908
+ #: ../admin/class-portfolio.php:465
909
  msgid "Portfolio Archive Featured Image"
910
  msgstr ""
911
 
912
+ #: ../admin/class-portfolio.php:827
913
  msgid ""
914
  "Your Portfolio Archive currently has no entries. You can start creating "
915
  "them on your dashboard."
919
  msgid "Service Items"
920
  msgstr ""
921
 
922
+ #: ../admin/class-service.php:103 ../admin/class-service.php:284
923
+ #: ../admin/class-service.php:290 ../admin/partials/dashboard-display.php:112
924
  #: ../admin/partials/essential-content-types-admin-display.php:118
925
  #: ../admin/partials/essential-content-types-admin-display.php:297
926
  msgid "Services"
927
  msgstr ""
928
 
929
  #: ../admin/class-service.php:104 ../admin/class-service.php:105
930
+ #: ../admin/class-service.php:242
931
  msgid "Service"
932
  msgstr ""
933
 
971
  msgid "Services list"
972
  msgstr ""
973
 
974
+ #: ../admin/class-service.php:155 ../admin/class-service.php:157
975
  msgid "Service Types"
976
  msgstr ""
977
 
978
+ #: ../admin/class-service.php:156
979
  msgid "Service Type"
980
  msgstr ""
981
 
982
+ #: ../admin/class-service.php:158
983
  msgid "All Service Types"
984
  msgstr ""
985
 
986
+ #: ../admin/class-service.php:159
987
  msgid "Edit Service Type"
988
  msgstr ""
989
 
990
+ #: ../admin/class-service.php:160
991
  msgid "View Service Type"
992
  msgstr ""
993
 
994
+ #: ../admin/class-service.php:161
995
  msgid "Update Service Type"
996
  msgstr ""
997
 
998
+ #: ../admin/class-service.php:162
999
  msgid "Add New Service Type"
1000
  msgstr ""
1001
 
1002
+ #: ../admin/class-service.php:163
1003
  msgid "New Service Type Name"
1004
  msgstr ""
1005
 
1006
+ #: ../admin/class-service.php:164
1007
  msgid "Parent Service Type"
1008
  msgstr ""
1009
 
1010
+ #: ../admin/class-service.php:165
1011
  msgid "Parent Service Type:"
1012
  msgstr ""
1013
 
1014
+ #: ../admin/class-service.php:166
1015
  msgid "Search Service Types"
1016
  msgstr ""
1017
 
1018
+ #: ../admin/class-service.php:167
1019
  msgid "Service type list navigation"
1020
  msgstr ""
1021
 
1022
+ #: ../admin/class-service.php:168
1023
  msgid "Service type list"
1024
  msgstr ""
1025
 
1026
+ #: ../admin/class-service.php:182 ../admin/class-service.php:184
1027
  msgid "Service Tags"
1028
  msgstr ""
1029
 
1030
+ #: ../admin/class-service.php:183
1031
  msgid "Service Tag"
1032
  msgstr ""
1033
 
1034
+ #: ../admin/class-service.php:185
1035
  msgid "All Service Tags"
1036
  msgstr ""
1037
 
1038
+ #: ../admin/class-service.php:186
1039
  msgid "Edit Service Tag"
1040
  msgstr ""
1041
 
1042
+ #: ../admin/class-service.php:187
1043
  msgid "View Service Tag"
1044
  msgstr ""
1045
 
1046
+ #: ../admin/class-service.php:188
1047
  msgid "Update Service Tag"
1048
  msgstr ""
1049
 
1050
+ #: ../admin/class-service.php:189
1051
  msgid "Add New Service Tag"
1052
  msgstr ""
1053
 
1054
+ #: ../admin/class-service.php:190
1055
  msgid "New Service Tag Name"
1056
  msgstr ""
1057
 
1058
+ #: ../admin/class-service.php:191
1059
  msgid "Search Service Tags"
1060
  msgstr ""
1061
 
1062
+ #: ../admin/class-service.php:192
1063
  msgid "Popular Service Tags"
1064
  msgstr ""
1065
 
1066
+ #: ../admin/class-service.php:197
1067
  msgid "Service tag list navigation"
1068
  msgstr ""
1069
 
1070
+ #: ../admin/class-service.php:198
1071
  msgid "Service tag list"
1072
  msgstr ""
1073
 
1074
+ #: ../admin/class-service.php:218
1075
  #, php-format
1076
  msgid "Service updated. <a href=\"%s\">View item</a>"
1077
  msgstr ""
1078
 
1079
+ #: ../admin/class-service.php:221
1080
  msgid "Service updated."
1081
  msgstr ""
1082
 
1083
+ #: ../admin/class-service.php:223
1084
  #, php-format
1085
  msgid "Service restored to revision from %s"
1086
  msgstr ""
1087
 
1088
+ #: ../admin/class-service.php:224
1089
  #, php-format
1090
  msgid "Service published. <a href=\"%s\">View content</a>"
1091
  msgstr ""
1092
 
1093
+ #: ../admin/class-service.php:225
1094
  msgid "Service saved."
1095
  msgstr ""
1096
 
1097
+ #: ../admin/class-service.php:226
1098
  #, php-format
1099
  msgid ""
1100
  "Service submitted. <a target=\"_blank\" href=\"%s\">Preview content</a>"
1101
  msgstr ""
1102
 
1103
+ #: ../admin/class-service.php:227
1104
  #, php-format
1105
  msgid ""
1106
  "Service scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
1107
  "\"%2$s\">Preview service</a>"
1108
  msgstr ""
1109
 
1110
+ #: ../admin/class-service.php:230
1111
  #, php-format
1112
  msgid ""
1113
  "Service item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
1114
  "content</a>"
1115
  msgstr ""
1116
 
1117
+ #: ../admin/class-service.php:298
1118
  msgid "Service Archive Title"
1119
  msgstr ""
1120
 
1121
+ #: ../admin/class-service.php:311
1122
  msgid "Service Archive Content"
1123
  msgstr ""
1124
 
1125
+ #: ../admin/class-service.php:325
1126
  msgid "Service Archive Featured Image"
1127
  msgstr ""
1128
 
1129
+ #: ../admin/class-service.php:681
1130
  msgid ""
1131
  "Your Service Archive currently has no entries. You can start creating them "
1132
  "on your dashboard."
1133
  msgstr ""
1134
 
1135
+ #: ../admin/class-testimonial.php:118 ../admin/class-testimonial.php:269
1136
+ #: ../admin/class-testimonial.php:271 ../admin/class-testimonial.php:461
1137
+ #: ../admin/class-testimonial.php:471
1138
  #: ../admin/partials/dashboard-display.php:57
1139
  #: ../admin/partials/essential-content-types-admin-display.php:108
1140
  msgid "Testimonials"
1148
  msgid "Enable Testimonials for this site."
1149
  msgstr ""
1150
 
1151
+ #: ../admin/class-testimonial.php:164
1152
  #, php-format
1153
  msgid "Testimonial pages display at most %1$s testimonials"
1154
  msgstr ""
1155
 
1156
+ #: ../admin/class-testimonial.php:267
1157
  msgid "Customer Testimonials"
1158
  msgstr ""
1159
 
1160
+ #: ../admin/class-testimonial.php:270
1161
  #: ../admin/partials/essential-content-types-admin-display.php:305
1162
  msgid "Testimonial"
1163
  msgstr ""
1164
 
1165
+ #: ../admin/class-testimonial.php:272
1166
  msgid "All Testimonials"
1167
  msgstr ""
1168
 
1169
+ #: ../admin/class-testimonial.php:274
1170
  msgid "Add New Testimonial"
1171
  msgstr ""
1172
 
1173
+ #: ../admin/class-testimonial.php:275
1174
  msgid "Edit Testimonial"
1175
  msgstr ""
1176
 
1177
+ #: ../admin/class-testimonial.php:276
1178
  msgid "New Testimonial"
1179
  msgstr ""
1180
 
1181
+ #: ../admin/class-testimonial.php:277
1182
  msgid "View Testimonial"
1183
  msgstr ""
1184
 
1185
+ #: ../admin/class-testimonial.php:278
1186
  msgid "Search Testimonials"
1187
  msgstr ""
1188
 
1189
+ #: ../admin/class-testimonial.php:279
1190
  msgid "No Testimonials found"
1191
  msgstr ""
1192
 
1193
+ #: ../admin/class-testimonial.php:280
1194
  msgid "No Testimonials found in Trash"
1195
  msgstr ""
1196
 
1197
+ #: ../admin/class-testimonial.php:281
1198
  msgid "Filter Testimonials list"
1199
  msgstr ""
1200
 
1201
+ #: ../admin/class-testimonial.php:282
1202
  msgid "Testimonial list navigation"
1203
  msgstr ""
1204
 
1205
+ #: ../admin/class-testimonial.php:283
1206
  msgid "Testimonials list"
1207
  msgstr ""
1208
 
1209
+ #: ../admin/class-testimonial.php:326
1210
  #, php-format
1211
  msgid "Testimonial updated. <a href=\"%s\">View testimonial</a>"
1212
  msgstr ""
1213
 
1214
+ #: ../admin/class-testimonial.php:329
1215
  msgid "Testimonial updated."
1216
  msgstr ""
1217
 
1218
+ #: ../admin/class-testimonial.php:331
1219
  #, php-format
1220
  msgid "Testimonial restored to revision from %s"
1221
  msgstr ""
1222
 
1223
+ #: ../admin/class-testimonial.php:332
1224
  #, php-format
1225
  msgid "Testimonial published. <a href=\"%s\">View testimonial</a>"
1226
  msgstr ""
1227
 
1228
+ #: ../admin/class-testimonial.php:333
1229
  msgid "Testimonial saved."
1230
  msgstr ""
1231
 
1232
+ #: ../admin/class-testimonial.php:334
1233
  #, php-format
1234
  msgid ""
1235
  "Testimonial submitted. <a target=\"_blank\" href=\"%s\">Preview "
1236
  "testimonial</a>"
1237
  msgstr ""
1238
 
1239
+ #: ../admin/class-testimonial.php:336
1240
  #, php-format
1241
  msgid ""
1242
  "Testimonial scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
1243
  "\"%2$s\">Preview testimonial</a>"
1244
  msgstr ""
1245
 
1246
+ #: ../admin/class-testimonial.php:341
1247
  #, php-format
1248
  msgid ""
1249
  "Testimonial draft updated. <a target=\"_blank\" href=\"%s\">Preview "
1250
  "testimonial</a>"
1251
  msgstr ""
1252
 
1253
+ #: ../admin/class-testimonial.php:354
1254
  msgid "Enter the customer's name here"
1255
  msgstr ""
1256
 
1257
+ #: ../admin/class-testimonial.php:364
1258
  msgid "Customer Name"
1259
  msgstr ""
1260
 
1261
+ #: ../admin/class-testimonial.php:431
1262
  msgid "Customize Testimonials Archive"
1263
  msgstr ""
1264
 
1265
+ #: ../admin/class-testimonial.php:432
1266
  msgid "Customize"
1267
  msgstr ""
1268
 
1269
+ #: ../admin/class-testimonial.php:481
1270
  msgid "Testimonial Archive Title"
1271
  msgstr ""
1272
 
1273
+ #: ../admin/class-testimonial.php:501
1274
  msgid "Testimonial Archive Content"
1275
  msgstr ""
1276
 
1277
+ #: ../admin/class-testimonial.php:523
1278
  msgid "Testimonial Archive Featured Image"
1279
  msgstr ""
1280
 
1281
+ #: ../admin/class-testimonial.php:808
1282
  msgid "Position"
1283
  msgstr ""
1284
 
1285
+ #: ../admin/class-testimonial.php:842
1286
  msgid "Testmonial Options"
1287
  msgstr ""
1288
 
1289
+ #: ../admin/class-testimonial.php:878
1290
  msgid ""
1291
  "Your Testimonial Archive currently has no entries. You can start creating "
1292
  "them on your dashboard."
1293
  msgstr ""
1294
 
1295
+ #: ../admin/class-testimonial.php:928
1296
  msgid "Previous Slide"
1297
  msgstr ""
1298
 
1299
+ #: ../admin/class-testimonial.php:935
1300
  msgid "Next Slide"
1301
  msgstr ""
1302
 
1303
+ #: ../admin/class-testimonial.php:998
1304
  msgid "Please define default parameters in the form of an array."
1305
  msgstr ""
1306
 
1307
+ #: ../admin/class-testimonial.php:1003
1308
  msgid "Please define an SVG icon filename."
1309
  msgstr ""
1310