Essential Content Types - Version 1.0.0

Version Description

Download this release

Release Info

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

Version 1.0.0

README.txt ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Plugin Name ===
2
+ Contributors: catchthemes
3
+ Donate link: https://catchthemes.com/donate/
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
5
+ Requires at least: 4.5
6
+ Tested up to: 4.7.2
7
+ Stable tag: trunk
8
+ License: GPLv3 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
+
11
+ Essential Content Types allows you to feature the impressive content through different content/post types on your website just the way you want it. These content/post types are missed by the themes in WordPress Theme Directory as the feature falls more towards the plugins’ territory.
12
+
13
+ == Description ==
14
+
15
+ **Essential Content Types** allows you to feature the impressive content through different content/post types on your website just the way you want it. These content/post types are missed by the themes in WordPress Theme Directory as the feature falls more towards the plugins' territory.
16
+
17
+ Content is at the forefront of any website. Changing the layout of your important content changes the way your website looks, which may not be a plus point if your current website layout is loved by your users.
18
+
19
+ Additionally, switching themes changes your website layout completely. Therefore, to keep things looking spic-and- span in your website, we bring you Essential Content.
20
+
21
+ Essential Content allows you to add up to three content/post types:
22
+ * Portfolio – Create and display your portfolio on your website’s Frontpage
23
+ * Testimonials – Add customer testimonials to your website’s Frontpage
24
+ * Featured Content – Display the content you want as featured content on the Frontpage to attract visitors' attention
25
+
26
+ Features of Essential Content:
27
+ * Enable/Disable any content/post type as needed
28
+ * Light-weight
29
+ * Supports all themes on WordPress
30
+
31
+ Essential Content is inspired by *Jetpack's Custom Content Types feature*.
32
+
33
+ However, not everyone wants to have a plugin that “does-it- all”. Some may want plugins to be niche focused and concentrate on smaller areas.
34
+
35
+ That is precisely what we have done with Essential Content. Essential content, true to its name, has only the essential elements. We have added the features that WordPressers use most. We have ruled out all other elements to make it non-bloated and clean. It takes up lesser space and does the job well.
36
+
37
+ If you think we have missed any essential content/post types, please let us know. We’ll review the frequency of usage and add your suggestions.
38
+
39
+ ***Portfolio Shortcode***
40
+
41
+ You can use shortcodes to embed portfolio projects on posts and pages.
42
+
43
+ **Embedding Portfolio Projects**
44
+
45
+ To embed portfolio projects on posts and pages, first activate the Portfolio custom content type on your site and add some projects to your portfolio.
46
+
47
+ Next, add the [portfolio] shortcode to a post or page. The shortcode will display projects in different ways, depending on how you use the optional attributes to customize the portfolio layout.
48
+
49
+ **Attributes**
50
+ * display_types: display Project Types. (true/false)
51
+ * display_tags: display Project Tags. (true/false)
52
+ * display_content: display project content. (true/false)
53
+ * include_type: display specific Project Types. Defaults to all. (comma-separated list of Project Type slugs)
54
+ * include_tag: display specific Project Tags. Defaults to all. (comma-separated list of Project Tag slugs)
55
+ * columns: number of columns in shortcode. Defaults to 2. (number, 1-6)
56
+ * showposts: number of projects to display. Defaults to all. (number)
57
+ * order: display projects in ascending or descending order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display projects in descending order instead. (ASC/DESC)
58
+ * orderby: sort projects by different criteria, including author name, project title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
59
+
60
+ **Example**
61
+ [portfolio display_types=true display_tags=false include_type=grooming-tips,best-kitties columns=2 showposts=10 orderby=title]
62
+ The example will display up to ten portfolio projects in two columns, in ascending alphabetical order by project title. It will display Project Types, hide Project Tags, and only display projects that are assigned the “Grooming Tips” or “Best Kitties” Project Types.
63
+
64
+
65
+ ***Featured Content Shortcode***
66
+
67
+ You can use shortcodes to embed featured content on posts and pages.
68
+
69
+ **Embedding Featured Content Projects**
70
+
71
+ To embed featured content on posts and pages, first activate the Featured Content content type on your site and add some projects to your featured content.
72
+
73
+ Next, add the [featured_content] shortcode to a post or page. The shortcode will display projects in different ways, depending on how you use the optional attributes to customize the featured content layout.
74
+
75
+ **Attributes**
76
+ * display_types: display Content Types. (true/false)
77
+ * display_tags: display Content Tags. (true/false)
78
+ * display_content: display project content. (true/false)
79
+ * include_type: display specific Content Types. Defaults to all. (comma-separated list of Content Type slugs)
80
+ * include_tag: display specific Content Tags. Defaults to all. (comma-separated list of Content Tag slugs)
81
+ * columns: number of columns in shortcode. Defaults to 2. (number, 1-6)
82
+ * showposts: number of projects to display. Defaults to all. (number)
83
+ * order: display projects in ascending or descending order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display projects in descending order instead. (ASC/DESC)
84
+ * orderby: sort projects by different criteria, including author name, project title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
85
+
86
+ **Example**
87
+ [featured_content display_types=true display_tags=false include_type=grooming-tips,best-kitties columns=2 showposts=10 orderby=title]
88
+ The example will display up to ten featured content in two columns, in ascending alphabetical order by project title. It will display Content Types, hide Content Tags, and only display projects that are assigned the “Grooming Tips” or “Best Kitties” Content Types.
89
+
90
+ ***Testimonials Shortcode***
91
+
92
+ You can use shortcodes to embed testimonials on posts and pages.
93
+ Embedding Testimonials
94
+
95
+ To embed testimonials on posts and pages, first activate the Testimonial custom content type on your site and add some testimonials.
96
+
97
+ Next, add the [testimonials] shortcode to a post or page. The shortcode will display testimonials in different ways, depending on how you use the optional attributes to customize the testimonials layout.
98
+
99
+ **Attributes**
100
+ * display_content: display testimonial content. (full/true/false)
101
+ * image: display the featured image. (true/false) Defaults to true.
102
+ * columns: number of columns in shortcode. Defaults to 1. (number, 1-6)
103
+ * showposts: number of testimonials to display. Defaults to all. (number)
104
+ * order: display testimonials in ascending or descending chronological order. Defaults to ASC for sorting in ascending order, but you can reverse the order by using DESC to display testimonials in descending order instead. (ASC/DESC)
105
+ * orderby: sort testimonials by different criteria, including author name, testimonial title, and even rand to display in a random order. Defaults to sorting by date. (author, date, title, rand)
106
+
107
+ **Example**
108
+
109
+ [testimonials columns=2 showposts=10 orderby=title]
110
+ The example will display up to ten testimonials in two columns, in ascending alphabetical order by testimonial title.
111
+
112
+ == Installation ==
113
+
114
+ 1. Upload `essential-content-types.zip` folder to the `/wp-content/plugins/` directory
115
+ 2. Activate the plugin through the 'Plugins' menu in WordPress
116
+ 3. Use Shortcodes in your posts/pages/templates
117
+
118
+ == Screenshots ==
119
+
120
+ 1. Main Dashboard
121
+ 2. Customizer: Portfolio Archive Options
122
+ 3. Customizer: Testimonial Archive Options
123
+ 4. Customizer: Featured Content Archive Options
124
+
125
+ == Changelog ==
126
+
127
+ = 1.0.0 =
128
+ * Initial Release
admin/class-essential-content-types-admin.php ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The admin-specific functionality of the plugin.
5
+ *
6
+ * @link https://catchthemes.com
7
+ * @since 1.0.0
8
+ *
9
+ * @package Essential_Content_Types
10
+ * @subpackage Essential_Content_Types/admin
11
+ */
12
+
13
+ /**
14
+ * The admin-specific functionality of the plugin.
15
+ *
16
+ * Defines the plugin name, version, and two examples hooks for how to
17
+ * enqueue the admin-specific stylesheet and JavaScript.
18
+ *
19
+ * @package Essential_Content_Types
20
+ * @subpackage Essential_Content_Types/admin
21
+ * @author Catch Themes <info@catchthemes.com>
22
+ */
23
+ class Essential_Content_Types_Admin {
24
+
25
+ /**
26
+ * The ID of this plugin.
27
+ *
28
+ * @since 1.0.0
29
+ * @access private
30
+ * @var string $plugin_name The ID of this plugin.
31
+ */
32
+ private $plugin_name;
33
+
34
+ /**
35
+ * The version of this plugin.
36
+ *
37
+ * @since 1.0.0
38
+ * @access private
39
+ * @var string $version The current version of this plugin.
40
+ */
41
+ private $version;
42
+
43
+ /**
44
+ * Initialize the class and set its properties.
45
+ *
46
+ * @since 1.0.0
47
+ * @param string $plugin_name The name of this plugin.
48
+ * @param string $version The version of this plugin.
49
+ */
50
+ public function __construct( $plugin_name, $version ) {
51
+
52
+ $this->plugin_name = $plugin_name;
53
+ $this->version = $version;
54
+
55
+ $this->load_dependencies();
56
+
57
+ }
58
+
59
+ /**
60
+ * Load the required dependencies for this plugin.
61
+ *
62
+ * Include the following files that make up the plugin:
63
+ *
64
+ * - Essential_Content_Types_Loader. Orchestrates the hooks of the plugin.
65
+ * - Essential_Content_Types_i18n. Defines internationalization functionality.
66
+ * - Essential_Content_Types_Admin. Defines all hooks for the admin area.
67
+ * - Essential_Content_Types_Public. Defines all hooks for the public side of the site.
68
+ *
69
+ * Create an instance of the loader which will be used to register the hooks
70
+ * with WordPress.
71
+ *
72
+ * @since 1.0.0
73
+ * @access private
74
+ */
75
+ private function load_dependencies() {
76
+
77
+ $portfolio_options = get_option( 'ect_portfolio' );
78
+ if ( $portfolio_options['status'] ) {
79
+ /**
80
+ * Load Portfolio Content Type
81
+ */
82
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-portfolio.php';
83
+ }
84
+
85
+ $testimonial_options = get_option( 'ect_testimonial' );
86
+ if ( $testimonial_options['status'] ) {
87
+ /**
88
+ * Load Testimonial Content Type
89
+ */
90
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-testimonial.php';
91
+ }
92
+
93
+ $featured_content_options = get_option( 'ect_featured_content' );
94
+ if ( $featured_content_options['status'] ) {
95
+ /**
96
+ * Load Featured Content Type
97
+ */
98
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-featured-content.php';
99
+ }
100
+
101
+ }
102
+
103
+
104
+ /**
105
+ * Register the stylesheets for the admin area.
106
+ *
107
+ * @since 1.0.0
108
+ */
109
+ public function enqueue_styles( $hook_suffix ) {
110
+ $allowed_pages = array(
111
+ 'toplevel_page_essential-content-types' => 1,
112
+ 'essential-content-types_page_ect-portfolio' => 1,
113
+ 'essential-content-types_page_ect-testimonial' => 1,
114
+ 'essential-content-types_page_ect-featured-content' => 1,
115
+ );
116
+
117
+ if ( ! isset( $allowed_pages[ $hook_suffix ] ) ){
118
+ return;
119
+ }
120
+
121
+ wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/essential-content-types-admin.css', array(), $this->version, 'all' );
122
+
123
+ }
124
+
125
+ /**
126
+ * Register the JavaScript for the admin area.
127
+ *
128
+ * @since 1.0.0
129
+ */
130
+ public function enqueue_scripts( $hook_suffix ) {
131
+ $allowed_pages = array(
132
+ 'toplevel_page_essential-content-types' => 1,
133
+ 'essential-content-types_page_ect-portfolio' => 1,
134
+ 'essential-content-types_page_ect-testimonial' => 1,
135
+ 'essential-content-types_page_ect-featured-content' => 1,
136
+ );
137
+
138
+ if ( ! isset( $allowed_pages[ $hook_suffix ] ) ){
139
+ return;
140
+ }
141
+
142
+ wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/essential-content-types-admin.js', array( 'jquery' ), $this->version, false );
143
+
144
+ }
145
+
146
+ /**
147
+ * Add settings menu
148
+ */
149
+ function settings_menu() {
150
+ // Add Main Menu
151
+ add_menu_page(
152
+ esc_html__( 'Essential Content Types', 'essential-content-types' ), //$page_title
153
+ esc_html__( 'Essential Content Types', 'essential-content-types' ), //$menu_title
154
+ 'manage_options', //$capability
155
+ 'essential-content-types', //$menu_slug
156
+ array( $this, 'main_settings_display' ), //$function
157
+ 'dashicons-layout', //$icon_url
158
+ '99.01564' //$position
159
+ );
160
+ }
161
+
162
+ /**
163
+ * Dashboard Page include
164
+ */
165
+ function main_settings_display() {
166
+ if ( !current_user_can( 'manage_options' ) ) {
167
+ wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
168
+ }
169
+
170
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/dashboard-display.php';
171
+ }
172
+
173
+ function dashboard_switch() {
174
+ $value = ( 'true' == $_POST['value'] ) ? 1 : 0;
175
+
176
+ $option_name = $_POST['option_name'];
177
+
178
+ $option_value = get_option( $option_name );
179
+
180
+ $option_value['status'] = $value;
181
+
182
+ if( update_option( $option_name, $option_value ) ) {
183
+ echo $value;
184
+ } else {
185
+ esc_html_e( 'Connection Error. Please try again.', 'essential-content-types' );
186
+ }
187
+
188
+ wp_die(); // this is required to terminate immediately and return a proper response
189
+ }
190
+
191
+ }
admin/class-featured-content.php ADDED
@@ -0,0 +1,865 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 = '0.1';
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
+ // 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_featured_content_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 Featured Content 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 Featured Content 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( 'featured-content-admin-thumb', 50, 50, true );
73
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
74
+
75
+ // register featured_content shortcode and featured_content shortcode (legacy)
76
+ add_shortcode( 'featured_content', array( $this, 'featured_content_shortcode' ) );
77
+ add_shortcode( 'ect_featured_content', array( $this, 'featured_content_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">' . __( 'Featured Contents', '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 Featured Content 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 "featured-content" */ __( '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 Featured Contents for this site.', 'essential-content-types' ); ?>
131
+ <a target="_blank" href="http://en.support.wordpress.com/featured_contents/"><?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( __( 'Featured Content 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( 'featured-content-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( 'featured-content-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
+ $featured_contents = 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( $featured_contents ) ) {
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' => __( 'Featured Content Items', 'essential-content-types' ),
229
+ 'labels' => array(
230
+ 'name' => esc_html__( 'Featured Contents', 'essential-content-types' ),
231
+ 'singular_name' => esc_html__( 'Featured Content', 'essential-content-types' ),
232
+ 'menu_name' => esc_html__( 'Featured Content', 'essential-content-types' ),
233
+ 'all_items' => esc_html__( 'All Contents', 'essential-content-types' ),
234
+ 'add_new' => esc_html__( 'Add New', 'essential-content-types' ),
235
+ 'add_new_item' => esc_html__( 'Add New Content', 'essential-content-types' ),
236
+ 'edit_item' => esc_html__( 'Edit Content', 'essential-content-types' ),
237
+ 'new_item' => esc_html__( 'New Content', 'essential-content-types' ),
238
+ 'view_item' => esc_html__( 'View Content', 'essential-content-types' ),
239
+ 'search_items' => esc_html__( 'Search Contents', 'essential-content-types' ),
240
+ 'not_found' => esc_html__( 'No Contents found', 'essential-content-types' ),
241
+ 'not_found_in_trash' => esc_html__( 'No Contents found in Trash', 'essential-content-types' ),
242
+ 'filter_items_list' => esc_html__( 'Filter projects list', 'essential-content-types' ),
243
+ 'items_list_navigation' => esc_html__( 'Content list navigation', 'essential-content-types' ),
244
+ 'items_list' => esc_html__( 'Contents list', 'essential-content-types' ),
245
+ ),
246
+ 'supports' => array(
247
+ 'title',
248
+ 'editor',
249
+ 'thumbnail',
250
+ 'author',
251
+ 'comments',
252
+ ),
253
+ 'rewrite' => array(
254
+ 'slug' => 'featured-content',
255
+ 'with_front' => false,
256
+ 'feeds' => true,
257
+ 'pages' => true,
258
+ ),
259
+ 'public' => true,
260
+ 'show_ui' => true,
261
+ 'menu_position' => 20, // below Pages
262
+ 'menu_icon' => 'dashicons-grid-view', // 3.8+ dashicon option
263
+ 'capability_type' => 'page',
264
+ 'map_meta_cap' => true,
265
+ 'taxonomies' => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
266
+ 'has_archive' => true,
267
+ 'query_var' => 'featured_content',
268
+ 'show_in_rest' => true,
269
+ ) );
270
+
271
+ register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
272
+ 'hierarchical' => true,
273
+ 'labels' => array(
274
+ 'name' => esc_html__( 'Content Types', 'essential-content-types' ),
275
+ 'singular_name' => esc_html__( 'Content Type', 'essential-content-types' ),
276
+ 'menu_name' => esc_html__( 'Content Types', 'essential-content-types' ),
277
+ 'all_items' => esc_html__( 'All Content Types', 'essential-content-types' ),
278
+ 'edit_item' => esc_html__( 'Edit Content Type', 'essential-content-types' ),
279
+ 'view_item' => esc_html__( 'View Content Type', 'essential-content-types' ),
280
+ 'update_item' => esc_html__( 'Update Content Type', 'essential-content-types' ),
281
+ 'add_new_item' => esc_html__( 'Add New Content Type', 'essential-content-types' ),
282
+ 'new_item_name' => esc_html__( 'New Content Type Name', 'essential-content-types' ),
283
+ 'parent_item' => esc_html__( 'Parent Content Type', 'essential-content-types' ),
284
+ 'parent_item_colon' => esc_html__( 'Parent Content Type:', 'essential-content-types' ),
285
+ 'search_items' => esc_html__( 'Search Content Types', 'essential-content-types' ),
286
+ 'items_list_navigation' => esc_html__( 'Content type list navigation', 'essential-content-types' ),
287
+ 'items_list' => esc_html__( 'Content type list', 'essential-content-types' ),
288
+ ),
289
+ 'public' => true,
290
+ 'show_ui' => true,
291
+ 'show_in_nav_menus' => true,
292
+ 'show_in_rest' => true,
293
+ 'show_admin_column' => true,
294
+ 'query_var' => true,
295
+ 'rewrite' => array( 'slug' => 'project-type' ),
296
+ ) );
297
+
298
+ register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
299
+ 'hierarchical' => false,
300
+ 'labels' => array(
301
+ 'name' => esc_html__( 'Content Tags', 'essential-content-types' ),
302
+ 'singular_name' => esc_html__( 'Content Tag', 'essential-content-types' ),
303
+ 'menu_name' => esc_html__( 'Content Tags', 'essential-content-types' ),
304
+ 'all_items' => esc_html__( 'All Content Tags', 'essential-content-types' ),
305
+ 'edit_item' => esc_html__( 'Edit Content Tag', 'essential-content-types' ),
306
+ 'view_item' => esc_html__( 'View Content Tag', 'essential-content-types' ),
307
+ 'update_item' => esc_html__( 'Update Content Tag', 'essential-content-types' ),
308
+ 'add_new_item' => esc_html__( 'Add New Content Tag', 'essential-content-types' ),
309
+ 'new_item_name' => esc_html__( 'New Content Tag Name', 'essential-content-types' ),
310
+ 'search_items' => esc_html__( 'Search Content Tags', 'essential-content-types' ),
311
+ 'popular_items' => esc_html__( 'Popular Content Tags', 'essential-content-types' ),
312
+ 'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
313
+ 'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
314
+ 'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
315
+ 'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
316
+ 'items_list_navigation' => esc_html__( 'Content tag list navigation', 'essential-content-types' ),
317
+ 'items_list' => esc_html__( 'Content tag list', 'essential-content-types' ),
318
+ ),
319
+ 'public' => true,
320
+ 'show_ui' => true,
321
+ 'show_in_nav_menus' => true,
322
+ 'show_in_rest' => true,
323
+ 'show_admin_column' => true,
324
+ 'query_var' => true,
325
+ 'rewrite' => array( 'slug' => 'project-tag' ),
326
+ ) );
327
+ }
328
+
329
+ /**
330
+ * Update messages for the Featured Content admin.
331
+ */
332
+ function updated_messages( $messages ) {
333
+ global $post;
334
+
335
+ $messages[self::CUSTOM_POST_TYPE] = array(
336
+ 0 => '', // Unused. Messages start at index 1.
337
+ 1 => sprintf( __( 'Content updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
338
+ 2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
339
+ 3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
340
+ 4 => esc_html__( 'Content updated.', 'essential-content-types' ),
341
+ /* translators: %s: date and time of the revision */
342
+ 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,
343
+ 6 => sprintf( __( 'Content published. <a href="%s">View project</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
344
+ 7 => esc_html__( 'Content saved.', 'essential-content-types' ),
345
+ 8 => sprintf( __( 'Content submitted. <a target="_blank" href="%s">Preview project</a>', 'essential-content-types'), esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) ),
346
+ 9 => sprintf( __( 'Content scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview project</a>', 'essential-content-types' ),
347
+ // translators: Publish box date format, see http://php.net/date
348
+ date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
349
+ 10 => sprintf( __( 'Content 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 ) ) ) ),
350
+ );
351
+
352
+ return $messages;
353
+ }
354
+
355
+ /**
356
+ * Change ‘Title’ column label
357
+ * Add Featured Image column
358
+ */
359
+ function edit_admin_columns( $columns ) {
360
+ // change 'Title' to 'Content'
361
+ $columns['title'] = __( 'Content', 'essential-content-types' );
362
+ if ( current_theme_supports( 'post-thumbnails' ) ) {
363
+ // add featured image before 'Content'
364
+ $columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
365
+ }
366
+
367
+ return $columns;
368
+ }
369
+
370
+ /**
371
+ * Add featured image to column
372
+ */
373
+ function image_column( $column, $post_id ) {
374
+ global $post;
375
+ switch ( $column ) {
376
+ case 'thumbnail':
377
+ echo get_the_post_thumbnail( $post_id, 'featured-content-admin-thumb' );
378
+ break;
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Adjust image column width
384
+ */
385
+ function enqueue_admin_styles( $hook ) {
386
+ $screen = get_current_screen();
387
+
388
+ if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
389
+ 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; } }' );
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Adds featured_content section to the Customizer.
395
+ */
396
+ function customize_register( $wp_customize ) {
397
+ $options = get_theme_support( self::CUSTOM_POST_TYPE );
398
+
399
+ 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'] ) ) {
400
+ return;
401
+ }
402
+
403
+ $wp_customize->add_section( 'featured_content', array(
404
+ 'title' => esc_html__( 'Featured Content', 'essential-content-types' ),
405
+ 'theme_supports' => self::CUSTOM_POST_TYPE,
406
+ 'priority' => 130,
407
+ ) );
408
+
409
+ if ( isset( $options[0]['title'] ) && true === $options[0]['title'] ) {
410
+ $wp_customize->add_setting( 'featured_content_title', array(
411
+ 'default' => esc_html__( 'Contents', 'essential-content-types' ),
412
+ 'type' => 'option',
413
+ 'sanitize_callback' => 'sanitize_text_field',
414
+ 'sanitize_js_callback' => 'sanitize_text_field',
415
+ ) );
416
+
417
+ $wp_customize->add_control( 'featured_content_title', array(
418
+ 'section' => 'featured_content',
419
+ 'label' => esc_html__( 'Featured Content Archive Title', 'essential-content-types' ),
420
+ 'type' => 'text',
421
+ ) );
422
+ }
423
+
424
+ if ( isset( $options[0]['content'] ) && true === $options[0]['content'] ) {
425
+ $wp_customize->add_setting( 'featured_content_content', array(
426
+ 'default' => '',
427
+ 'type' => 'option',
428
+ 'sanitize_callback' => 'wp_kses_post',
429
+ 'sanitize_js_callback' => 'wp_kses_post',
430
+ ) );
431
+
432
+ $wp_customize->add_control( 'featured_content_content', array(
433
+ 'section' => 'featured_content',
434
+ 'label' => esc_html__( 'Featured Content Archive Content', 'essential-content-types' ),
435
+ 'type' => 'textarea',
436
+ ) );
437
+ }
438
+
439
+ if ( isset( $options[0]['featured-image'] ) && true === $options[0]['featured-image'] ) {
440
+ $wp_customize->add_setting( 'featured_content_featured_image', array(
441
+ 'default' => '',
442
+ 'type' => 'option',
443
+ 'sanitize_callback' => 'attachment_url_to_postid',
444
+ 'sanitize_js_callback' => 'attachment_url_to_postid',
445
+ 'theme_supports' => 'post-thumbnails',
446
+ ) );
447
+
448
+ $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'featured_content_featured_image', array(
449
+ 'section' => 'featured_content',
450
+ 'label' => esc_html__( 'Featured Content Archive Featured Image', 'essential-content-types' ),
451
+ ) ) );
452
+ }
453
+ }
454
+
455
+ /**
456
+ * Follow CPT reading setting on CPT archive and taxonomy pages
457
+ */
458
+ function query_reading_setting( $query ) {
459
+ if ( ! is_admin() &&
460
+ $query->is_main_query() &&
461
+ ( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
462
+ ) {
463
+ $query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, '10' ) );
464
+ }
465
+ }
466
+
467
+ /**
468
+ * Add to REST API post type whitelist
469
+ */
470
+ function allow_featured_content_rest_api_type( $post_types ) {
471
+ $post_types[] = self::CUSTOM_POST_TYPE;
472
+
473
+ return $post_types;
474
+ }
475
+
476
+ /**
477
+ * Our [featured_content] shortcode.
478
+ * Prints Featured Content data styled to look good on *any* theme.
479
+ *
480
+ * @return featured_content_shortcode_html
481
+ */
482
+ static function featured_content_shortcode( $atts ) {
483
+ // Default attributes
484
+ $atts = shortcode_atts( array(
485
+ 'image' => true,
486
+ 'display_types' => true,
487
+ 'display_tags' => true,
488
+ 'display_content' => true,
489
+ 'display_author' => false,
490
+ 'show_filter' => false,
491
+ 'include_type' => false,
492
+ 'include_tag' => false,
493
+ 'columns' => 2,
494
+ 'showposts' => -1,
495
+ 'order' => 'asc',
496
+ 'orderby' => 'date',
497
+ ), $atts, 'featured_content' );
498
+
499
+ // A little sanitization
500
+ if ( $atts['image'] && 'true' != $atts['image'] ) {
501
+ $atts['image'] = false;
502
+ }
503
+
504
+ if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
505
+ $atts['display_types'] = false;
506
+ }
507
+
508
+ if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
509
+ $atts['display_tags'] = false;
510
+ }
511
+
512
+ if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
513
+ $atts['display_author'] = false;
514
+ }
515
+
516
+ if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
517
+ $atts['display_content'] = false;
518
+ }
519
+
520
+ if ( $atts['include_type'] ) {
521
+ $atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
522
+ }
523
+
524
+ if ( $atts['include_tag'] ) {
525
+ $atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
526
+ }
527
+
528
+ $atts['columns'] = absint( $atts['columns'] );
529
+
530
+ $atts['showposts'] = intval( $atts['showposts'] );
531
+
532
+
533
+ if ( $atts['order'] ) {
534
+ $atts['order'] = urldecode( $atts['order'] );
535
+ $atts['order'] = strtoupper( $atts['order'] );
536
+ if ( 'DESC' != $atts['order'] ) {
537
+ $atts['order'] = 'ASC';
538
+ }
539
+ }
540
+
541
+ if ( $atts['orderby'] ) {
542
+ $atts['orderby'] = urldecode( $atts['orderby'] );
543
+ $atts['orderby'] = strtolower( $atts['orderby'] );
544
+ $allowed_keys = array( 'author', 'date', 'title', 'rand' );
545
+
546
+ $parsed = array();
547
+ foreach ( explode( ',', $atts['orderby'] ) as $featured_content_index_number => $orderby ) {
548
+ if ( ! in_array( $orderby, $allowed_keys ) ) {
549
+ continue;
550
+ }
551
+ $parsed[] = $orderby;
552
+ }
553
+
554
+ if ( empty( $parsed ) ) {
555
+ unset( $atts['orderby'] );
556
+ } else {
557
+ $atts['orderby'] = implode( ' ', $parsed );
558
+ }
559
+ }
560
+
561
+ // enqueue shortcode styles when shortcode is used
562
+ wp_enqueue_style( 'featured-content-style', plugins_url( 'css/featured-content-shortcode.css', __FILE__ ), array(), '20140326' );
563
+
564
+ return self::featured_content_shortcode_html( $atts );
565
+ }
566
+
567
+ /**
568
+ * Query to retrieve entries from the Featured Content post_type.
569
+ *
570
+ * @return object
571
+ */
572
+ static function featured_content_query( $atts ) {
573
+ // Default query arguments
574
+ $default = array(
575
+ 'order' => $atts['order'],
576
+ 'orderby' => $atts['orderby'],
577
+ 'posts_per_page' => $atts['showposts'],
578
+ );
579
+
580
+ $args = wp_parse_args( $atts, $default );
581
+ $args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
582
+
583
+ if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
584
+ $args['tax_query'] = array();
585
+ }
586
+
587
+ // If 'include_type' has been set use it on the main query
588
+ if ( false != $atts['include_type'] ) {
589
+ array_push( $args['tax_query'], array(
590
+ 'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
591
+ 'field' => 'slug',
592
+ 'terms' => $atts['include_type'],
593
+ ) );
594
+ }
595
+
596
+ // If 'include_tag' has been set use it on the main query
597
+ if ( false != $atts['include_tag'] ) {
598
+ array_push( $args['tax_query'], array(
599
+ 'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
600
+ 'field' => 'slug',
601
+ 'terms' => $atts['include_tag'],
602
+ ) );
603
+ }
604
+
605
+ if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
606
+ $args['tax_query']['relation'] = 'AND';
607
+ }
608
+
609
+ // Run the query and return
610
+ $query = new WP_Query( $args );
611
+ return $query;
612
+ }
613
+
614
+ /**
615
+ * The Featured Content shortcode loop.
616
+ *
617
+ * @todo add theme color styles
618
+ * @return html
619
+ */
620
+ static function featured_content_shortcode_html( $atts ) {
621
+
622
+ $query = self::featured_content_query( $atts );
623
+ $featured_content_index_number = 0;
624
+
625
+ ob_start();
626
+
627
+ // If we have posts, create the html
628
+ // with hfeatured_content markup
629
+ if ( $query->have_posts() ) {
630
+
631
+ // Render styles
632
+ //self::themecolor_styles();
633
+
634
+ ?>
635
+ <div class="featured-content-shortcode column-<?php echo esc_attr( $atts['columns'] ); ?>">
636
+ <?php // open .featured-content
637
+
638
+ // Construct the loop...
639
+ while ( $query->have_posts() ) {
640
+ $query->the_post();
641
+ $post_id = get_the_ID();
642
+ ?>
643
+ <div class="featured-content-entry <?php echo esc_attr( self::get_project_class( $featured_content_index_number, $atts['columns'] ) ); ?>">
644
+ <header class="featured-content-entry-header">
645
+ <?php
646
+ // Featured image
647
+ if ( false != $atts['image'] ) {
648
+ echo self::get_featured_content_thumbnail_link( $post_id );
649
+ }
650
+ ?>
651
+
652
+ <h2 class="featured-content-entry-title"><a href="<?php echo esc_url( get_permalink() ); ?>" title="<?php echo esc_attr( the_title_attribute( ) ); ?>"><?php the_title(); ?></a></h2>
653
+
654
+ <div class="featured-content-entry-meta">
655
+ <?php
656
+ if ( false != $atts['display_types'] ) {
657
+ echo self::get_project_type( $post_id );
658
+ }
659
+
660
+ if ( false != $atts['display_tags'] ) {
661
+ echo self::get_project_tags( $post_id );
662
+ }
663
+
664
+ if ( false != $atts['display_author'] ) {
665
+ echo self::get_project_author( $post_id );
666
+ }
667
+ ?>
668
+ </div>
669
+
670
+ </header>
671
+
672
+ <?php
673
+ // The content
674
+ if ( false !== $atts['display_content'] ) {
675
+ if ( 'full' === $atts['display_content'] ) {
676
+ ?>
677
+ <div class="featured-content-entry-content"><?php the_content(); ?></div>
678
+ <?php
679
+ } else {
680
+ ?>
681
+ <div class="featured-content-entry-content"><?php the_excerpt(); ?></div>
682
+ <?php
683
+ }
684
+ }
685
+ ?>
686
+ </div><!-- close .featured-content-entry -->
687
+ <?php $featured_content_index_number++;
688
+ } // end of while loop
689
+
690
+ wp_reset_postdata();
691
+ ?>
692
+ </div><!-- close .featured-content -->
693
+ <?php
694
+ } else { ?>
695
+ <p><em><?php _e( 'Your Featured Content Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types' ); ?></p></em>
696
+ <?php
697
+ }
698
+ $html = ob_get_clean();
699
+
700
+ // If there is a [featured_content] within a [featured_content], remove the shortcode
701
+ if ( has_shortcode( $html, 'featured_content' ) ){
702
+ remove_shortcode( 'featured_content' );
703
+ }
704
+
705
+ // Return the HTML block
706
+ return $html;
707
+ }
708
+
709
+ /**
710
+ * Individual project class
711
+ *
712
+ * @return string
713
+ */
714
+ static function get_project_class( $featured_content_index_number, $columns ) {
715
+ $project_types = wp_get_object_terms( get_the_ID(), self::CUSTOM_TAXONOMY_TYPE, array( 'fields' => 'slugs' ) );
716
+ $class = array();
717
+
718
+ $class[] = 'featured-content-entry-column-'.$columns;
719
+ // add a type- class for each project type
720
+ foreach ( $project_types as $project_type ) {
721
+ $class[] = 'type-' . esc_html( $project_type );
722
+ }
723
+ if( $columns > 1) {
724
+ if ( ( $featured_content_index_number % 2 ) == 0 ) {
725
+ $class[] = 'featured-content-entry-mobile-first-item-row';
726
+ } else {
727
+ $class[] = 'featured-content-entry-mobile-last-item-row';
728
+ }
729
+ }
730
+
731
+ // add first and last classes to first and last items in a row
732
+ if ( ( $featured_content_index_number % $columns ) == 0 ) {
733
+ $class[] = 'featured-content-entry-first-item-row';
734
+ } elseif ( ( $featured_content_index_number % $columns ) == ( $columns - 1 ) ) {
735
+ $class[] = 'featured-content-entry-last-item-row';
736
+ }
737
+
738
+
739
+ /**
740
+ * Filter the class applied to project div in the featured_content
741
+ *
742
+ * @module custom-content-types
743
+ *
744
+ * @since 3.1.0
745
+ *
746
+ * @param string $class class name of the div.
747
+ * @param int $featured_content_index_number iterator count the number of columns up starting from 0.
748
+ * @param int $columns number of columns to display the content in.
749
+ *
750
+ */
751
+ return apply_filters( 'featured-content-project-post-class', implode( " ", $class ) , $featured_content_index_number, $columns );
752
+ }
753
+
754
+ /**
755
+ * Displays the project type that a project belongs to.
756
+ *
757
+ * @return html
758
+ */
759
+ static function get_project_type( $post_id ) {
760
+ $project_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
761
+
762
+ // If no types, return empty string
763
+ if ( empty( $project_types ) || is_wp_error( $project_types ) ) {
764
+ return;
765
+ }
766
+
767
+ $html = '<div class="project-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
768
+ $types = array();
769
+ // Loop thorugh all the types
770
+ foreach ( $project_types as $project_type ) {
771
+ $project_type_link = get_term_link( $project_type, self::CUSTOM_TAXONOMY_TYPE );
772
+
773
+ if ( is_wp_error( $project_type_link ) ) {
774
+ return $project_type_link;
775
+ }
776
+
777
+ $types[] = '<a href="' . esc_url( $project_type_link ) . '" rel="tag">' . esc_html( $project_type->name ) . '</a>';
778
+ }
779
+ $html .= ' '.implode( ', ', $types );
780
+ $html .= '</div>';
781
+
782
+ return $html;
783
+ }
784
+
785
+ /**
786
+ * Displays the project tags that a project belongs to.
787
+ *
788
+ * @return html
789
+ */
790
+ static function get_project_tags( $post_id ) {
791
+ $project_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
792
+
793
+ // If no tags, return empty string
794
+ if ( empty( $project_tags ) || is_wp_error( $project_tags ) ) {
795
+ return false;
796
+ }
797
+
798
+ $html = '<div class="project-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
799
+ $tags = array();
800
+ // Loop thorugh all the tags
801
+ foreach ( $project_tags as $project_tag ) {
802
+ $project_tag_link = get_term_link( $project_tag, self::CUSTOM_TAXONOMY_TYPE );
803
+
804
+ if ( is_wp_error( $project_tag_link ) ) {
805
+ return $project_tag_link;
806
+ }
807
+
808
+ $tags[] = '<a href="' . esc_url( $project_tag_link ) . '" rel="tag">' . esc_html( $project_tag->name ) . '</a>';
809
+ }
810
+ $html .= ' '. implode( ', ', $tags );
811
+ $html .= '</div>';
812
+
813
+ return $html;
814
+ }
815
+
816
+ /**
817
+ * Displays the author of the current featured_content project.
818
+ *
819
+ * @return html
820
+ */
821
+ static function get_project_author() {
822
+ $html = '<div class="project-author">';
823
+ /* translators: %1$s is link to author posts, %2$s is author display name */
824
+ $html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
825
+ esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
826
+ esc_html( get_the_author() )
827
+ );
828
+ $html .= '</div>';
829
+
830
+ return $html;
831
+ }
832
+
833
+ /**
834
+ * Display the featured image if it's available
835
+ *
836
+ * @return html
837
+ */
838
+ static function get_featured_content_thumbnail_link( $post_id ) {
839
+ if ( has_post_thumbnail( $post_id ) ) {
840
+ /**
841
+ * Change the Featured Content thumbnail size.
842
+ *
843
+ * @module custom-content-types
844
+ *
845
+ * @since 3.4.0
846
+ *
847
+ * @param string|array $var Either a registered size keyword or size array.
848
+ */
849
+ 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', 'large' ) ) . '</a>';
850
+ }
851
+ }
852
+ }
853
+ add_action( 'init', array( 'Essential_Content_Featured_Content', 'init' ) );
854
+
855
+ /**
856
+ * Add Featured Content support
857
+ */
858
+ function essential_content_feature_content_support() {
859
+ add_theme_support( 'featured-content', array(
860
+ 'title' => true,
861
+ 'content' => true,
862
+ 'featured-image' => true,
863
+ ) );
864
+ }
865
+ add_action( 'after_setup_theme', 'essential_content_feature_content_support' );
admin/class-portfolio.php ADDED
@@ -0,0 +1,862 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 = '0.1';
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
+ 'thumbnail',
250
+ 'author',
251
+ 'comments',
252
+ 'publicize',
253
+ ),
254
+ 'rewrite' => array(
255
+ 'slug' => 'portfolio',
256
+ 'with_front' => false,
257
+ 'feeds' => true,
258
+ 'pages' => true,
259
+ ),
260
+ 'public' => true,
261
+ 'show_ui' => true,
262
+ 'menu_position' => 20, // below Pages
263
+ 'menu_icon' => 'dashicons-portfolio', // 3.8+ dashicon option
264
+ 'capability_type' => 'page',
265
+ 'map_meta_cap' => true,
266
+ 'taxonomies' => array( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_TAXONOMY_TAG ),
267
+ 'has_archive' => true,
268
+ 'query_var' => 'portfolio',
269
+ 'show_in_rest' => true,
270
+ ) );
271
+
272
+ register_taxonomy( self::CUSTOM_TAXONOMY_TYPE, self::CUSTOM_POST_TYPE, array(
273
+ 'hierarchical' => true,
274
+ 'labels' => array(
275
+ 'name' => esc_html__( 'Project Types', 'essential-content-types' ),
276
+ 'singular_name' => esc_html__( 'Project Type', 'essential-content-types' ),
277
+ 'menu_name' => esc_html__( 'Project Types', 'essential-content-types' ),
278
+ 'all_items' => esc_html__( 'All Project Types', 'essential-content-types' ),
279
+ 'edit_item' => esc_html__( 'Edit Project Type', 'essential-content-types' ),
280
+ 'view_item' => esc_html__( 'View Project Type', 'essential-content-types' ),
281
+ 'update_item' => esc_html__( 'Update Project Type', 'essential-content-types' ),
282
+ 'add_new_item' => esc_html__( 'Add New Project Type', 'essential-content-types' ),
283
+ 'new_item_name' => esc_html__( 'New Project Type Name', 'essential-content-types' ),
284
+ 'parent_item' => esc_html__( 'Parent Project Type', 'essential-content-types' ),
285
+ 'parent_item_colon' => esc_html__( 'Parent Project Type:', 'essential-content-types' ),
286
+ 'search_items' => esc_html__( 'Search Project Types', 'essential-content-types' ),
287
+ 'items_list_navigation' => esc_html__( 'Project type list navigation', 'essential-content-types' ),
288
+ 'items_list' => esc_html__( 'Project type list', 'essential-content-types' ),
289
+ ),
290
+ 'public' => true,
291
+ 'show_ui' => true,
292
+ 'show_in_nav_menus' => true,
293
+ 'show_in_rest' => true,
294
+ 'show_admin_column' => true,
295
+ 'query_var' => true,
296
+ 'rewrite' => array( 'slug' => 'project-type' ),
297
+ ) );
298
+
299
+ register_taxonomy( self::CUSTOM_TAXONOMY_TAG, self::CUSTOM_POST_TYPE, array(
300
+ 'hierarchical' => false,
301
+ 'labels' => array(
302
+ 'name' => esc_html__( 'Project Tags', 'essential-content-types' ),
303
+ 'singular_name' => esc_html__( 'Project Tag', 'essential-content-types' ),
304
+ 'menu_name' => esc_html__( 'Project Tags', 'essential-content-types' ),
305
+ 'all_items' => esc_html__( 'All Project Tags', 'essential-content-types' ),
306
+ 'edit_item' => esc_html__( 'Edit Project Tag', 'essential-content-types' ),
307
+ 'view_item' => esc_html__( 'View Project Tag', 'essential-content-types' ),
308
+ 'update_item' => esc_html__( 'Update Project Tag', 'essential-content-types' ),
309
+ 'add_new_item' => esc_html__( 'Add New Project Tag', 'essential-content-types' ),
310
+ 'new_item_name' => esc_html__( 'New Project Tag Name', 'essential-content-types' ),
311
+ 'search_items' => esc_html__( 'Search Project Tags', 'essential-content-types' ),
312
+ 'popular_items' => esc_html__( 'Popular Project Tags', 'essential-content-types' ),
313
+ 'separate_items_with_commas' => esc_html__( 'Separate tags with commas', 'essential-content-types' ),
314
+ 'add_or_remove_items' => esc_html__( 'Add or remove tags', 'essential-content-types' ),
315
+ 'choose_from_most_used' => esc_html__( 'Choose from the most used tags', 'essential-content-types' ),
316
+ 'not_found' => esc_html__( 'No tags found.', 'essential-content-types' ),
317
+ 'items_list_navigation' => esc_html__( 'Project tag list navigation', 'essential-content-types' ),
318
+ 'items_list' => esc_html__( 'Project tag list', 'essential-content-types' ),
319
+ ),
320
+ 'public' => true,
321
+ 'show_ui' => true,
322
+ 'show_in_nav_menus' => true,
323
+ 'show_in_rest' => true,
324
+ 'show_admin_column' => true,
325
+ 'query_var' => true,
326
+ 'rewrite' => array( 'slug' => 'project-tag' ),
327
+ ) );
328
+ }
329
+
330
+ /**
331
+ * Update messages for the Portfolio admin.
332
+ */
333
+ function updated_messages( $messages ) {
334
+ global $post;
335
+
336
+ $messages[self::CUSTOM_POST_TYPE] = array(
337
+ 0 => '', // Unused. Messages start at index 1.
338
+ 1 => sprintf( __( 'Project updated. <a href="%s">View item</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
339
+ 2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
340
+ 3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
341
+ 4 => esc_html__( 'Project updated.', 'essential-content-types' ),
342
+ /* translators: %s: date and time of the revision */
343
+ 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,
344
+ 6 => sprintf( __( 'Project published. <a href="%s">View project</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
345
+ 7 => esc_html__( 'Project saved.', 'essential-content-types' ),
346
+ 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 ) ) ) ),
347
+ 9 => sprintf( __( 'Project scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview project</a>', 'essential-content-types' ),
348
+ // translators: Publish box date format, see http://php.net/date
349
+ date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink( $post->ID ) ) ),
350
+ 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 ) ) ) ),
351
+ );
352
+
353
+ return $messages;
354
+ }
355
+
356
+ /**
357
+ * Change ‘Title’ column label
358
+ * Add Featured Image column
359
+ */
360
+ function edit_admin_columns( $columns ) {
361
+ // change 'Title' to 'Project'
362
+ $columns['title'] = __( 'Project', 'essential-content-types' );
363
+ if ( current_theme_supports( 'post-thumbnails' ) ) {
364
+ // add featured image before 'Project'
365
+ $columns = array_slice( $columns, 0, 1, true ) + array( 'thumbnail' => '' ) + array_slice( $columns, 1, NULL, true );
366
+ }
367
+
368
+ return $columns;
369
+ }
370
+
371
+ /**
372
+ * Add featured image to column
373
+ */
374
+ function image_column( $column, $post_id ) {
375
+ global $post;
376
+ switch ( $column ) {
377
+ case 'thumbnail':
378
+ echo get_the_post_thumbnail( $post_id, 'jetpack-portfolio-admin-thumb' );
379
+ break;
380
+ }
381
+ }
382
+
383
+ /**
384
+ * Adjust image column width
385
+ */
386
+ function enqueue_admin_styles( $hook ) {
387
+ $screen = get_current_screen();
388
+
389
+ if ( 'edit.php' == $hook && self::CUSTOM_POST_TYPE == $screen->post_type && current_theme_supports( 'post-thumbnails' ) ) {
390
+ 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; } }' );
391
+ }
392
+ }
393
+
394
+ /**
395
+ * Adds portfolio section to the Customizer.
396
+ */
397
+ function customize_register( $wp_customize ) {
398
+ $options = get_theme_support( self::CUSTOM_POST_TYPE );
399
+
400
+ 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'] ) ) {
401
+ return;
402
+ }
403
+
404
+ $wp_customize->add_section( 'jetpack_portfolio', array(
405
+ 'title' => esc_html__( 'Portfolio', 'essential-content-types' ),
406
+ 'theme_supports' => self::CUSTOM_POST_TYPE,
407
+ 'priority' => 130,
408
+ ) );
409
+
410
+ if ( isset( $options[0]['title'] ) && true === $options[0]['title'] ) {
411
+ $wp_customize->add_setting( 'jetpack_portfolio_title', array(
412
+ 'default' => esc_html__( 'Projects', 'essential-content-types' ),
413
+ 'type' => 'option',
414
+ 'sanitize_callback' => 'sanitize_text_field',
415
+ 'sanitize_js_callback' => 'sanitize_text_field',
416
+ ) );
417
+
418
+ $wp_customize->add_control( 'jetpack_portfolio_title', array(
419
+ 'section' => 'jetpack_portfolio',
420
+ 'label' => esc_html__( 'Portfolio Archive Title', 'essential-content-types' ),
421
+ 'type' => 'text',
422
+ ) );
423
+ }
424
+
425
+ if ( isset( $options[0]['content'] ) && true === $options[0]['content'] ) {
426
+ $wp_customize->add_setting( 'jetpack_portfolio_content', array(
427
+ 'default' => '',
428
+ 'type' => 'option',
429
+ 'sanitize_callback' => 'wp_kses_post',
430
+ 'sanitize_js_callback' => 'wp_kses_post',
431
+ ) );
432
+
433
+ $wp_customize->add_control( 'jetpack_portfolio_content', array(
434
+ 'section' => 'jetpack_portfolio',
435
+ 'label' => esc_html__( 'Portfolio Archive Content', 'essential-content-types' ),
436
+ 'type' => 'textarea',
437
+ ) );
438
+ }
439
+
440
+ if ( isset( $options[0]['featured-image'] ) && true === $options[0]['featured-image'] ) {
441
+ $wp_customize->add_setting( 'jetpack_portfolio_featured_image', array(
442
+ 'default' => '',
443
+ 'type' => 'option',
444
+ 'sanitize_callback' => 'attachment_url_to_postid',
445
+ 'sanitize_js_callback' => 'attachment_url_to_postid',
446
+ 'theme_supports' => 'post-thumbnails',
447
+ ) );
448
+
449
+ $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'jetpack_portfolio_featured_image', array(
450
+ 'section' => 'jetpack_portfolio',
451
+ 'label' => esc_html__( 'Portfolio Archive Featured Image', 'essential-content-types' ),
452
+ ) ) );
453
+ }
454
+ }
455
+
456
+ /**
457
+ * Follow CPT reading setting on CPT archive and taxonomy pages
458
+ */
459
+ function query_reading_setting( $query ) {
460
+ if ( ! is_admin() &&
461
+ $query->is_main_query() &&
462
+ ( $query->is_post_type_archive( self::CUSTOM_POST_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TYPE ) || $query->is_tax( self::CUSTOM_TAXONOMY_TAG ) )
463
+ ) {
464
+ $query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, '10' ) );
465
+ }
466
+ }
467
+
468
+ /**
469
+ * Add to REST API post type whitelist
470
+ */
471
+ function allow_portfolio_rest_api_type( $post_types ) {
472
+ $post_types[] = self::CUSTOM_POST_TYPE;
473
+
474
+ return $post_types;
475
+ }
476
+
477
+ /**
478
+ * Our [portfolio] shortcode.
479
+ * Prints Portfolio data styled to look good on *any* theme.
480
+ *
481
+ * @return portfolio_shortcode_html
482
+ */
483
+ static function portfolio_shortcode( $atts ) {
484
+ // Default attributes
485
+ $atts = shortcode_atts( array(
486
+ 'display_types' => true,
487
+ 'display_tags' => true,
488
+ 'display_content' => true,
489
+ 'display_author' => false,
490
+ 'show_filter' => false,
491
+ 'include_type' => false,
492
+ 'include_tag' => false,
493
+ 'columns' => 2,
494
+ 'showposts' => -1,
495
+ 'order' => 'asc',
496
+ 'orderby' => 'date',
497
+ ), $atts, 'portfolio' );
498
+
499
+ // A little sanitization
500
+ if ( $atts['display_types'] && 'true' != $atts['display_types'] ) {
501
+ $atts['display_types'] = false;
502
+ }
503
+
504
+ if ( $atts['display_tags'] && 'true' != $atts['display_tags'] ) {
505
+ $atts['display_tags'] = false;
506
+ }
507
+
508
+ if ( $atts['display_author'] && 'true' != $atts['display_author'] ) {
509
+ $atts['display_author'] = false;
510
+ }
511
+
512
+ if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
513
+ $atts['display_content'] = false;
514
+ }
515
+
516
+ if ( $atts['include_type'] ) {
517
+ $atts['include_type'] = explode( ',', str_replace( ' ', '', $atts['include_type'] ) );
518
+ }
519
+
520
+ if ( $atts['include_tag'] ) {
521
+ $atts['include_tag'] = explode( ',', str_replace( ' ', '', $atts['include_tag'] ) );
522
+ }
523
+
524
+ $atts['columns'] = absint( $atts['columns'] );
525
+
526
+ $atts['showposts'] = intval( $atts['showposts'] );
527
+
528
+
529
+ if ( $atts['order'] ) {
530
+ $atts['order'] = urldecode( $atts['order'] );
531
+ $atts['order'] = strtoupper( $atts['order'] );
532
+ if ( 'DESC' != $atts['order'] ) {
533
+ $atts['order'] = 'ASC';
534
+ }
535
+ }
536
+
537
+ if ( $atts['orderby'] ) {
538
+ $atts['orderby'] = urldecode( $atts['orderby'] );
539
+ $atts['orderby'] = strtolower( $atts['orderby'] );
540
+ $allowed_keys = array( 'author', 'date', 'title', 'rand' );
541
+
542
+ $parsed = array();
543
+ foreach ( explode( ',', $atts['orderby'] ) as $portfolio_index_number => $orderby ) {
544
+ if ( ! in_array( $orderby, $allowed_keys ) ) {
545
+ continue;
546
+ }
547
+ $parsed[] = $orderby;
548
+ }
549
+
550
+ if ( empty( $parsed ) ) {
551
+ unset( $atts['orderby'] );
552
+ } else {
553
+ $atts['orderby'] = implode( ' ', $parsed );
554
+ }
555
+ }
556
+
557
+ // enqueue shortcode styles when shortcode is used
558
+ wp_enqueue_style( 'jetpack-portfolio-style', plugins_url( 'css/portfolio-shortcode.css', __FILE__ ), array(), '20140326' );
559
+
560
+ return self::portfolio_shortcode_html( $atts );
561
+ }
562
+
563
+ /**
564
+ * Query to retrieve entries from the Portfolio post_type.
565
+ *
566
+ * @return object
567
+ */
568
+ static function portfolio_query( $atts ) {
569
+ // Default query arguments
570
+ $default = array(
571
+ 'order' => $atts['order'],
572
+ 'orderby' => $atts['orderby'],
573
+ 'posts_per_page' => $atts['showposts'],
574
+ );
575
+
576
+ $args = wp_parse_args( $atts, $default );
577
+ $args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
578
+
579
+ if ( false != $atts['include_type'] || false != $atts['include_tag'] ) {
580
+ $args['tax_query'] = array();
581
+ }
582
+
583
+ // If 'include_type' has been set use it on the main query
584
+ if ( false != $atts['include_type'] ) {
585
+ array_push( $args['tax_query'], array(
586
+ 'taxonomy' => self::CUSTOM_TAXONOMY_TYPE,
587
+ 'field' => 'slug',
588
+ 'terms' => $atts['include_type'],
589
+ ) );
590
+ }
591
+
592
+ // If 'include_tag' has been set use it on the main query
593
+ if ( false != $atts['include_tag'] ) {
594
+ array_push( $args['tax_query'], array(
595
+ 'taxonomy' => self::CUSTOM_TAXONOMY_TAG,
596
+ 'field' => 'slug',
597
+ 'terms' => $atts['include_tag'],
598
+ ) );
599
+ }
600
+
601
+ if ( false != $atts['include_type'] && false != $atts['include_tag'] ) {
602
+ $args['tax_query']['relation'] = 'AND';
603
+ }
604
+
605
+ // Run the query and return
606
+ $query = new WP_Query( $args );
607
+ return $query;
608
+ }
609
+
610
+ /**
611
+ * The Portfolio shortcode loop.
612
+ *
613
+ * @todo add theme color styles
614
+ * @return html
615
+ */
616
+ static function portfolio_shortcode_html( $atts ) {
617
+
618
+ $query = self::portfolio_query( $atts );
619
+ $portfolio_index_number = 0;
620
+
621
+ ob_start();
622
+
623
+ // If we have posts, create the html
624
+ // with hportfolio markup
625
+ if ( $query->have_posts() ) {
626
+
627
+ // Render styles
628
+ //self::themecolor_styles();
629
+
630
+ ?>
631
+ <div class="jetpack-portfolio-shortcode column-<?php echo esc_attr( $atts['columns'] ); ?>">
632
+ <?php // open .jetpack-portfolio
633
+
634
+ // Construct the loop...
635
+ while ( $query->have_posts() ) {
636
+ $query->the_post();
637
+ $post_id = get_the_ID();
638
+ ?>
639
+ <div class="portfolio-entry <?php echo esc_attr( self::get_project_class( $portfolio_index_number, $atts['columns'] ) ); ?>">
640
+ <header class="portfolio-entry-header">
641
+ <?php
642
+ // Featured image
643
+ echo self::get_portfolio_thumbnail_link( $post_id );
644
+ ?>
645
+
646
+ <h2 class="portfolio-entry-title"><a href="<?php echo esc_url( get_permalink() ); ?>" title="<?php echo esc_attr( the_title_attribute( ) ); ?>"><?php the_title(); ?></a></h2>
647
+
648
+ <div class="portfolio-entry-meta">
649
+ <?php
650
+ if ( false != $atts['display_types'] ) {
651
+ echo self::get_project_type( $post_id );
652
+ }
653
+
654
+ if ( false != $atts['display_tags'] ) {
655
+ echo self::get_project_tags( $post_id );
656
+ }
657
+
658
+ if ( false != $atts['display_author'] ) {
659
+ echo self::get_project_author( $post_id );
660
+ }
661
+ ?>
662
+ </div>
663
+
664
+ </header>
665
+
666
+ <?php
667
+ // The content
668
+ if ( false !== $atts['display_content'] ) {
669
+ if ( 'full' === $atts['display_content'] ) {
670
+ ?>
671
+ <div class="portfolio-entry-content"><?php the_content(); ?></div>
672
+ <?php
673
+ } else {
674
+ ?>
675
+ <div class="portfolio-entry-content"><?php the_excerpt(); ?></div>
676
+ <?php
677
+ }
678
+ }
679
+ ?>
680
+ </div><!-- close .portfolio-entry -->
681
+ <?php $portfolio_index_number++;
682
+ } // end of while loop
683
+
684
+ wp_reset_postdata();
685
+ ?>
686
+ </div><!-- close .jetpack-portfolio -->
687
+ <?php
688
+ } else { ?>
689
+ <p><em><?php _e( 'Your Portfolio Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types' ); ?></p></em>
690
+ <?php
691
+ }
692
+ $html = ob_get_clean();
693
+
694
+ // If there is a [portfolio] within a [portfolio], remove the shortcode
695
+ if ( has_shortcode( $html, 'portfolio' ) ){
696
+ remove_shortcode( 'portfolio' );
697
+ }
698
+
699
+ // Return the HTML block
700
+ return $html;
701
+ }
702
+
703
+ /**
704
+ * Individual project class
705
+ *
706
+ * @return string
707
+ */
708
+ static function get_project_class( $portfolio_index_number, $columns ) {
709
+ $project_types = wp_get_object_terms( get_the_ID(), self::CUSTOM_TAXONOMY_TYPE, array( 'fields' => 'slugs' ) );
710
+ $class = array();
711
+
712
+ $class[] = 'portfolio-entry-column-'.$columns;
713
+ // add a type- class for each project type
714
+ foreach ( $project_types as $project_type ) {
715
+ $class[] = 'type-' . esc_html( $project_type );
716
+ }
717
+ if( $columns > 1) {
718
+ if ( ( $portfolio_index_number % 2 ) == 0 ) {
719
+ $class[] = 'portfolio-entry-mobile-first-item-row';
720
+ } else {
721
+ $class[] = 'portfolio-entry-mobile-last-item-row';
722
+ }
723
+ }
724
+
725
+ // add first and last classes to first and last items in a row
726
+ if ( ( $portfolio_index_number % $columns ) == 0 ) {
727
+ $class[] = 'portfolio-entry-first-item-row';
728
+ } elseif ( ( $portfolio_index_number % $columns ) == ( $columns - 1 ) ) {
729
+ $class[] = 'portfolio-entry-last-item-row';
730
+ }
731
+
732
+
733
+ /**
734
+ * Filter the class applied to project div in the portfolio
735
+ *
736
+ * @module custom-content-types
737
+ *
738
+ * @since 3.1.0
739
+ *
740
+ * @param string $class class name of the div.
741
+ * @param int $portfolio_index_number iterator count the number of columns up starting from 0.
742
+ * @param int $columns number of columns to display the content in.
743
+ *
744
+ */
745
+ return apply_filters( 'portfolio-project-post-class', implode( " ", $class ) , $portfolio_index_number, $columns );
746
+ }
747
+
748
+ /**
749
+ * Displays the project type that a project belongs to.
750
+ *
751
+ * @return html
752
+ */
753
+ static function get_project_type( $post_id ) {
754
+ $project_types = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TYPE );
755
+
756
+ // If no types, return empty string
757
+ if ( empty( $project_types ) || is_wp_error( $project_types ) ) {
758
+ return;
759
+ }
760
+
761
+ $html = '<div class="project-types"><span>' . __( 'Types', 'essential-content-types' ) . ':</span>';
762
+ $types = array();
763
+ // Loop thorugh all the types
764
+ foreach ( $project_types as $project_type ) {
765
+ $project_type_link = get_term_link( $project_type, self::CUSTOM_TAXONOMY_TYPE );
766
+
767
+ if ( is_wp_error( $project_type_link ) ) {
768
+ return $project_type_link;
769
+ }
770
+
771
+ $types[] = '<a href="' . esc_url( $project_type_link ) . '" rel="tag">' . esc_html( $project_type->name ) . '</a>';
772
+ }
773
+ $html .= ' '.implode( ', ', $types );
774
+ $html .= '</div>';
775
+
776
+ return $html;
777
+ }
778
+
779
+ /**
780
+ * Displays the project tags that a project belongs to.
781
+ *
782
+ * @return html
783
+ */
784
+ static function get_project_tags( $post_id ) {
785
+ $project_tags = get_the_terms( $post_id, self::CUSTOM_TAXONOMY_TAG );
786
+
787
+ // If no tags, return empty string
788
+ if ( empty( $project_tags ) || is_wp_error( $project_tags ) ) {
789
+ return false;
790
+ }
791
+
792
+ $html = '<div class="project-tags"><span>' . __( 'Tags', 'essential-content-types' ) . ':</span>';
793
+ $tags = array();
794
+ // Loop thorugh all the tags
795
+ foreach ( $project_tags as $project_tag ) {
796
+ $project_tag_link = get_term_link( $project_tag, self::CUSTOM_TAXONOMY_TYPE );
797
+
798
+ if ( is_wp_error( $project_tag_link ) ) {
799
+ return $project_tag_link;
800
+ }
801
+
802
+ $tags[] = '<a href="' . esc_url( $project_tag_link ) . '" rel="tag">' . esc_html( $project_tag->name ) . '</a>';
803
+ }
804
+ $html .= ' '. implode( ', ', $tags );
805
+ $html .= '</div>';
806
+
807
+ return $html;
808
+ }
809
+
810
+ /**
811
+ * Displays the author of the current portfolio project.
812
+ *
813
+ * @return html
814
+ */
815
+ static function get_project_author() {
816
+ $html = '<div class="project-author">';
817
+ /* translators: %1$s is link to author posts, %2$s is author display name */
818
+ $html .= sprintf( __( '<span>Author:</span> <a href="%1$s">%2$s</a>', 'essential-content-types' ),
819
+ esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
820
+ esc_html( get_the_author() )
821
+ );
822
+ $html .= '</div>';
823
+
824
+ return $html;
825
+ }
826
+
827
+ /**
828
+ * Display the featured image if it's available
829
+ *
830
+ * @return html
831
+ */
832
+ static function get_portfolio_thumbnail_link( $post_id ) {
833
+ if ( has_post_thumbnail( $post_id ) ) {
834
+ /**
835
+ * Change the Portfolio thumbnail size.
836
+ *
837
+ * @module custom-content-types
838
+ *
839
+ * @since 3.4.0
840
+ *
841
+ * @param string|array $var Either a registered size keyword or size array.
842
+ */
843
+ 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', 'large' ) ) . '</a>';
844
+ }
845
+ }
846
+ }
847
+ add_action( 'init', array( 'Essential_Content_Jetpack_Portfolio', 'init' ) );
848
+
849
+ /**
850
+ * Add Portfolio support
851
+ */
852
+ function essential_content_portfolio_support() {
853
+ /*
854
+ * Adding theme support for Jetpack Portfolio CPT.
855
+ */
856
+ add_theme_support( 'jetpack-portfolio', array(
857
+ 'title' => true,
858
+ 'content' => true,
859
+ 'featured-image' => true,
860
+ ) );
861
+ }
862
+ add_action( 'after_setup_theme', 'essential_content_portfolio_support' );
admin/class-testimonial.php ADDED
@@ -0,0 +1,740 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 = '0.1';
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
+ 'thumbnail',
283
+ 'page-attributes',
284
+ 'revisions',
285
+ ),
286
+ 'rewrite' => array(
287
+ 'slug' => 'testimonial',
288
+ 'with_front' => false,
289
+ 'feeds' => false,
290
+ 'pages' => true,
291
+ ),
292
+ 'public' => true,
293
+ 'show_ui' => true,
294
+ 'menu_position' => 20, // below Pages
295
+ 'menu_icon' => 'dashicons-testimonial',
296
+ 'capability_type' => 'page',
297
+ 'map_meta_cap' => true,
298
+ 'has_archive' => true,
299
+ 'query_var' => 'testimonial',
300
+ 'show_in_rest' => true,
301
+ ) );
302
+ }
303
+
304
+ /**
305
+ * Update messages for the Testimonial admin.
306
+ */
307
+ function updated_messages( $messages ) {
308
+ global $post;
309
+
310
+ $messages[ self::CUSTOM_POST_TYPE ] = array(
311
+ 0 => '', // Unused. Messages start at index 1.
312
+ 1 => sprintf( __( 'Testimonial updated. <a href="%s">View testimonial</a>', 'essential-content-types'), esc_url( get_permalink( $post->ID ) ) ),
313
+ 2 => esc_html__( 'Custom field updated.', 'essential-content-types' ),
314
+ 3 => esc_html__( 'Custom field deleted.', 'essential-content-types' ),
315
+ 4 => esc_html__( 'Testimonial updated.', 'essential-content-types' ),
316
+ /* translators: %s: date and time of the revision */
317
+ 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,
318
+ 6 => sprintf( __( 'Testimonial published. <a href="%s">View testimonial</a>', 'essential-content-types' ), esc_url( get_permalink( $post->ID ) ) ),
319
+ 7 => esc_html__( 'Testimonial saved.', 'essential-content-types' ),
320
+ 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 ) ) ) ),
321
+ 9 => sprintf( __( 'Testimonial scheduled for: <strong>%1$s</strong>. <a target="_blank" href="%2$s">Preview testimonial</a>', 'essential-content-types' ),
322
+ // translators: Publish box date format, see http://php.net/date
323
+ date_i18n( __( 'M j, Y @ G:i', 'essential-content-types' ), strtotime( $post->post_date ) ), esc_url( get_permalink($post->ID) ) ),
324
+ 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 ) ) ) ),
325
+ );
326
+
327
+ return $messages;
328
+ }
329
+
330
+ /**
331
+ * Change ‘Enter Title Here’ text for the Testimonial.
332
+ */
333
+ function change_default_title( $title ) {
334
+ $screen = get_current_screen();
335
+
336
+ if ( self::CUSTOM_POST_TYPE == $screen->post_type )
337
+ $title = esc_html__( "Enter the customer's name here", 'essential-content-types' );
338
+
339
+ return $title;
340
+ }
341
+
342
+ /**
343
+ * Change ‘Title’ column label on all Testimonials page.
344
+ */
345
+ function edit_title_column_label( $columns ) {
346
+ $columns['title'] = esc_html__( 'Customer Name', 'essential-content-types' );
347
+
348
+ return $columns;
349
+ }
350
+
351
+ /**
352
+ * Follow CPT reading setting on CPT archive page
353
+ */
354
+ function query_reading_setting( $query ) {
355
+ if ( ! is_admin()
356
+ && $query->is_main_query()
357
+ && $query->is_post_type_archive( self::CUSTOM_POST_TYPE )
358
+ ) {
359
+ $query->set( 'posts_per_page', get_option( self::OPTION_READING_SETTING, '10' ) );
360
+ }
361
+ }
362
+
363
+ /*
364
+ * If Infinite Scroll is set to 'click', use our custom reading setting instead of core's `posts_per_page`.
365
+ */
366
+ function infinite_scroll_click_posts_per_page( $settings ) {
367
+ global $wp_query;
368
+
369
+ if ( ! is_admin() && true === $settings['click_handle'] && $wp_query->is_post_type_archive( self::CUSTOM_POST_TYPE ) ) {
370
+ $settings['posts_per_page'] = get_option( self::OPTION_READING_SETTING, $settings['posts_per_page'] );
371
+ }
372
+
373
+ return $settings;
374
+ }
375
+
376
+ /**
377
+ * Add CPT to Dotcom sitemap
378
+ */
379
+ function add_to_sitemap( $post_types ) {
380
+ $post_types[] = self::CUSTOM_POST_TYPE;
381
+
382
+ return $post_types;
383
+ }
384
+
385
+ function set_testimonial_option() {
386
+ $testimonials = wp_count_posts( self::CUSTOM_POST_TYPE );
387
+ $published_testimonials = $testimonials->publish;
388
+
389
+ update_option( self::OPTION_NAME, $published_testimonials );
390
+ }
391
+
392
+ function count_testimonials() {
393
+ $testimonials = get_transient( 'jetpack-testimonial-count-cache' );
394
+
395
+ if ( false === $testimonials ) {
396
+ $testimonials = (int) wp_count_posts( self::CUSTOM_POST_TYPE )->publish;
397
+
398
+ if ( ! empty( $testimonials ) ) {
399
+ set_transient( 'jetpack-testimonial-count-cache', $testimonials, 60*60*12 );
400
+ }
401
+ }
402
+
403
+ return $testimonials;
404
+ }
405
+
406
+ /**
407
+ * Adds a submenu link to the Customizer.
408
+ */
409
+ function add_customize_page() {
410
+ add_submenu_page(
411
+ 'edit.php?post_type=' . self::CUSTOM_POST_TYPE,
412
+ esc_html__( 'Customize Testimonials Archive', 'essential-content-types' ),
413
+ esc_html__( 'Customize', 'essential-content-types' ),
414
+ 'edit_theme_options',
415
+ add_query_arg( array(
416
+ 'url' => urlencode( home_url( '/testimonial/' ) ),
417
+ 'autofocus[section]' => 'jetpack_testimonials'
418
+ ), 'customize.php' )
419
+ );
420
+ }
421
+
422
+ /**
423
+ * Adds testimonial section to the Customizer.
424
+ */
425
+ function customize_register( $wp_customize ) {
426
+ essential_content_testimonial_custom_control_classes();
427
+
428
+ $wp_customize->add_section( 'jetpack_testimonials', array(
429
+ 'title' => esc_html__( 'Testimonials', 'essential-content-types' ),
430
+ 'theme_supports' => self::CUSTOM_POST_TYPE,
431
+ 'priority' => 130,
432
+ ) );
433
+
434
+ $wp_customize->add_setting( 'jetpack_testimonials[page-title]', array(
435
+ 'default' => esc_html__( 'Testimonials', 'essential-content-types' ),
436
+ 'sanitize_callback' => array( 'Essential_Content_Jetpack_Testimonial_Title_Control', 'sanitize_content' ),
437
+ 'sanitize_js_callback' => array( 'Essential_Content_Jetpack_Testimonial_Title_Control', 'sanitize_content' ),
438
+ ) );
439
+ $wp_customize->add_control( 'jetpack_testimonials[page-title]', array(
440
+ 'section' => 'jetpack_testimonials',
441
+ 'label' => esc_html__( 'Testimonial Archive Title', 'essential-content-types' ),
442
+ 'type' => 'text',
443
+ ) );
444
+
445
+ $wp_customize->add_setting( 'jetpack_testimonials[page-content]', array(
446
+ 'default' => '',
447
+ 'sanitize_callback' => array( 'Essential_Content_Jetpack_Testimonial_Textarea_Control', 'sanitize_content' ),
448
+ 'sanitize_js_callback' => array( 'Essential_Content_Jetpack_Testimonial_Textarea_Control', 'sanitize_content' ),
449
+ ) );
450
+ $wp_customize->add_control( new Essential_Content_Jetpack_Testimonial_Textarea_Control( $wp_customize, 'jetpack_testimonials[page-content]', array(
451
+ 'section' => 'jetpack_testimonials',
452
+ 'settings' => 'jetpack_testimonials[page-content]',
453
+ 'label' => esc_html__( 'Testimonial Archive Content', 'essential-content-types' ),
454
+ ) ) );
455
+
456
+ $wp_customize->add_setting( 'jetpack_testimonials[featured-image]', array(
457
+ 'default' => '',
458
+ 'sanitize_callback' => 'attachment_url_to_postid',
459
+ 'sanitize_js_callback' => 'attachment_url_to_postid',
460
+ 'theme_supports' => 'post-thumbnails',
461
+ ) );
462
+ $wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, 'jetpack_testimonials[featured-image]', array(
463
+ 'section' => 'jetpack_testimonials',
464
+ 'label' => esc_html__( 'Testimonial Archive Featured Image', 'essential-content-types' ),
465
+ ) ) );
466
+
467
+ // The featured image control doesn't display properly in the Customizer unless we coerce
468
+ // it back into a URL sooner, since that's what WP_Customize_Upload_Control::to_json() expects
469
+ if ( is_admin() ) {
470
+ add_filter( 'theme_mod_jetpack_testimonials', array( $this, 'coerce_testimonial_image_to_url' ) );
471
+ }
472
+ }
473
+
474
+ public function coerce_testimonial_image_to_url( $opt ) {
475
+ if ( ! $opt || ! is_array( $opt ) ) {
476
+ return $opt;
477
+ }
478
+ if ( ! isset( $opt['featured-image'] ) || ! is_scalar( $opt['featured-image'] ) ) {
479
+ return $opt;
480
+ }
481
+ $url = wp_get_attachment_url( $opt['featured-image'] );
482
+ if ( $url ) {
483
+ $opt['featured-image'] = $url;
484
+ }
485
+ return $opt;
486
+ }
487
+
488
+ /**
489
+ * Our [testimonial] shortcode.
490
+ * Prints Testimonial data styled to look good on *any* theme.
491
+ *
492
+ * @return jetpack_testimonial_shortcode_html
493
+ */
494
+ static function jetpack_testimonial_shortcode( $atts ) {
495
+ // Default attributes
496
+ $atts = shortcode_atts( array(
497
+ 'display_content' => true,
498
+ 'image' => true,
499
+ 'columns' => 1,
500
+ 'showposts' => -1,
501
+ 'order' => 'asc',
502
+ 'orderby' => 'date',
503
+ ), $atts, 'testimonial' );
504
+
505
+ // A little sanitization
506
+ if ( $atts['display_content'] && 'true' != $atts['display_content'] && 'full' != $atts['display_content'] ) {
507
+ $atts['display_content'] = false;
508
+ }
509
+
510
+ if ( $atts['image'] && 'true' != $atts['image'] ) {
511
+ $atts['image'] = false;
512
+ }
513
+
514
+ $atts['columns'] = absint( $atts['columns'] );
515
+
516
+ $atts['showposts'] = intval( $atts['showposts'] );
517
+
518
+ if ( $atts['order'] ) {
519
+ $atts['order'] = urldecode( $atts['order'] );
520
+ $atts['order'] = strtoupper( $atts['order'] );
521
+ if ( 'DESC' != $atts['order'] ) {
522
+ $atts['order'] = 'ASC';
523
+ }
524
+ }
525
+
526
+ if ( $atts['orderby'] ) {
527
+ $atts['orderby'] = urldecode( $atts['orderby'] );
528
+ $atts['orderby'] = strtolower( $atts['orderby'] );
529
+ $allowed_keys = array('author', 'date', 'title', 'rand');
530
+
531
+ $parsed = array();
532
+ foreach ( explode( ',', $atts['orderby'] ) as $testimonial_index_number => $orderby ) {
533
+ if ( ! in_array( $orderby, $allowed_keys ) ) {
534
+ continue;
535
+ }
536
+ $parsed[] = $orderby;
537
+ }
538
+
539
+ if ( empty( $parsed ) ) {
540
+ unset($atts['orderby']);
541
+ } else {
542
+ $atts['orderby'] = implode( ' ', $parsed );
543
+ }
544
+ }
545
+
546
+ // enqueue shortcode styles when shortcode is used
547
+ wp_enqueue_style( 'jetpack-testimonial-style', plugins_url( 'css/testimonial-shortcode.css', __FILE__ ), array(), '20140326' );
548
+
549
+ return self::jetpack_testimonial_shortcode_html( $atts );
550
+ }
551
+
552
+ /**
553
+ * The Testimonial shortcode loop.
554
+ *
555
+ * @return html
556
+ */
557
+ static function jetpack_testimonial_shortcode_html( $atts ) {
558
+ // Default query arguments
559
+ $defaults = array(
560
+ 'order' => $atts['order'],
561
+ 'orderby' => $atts['orderby'],
562
+ 'posts_per_page' => $atts['showposts'],
563
+ );
564
+
565
+ $args = wp_parse_args( $atts, $defaults );
566
+ $args['post_type'] = self::CUSTOM_POST_TYPE; // Force this post type
567
+ $query = new WP_Query( $args );
568
+
569
+ $testimonial_index_number = 0;
570
+
571
+ ob_start();
572
+
573
+ // If we have testimonials, create the html
574
+ if ( $query->have_posts() ) {
575
+
576
+ ?>
577
+ <div class="jetpack-testimonial-shortcode column-<?php echo esc_attr( $atts['columns'] ); ?>">
578
+ <?php // open .jetpack-testimonial-shortcode
579
+
580
+ // Construct the loop...
581
+ while ( $query->have_posts() ) {
582
+ $query->the_post();
583
+ $post_id = get_the_ID();
584
+ ?>
585
+ <div class="testimonial-entry <?php echo esc_attr( self::get_testimonial_class( $testimonial_index_number, $atts['columns'], has_post_thumbnail( $post_id ) ) ); ?>">
586
+ <?php
587
+ // The content
588
+ if ( false !== $atts['display_content'] ) {
589
+ if ( 'full' === $atts['display_content'] ) {
590
+ ?>
591
+ <div class="testimonial-entry-content"><?php the_content(); ?></div>
592
+ <?php
593
+ } else {
594
+ ?>
595
+ <div class="testimonial-entry-content"><?php the_excerpt(); ?></div>
596
+ <?php
597
+ }
598
+ }
599
+ ?>
600
+ <span class="testimonial-entry-title">&#8213; <a href="<?php echo esc_url( get_permalink() ); ?>" title="<?php echo esc_attr( the_title_attribute( ) ); ?>"><?php the_title(); ?></a></span>
601
+ <?php
602
+ // Featured image
603
+ if ( false !== $atts['image'] ) :
604
+ echo self::get_testimonial_thumbnail_link( $post_id );
605
+ endif;
606
+ ?>
607
+ </div><!-- close .testimonial-entry -->
608
+ <?php
609
+ $testimonial_index_number++;
610
+ } // end of while loop
611
+
612
+ wp_reset_postdata();
613
+ ?>
614
+ </div><!-- close .jetpack-testimonial-shortcode -->
615
+ <?php
616
+ } else { ?>
617
+ <p><em><?php _e( 'Your Testimonial Archive currently has no entries. You can start creating them on your dashboard.', 'essential-content-types' ); ?></p></em>
618
+ <?php
619
+ }
620
+ $html = ob_get_clean();
621
+
622
+ // Return the HTML block
623
+ return $html;
624
+ }
625
+
626
+ /**
627
+ * Individual testimonial class
628
+ *
629
+ * @return string
630
+ */
631
+ static function get_testimonial_class( $testimonial_index_number, $columns, $image ) {
632
+ $class = array();
633
+
634
+ $class[] = 'testimonial-entry-column-'.$columns;
635
+
636
+ if( $columns > 1) {
637
+ if ( ( $testimonial_index_number % 2 ) == 0 ) {
638
+ $class[] = 'testimonial-entry-mobile-first-item-row';
639
+ } else {
640
+ $class[] = 'testimonial-entry-mobile-last-item-row';
641
+ }
642
+ }
643
+
644
+ // add first and last classes to first and last items in a row
645
+ if ( ( $testimonial_index_number % $columns ) == 0 ) {
646
+ $class[] = 'testimonial-entry-first-item-row';
647
+ } elseif ( ( $testimonial_index_number % $columns ) == ( $columns - 1 ) ) {
648
+ $class[] = 'testimonial-entry-last-item-row';
649
+ }
650
+
651
+ // add class if testimonial has a featured image
652
+ if ( false !== $image ) {
653
+ $class[] = 'has-testimonial-thumbnail';
654
+ }
655
+
656
+ /**
657
+ * Filter the class applied to testimonial div in the testimonial
658
+ *
659
+ * @module custom-content-types
660
+ *
661
+ * @since 3.4.0
662
+ *
663
+ * @param string $class class name of the div.
664
+ * @param int $testimonial_index_number iterator count the number of columns up starting from 0.
665
+ * @param int $columns number of columns to display the content in.
666
+ * @param boolean $image has a thumbnail or not.
667
+ *
668
+ */
669
+ return apply_filters( 'testimonial-entry-post-class', implode( " ", $class ) , $testimonial_index_number, $columns, $image );
670
+ }
671
+
672
+ /**
673
+ * Display the featured image if it's available
674
+ *
675
+ * @return html
676
+ */
677
+ static function get_testimonial_thumbnail_link( $post_id ) {
678
+ if ( has_post_thumbnail( $post_id ) ) {
679
+ /**
680
+ * Change the thumbnail size for the Testimonial CPT.
681
+ *
682
+ * @module custom-content-types
683
+ *
684
+ * @since 3.4.0
685
+ *
686
+ * @param string|array $var Either a registered size keyword or size array.
687
+ */
688
+ return '<a class="testimonial-featured-image" href="' . esc_url( get_permalink( $post_id ) ) . '">' . get_the_post_thumbnail( $post_id, apply_filters( 'jetpack_testimonial_thumbnail_size', 'thumbnail' ) ) . '</a>';
689
+ }
690
+ }
691
+ }
692
+ add_action( 'init', array( 'Essential_Content_Jetpack_Testimonial', 'init' ) );
693
+
694
+
695
+ function essential_content_testimonial_custom_control_classes() {
696
+ class Essential_Content_Jetpack_Testimonial_Title_Control extends WP_Customize_Control {
697
+ public static function sanitize_content( $value ) {
698
+ if ( '' != $value )
699
+ $value = trim( convert_chars( wptexturize( $value ) ) );
700
+
701
+ return $value;
702
+ }
703
+ }
704
+
705
+ class Essential_Content_Jetpack_Testimonial_Textarea_Control extends WP_Customize_Control {
706
+ public $type = 'textarea';
707
+
708
+ public function render_content() {
709
+ ?>
710
+ <label>
711
+ <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
712
+ <textarea rows="5" style="width:100%;" <?php $this->link(); ?>><?php echo esc_textarea( $this->value() ); ?></textarea>
713
+ </label>
714
+ <?php
715
+ }
716
+
717
+ public static function sanitize_content( $value ) {
718
+ if ( ! empty( $value ) )
719
+ /** This filter is already documented in core. wp-includes/post-template.php */
720
+ $value = apply_filters( 'the_content', $value );
721
+
722
+ $value = preg_replace( '@<div id="jp-post-flair"([^>]+)?>(.+)?</div>@is', '', $value ); // Strip WPCOM and Jetpack post flair if included in content
723
+
724
+ return $value;
725
+ }
726
+ }
727
+ }
728
+
729
+
730
+
731
+ /**
732
+ * Add Testimonial support
733
+ */
734
+ function essential_content_testimonial_support() {
735
+ /*
736
+ * Adding theme support for Jetpack Testimonial CPT.
737
+ */
738
+ add_theme_support( 'jetpack-testimonial' );
739
+ }
740
+ add_action( 'after_setup_theme', 'essential_content_testimonial_support' );
admin/css/essential-content-types-admin.css ADDED
@@ -0,0 +1,729 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * All of the CSS for your admin-specific functionality should be
3
+ * included in this file.
4
+ */
5
+ /*--------------------------------------------------------------
6
+ >>> TABLE OF CONTENTS:
7
+ ----------------------------------------------------------------
8
+ # Typography
9
+ # Layout
10
+ # Clearing
11
+ # Lists
12
+ # Media
13
+ # Links
14
+ # Header
15
+ # Content
16
+ # Toggle Switch
17
+ # Other Products
18
+ # Footer
19
+ # Media Queries
20
+ ## >= 320px
21
+ ## >= 768px
22
+ ## >= 1024px
23
+ ## >= 1280px
24
+ --------------------------------------------------------------*/
25
+
26
+ /*--------------------------------------------------------------
27
+ # Typography
28
+ --------------------------------------------------------------*/
29
+ body,
30
+ button,
31
+ input,
32
+ select,
33
+ textarea,
34
+ p {
35
+ color: #1a1a1a;
36
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
37
+ font-size: 16px;
38
+ font-size: 1rem;
39
+ font-weight: 400;
40
+ line-height: 1.5;
41
+ word-wrap: break-word;
42
+ -webkit-hyphens: auto;
43
+ -moz-hyphens: auto;
44
+ -ms-hyphens: auto;
45
+ hyphens: auto;
46
+ }
47
+
48
+ h1,
49
+ h2,
50
+ h3,
51
+ h4,
52
+ h5,
53
+ h6 {
54
+ clear: both;
55
+ font-weight: 700;
56
+ line-height: 1.3;
57
+ margin: 0;
58
+ text-rendering: optimizeLegibility;
59
+ }
60
+
61
+ h1 {
62
+ font-size: 24px;
63
+ font-size: 1.5rem;
64
+ }
65
+
66
+ h2 {
67
+ font-size: 20px;
68
+ font-size: 1.25rem;
69
+ }
70
+
71
+ h3 {
72
+ font-size: 18px;
73
+ font-size: 1.125rem;
74
+ }
75
+
76
+ h4 {
77
+ font-size: 16px;
78
+ font-size: 1rem;
79
+ }
80
+
81
+ h5 {
82
+ font-size: 14px;
83
+ font-size: 0.875rem;
84
+ }
85
+
86
+ h6 {
87
+ font-size: 13px;
88
+ font-size: 0.8125rem;
89
+ }
90
+
91
+ p {
92
+ margin: 0 0 1.5em;
93
+ }
94
+
95
+ /*--------------------------------------------------------------
96
+ # Layout
97
+ --------------------------------------------------------------*/
98
+ html {
99
+ -webkit-box-sizing: border-box;
100
+ -moz-box-sizing: border-box;
101
+ box-sizing: border-box;
102
+ }
103
+
104
+ *,
105
+ *:before,
106
+ *:after {
107
+ -webkit-box-sizing: inherit;
108
+ -moz-box-sizing: inherit;
109
+ box-sizing: inherit;
110
+ }
111
+
112
+ * {
113
+ padding: 0;
114
+ margin: 0;
115
+ }
116
+
117
+ body {
118
+ background-color: #fff;
119
+ }
120
+
121
+ #wpcontent {
122
+ padding-left: 0;
123
+ }
124
+
125
+ .container {
126
+ padding: 20px;
127
+ }
128
+
129
+ #dashboard {
130
+ max-width: 1220px;
131
+ margin: 0 auto;
132
+ }
133
+
134
+ /*--------------------------------------------------------------
135
+ # Clearing
136
+ --------------------------------------------------------------*/
137
+ .clear:before,
138
+ .clear:after {
139
+ content: "";
140
+ display: table;
141
+ }
142
+
143
+ .clear:after {
144
+ clear: both;
145
+ }
146
+
147
+ /*--------------------------------------------------------------
148
+ # Lists
149
+ --------------------------------------------------------------*/
150
+ ul,
151
+ ol {
152
+ margin: 0 0 1.5em 2em;
153
+ padding: 0;
154
+ }
155
+
156
+ li {
157
+ margin: 0;
158
+ }
159
+
160
+ ul {
161
+ list-style: disc;
162
+ }
163
+
164
+ ol {
165
+ list-style: decimal;
166
+ }
167
+
168
+ li > ul,
169
+ li > ol {
170
+ margin-top: 0.55em;
171
+ margin-left: 1.5em;
172
+ margin-bottom: 0;
173
+ }
174
+
175
+ li {
176
+ margin-bottom: 0.55em;
177
+ }
178
+
179
+ dt {
180
+ font-weight: 700;
181
+ }
182
+
183
+ dd {
184
+ margin: 0 1.5em 1.5em;
185
+ }
186
+
187
+
188
+ /*--------------------------------------------------------------
189
+ # Media
190
+ --------------------------------------------------------------*/
191
+ img {
192
+ height: auto; /* Make sure images are scaled correctly. */
193
+ max-width: 100%; /* Adhere to container width. */
194
+ vertical-align: middle;
195
+ }
196
+
197
+
198
+ /*--------------------------------------------------------------
199
+ # Links
200
+ --------------------------------------------------------------*/
201
+ a {
202
+ color: #0085c3;
203
+ cursor: pointer;
204
+ text-decoration: none;
205
+ }
206
+
207
+ a:hover,
208
+ a:focus,
209
+ a:active {
210
+ color: #444;
211
+ text-decoration: underline;
212
+ }
213
+
214
+ a:focus {
215
+ outline: thin dotted;
216
+ }
217
+
218
+ a:hover,
219
+ a:active {
220
+ outline: 0;
221
+ }
222
+
223
+ /*--------------------------------------------------------------
224
+ # Header
225
+ --------------------------------------------------------------*/
226
+ #masthead {
227
+ background: url("../images/header_1680x394.jpg");
228
+ background-attachment: fixed;
229
+ background-repeat: no-repeat;
230
+ background-size: cover;
231
+ background-position: center;
232
+ }
233
+
234
+ #masthead .wrapper {
235
+ display: -webkit-box;
236
+ display: -ms-flexbox;
237
+ display: flex;
238
+ -ms-flex-flow: column wrap;
239
+ flex-flow : column wrap;
240
+ }
241
+
242
+ #plugin-description {
243
+ margin: 0 auto;
244
+ max-width: 960px;
245
+ padding-bottom: 20px;
246
+ text-align: center;
247
+ }
248
+
249
+ #plugin-description p:last-child {
250
+ margin-bottom: 0;
251
+ }
252
+
253
+ #site-branding {
254
+ display: block;
255
+ order: 1;
256
+ padding: 30px 20px;
257
+ text-align: center;
258
+ width: 100%;
259
+ }
260
+
261
+ .site-title {
262
+ font-family: "Trebuchet MS", Helvetica, sans-serif;
263
+ text-transform: capitalize;
264
+ }
265
+
266
+ .site-title a {
267
+ color: #0085c3;
268
+ }
269
+
270
+ .site-title-additional {
271
+ color: #006ea4;
272
+ }
273
+
274
+ .setting {
275
+ padding: 0 7px;
276
+ color: #fff;
277
+ }
278
+
279
+ /*--------------------------------------------------------------
280
+ # Content
281
+ --------------------------------------------------------------*/
282
+ .container {
283
+ display: -webkit-box;
284
+ display: -ms-flexbox;
285
+ display: flex;
286
+ -ms-flex-flow: column wrap;
287
+ flex-flow: column wrap;
288
+ justify-content: center;
289
+ margin: 0 auto;
290
+ max-width: 680px;
291
+ }
292
+
293
+ .module-container {
294
+ display: -webkit-box;
295
+ display: -ms-flexbox;
296
+ display: flex;
297
+ -ms-flex-flow: column wrap;
298
+ flex-flow: column wrap;
299
+ -webkit-box-pack: flex-start;
300
+ -ms-flex-pack: flex-start;
301
+ justify-content:flex-start;
302
+ }
303
+
304
+ .module-header {
305
+ background-color: #0685c3 ;
306
+ cursor: pointer;
307
+ display: -webkit-box;
308
+ display: -ms-flexbox;
309
+ display: flex;
310
+ -ms-flex-flow: column wrap;
311
+ flex-flow: column wrap;
312
+ margin: -2px -2px 0;
313
+ padding: 11px 25px;
314
+ position: relative;
315
+ }
316
+
317
+ .module-header.active {
318
+ background-color: #0685c3;
319
+ -webkit-transition: all 0.2s ease;
320
+ -moz-transition: all 0.2s ease;
321
+ o-transition: all 0.2s ease;
322
+ transition: all 0.2s ease;
323
+ }
324
+
325
+ .module-header.inactive {
326
+ background-color:#00618d;
327
+ -webkit-transition: all 0.2s ease;
328
+ -moz-transition: all 0.2s ease;
329
+ o-transition: all 0.2s ease;
330
+ transition: all 0.2s ease;
331
+ }
332
+
333
+ .module-title,
334
+ .other-catchthemes-products .module-content {
335
+ color: #fff;
336
+ font-family: "Trebuchet MS", Helvetica, sans-serif;
337
+ font-weight: normal;
338
+ text-transform: uppercase;
339
+ }
340
+
341
+ .catch-modules {
342
+ background-color: #f9f9f9;
343
+ border-radius: 3px;
344
+ border: 2px solid #ccc;
345
+ border-top: 0;
346
+ display: -webkit-box;
347
+ display: -ms-flexbox;
348
+ display: flex;
349
+ -ms-flex-flow: column wrap;
350
+ flex-flow: column wrap;
351
+ }
352
+
353
+ .catch-module-long {
354
+ background-color: #f9f9f9;
355
+ border-radius: 3px;
356
+ border: 2px solid #ccc;
357
+ border-top: 0;
358
+ display: -webkit-box;
359
+ display: -ms-flexbox;
360
+ display: flex;
361
+ -ms-flex-flow: column wrap;
362
+ flex-flow:column wrap;
363
+ }
364
+
365
+ .module-content {
366
+ padding: 15px;
367
+ }
368
+
369
+ .module-content p:last-child {
370
+ margin-bottom: 0;
371
+ }
372
+
373
+ #main-nav .dashicons {
374
+ line-height: 2.7;
375
+ }
376
+
377
+ /*--------------------------------------------------------------
378
+ # Toggle Switch
379
+ --------------------------------------------------------------*/
380
+ .switch {
381
+ -webkit-box-flex: 0;
382
+ -webkit-flex-grow: 0;
383
+ -moz-box-flex: 0;
384
+ -ms-flex-positive: 0;
385
+ flex-grow: 0;
386
+ -webkit-flex-shrink: 0;
387
+ -ms-flex-negative: 0;
388
+ flex-shrink: 0;
389
+ position: relative;
390
+ float: none;
391
+ right: 0;
392
+ }
393
+
394
+ .module-title.active {
395
+ background-color: #0085c3;
396
+ }
397
+
398
+ .switch label {
399
+ background-color: #fff;
400
+ border-radius: 11px;
401
+ cursor: pointer;
402
+ height: 21px;
403
+ left:0;
404
+ position: absolute;
405
+ top: 0;
406
+ width: 41px;
407
+ }
408
+
409
+ .switch input[type="checkbox"] {
410
+ visibility: hidden;
411
+ }
412
+
413
+ .switch label:after {
414
+ background-color: #00618d;
415
+ border-radius: 100%;
416
+ content: '';
417
+ height: 17px;
418
+ left: 2px;
419
+ position: absolute;
420
+ -webkit-transition: all 0.2s ease-in-out;
421
+ -moz-transition: all 0.2s ease-in-out;
422
+ o-transition: all 0.2s ease-in-out;
423
+ transition: all 0.2s ease-in-out;
424
+ top: 2px;
425
+ width: 17px;
426
+ }
427
+
428
+ .switch input[type="checkbox"]:checked + label:after {
429
+ left: 22px;
430
+ background-color: #0085c3;
431
+ }
432
+
433
+ .loader {
434
+ border: 5px solid #00618d;
435
+ border-radius: 50%;
436
+ border-top: 2px solid transparent;
437
+ width: 20px;
438
+ height: 20px;
439
+ -webkit-animation: spin 2s linear infinite;
440
+ animation: spin 2s linear infinite;
441
+ position: absolute;
442
+ top: -20px;
443
+ right: 20px;
444
+ display: none;
445
+ }
446
+
447
+ @-webkit-keyframes spin {
448
+ 0% { -webkit-transform: rotate(0deg); }
449
+ 100% { -webkit-transform: rotate(360deg); }
450
+ }
451
+
452
+ @keyframes spin {
453
+ 0% { transform: rotate(0deg); }
454
+ 100% { transform: rotate(360deg); }
455
+ }
456
+
457
+ /*--------------------------------------------------------------
458
+ # Other Products
459
+ --------------------------------------------------------------*/
460
+ .other-catchthemes-products {
461
+ background-color: #f9f9f9;
462
+ clear: both;
463
+ display: block;
464
+ }
465
+ .other-catchthemes-products .module-content {
466
+ border: none;
467
+ padding: 0;
468
+ position: relative;
469
+ text-align: center;
470
+ }
471
+
472
+ .other-catchthemes-products .catch-modules {
473
+ background-color: #fff;
474
+ border: 1px solid #dedede;
475
+ }
476
+
477
+ .other-catchthemes-products .catch-modules a {
478
+ color: #444;
479
+ display: block;
480
+ padding: 1em;
481
+ }
482
+
483
+ .other-catchthemes-products .catch-modules a:hover,
484
+ .other-catchthemes-products .catch-modules a:focus {
485
+ color: #0085c3;
486
+ text-decoration: none;
487
+ }
488
+
489
+ .other-catchthemes-products .catch-modules .more-details {
490
+ background-color: #00618d;
491
+ color: #fff;
492
+ padding: 16px;
493
+ position: absolute;
494
+ left: 25%;
495
+ font-size: 15px;
496
+ font-size: 0.9375rem;
497
+ right: 25%;
498
+ text-align: center;
499
+ top: 35%;
500
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
501
+ opacity: 0;
502
+ -webkit-transition: opacity 0.1s ease-in-out;
503
+ transition: opacity 0.1s ease-in-out;
504
+ }
505
+
506
+ .other-catchthemes-products .module-content:hover .more-details,
507
+ .other-catchthemes-products .module-content:focus .more-details {
508
+ color: #fff;
509
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
510
+ opacity: 1;
511
+ text-decoration: none;
512
+ }
513
+
514
+ .other-catchthemes-products .catch-modules .modules-thumbnail {
515
+ padding: 0;
516
+ }
517
+
518
+ /*--------------------------------------------------------------
519
+ # Footer
520
+ --------------------------------------------------------------*/
521
+ .footer-navigation {
522
+ font-family: "Trebuchet MS", Helvetica, sans-serif;
523
+ }
524
+
525
+ .menu-footer-container {
526
+ padding: 10px 20px 30px;
527
+ }
528
+
529
+ .footer-navigation ul {
530
+ list-style: none;
531
+ }
532
+
533
+ .footer-navigation a {
534
+ color: #444;
535
+ text-transform: capitalize;
536
+ padding: 10px 8px 10px 6px;
537
+ display: block;
538
+ }
539
+
540
+ .footer-navigation a:hover,
541
+ .footer-navigation a:focus {
542
+ color: #0085c3;
543
+ text-decoration: none;
544
+ }
545
+
546
+ .site-footer .menu-footer {
547
+ display: -webkit-box;
548
+ display: -ms-flexbox;
549
+ display: flex;
550
+ -ms-flex-flow: row wrap;
551
+ flex-flow: row wrap;
552
+ -webkit-box-pack: center;
553
+ -ms-flex-pack: center;
554
+ justify-content: center;
555
+ align-items: center;
556
+ margin: 0;
557
+ }
558
+
559
+ .site-footer .menu-footer li {
560
+ margin: 0;
561
+ }
562
+
563
+ .auto-fold #wpcontent {
564
+ padding-left: 0;
565
+ }
566
+
567
+ /*--------------------------------------------------------------
568
+ # Media Queries
569
+ --------------------------------------------------------------*/
570
+
571
+ /*--------------------------------------------------------------
572
+ ## >= 320px
573
+ --------------------------------------------------------------*/
574
+ @media screen and (min-width: 20em) {
575
+ .module-header {
576
+ display: -webkit-box;
577
+ display: -ms-flexbox;
578
+ display: flex;
579
+ -ms-flex-flow: row wrap;
580
+ flex-flow: row wrap;
581
+ -webkit-box-pack: space-between;
582
+ -ms-flex-pack: space-between;
583
+ justify-content: space-between;
584
+ }
585
+
586
+ .module-title {
587
+ margin-bottom: 0;
588
+ }
589
+
590
+ .switch {
591
+ margin-right: 25px;
592
+ }
593
+ }
594
+
595
+ /*--------------------------------------------------------------
596
+ ## >= 768px
597
+ --------------------------------------------------------------*/
598
+ @media screen and (min-width: 48em) {
599
+ .container {
600
+ padding: 30px;
601
+ max-width: 100%;
602
+ }
603
+
604
+ .module-container {
605
+ -ms-flex-flow: row wrap;
606
+ flex-flow: row wrap;
607
+ -webkit-box-pack: space-between;
608
+ -ms-flex-pack: space-between;
609
+ justify-content: space-between;
610
+ }
611
+
612
+ #plugin-description {
613
+ padding-bottom: 30px;
614
+ }
615
+
616
+ .catch-modules {
617
+ flex: 0 1 48.5%;
618
+ }
619
+
620
+ .module-content {
621
+ padding: 20px;
622
+ }
623
+
624
+ .menu-footer-container {
625
+ padding: 10px 40px 30px;
626
+ }
627
+ }
628
+
629
+ /*--------------------------------------------------------------
630
+ ## >= 1024px
631
+ --------------------------------------------------------------*/
632
+ @media screen and (min-width: 64em) {
633
+ h1 {
634
+ font-size: 32px;
635
+ font-size: 2rem;
636
+ }
637
+
638
+ h2 {
639
+ font-size: 22px;
640
+ font-size: 1.375rem;
641
+ }
642
+
643
+ #site-branding {
644
+ padding: 80px 40px;
645
+ }
646
+
647
+ .module-container {
648
+ -webkit-box-pack: flex-start;
649
+ -ms-flex-pack: flex-start;
650
+ justify-content: flex-start;
651
+ }
652
+
653
+ .module-container .wrapper {
654
+ display: -webkit-box;
655
+ display: -ms-flexbox;
656
+ display: flex;
657
+ -webkit-flex-wrap:wrap;
658
+ -ms-flex-wrap: wrap;
659
+ flex-wrap: wrap;
660
+ -webkit-box-pack: flex-start;
661
+ -ms-flex-pack: flex-start;
662
+ justify-content: flex-start;
663
+ }
664
+
665
+ .catch-modules {
666
+ -ms-flex: 31.33%;
667
+ -webkit-flex: 31.33%;
668
+ flex: 0 1 31.33%;
669
+ margin: 0 1%;
670
+ }
671
+
672
+ .menu-footer-container {
673
+ padding: 25px 40px;
674
+ }
675
+
676
+ .footer-navigation a {
677
+ padding: 10px;
678
+ }
679
+ }
680
+
681
+ /*--------------------------------------------------------------
682
+ ## >= 1280px
683
+ --------------------------------------------------------------*/
684
+ @media screen and (min-width: 80em) {
685
+ body,
686
+ button,
687
+ input,
688
+ select,
689
+ textarea,
690
+ p {
691
+ font-size: 18px;
692
+ font-size: 1.1875rem;
693
+ }
694
+
695
+ h1 {
696
+ font-size: 48px;
697
+ font-size: 3rem;
698
+ }
699
+
700
+ h2 {
701
+ font-size: 24px;
702
+ font-size: 1.5rem;
703
+ }
704
+
705
+ h3 {
706
+ font-size: 20px;
707
+ font-size: 1.25rem;
708
+ }
709
+
710
+ .container {
711
+ padding: 60px 40px;
712
+ }
713
+
714
+ #plugin-description {
715
+ padding-bottom: 40px;
716
+ }
717
+
718
+ #site-branding {
719
+ padding: 100px 50px;
720
+ }
721
+
722
+ .module-content {
723
+ padding: 25px;
724
+ }
725
+
726
+ .footer-navigation a {
727
+ padding: 10px 10px 10px 13px;
728
+ }
729
+ }
admin/css/featured-content-shortcode.css ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .ect-featured-content-shortcode {
2
+ clear: both;
3
+ margin: 0;
4
+ overflow: hidden;
5
+ padding: 0;
6
+ }
7
+
8
+ .featured-content-entry {
9
+ float: left;
10
+ margin: 0 0 3em;
11
+ padding: 0;
12
+ width: 100%;
13
+ }
14
+
15
+ /* Column setting */
16
+ .featured-content-entry-column-1 {
17
+ width: 100%;
18
+ }
19
+
20
+ .featured-content-entry-column-2 {
21
+ margin-right: 4%;
22
+ width: 48%;
23
+ }
24
+
25
+ .featured-content-entry-column-3 {
26
+ margin-right: 3.5%;
27
+ width: 31%;
28
+ }
29
+
30
+ .featured-content-entry-column-4 {
31
+ margin-right: 3%;
32
+ width: 22%;
33
+ }
34
+
35
+ .featured-content-entry-column-5 {
36
+ margin-right: 2.5%;
37
+ width: 18%;
38
+ }
39
+
40
+ .featured-content-entry-column-6 {
41
+ margin-right: 2%;
42
+ width: 15%;
43
+ }
44
+ .featured-content-entry-first-item-row {
45
+ clear: both;
46
+ }
47
+ .featured-content-entry-last-item-row {
48
+ margin-right: 0;
49
+ }
50
+
51
+ @media screen and (max-width:768px) {
52
+ .featured-content-entry-mobile-first-item-row{
53
+ margin-right: 4%;
54
+ width: 48%;
55
+ clear:both;
56
+ }
57
+ .featured-content-entry-first-item-row {
58
+ clear:none;
59
+ }
60
+ .featured-content-entry-mobile-last-item-row{
61
+ width: 48%;
62
+ margin-right: 0;
63
+ }
64
+ }
65
+ /* Entry Header */
66
+ .featured-content-entry-header {
67
+ border: 0;
68
+ margin: 0;
69
+ padding: 0;
70
+ }
71
+
72
+ .featured-content-featured-image {
73
+ margin: 0;
74
+ padding: 0;
75
+ }
76
+
77
+ .featured-content-featured-image img {
78
+ border: 0;
79
+ height: auto;
80
+ max-width: 100%;
81
+ vertical-align: middle;
82
+ }
83
+
84
+ .featured-content-entry-title {
85
+ font-weight: 700;
86
+ margin: 0;
87
+ padding: 0;
88
+ }
89
+
90
+ .featured-content-featured-image + .featured-content-entry-title {
91
+ margin-top: 1.0em;
92
+ }
93
+
94
+ .featured-content-entry-title a {
95
+ border: 0;
96
+ text-decoration: none;
97
+ }
98
+
99
+ /* Entry Meta */
100
+ .featured-content-entry-meta {
101
+ margin: 0;
102
+ padding: 0;
103
+ }
104
+
105
+ .featured-content-entry-title + .featured-content-entry-meta {
106
+ margin-top: 0.75em;
107
+ }
108
+
109
+ .featured-content-entry-title + .featured-content-entry-meta:empty {
110
+ margin: 0;
111
+ }
112
+
113
+ .featured-content-entry-meta span,
114
+ .featured-content-entry-meta a {
115
+ font-size: 0.9em;
116
+ padding: 0;
117
+ }
118
+
119
+ .featured-content-entry-meta a {
120
+ border: 0;
121
+ text-decoration: none;
122
+ }
123
+ /* Entry Content */
124
+ .featured-content-entry-content {
125
+ margin: 0.75em 0 0;
126
+ padding: 0;
127
+ }
128
+
129
+ .featured-content-entry-content > :last-child {
130
+ margin: 0;
131
+ }
admin/css/portfolio-shortcode.css ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .jetpack-portfolio-shortcode {
2
+ clear: both;
3
+ margin: 0;
4
+ overflow: hidden;
5
+ padding: 0;
6
+ }
7
+
8
+ .portfolio-entry {
9
+ float: left;
10
+ margin: 0 0 3em;
11
+ padding: 0;
12
+ width: 100%;
13
+ }
14
+
15
+ /* Column setting */
16
+ .portfolio-entry-column-1 {
17
+ width: 100%;
18
+ }
19
+
20
+ .portfolio-entry-column-2 {
21
+ margin-right: 4%;
22
+ width: 48%;
23
+ }
24
+
25
+ .portfolio-entry-column-3 {
26
+ margin-right: 3.5%;
27
+ width: 31%;
28
+ }
29
+
30
+ .portfolio-entry-column-4 {
31
+ margin-right: 3%;
32
+ width: 22%;
33
+ }
34
+
35
+ .portfolio-entry-column-5 {
36
+ margin-right: 2.5%;
37
+ width: 18%;
38
+ }
39
+
40
+ .portfolio-entry-column-6 {
41
+ margin-right: 2%;
42
+ width: 15%;
43
+ }
44
+ .portfolio-entry-first-item-row {
45
+ clear: both;
46
+ }
47
+ .portfolio-entry-last-item-row {
48
+ margin-right: 0;
49
+ }
50
+
51
+ @media screen and (max-width:768px) {
52
+ .portfolio-entry-mobile-first-item-row{
53
+ margin-right: 4%;
54
+ width: 48%;
55
+ clear:both;
56
+ }
57
+ .portfolio-entry-first-item-row {
58
+ clear:none;
59
+ }
60
+ .portfolio-entry-mobile-last-item-row{
61
+ width: 48%;
62
+ margin-right: 0;
63
+ }
64
+ }
65
+ /* Entry Header */
66
+ .portfolio-entry-header {
67
+ border: 0;
68
+ margin: 0;
69
+ padding: 0;
70
+ }
71
+
72
+ .portfolio-featured-image {
73
+ margin: 0;
74
+ padding: 0;
75
+ }
76
+
77
+ .portfolio-featured-image img {
78
+ border: 0;
79
+ height: auto;
80
+ max-width: 100%;
81
+ vertical-align: middle;
82
+ }
83
+
84
+ .portfolio-entry-title {
85
+ font-weight: 700;
86
+ margin: 0;
87
+ padding: 0;
88
+ }
89
+
90
+ .portfolio-featured-image + .portfolio-entry-title {
91
+ margin-top: 1.0em;
92
+ }
93
+
94
+ .portfolio-entry-title a {
95
+ border: 0;
96
+ text-decoration: none;
97
+ }
98
+
99
+ /* Entry Meta */
100
+ .portfolio-entry-meta {
101
+ margin: 0;
102
+ padding: 0;
103
+ }
104
+
105
+ .portfolio-entry-title + .portfolio-entry-meta {
106
+ margin-top: 0.75em;
107
+ }
108
+
109
+ .portfolio-entry-title + .portfolio-entry-meta:empty {
110
+ margin: 0;
111
+ }
112
+
113
+ .portfolio-entry-meta span,
114
+ .portfolio-entry-meta a {
115
+ font-size: 0.9em;
116
+ padding: 0;
117
+ }
118
+
119
+ .portfolio-entry-meta a {
120
+ border: 0;
121
+ text-decoration: none;
122
+ }
123
+ /* Entry Content */
124
+ .portfolio-entry-content {
125
+ margin: 0.75em 0 0;
126
+ padding: 0;
127
+ }
128
+
129
+ .portfolio-entry-content > :last-child {
130
+ margin: 0;
131
+ }
admin/css/testimonial-shortcode.css ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .jetpack-testimonial-shortcode {
2
+ clear: both;
3
+ margin: 0;
4
+ overflow: hidden;
5
+ padding: 0;
6
+ }
7
+
8
+ .testimonial-entry {
9
+ float: left;
10
+ margin: 0 0 3em;
11
+ padding: 0;
12
+ width: 100%;
13
+ }
14
+
15
+ /* Column setting */
16
+ .testimonial-entry-column-1 {
17
+ width: 100%;
18
+ }
19
+
20
+ .testimonial-entry-column-2 {
21
+ margin-right: 4%;
22
+ width: 48%;
23
+ }
24
+
25
+ .testimonial-entry-column-3 {
26
+ margin-right: 3.5%;
27
+ width: 31%;
28
+ }
29
+
30
+ .testimonial-entry-column-4 {
31
+ margin-right: 3%;
32
+ width: 22%;
33
+ }
34
+
35
+ .testimonial-entry-column-5 {
36
+ margin-right: 2.5%;
37
+ width: 18%;
38
+ }
39
+
40
+ .testimonial-entry-column-6 {
41
+ margin-right: 2%;
42
+ width: 15%;
43
+ }
44
+ .testimonial-entry-first-item-row {
45
+ clear: both;
46
+ }
47
+ .testimonial-entry-last-item-row {
48
+ margin-right: 0;
49
+ }
50
+
51
+ @media screen and (max-width:768px) {
52
+ .testimonial-entry-mobile-first-item-row{
53
+ margin-right: 4%;
54
+ width: 48%;
55
+ clear:both;
56
+ }
57
+ .testimonial-entry-first-item-row {
58
+ clear:none;
59
+ }
60
+ .testimonial-entry-mobile-last-item-row{
61
+ width: 48%;
62
+ margin-right: 0;
63
+ }
64
+ }
65
+
66
+ .testimonial-featured-image {
67
+ padding: 0;
68
+ margin: 0;
69
+ }
70
+
71
+ .testimonial-featured-image img {
72
+ border: 0;
73
+ height: auto;
74
+ max-width: 100%;
75
+ vertical-align: middle;
76
+ }
77
+
78
+ .testimonial-entry-title {
79
+ font-weight: 700;
80
+ margin: 0;
81
+ padding: 0;
82
+ display: block;
83
+ }
84
+
85
+ .testimonial-featured-image + .testimonial-entry-title {
86
+ margin-top: 1.0em;
87
+ }
88
+
89
+ .testimonial-entry-title a {
90
+ border: 0;
91
+ text-decoration: none;
92
+ }
93
+
94
+ /* Entry Content */
95
+ .testimonial-entry-content {
96
+ margin: 0.75em 0;
97
+ padding: 0;
98
+ }
99
+
100
+ .testimonial-entry-content > :last-child {
101
+ margin: 0;
102
+ }
admin/images/free-plugins.jpg ADDED
Binary file
admin/images/free-themes.jpg ADDED
Binary file
admin/images/header_1680x394.jpg ADDED
Binary file
admin/images/premium-themes.jpg ADDED
Binary file
admin/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
admin/js/essential-content-types-admin.js ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function( $ ) {
2
+ 'use strict';
3
+
4
+ $(function() {
5
+ $( document ).on( 'scroll', function() {
6
+ if ( $( this ).scrollTop() > 1 ) {
7
+ $( 'nav#main-nav' ).addClass( 'sticky' );
8
+ } else {
9
+ $( 'nav#main-nav' ).removeClass( 'sticky' );
10
+ }
11
+ });
12
+
13
+ /* For Input Switch */
14
+ $( '.input-switch' ).on( 'click', function() {
15
+ var loader = $( this ).parent().next();
16
+
17
+ loader.show();
18
+
19
+ var main_control = $( this );
20
+ var data = {
21
+ 'action' : 'ect_dashboard_switch',
22
+ 'value' : this.checked,
23
+ 'option_name' : main_control.attr( 'rel' )
24
+ };
25
+
26
+ $.post( ajaxurl, data, function( response ) {
27
+ response = $.trim( response );
28
+
29
+ if ( '1' == response ) {
30
+ main_control.parent().parent().addClass( 'active' );
31
+ main_control.parent().parent().removeClass( 'inactive' );
32
+ } else if( '0' == response ) {
33
+ main_control.parent().parent().addClass( 'inactive' );
34
+ main_control.parent().parent().removeClass( 'active' );
35
+ } else {
36
+ alert( response );
37
+ }
38
+
39
+ loader.hide();
40
+ });
41
+ });
42
+ /* For Input Switch End */
43
+ });
44
+
45
+ })( jQuery );
admin/partials/dashboard-display.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provide a admin area dashboard view for the plugin
5
+ *
6
+ * This file is used to markup the admin-facing aspects of the plugin.
7
+ *
8
+ * @link https://catchthemes.com
9
+ * @since 1.0.0
10
+ *
11
+ * @package Essential_Content_Types
12
+ * @subpackage Essential_Content_Types/admin/partials
13
+ */
14
+ ?>
15
+
16
+ <div class="wpbody-content" aria-label="Main Content">
17
+ <?php
18
+ //Add header
19
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . '/partials/header.php';
20
+ ?>
21
+
22
+ <div id="dashboard">
23
+ <div class="container">
24
+ <div id="plugin-description">
25
+ <p><?php esc_html_e( '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.', 'essential-content-types' ); ?></p>
26
+ </div>
27
+
28
+ <div class="module-container">
29
+ <div id="module-portfolio" class="catch-modules">
30
+ <?php
31
+ $portfolio_options = get_option( 'ect_portfolio' );
32
+ ?>
33
+ <div class="module-header <?php echo $portfolio_options['status'] ? 'active' : 'inactive'; ?>">
34
+ <h3 class="module-title"><?php esc_html_e( 'Portfolios/Projects', 'essential-content-types' ); ?></h3>
35
+ <div class="switch">
36
+ <input type="checkbox" id="ect_portfolio" class="input-switch" rel="ect_portfolio" <?php checked( true, $portfolio_options['status'] ); ?> >
37
+ <label for="ect_portfolio"></label>
38
+ </div>
39
+
40
+ <div class="loader"></div>
41
+ </div>
42
+
43
+ <div class="module-content">
44
+ <p><?php esc_html_e( 'Portfolio – Create and display your portfolio on your website.', 'essential-content-types' ); ?></p>
45
+
46
+ <p><?php esc_html_e( 'Once enabled, Portfolio Post Type options will appear on Dashboard Menu', 'essential-content-types' ); ?></p>
47
+
48
+ <p><?php printf( esc_html__( '%1$sClick here%2$s to view Portfolio Archive Options.', 'essential-content-types' ) , '<a href ="' . esc_url( admin_url( 'customize.php?autofocus[control]=jetpack_portfolio_title' ) ) . '" target="_blank">', '</a>' ); ?></p>
49
+ </div>
50
+ </div><!-- #module-portfolio -->
51
+
52
+ <div id="module-testimonial" class="catch-modules">
53
+ <?php
54
+ $options = get_option( 'ect_testimonial' );
55
+ ?>
56
+ <div class="module-header <?php echo $options['status'] ? 'active' : 'inactive'; ?>">
57
+ <h3 class="module-title"><?php esc_html_e( 'Testimonials', 'essential-content-types' ); ?></h3>
58
+ <div class="switch">
59
+ <input type="checkbox" id="ect_testimonial" class="input-switch" rel="ect_testimonial" <?php checked( true, $options['status'] ); ?> >
60
+ <label for="ect_testimonial"></label>
61
+ </div>
62
+
63
+ <div class="loader"></div>
64
+ </div>
65
+
66
+ <div class="module-content">
67
+ <p><?php esc_html_e( 'Testimonials – Add customer testimonials to your website.', 'essential-content-types' ); ?></p>
68
+
69
+ <p><?php esc_html_e( 'Once enabled, Testimonials Post Type options will appear on Dashboard Menu', 'essential-content-types' ); ?></p>
70
+
71
+ <p><?php printf( esc_html__( '%1$sClick here%2$s to view Testimonial Achive Options.', 'essential-content-types' ) , '<a href ="' . esc_url( admin_url( 'customize.php?autofocus[control]=jetpack_testimonials[page-title]' ) ) . '" target="_blank">', '</a>' ); ?></p>
72
+ </div>
73
+ </div><!-- #module-testimonial -->
74
+
75
+ <div id="module-featured-content" class="catch-modules">
76
+ <?php
77
+ $featured_content_options = get_option( 'ect_featured_content' );
78
+ ?>
79
+ <div class="module-header <?php echo $featured_content_options['status'] ? 'active' : 'inactive'; ?>">
80
+ <h3 class="module-title"><?php esc_html_e( 'Featured Content', 'essential-content-types' ); ?></h3>
81
+
82
+ <div class="switch">
83
+ <input type="checkbox" id="ect_featured_content" class="input-switch" rel="ect_featured_content" <?php checked( true, $featured_content_options['status'] ); ?> >
84
+ <label for="ect_featured_content"></label>
85
+ </div>
86
+
87
+ <div class="loader"></div>
88
+ </div>
89
+
90
+ <div class="module-content">
91
+ <p><?php esc_html_e( 'Featured Content – Display the content you want as featured content to attract visitors\' attention.', 'essential-content-types' ); ?></p>
92
+
93
+ <p><?php esc_html_e( 'Once enabled, Featured Content Post Type options will appear on Dashboard Menu', 'essential-content-types' ); ?></p>
94
+
95
+ <p><?php printf( esc_html__( '%1$sClick here%2$s to view Featured Content Archive Options.', 'essential-content-types' ) , '<a href ="' . esc_url( admin_url( 'customize.php?autofocus[control]=featured_content_title' ) ) . '" target="_blank">', '</a>' ); ?></p>
96
+ </div>
97
+ </div><!-- #module-featured-content -->
98
+ </div><!-- .module-container -->
99
+ </div><!-- .container -->
100
+ </div> <!-- #dashboard -->
101
+
102
+ <?php
103
+ //Add other products
104
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . '/partials/other-products.php';
105
+ ?>
106
+
107
+ <?php
108
+ //Add footer
109
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . '/partials/footer.php';
110
+ ?>
111
+ </div> <!-- Main Content-->
admin/partials/essential-content-types-admin-display.php ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provide a admin area view for the plugin
5
+ *
6
+ * This file is used to markup the admin-facing aspects of the plugin.
7
+ *
8
+ * @link https://catchthemes.com
9
+ * @since 1.0.0
10
+ *
11
+ * @package Essential_Content_Types
12
+ * @subpackage Essential_Content_Types/admin/partials
13
+ */
14
+ ?>
15
+
16
+ <!-- This file should primarily consist of HTML with a little bit of PHP. -->
17
+ <div class="wpbody-content" aria-label="Main Content">
18
+ <header id="masthead" class="site-header" role="banner">
19
+ <div class="wrapper">
20
+ <div id="site-branding">
21
+ <h1 class="site-title"><a href="#">CATCH <span class="site-title-additional">WEB TOOLS</span></a></h1>
22
+ </div>
23
+
24
+ <nav id="main-nav" class="ect-main-navigation" aria-label="Priamry Menu" role="navigation">
25
+ <ul>
26
+ <li id="list-item-1"><a href="#" id="display-none" class="active">dashboard</a>
27
+ <span class="setting"><i class="dashicons dashicons-menu" aria-hidden="true"></i></span>
28
+ <ul class="drop-menu" >
29
+ <li><a href="#" class="active">dashboard</a></li>
30
+ <li><a href="">webmaster tools</a></li>
31
+ <li><a href="">custom CSS</a></li>
32
+ <li><a href="">social icons</a></li>
33
+ <li><a href="">open graph</a></li>
34
+ <li><a href="">SEO</a></li>
35
+ <li><a href="">to top</a></li>
36
+ </ul>
37
+ </li>
38
+ </ul>
39
+ </nav>
40
+ </div><!-- wrapper-->
41
+ </header> <!-- masthead -->
42
+
43
+ <div id="dashboard">
44
+ <div class="container">
45
+ <div id="plugin-description">
46
+ <p>Catch Web Tools is a simple and lightweight WordPress plugin to Help you manage your WordPress site. Power up your WordPress site with powerful features that were till now only available to Catch Themes users. We currently offer Webmaster Tools, Open Graph, Custom CSS, Social Icons, Catch IDs and basic SEO Optimization. </p>
47
+ </div>
48
+
49
+ <div id="module-container" class="wrapper">
50
+ <div id="module-webmaster-tools" class="catch-modules">
51
+ <div class="module-header inactive">
52
+ <h3 class="module-title">WebMaster tools</h3>
53
+ <div class="switch">
54
+ <input type="checkbox" id="checkbox1" class="input-switch">
55
+ <label for="checkbox1"></label>
56
+ </div>
57
+ </div>
58
+
59
+ <div class="module-content">
60
+ <p>Webmaster Tools gives you an option to add in the Site Verfication Code and Header and Footer Script required to manage your site.
61
+ </p>
62
+ </div>
63
+ </div>
64
+
65
+ <div id="module-customcss" class="catch-modules">
66
+ <div class="module-header">
67
+ <h3 class="module-title">Custom CSS</h3>
68
+ </div>
69
+
70
+ <div class="module-content">
71
+ <p>Custom CSS gives you an option to add in your CSS to your WordPress site without building Child Theme. You can just add your Custom CSS and save, it will show up in the frontend head section. Leave it blank if it is not needed.</p>
72
+ </div>
73
+ </div>
74
+
75
+ <div id="module-catchids" class="catch-modules">
76
+ <div class="module-header inactive">
77
+ <h3 class="module-title">Catch IDs</h3>
78
+ <div class="switch">
79
+ <input type="checkbox" id="checkbox2" class="input-switch">
80
+ <label for="checkbox2"></label>
81
+ </div>
82
+ </div>
83
+
84
+ <div class="module-content">
85
+ <p>Catch IDs will show Post ID, Page ID, Media ID, Links ID, Category ID, ag ID and UserID in the respective admin section tables.</p>
86
+ </div>
87
+ </div>
88
+
89
+ <div id="module-socialicons" class="catch-modules">
90
+ <div class="module-header inactive">
91
+ <h3 class="module-title">Social Icons</h3>
92
+ <div class="switch">
93
+ <input type="checkbox" id="checkbox3" class="input-switch">
94
+ <label for="checkbox3"></label>
95
+ </div>
96
+ </div>
97
+
98
+ <div class="module-content">
99
+ <p>You can add Social Icons by adding in Widgets in your Sidebar or by adding in Shortcode in your Page/Post Content or by adding the function in your template files.</p>
100
+ </div>
101
+ </div>
102
+
103
+ <div id="module-opengraph" class="catch-modules">
104
+ <div class="module-header inactive">
105
+ <h3 class="module-title">Open Graph</h3>
106
+ <div class="switch">
107
+ <input type="checkbox" id="checkbox4" class="input-switch">
108
+ <label for="checkbox4"></label>
109
+ </div>
110
+ </div>
111
+
112
+ <div class="module-content">
113
+ <p>The Open Graph protocol enables your site to become a rich object in a social graph. For instance, this is used on Facebook to allow any web page to have the same functionality as any other object on Facebook. </p>
114
+ </div>
115
+ </div>
116
+
117
+ <div id="module-seo" class="catch-modules">
118
+ <div class="module-header inactive">
119
+ <h3 class="module-title">SEO (BETA version) </h3>
120
+ <div class="switch">
121
+ <input type="checkbox" id="checkbox5" class="input-switch">
122
+ <label for="checkbox5"></label>
123
+ </div>
124
+ </div>
125
+
126
+ <div class="module-content">
127
+ <p>SEO is in beta version. SEO can be used to add SEO meta tags to Homepage, specific Pages or Posts and Categories page. This section adds SEO meta data to site's section.</p>
128
+ </div>
129
+ </div>
130
+
131
+ <div id="module-catchupdater" class="catch-modules">
132
+ <div class="module-header">
133
+ <h3 class="module-title">Catch Updater</h3>
134
+ </div>
135
+
136
+ <div class="module-content">
137
+ <p>Catch Updater is a simple and lightweight WordPress Theme Updater Module, which enables you to update your themes easily using WordPress Admin Panel.</p>
138
+ </div>
139
+ </div>
140
+
141
+ <div id="module-to-top" class="catch-modules">
142
+ <div class="module-header inactive">
143
+ <h3 class="module-title">To Top</h3>
144
+ <div class="switch">
145
+ <input type="checkbox" id="checkbox6" class="input-switch">
146
+ <label for="checkbox6"></label>
147
+ </div>
148
+ </div>
149
+
150
+ <div class="module-content">
151
+ <p>To Top plugin allows the visitor as well as admin to easily scroll back to the top of the page, with fully customizable options and ability to use image.</p>
152
+ </div>
153
+ </div>
154
+
155
+ <div id="module-security-tips" class="catch-module-long">
156
+ <div class="module-header">
157
+ <h3 class="module-title">Security Tips</h3>
158
+ </div>
159
+
160
+ <div class="module-content">
161
+ <p>Caution!!! A user with username: admin exists, need to rename this username or remove it</p>
162
+ <p>Caution!!! WordPress Table Prefix is "wp_", need to change this prefix</p>
163
+ <p>Congratulations!!! Your WordPress version is the latest.</p>
164
+ </div>
165
+ </div>
166
+ </div> <!-- Module Container -->
167
+ </div> <!-- Container-->
168
+ </div> <!-- Dashboard -->
169
+
170
+
171
+ <footer id="colophon" class="site-footer" role="content-info">
172
+ <div class="footer-container">
173
+ <nav class="footer-navigation" role="navigation" aria-label="Footer Menu">
174
+ <div class="menu-footer-container">
175
+ <ul class="menu-footer">
176
+ <li><a href="#">support Forum</a></li>
177
+ <li><a href="#">Plugin Details</a></li>
178
+ <li><a href="#">Facebook</a></li>
179
+ <li><a href="#">Twitter</a></li>
180
+ <li><a href="#">5 Star Rating</a></li>
181
+ </ul>
182
+ </div>
183
+ </nav>
184
+ </div>
185
+ </footer>
186
+ </div> <!-- Main Content-->
admin/partials/footer.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provide a admin area common footer view for the plugin
5
+ *
6
+ * This file is used to markup the admin-facing aspects of the plugin.
7
+ *
8
+ * @link https://catchthemes.com
9
+ * @since 1.0.0
10
+ *
11
+ * @package Essential_Content_Types
12
+ * @subpackage Essential_Content_Types/admin/partials
13
+ */
14
+ ?>
15
+
16
+ <footer id="colophon" class="site-footer" role="content-info">
17
+ <div class="footer-container">
18
+ <nav class="footer-navigation" role="navigation" aria-label="Footer Menu">
19
+ <div class="menu-footer-container">
20
+ <ul class="menu-footer">
21
+ <li>
22
+ <a href="https://catchthemes.com/donate" target="_blank"><?php esc_html_e( 'Donate', 'essential-content-types' ) ; ?></a>
23
+ </li>
24
+
25
+ <li>
26
+ <a href="https://catchthemes.com/support-forum" target="_blank"><?php esc_html_e( 'Support Forum', 'essential-content-types' ) ; ?></a>
27
+ </li>
28
+
29
+ <li>
30
+ <a href="https://catchthemes.com/wp-plugins/essential-content-types" target="_blank"><?php esc_html_e( 'Plugin Details', 'essential-content-types' ) ; ?></a>
31
+ </li>
32
+
33
+ <li>
34
+ <a href="https://facebook.com/catchthemes" target="_blank"><?php esc_html_e( 'Facebook', 'essential-content-types' ) ; ?></a>
35
+ </li>
36
+
37
+ <li>
38
+ <a href="https://twitter.com/catchthemes" target="_blank"><?php esc_html_e( 'Twitter', 'essential-content-types' ) ; ?></a>
39
+ </li>
40
+
41
+ <li>
42
+ <a href="https://wordpress.org/support/plugin/to-top/reviews/?rate=5#new-post" target="_blank"><?php esc_html_e( '5 Star Rating', 'essential-content-types' ) ; ?></a>
43
+ </li>
44
+ </ul><!-- .menu-footer -->
45
+ </div><!-- .menu-footer-container -->
46
+ </nav><!-- .footer-navigation -->
47
+ </div><!-- .footer-container -->
48
+ </footer><!-- #colophon -->
admin/partials/header.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provide a admin area common header view for the plugin
5
+ *
6
+ * This file is used to markup the admin-facing aspects of the plugin.
7
+ *
8
+ * @link https://catchthemes.com
9
+ * @since 1.0.0
10
+ *
11
+ * @package Essential_Content_Types
12
+ * @subpackage Essential_Content_Types/admin/partials
13
+ */
14
+ ?>
15
+
16
+ <header id="masthead" class="site-header" role="banner">
17
+ <div class="wrapper">
18
+ <div id="site-branding">
19
+ <h1 class="site-title"><a href="#">ESSENTIAL <span class="site-title-additional">CONTENT TYPES</span></a></h1>
20
+ </div>
21
+ </div><!-- .wrapper-->
22
+ </header> <!-- #masthead -->
admin/partials/other-products.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Provide a admin area common other products view for the plugin
5
+ *
6
+ * This file is used to markup the admin-facing aspects of the plugin.
7
+ *
8
+ * @link https://catchthemes.com
9
+ * @since 1.0.0
10
+ *
11
+ * @package Essential_Content_Types
12
+ * @subpackage Essential_Content_Types/admin/partials
13
+ */
14
+ ?>
15
+
16
+ <div class="other-catchthemes-products">
17
+ <div class="container">
18
+ <div class="module-container">
19
+ <div id="module-premium-themes" class="catch-modules">
20
+ <div class="module-content">
21
+ <a class="modules-thumbnail" href="https://catchthemes.com/themes/category/premium/" target="_blank" title="<?php esc_attr_e( 'View Premium Themes', 'essential-content-types' ); ?>">
22
+ <img src="<?php echo esc_url( plugins_url( 'images/premium-themes.jpg', dirname(__FILE__) ) ) ; ?>" alt="<?php esc_attr_e( 'Premium Themes', 'essential-content-types' ); ?>" title ="<?php esc_attr_e( 'Premium Themes', 'essential-content-types' ); ?>">
23
+ </a>
24
+
25
+ <a class="modules-link" href="https://catchthemes.com/themes/category/premium/" target="_blank" title="<?php esc_attr_e( 'View Premium Themes', 'essential-content-types' ); ?>"><?php esc_html_e( 'Premium Themes', 'essential-content-types' ); ?></a>
26
+
27
+ <a class="more-details" href="https://catchthemes.com/themes/category/premium/" target="_blank"><?php esc_html_e( 'View Themes', 'essential-content-types' ); ?></a>
28
+ </div>
29
+ </div><!-- #module-premium-themes -->
30
+
31
+ <div id="module-premium-plugins" class="catch-modules">
32
+ <div class="module-content">
33
+ <a class="modules-thumbnail" href="https://catchthemes.com/wp-plugins/" target="_blank" title="<?php esc_attr_e( 'View Plugins', 'essential-content-types' ); ?>">
34
+ <img src="<?php echo esc_url( plugins_url( 'images/free-plugins.jpg', dirname(__FILE__) ) ) ; ?>" alt="<?php esc_attr_e( 'Free Plugins', 'essential-content-types' ); ?>" title ="<?php esc_attr_e( 'Free Plugins', 'essential-content-types' ); ?>">
35
+ </a>
36
+
37
+ <a class="modules-link" href="https://catchthemes.com/wp-plugins/" target="_blank" title="<?php esc_attr_e( 'View Free Plugins', 'essential-content-types' ); ?>"><?php esc_html_e( 'Free Plugins', 'essential-content-types' ); ?></a>
38
+
39
+ <a class="more-details" href="https://catchthemes.com/wp-plugins/" target="_blank"><?php esc_html_e( 'View Plugins', 'essential-content-types' ); ?></a>
40
+ </div>
41
+ </div><!-- #module-free-plugins -->
42
+
43
+ <div id="module-free-themes" class="catch-modules">
44
+ <div class="module-content">
45
+ <a class="modules-thumbnail" href="https://catchthemes.com/themes/category/free/" target="_blank" title="<?php esc_attr_e( 'View Free Themes', 'essential-content-types' ); ?>">
46
+ <img src="<?php echo esc_url( plugins_url( 'images/free-themes.jpg', dirname(__FILE__) ) ) ; ?>" alt="<?php esc_attr_e( 'Free Themes', 'essential-content-types' ); ?>" title ="<?php esc_attr_e( 'Free Themes', 'essential-content-types' ); ?>">
47
+ </a>
48
+
49
+ <a class="modules-link" href="https://catchthemes.com/themes/category/free/" target="_blank" title="<?php esc_attr_e( 'View Free Themes', 'essential-content-types' ); ?>"><?php esc_html_e( 'Free Themes', 'essential-content-types' ); ?></a>
50
+
51
+ <a class="more-details" href="https://catchthemes.com/themes/category/free/" target="_blank"><?php esc_html_e( 'View Themes', 'essential-content-types' ); ?></a>
52
+ </div>
53
+ </div><!-- #module-free-themes -->
54
+ </div><!-- #module-featured-content -->
55
+ </div><!-- .container -->
56
+ </div><!-- .other-catchthemes-products -->
essential-content-types.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The plugin bootstrap file
5
+ *
6
+ * This file is read by WordPress to generate the plugin information in the plugin
7
+ * admin area. This file also includes all of the dependencies used by the plugin,
8
+ * registers the activation and deactivation functions, and defines a function
9
+ * that starts the plugin.
10
+ *
11
+ * @link https://catchthemes.com
12
+ * @since 1.0.0
13
+ * @package Essential_Content_Types
14
+ *
15
+ * @wordpress-plugin
16
+ * Plugin Name: Essential Content Types
17
+ * Plugin URI: https://catchthemes.com/wp-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.0.0
20
+ * Author: Catch Themes
21
+ * Author URI: https://catchthemes.com
22
+ * License: GPL-3.0+
23
+ * License URI: http://www.gnu.org/licenses/gpl-3.0.txt
24
+ * Text Domain: essential-content-types
25
+ * Domain Path: /languages
26
+ */
27
+
28
+ // If this file is called directly, abort.
29
+ if ( ! defined( 'WPINC' ) ) {
30
+ die;
31
+ }
32
+
33
+ /**
34
+ * The code that runs during plugin activation.
35
+ * This action is documented in includes/class-essential-content-types-activator.php
36
+ */
37
+ function activate_essential_content_types() {
38
+ require_once plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types-activator.php';
39
+ Essential_Content_Types_Activator::activate();
40
+ }
41
+
42
+ /**
43
+ * The code that runs during plugin deactivation.
44
+ * This action is documented in includes/class-essential-content-types-deactivator.php
45
+ */
46
+ function deactivate_essential_content_types() {
47
+ require_once plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types-deactivator.php';
48
+ Essential_Content_Types_Deactivator::deactivate();
49
+ }
50
+
51
+ register_activation_hook( __FILE__, 'activate_essential_content_types' );
52
+ register_deactivation_hook( __FILE__, 'deactivate_essential_content_types' );
53
+
54
+ /**
55
+ * The core plugin class that is used to define internationalization,
56
+ * admin-specific hooks, and public-facing site hooks.
57
+ */
58
+ require plugin_dir_path( __FILE__ ) . 'includes/class-essential-content-types.php';
59
+
60
+ /**
61
+ * Begins execution of the plugin.
62
+ *
63
+ * Since everything within the plugin is registered via hooks,
64
+ * then kicking off the plugin from this point in the file does
65
+ * not affect the page life cycle.
66
+ *
67
+ * @since 1.0.0
68
+ */
69
+ function run_essential_content_types() {
70
+
71
+ $plugin = new Essential_Content_Types();
72
+ $plugin->run();
73
+
74
+ }
75
+ run_essential_content_types();
includes/class-essential-content-types-activator.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Fired during plugin activation
5
+ *
6
+ * @link https://catchthemes.com
7
+ * @since 1.0.0
8
+ *
9
+ * @package Essential_Content_Types
10
+ * @subpackage Essential_Content_Types/includes
11
+ */
12
+
13
+ /**
14
+ * Fired during plugin activation.
15
+ *
16
+ * This class defines all code necessary to run during the plugin's activation.
17
+ *
18
+ * @since 1.0.0
19
+ * @package Essential_Content_Types
20
+ * @subpackage Essential_Content_Types/includes
21
+ * @author Catch Themes <info@catchthemes.com>
22
+ */
23
+ class Essential_Content_Types_Activator {
24
+
25
+ /**
26
+ * Short Description. (use period)
27
+ *
28
+ * Long Description.
29
+ *
30
+ * @since 1.0.0
31
+ */
32
+ public static function activate() {
33
+ array( 'Jetpack_Portfolio', 'activation_post_type_support' );
34
+
35
+ $options = array(
36
+ 'ect_portfolio',
37
+ 'ect_testimonial',
38
+ 'ect_featured_content'
39
+ );
40
+
41
+ $value = array( 'status' => 1 );
42
+
43
+ foreach ( $options as $option ) {
44
+ update_option( $option, $value );
45
+ }
46
+ }
47
+
48
+ }
includes/class-essential-content-types-deactivator.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Fired during plugin deactivation
5
+ *
6
+ * @link https://catchthemes.com
7
+ * @since 1.0.0
8
+ *
9
+ * @package Essential_Content_Types
10
+ * @subpackage Essential_Content_Types/includes
11
+ */
12
+
13
+ /**
14
+ * Fired during plugin deactivation.
15
+ *
16
+ * This class defines all code necessary to run during the plugin's deactivation.
17
+ *
18
+ * @since 1.0.0
19
+ * @package Essential_Content_Types
20
+ * @subpackage Essential_Content_Types/includes
21
+ * @author Catch Themes <info@catchthemes.com>
22
+ */
23
+ class Essential_Content_Types_Deactivator {
24
+
25
+ /**
26
+ * Short Description. (use period)
27
+ *
28
+ * Long Description.
29
+ *
30
+ * @since 1.0.0
31
+ */
32
+ public static function deactivate() {
33
+
34
+ }
35
+
36
+ }
includes/class-essential-content-types-i18n.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Define the internationalization functionality
5
+ *
6
+ * Loads and defines the internationalization files for this plugin
7
+ * so that it is ready for translation.
8
+ *
9
+ * @link https://catchthemes.com
10
+ * @since 1.0.0
11
+ *
12
+ * @package Essential_Content_Types
13
+ * @subpackage Essential_Content_Types/includes
14
+ */
15
+
16
+ /**
17
+ * Define the internationalization functionality.
18
+ *
19
+ * Loads and defines the internationalization files for this plugin
20
+ * so that it is ready for translation.
21
+ *
22
+ * @since 1.0.0
23
+ * @package Essential_Content_Types
24
+ * @subpackage Essential_Content_Types/includes
25
+ * @author Catch Themes <info@catchthemes.com>
26
+ */
27
+ class Essential_Content_Types_i18n {
28
+
29
+
30
+ /**
31
+ * Load the plugin text domain for translation.
32
+ *
33
+ * @since 1.0.0
34
+ */
35
+ public function load_plugin_textdomain() {
36
+
37
+ load_plugin_textdomain(
38
+ 'essential-content-types',
39
+ false,
40
+ dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/'
41
+ );
42
+
43
+ }
44
+
45
+ }
includes/class-essential-content-types-loader.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Register all actions and filters for the plugin
5
+ *
6
+ * @link https://catchthemes.com
7
+ * @since 1.0.0
8
+ *
9
+ * @package Essential_Content_Types
10
+ * @subpackage Essential_Content_Types/includes
11
+ */
12
+
13
+ /**
14
+ * Register all actions and filters for the plugin.
15
+ *
16
+ * Maintain a list of all hooks that are registered throughout
17
+ * the plugin, and register them with the WordPress API. Call the
18
+ * run function to execute the list of actions and filters.
19
+ *
20
+ * @package Essential_Content_Types
21
+ * @subpackage Essential_Content_Types/includes
22
+ * @author Catch Themes <info@catchthemes.com>
23
+ */
24
+ class Essential_Content_Types_Loader {
25
+
26
+ /**
27
+ * The array of actions registered with WordPress.
28
+ *
29
+ * @since 1.0.0
30
+ * @access protected
31
+ * @var array $actions The actions registered with WordPress to fire when the plugin loads.
32
+ */
33
+ protected $actions;
34
+
35
+ /**
36
+ * The array of filters registered with WordPress.
37
+ *
38
+ * @since 1.0.0
39
+ * @access protected
40
+ * @var array $filters The filters registered with WordPress to fire when the plugin loads.
41
+ */
42
+ protected $filters;
43
+
44
+ /**
45
+ * Initialize the collections used to maintain the actions and filters.
46
+ *
47
+ * @since 1.0.0
48
+ */
49
+ public function __construct() {
50
+
51
+ $this->actions = array();
52
+ $this->filters = array();
53
+
54
+ }
55
+
56
+ /**
57
+ * Add a new action to the collection to be registered with WordPress.
58
+ *
59
+ * @since 1.0.0
60
+ * @param string $hook The name of the WordPress action that is being registered.
61
+ * @param object $component A reference to the instance of the object on which the action is defined.
62
+ * @param string $callback The name of the function definition on the $component.
63
+ * @param int $priority Optional. he priority at which the function should be fired. Default is 10.
64
+ * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1.
65
+ */
66
+ public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
67
+ $this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args );
68
+ }
69
+
70
+ /**
71
+ * Add a new filter to the collection to be registered with WordPress.
72
+ *
73
+ * @since 1.0.0
74
+ * @param string $hook The name of the WordPress filter that is being registered.
75
+ * @param object $component A reference to the instance of the object on which the filter is defined.
76
+ * @param string $callback The name of the function definition on the $component.
77
+ * @param int $priority Optional. he priority at which the function should be fired. Default is 10.
78
+ * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1
79
+ */
80
+ public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
81
+ $this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args );
82
+ }
83
+
84
+ /**
85
+ * A utility function that is used to register the actions and hooks into a single
86
+ * collection.
87
+ *
88
+ * @since 1.0.0
89
+ * @access private
90
+ * @param array $hooks The collection of hooks that is being registered (that is, actions or filters).
91
+ * @param string $hook The name of the WordPress filter that is being registered.
92
+ * @param object $component A reference to the instance of the object on which the filter is defined.
93
+ * @param string $callback The name of the function definition on the $component.
94
+ * @param int $priority The priority at which the function should be fired.
95
+ * @param int $accepted_args The number of arguments that should be passed to the $callback.
96
+ * @return array The collection of actions and filters registered with WordPress.
97
+ */
98
+ private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) {
99
+
100
+ $hooks[] = array(
101
+ 'hook' => $hook,
102
+ 'component' => $component,
103
+ 'callback' => $callback,
104
+ 'priority' => $priority,
105
+ 'accepted_args' => $accepted_args
106
+ );
107
+
108
+ return $hooks;
109
+
110
+ }
111
+
112
+ /**
113
+ * Register the filters and actions with WordPress.
114
+ *
115
+ * @since 1.0.0
116
+ */
117
+ public function run() {
118
+
119
+ foreach ( $this->filters as $hook ) {
120
+ add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
121
+ }
122
+
123
+ foreach ( $this->actions as $hook ) {
124
+ add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
125
+ }
126
+
127
+ }
128
+
129
+ }
includes/class-essential-content-types.php ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * The file that defines the core plugin class
5
+ *
6
+ * A class definition that includes attributes and functions used across both the
7
+ * public-facing side of the site and the admin area.
8
+ *
9
+ * @link https://catchthemes.com
10
+ * @since 1.0.0
11
+ *
12
+ * @package Essential_Content_Types
13
+ * @subpackage Essential_Content_Types/includes
14
+ */
15
+
16
+ /**
17
+ * The core plugin class.
18
+ *
19
+ * This is used to define internationalization, admin-specific hooks, and
20
+ * public-facing site hooks.
21
+ *
22
+ * Also maintains the unique identifier of this plugin as well as the current
23
+ * version of the plugin.
24
+ *
25
+ * @since 1.0.0
26
+ * @package Essential_Content_Types
27
+ * @subpackage Essential_Content_Types/includes
28
+ * @author Catch Themes <info@catchthemes.com>
29
+ */
30
+ class Essential_Content_Types {
31
+
32
+ /**
33
+ * The loader that's responsible for maintaining and registering all hooks that power
34
+ * the plugin.
35
+ *
36
+ * @since 1.0.0
37
+ * @access protected
38
+ * @var Essential_Content_Types_Loader $loader Maintains and registers all hooks for the plugin.
39
+ */
40
+ protected $loader;
41
+
42
+ /**
43
+ * The unique identifier of this plugin.
44
+ *
45
+ * @since 1.0.0
46
+ * @access protected
47
+ * @var string $plugin_name The string used to uniquely identify this plugin.
48
+ */
49
+ protected $plugin_name;
50
+
51
+ /**
52
+ * The current version of the plugin.
53
+ *
54
+ * @since 1.0.0
55
+ * @access protected
56
+ * @var string $version The current version of the plugin.
57
+ */
58
+ protected $version;
59
+
60
+ /**
61
+ * Define the core functionality of the plugin.
62
+ *
63
+ * Set the plugin name and the plugin version that can be used throughout the plugin.
64
+ * Load the dependencies, define the locale, and set the hooks for the admin area and
65
+ * the public-facing side of the site.
66
+ *
67
+ * @since 1.0.0
68
+ */
69
+ public function __construct() {
70
+
71
+ $this->plugin_name = 'essential-content-types';
72
+ $this->version = '1.0.0';
73
+
74
+ $this->load_dependencies();
75
+ $this->set_locale();
76
+ $this->define_admin_hooks();
77
+
78
+ }
79
+
80
+ /**
81
+ * Load the required dependencies for this plugin.
82
+ *
83
+ * Include the following files that make up the plugin:
84
+ *
85
+ * - Essential_Content_Types_Loader. Orchestrates the hooks of the plugin.
86
+ * - Essential_Content_Types_i18n. Defines internationalization functionality.
87
+ * - Essential_Content_Types_Admin. Defines all hooks for the admin area.
88
+ * - Essential_Content_Types_Public. Defines all hooks for the public side of the site.
89
+ *
90
+ * Create an instance of the loader which will be used to register the hooks
91
+ * with WordPress.
92
+ *
93
+ * @since 1.0.0
94
+ * @access private
95
+ */
96
+ private function load_dependencies() {
97
+
98
+ /**
99
+ * The class responsible for orchestrating the actions and filters of the
100
+ * core plugin.
101
+ */
102
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-essential-content-types-loader.php';
103
+
104
+ /**
105
+ * The class responsible for defining internationalization functionality
106
+ * of the plugin.
107
+ */
108
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-essential-content-types-i18n.php';
109
+
110
+ /**
111
+ * The class responsible for defining all actions that occur in the admin area.
112
+ */
113
+ require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-essential-content-types-admin.php';
114
+
115
+ $this->loader = new Essential_Content_Types_Loader();
116
+
117
+ }
118
+
119
+ /**
120
+ * Define the locale for this plugin for internationalization.
121
+ *
122
+ * Uses the Essential_Content_Types_i18n class in order to set the domain and to register the hook
123
+ * with WordPress.
124
+ *
125
+ * @since 1.0.0
126
+ * @access private
127
+ */
128
+ private function set_locale() {
129
+
130
+ $plugin_i18n = new Essential_Content_Types_i18n();
131
+
132
+ $this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' );
133
+
134
+ }
135
+
136
+ /**
137
+ * Register all of the hooks related to the admin area functionality
138
+ * of the plugin.
139
+ *
140
+ * @since 1.0.0
141
+ * @access private
142
+ */
143
+ private function define_admin_hooks() {
144
+
145
+ $plugin_admin = new Essential_Content_Types_Admin( $this->get_plugin_name(), $this->get_version() );
146
+
147
+ $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
148
+ $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
149
+
150
+ $this->loader->add_action( 'admin_menu', $plugin_admin, 'settings_menu' );
151
+
152
+ ////Add ajax request handler for dashbaoard switch
153
+ $this->loader->add_action( 'wp_ajax_ect_dashboard_switch', $plugin_admin, 'dashboard_switch' );
154
+ }
155
+
156
+ /**
157
+ * Run the loader to execute all of the hooks with WordPress.
158
+ *
159
+ * @since 1.0.0
160
+ */
161
+ public function run() {
162
+ $this->loader->run();
163
+ }
164
+
165
+ /**
166
+ * The name of the plugin used to uniquely identify it within the context of
167
+ * WordPress and to define internationalization functionality.
168
+ *
169
+ * @since 1.0.0
170
+ * @return string The name of the plugin.
171
+ */
172
+ public function get_plugin_name() {
173
+ return $this->plugin_name;
174
+ }
175
+
176
+ /**
177
+ * The reference to the class that orchestrates the hooks with the plugin.
178
+ *
179
+ * @since 1.0.0
180
+ * @return Essential_Content_Types_Loader Orchestrates the hooks of the plugin.
181
+ */
182
+ public function get_loader() {
183
+ return $this->loader;
184
+ }
185
+
186
+ /**
187
+ * Retrieve the version number of the plugin.
188
+ *
189
+ * @since 1.0.0
190
+ * @return string The version number of the plugin.
191
+ */
192
+ public function get_version() {
193
+ return $this->version;
194
+ }
195
+
196
+ }
includes/index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
index.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php // Silence is golden
languages/essential-content-types.pot ADDED
@@ -0,0 +1,834 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2017 Catch Themes
2
+ # This file is distributed under the GNU General Public License v3.
3
+ #, fuzzy
4
+ msgid ""
5
+ msgstr ""
6
+ "Project-Id-Version: Essential Content Types\n"
7
+ "Report-Msgid-Bugs-To: https://wordpress.org/tags/_s\n"
8
+ "POT-Creation-Date: 2017-04-20 09:18+0545\n"
9
+ "PO-Revision-Date: 2016-12-07 23:04-0500\n"
10
+ "Last-Translator: Sakin Shrestha <info@catchthemes.com>\n"
11
+ "Language-Team: Catch Themes <info@catchthemes.com>\n"
12
+ "Language: en_US\n"
13
+ "MIME-Version: 1.0\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.0.1\n"
18
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;esc_attr_e;esc_attr__;_nx;"
19
+ "esc_html__;esc_html_e\n"
20
+ "X-Poedit-Basepath: .\n"
21
+ "X-Poedit-SourceCharset: UTF-8\n"
22
+ "X-Poedit-SearchPath-0: ..\n"
23
+
24
+ #: ../admin/class-essential-content-types-admin.php:152
25
+ #: ../admin/class-essential-content-types-admin.php:153
26
+ msgid "Essential Content Types"
27
+ msgstr ""
28
+
29
+ #: ../admin/class-essential-content-types-admin.php:167
30
+ msgid "You do not have sufficient permissions to access this page."
31
+ msgstr ""
32
+
33
+ #: ../admin/class-essential-content-types-admin.php:185
34
+ msgid "Connection Error. Please try again."
35
+ msgstr ""
36
+
37
+ #: ../admin/class-featured-content.php:97
38
+ #: ../admin/class-featured-content.php:230
39
+ msgid "Featured Contents"
40
+ msgstr ""
41
+
42
+ #: ../admin/class-featured-content.php:126 ../admin/class-portfolio.php:126
43
+ #, php-format
44
+ msgid "Your theme supports <strong>%s</strong>"
45
+ msgstr ""
46
+
47
+ #: ../admin/class-featured-content.php:130
48
+ msgid "Enable Featured Contents for this site."
49
+ msgstr ""
50
+
51
+ #: ../admin/class-featured-content.php:131 ../admin/class-portfolio.php:131
52
+ #: ../admin/class-testimonial.php:153
53
+ msgid "Learn More"
54
+ msgstr ""
55
+
56
+ #: ../admin/class-featured-content.php:138
57
+ #, php-format
58
+ msgid "Featured Content pages display at most %1$s projects"
59
+ msgstr ""
60
+
61
+ #: ../admin/class-featured-content.php:228
62
+ msgid "Featured Content Items"
63
+ msgstr ""
64
+
65
+ #: ../admin/class-featured-content.php:231
66
+ #: ../admin/class-featured-content.php:232
67
+ #: ../admin/class-featured-content.php:404
68
+ #: ../admin/partials/dashboard-display.php:80
69
+ msgid "Featured Content"
70
+ msgstr ""
71
+
72
+ #: ../admin/class-featured-content.php:233
73
+ msgid "All Contents"
74
+ msgstr ""
75
+
76
+ #: ../admin/class-featured-content.php:234 ../admin/class-portfolio.php:234
77
+ #: ../admin/class-testimonial.php:267
78
+ msgid "Add New"
79
+ msgstr ""
80
+
81
+ #: ../admin/class-featured-content.php:235
82
+ msgid "Add New Content"
83
+ msgstr ""
84
+
85
+ #: ../admin/class-featured-content.php:236
86
+ msgid "Edit Content"
87
+ msgstr ""
88
+
89
+ #: ../admin/class-featured-content.php:237
90
+ msgid "New Content"
91
+ msgstr ""
92
+
93
+ #: ../admin/class-featured-content.php:238
94
+ msgid "View Content"
95
+ msgstr ""
96
+
97
+ #: ../admin/class-featured-content.php:239
98
+ msgid "Search Contents"
99
+ msgstr ""
100
+
101
+ #: ../admin/class-featured-content.php:240
102
+ msgid "No Contents found"
103
+ msgstr ""
104
+
105
+ #: ../admin/class-featured-content.php:241
106
+ msgid "No Contents found in Trash"
107
+ msgstr ""
108
+
109
+ #: ../admin/class-featured-content.php:242 ../admin/class-portfolio.php:242
110
+ msgid "Filter projects list"
111
+ msgstr ""
112
+
113
+ #: ../admin/class-featured-content.php:243
114
+ msgid "Content list navigation"
115
+ msgstr ""
116
+
117
+ #: ../admin/class-featured-content.php:244
118
+ msgid "Contents list"
119
+ msgstr ""
120
+
121
+ #: ../admin/class-featured-content.php:274
122
+ #: ../admin/class-featured-content.php:276
123
+ msgid "Content Types"
124
+ msgstr ""
125
+
126
+ #: ../admin/class-featured-content.php:275
127
+ msgid "Content Type"
128
+ msgstr ""
129
+
130
+ #: ../admin/class-featured-content.php:277
131
+ msgid "All Content Types"
132
+ msgstr ""
133
+
134
+ #: ../admin/class-featured-content.php:278
135
+ msgid "Edit Content Type"
136
+ msgstr ""
137
+
138
+ #: ../admin/class-featured-content.php:279
139
+ msgid "View Content Type"
140
+ msgstr ""
141
+
142
+ #: ../admin/class-featured-content.php:280
143
+ msgid "Update Content Type"
144
+ msgstr ""
145
+
146
+ #: ../admin/class-featured-content.php:281
147
+ msgid "Add New Content Type"
148
+ msgstr ""
149
+
150
+ #: ../admin/class-featured-content.php:282
151
+ msgid "New Content Type Name"
152
+ msgstr ""
153
+
154
+ #: ../admin/class-featured-content.php:283
155
+ msgid "Parent Content Type"
156
+ msgstr ""
157
+
158
+ #: ../admin/class-featured-content.php:284
159
+ msgid "Parent Content Type:"
160
+ msgstr ""
161
+
162
+ #: ../admin/class-featured-content.php:285
163
+ msgid "Search Content Types"
164
+ msgstr ""
165
+
166
+ #: ../admin/class-featured-content.php:286
167
+ msgid "Content type list navigation"
168
+ msgstr ""
169
+
170
+ #: ../admin/class-featured-content.php:287
171
+ msgid "Content type list"
172
+ msgstr ""
173
+
174
+ #: ../admin/class-featured-content.php:301
175
+ #: ../admin/class-featured-content.php:303
176
+ msgid "Content Tags"
177
+ msgstr ""
178
+
179
+ #: ../admin/class-featured-content.php:302
180
+ msgid "Content Tag"
181
+ msgstr ""
182
+
183
+ #: ../admin/class-featured-content.php:304
184
+ msgid "All Content Tags"
185
+ msgstr ""
186
+
187
+ #: ../admin/class-featured-content.php:305
188
+ msgid "Edit Content Tag"
189
+ msgstr ""
190
+
191
+ #: ../admin/class-featured-content.php:306
192
+ msgid "View Content Tag"
193
+ msgstr ""
194
+
195
+ #: ../admin/class-featured-content.php:307
196
+ msgid "Update Content Tag"
197
+ msgstr ""
198
+
199
+ #: ../admin/class-featured-content.php:308
200
+ msgid "Add New Content Tag"
201
+ msgstr ""
202
+
203
+ #: ../admin/class-featured-content.php:309
204
+ msgid "New Content Tag Name"
205
+ msgstr ""
206
+
207
+ #: ../admin/class-featured-content.php:310
208
+ msgid "Search Content Tags"
209
+ msgstr ""
210
+
211
+ #: ../admin/class-featured-content.php:311
212
+ msgid "Popular Content Tags"
213
+ msgstr ""
214
+
215
+ #: ../admin/class-featured-content.php:312 ../admin/class-portfolio.php:313
216
+ msgid "Separate tags with commas"
217
+ msgstr ""
218
+
219
+ #: ../admin/class-featured-content.php:313 ../admin/class-portfolio.php:314
220
+ msgid "Add or remove tags"
221
+ msgstr ""
222
+
223
+ #: ../admin/class-featured-content.php:314 ../admin/class-portfolio.php:315
224
+ msgid "Choose from the most used tags"
225
+ msgstr ""
226
+
227
+ #: ../admin/class-featured-content.php:315 ../admin/class-portfolio.php:316
228
+ msgid "No tags found."
229
+ msgstr ""
230
+
231
+ #: ../admin/class-featured-content.php:316
232
+ msgid "Content tag list navigation"
233
+ msgstr ""
234
+
235
+ #: ../admin/class-featured-content.php:317
236
+ msgid "Content tag list"
237
+ msgstr ""
238
+
239
+ #: ../admin/class-featured-content.php:337
240
+ #, php-format
241
+ msgid "Content updated. <a href=\"%s\">View item</a>"
242
+ msgstr ""
243
+
244
+ #: ../admin/class-featured-content.php:338 ../admin/class-portfolio.php:339
245
+ #: ../admin/class-testimonial.php:313
246
+ msgid "Custom field updated."
247
+ msgstr ""
248
+
249
+ #: ../admin/class-featured-content.php:339 ../admin/class-portfolio.php:340
250
+ #: ../admin/class-testimonial.php:314
251
+ msgid "Custom field deleted."
252
+ msgstr ""
253
+
254
+ #: ../admin/class-featured-content.php:340
255
+ msgid "Content updated."
256
+ msgstr ""
257
+
258
+ #: ../admin/class-featured-content.php:342
259
+ #, php-format
260
+ msgid "Content restored to revision from %s"
261
+ msgstr ""
262
+
263
+ #: ../admin/class-featured-content.php:343
264
+ #, php-format
265
+ msgid "Content published. <a href=\"%s\">View project</a>"
266
+ msgstr ""
267
+
268
+ #: ../admin/class-featured-content.php:344
269
+ msgid "Content saved."
270
+ msgstr ""
271
+
272
+ #: ../admin/class-featured-content.php:345
273
+ #, php-format
274
+ msgid ""
275
+ "Content submitted. <a target=\"_blank\" href=\"%s\">Preview project</a>"
276
+ msgstr ""
277
+
278
+ #: ../admin/class-featured-content.php:346
279
+ #, php-format
280
+ msgid ""
281
+ "Content scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
282
+ "\"%2$s\">Preview project</a>"
283
+ msgstr ""
284
+
285
+ #: ../admin/class-featured-content.php:348 ../admin/class-portfolio.php:349
286
+ #: ../admin/class-testimonial.php:323
287
+ msgid "M j, Y @ G:i"
288
+ msgstr ""
289
+
290
+ #: ../admin/class-featured-content.php:349
291
+ #, php-format
292
+ msgid ""
293
+ "Content item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
294
+ "project</a>"
295
+ msgstr ""
296
+
297
+ #: ../admin/class-featured-content.php:361
298
+ msgid "Content"
299
+ msgstr ""
300
+
301
+ #: ../admin/class-featured-content.php:411
302
+ msgid "Contents"
303
+ msgstr ""
304
+
305
+ #: ../admin/class-featured-content.php:419
306
+ msgid "Featured Content Archive Title"
307
+ msgstr ""
308
+
309
+ #: ../admin/class-featured-content.php:434
310
+ msgid "Featured Content Archive Content"
311
+ msgstr ""
312
+
313
+ #: ../admin/class-featured-content.php:450
314
+ msgid "Featured Content Archive Featured Image"
315
+ msgstr ""
316
+
317
+ #: ../admin/class-featured-content.php:695
318
+ msgid ""
319
+ "Your Featured Content Archive currently has no entries. You can start "
320
+ "creating them on your dashboard."
321
+ msgstr ""
322
+
323
+ #: ../admin/class-featured-content.php:767 ../admin/class-portfolio.php:761
324
+ msgid "Types"
325
+ msgstr ""
326
+
327
+ #: ../admin/class-featured-content.php:798 ../admin/class-portfolio.php:792
328
+ msgid "Tags"
329
+ msgstr ""
330
+
331
+ #: ../admin/class-featured-content.php:824 ../admin/class-portfolio.php:818
332
+ #, php-format
333
+ msgid "<span>Author:</span> <a href=\"%1$s\">%2$s</a>"
334
+ msgstr ""
335
+
336
+ #: ../admin/class-portfolio.php:97
337
+ msgid "Portfolio Projects"
338
+ msgstr ""
339
+
340
+ #: ../admin/class-portfolio.php:130
341
+ msgid "Enable Portfolio Projects for this site."
342
+ msgstr ""
343
+
344
+ #: ../admin/class-portfolio.php:138
345
+ #, php-format
346
+ msgid "Portfolio pages display at most %1$s projects"
347
+ msgstr ""
348
+
349
+ #: ../admin/class-portfolio.php:228
350
+ msgid "Portfolio Items"
351
+ msgstr ""
352
+
353
+ #: ../admin/class-portfolio.php:230 ../admin/class-portfolio.php:412
354
+ msgid "Projects"
355
+ msgstr ""
356
+
357
+ #: ../admin/class-portfolio.php:231 ../admin/class-portfolio.php:362
358
+ msgid "Project"
359
+ msgstr ""
360
+
361
+ #: ../admin/class-portfolio.php:232 ../admin/class-portfolio.php:405
362
+ msgid "Portfolio"
363
+ msgstr ""
364
+
365
+ #: ../admin/class-portfolio.php:233
366
+ msgid "All Projects"
367
+ msgstr ""
368
+
369
+ #: ../admin/class-portfolio.php:235
370
+ msgid "Add New Project"
371
+ msgstr ""
372
+
373
+ #: ../admin/class-portfolio.php:236
374
+ msgid "Edit Project"
375
+ msgstr ""
376
+
377
+ #: ../admin/class-portfolio.php:237
378
+ msgid "New Project"
379
+ msgstr ""
380
+
381
+ #: ../admin/class-portfolio.php:238
382
+ msgid "View Project"
383
+ msgstr ""
384
+
385
+ #: ../admin/class-portfolio.php:239
386
+ msgid "Search Projects"
387
+ msgstr ""
388
+
389
+ #: ../admin/class-portfolio.php:240
390
+ msgid "No Projects found"
391
+ msgstr ""
392
+
393
+ #: ../admin/class-portfolio.php:241
394
+ msgid "No Projects found in Trash"
395
+ msgstr ""
396
+
397
+ #: ../admin/class-portfolio.php:243
398
+ msgid "Project list navigation"
399
+ msgstr ""
400
+
401
+ #: ../admin/class-portfolio.php:244
402
+ msgid "Projects list"
403
+ msgstr ""
404
+
405
+ #: ../admin/class-portfolio.php:275 ../admin/class-portfolio.php:277
406
+ msgid "Project Types"
407
+ msgstr ""
408
+
409
+ #: ../admin/class-portfolio.php:276
410
+ msgid "Project Type"
411
+ msgstr ""
412
+
413
+ #: ../admin/class-portfolio.php:278
414
+ msgid "All Project Types"
415
+ msgstr ""
416
+
417
+ #: ../admin/class-portfolio.php:279
418
+ msgid "Edit Project Type"
419
+ msgstr ""
420
+
421
+ #: ../admin/class-portfolio.php:280
422
+ msgid "View Project Type"
423
+ msgstr ""
424
+
425
+ #: ../admin/class-portfolio.php:281
426
+ msgid "Update Project Type"
427
+ msgstr ""
428
+
429
+ #: ../admin/class-portfolio.php:282
430
+ msgid "Add New Project Type"
431
+ msgstr ""
432
+
433
+ #: ../admin/class-portfolio.php:283
434
+ msgid "New Project Type Name"
435
+ msgstr ""
436
+
437
+ #: ../admin/class-portfolio.php:284
438
+ msgid "Parent Project Type"
439
+ msgstr ""
440
+
441
+ #: ../admin/class-portfolio.php:285
442
+ msgid "Parent Project Type:"
443
+ msgstr ""
444
+
445
+ #: ../admin/class-portfolio.php:286
446
+ msgid "Search Project Types"
447
+ msgstr ""
448
+
449
+ #: ../admin/class-portfolio.php:287
450
+ msgid "Project type list navigation"
451
+ msgstr ""
452
+
453
+ #: ../admin/class-portfolio.php:288
454
+ msgid "Project type list"
455
+ msgstr ""
456
+
457
+ #: ../admin/class-portfolio.php:302 ../admin/class-portfolio.php:304
458
+ msgid "Project Tags"
459
+ msgstr ""
460
+
461
+ #: ../admin/class-portfolio.php:303
462
+ msgid "Project Tag"
463
+ msgstr ""
464
+
465
+ #: ../admin/class-portfolio.php:305
466
+ msgid "All Project Tags"
467
+ msgstr ""
468
+
469
+ #: ../admin/class-portfolio.php:306
470
+ msgid "Edit Project Tag"
471
+ msgstr ""
472
+
473
+ #: ../admin/class-portfolio.php:307
474
+ msgid "View Project Tag"
475
+ msgstr ""
476
+
477
+ #: ../admin/class-portfolio.php:308
478
+ msgid "Update Project Tag"
479
+ msgstr ""
480
+
481
+ #: ../admin/class-portfolio.php:309
482
+ msgid "Add New Project Tag"
483
+ msgstr ""
484
+
485
+ #: ../admin/class-portfolio.php:310
486
+ msgid "New Project Tag Name"
487
+ msgstr ""
488
+
489
+ #: ../admin/class-portfolio.php:311
490
+ msgid "Search Project Tags"
491
+ msgstr ""
492
+
493
+ #: ../admin/class-portfolio.php:312
494
+ msgid "Popular Project Tags"
495
+ msgstr ""
496
+
497
+ #: ../admin/class-portfolio.php:317
498
+ msgid "Project tag list navigation"
499
+ msgstr ""
500
+
501
+ #: ../admin/class-portfolio.php:318
502
+ msgid "Project tag list"
503
+ msgstr ""
504
+
505
+ #: ../admin/class-portfolio.php:338
506
+ #, php-format
507
+ msgid "Project updated. <a href=\"%s\">View item</a>"
508
+ msgstr ""
509
+
510
+ #: ../admin/class-portfolio.php:341
511
+ msgid "Project updated."
512
+ msgstr ""
513
+
514
+ #: ../admin/class-portfolio.php:343
515
+ #, php-format
516
+ msgid "Project restored to revision from %s"
517
+ msgstr ""
518
+
519
+ #: ../admin/class-portfolio.php:344
520
+ #, php-format
521
+ msgid "Project published. <a href=\"%s\">View project</a>"
522
+ msgstr ""
523
+
524
+ #: ../admin/class-portfolio.php:345
525
+ msgid "Project saved."
526
+ msgstr ""
527
+
528
+ #: ../admin/class-portfolio.php:346
529
+ #, php-format
530
+ msgid ""
531
+ "Project submitted. <a target=\"_blank\" href=\"%s\">Preview project</a>"
532
+ msgstr ""
533
+
534
+ #: ../admin/class-portfolio.php:347
535
+ #, php-format
536
+ msgid ""
537
+ "Project scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href="
538
+ "\"%2$s\">Preview project</a>"
539
+ msgstr ""
540
+
541
+ #: ../admin/class-portfolio.php:350
542
+ #, php-format
543
+ msgid ""
544
+ "Project item draft updated. <a target=\"_blank\" href=\"%s\">Preview "
545
+ "project</a>"
546
+ msgstr ""
547
+
548
+ #: ../admin/class-portfolio.php:420
549
+ msgid "Portfolio Archive Title"
550
+ msgstr ""
551
+
552
+ #: ../admin/class-portfolio.php:435
553
+ msgid "Portfolio Archive Content"
554
+ msgstr ""
555
+
556
+ #: ../admin/class-portfolio.php:451
557
+ msgid "Portfolio Archive Featured Image"
558
+ msgstr ""
559
+
560
+ #: ../admin/class-portfolio.php:689
561
+ msgid ""
562
+ "Your Portfolio Archive currently has no entries. You can start creating "
563
+ "them on your dashboard."
564
+ msgstr ""
565
+
566
+ #: ../admin/class-testimonial.php:118 ../admin/class-testimonial.php:263
567
+ #: ../admin/class-testimonial.php:265 ../admin/class-testimonial.php:429
568
+ #: ../admin/class-testimonial.php:435
569
+ #: ../admin/partials/dashboard-display.php:57
570
+ msgid "Testimonials"
571
+ msgstr ""
572
+
573
+ #: ../admin/class-testimonial.php:148
574
+ msgid "Your theme supports Testimonials"
575
+ msgstr ""
576
+
577
+ #: ../admin/class-testimonial.php:152
578
+ msgid "Enable Testimonials for this site."
579
+ msgstr ""
580
+
581
+ #: ../admin/class-testimonial.php:161
582
+ #, php-format
583
+ msgid "Testimonial pages display at most %1$s testimonials"
584
+ msgstr ""
585
+
586
+ #: ../admin/class-testimonial.php:261
587
+ msgid "Customer Testimonials"
588
+ msgstr ""
589
+
590
+ #: ../admin/class-testimonial.php:264
591
+ msgid "Testimonial"
592
+ msgstr ""
593
+
594
+ #: ../admin/class-testimonial.php:266
595
+ msgid "All Testimonials"
596
+ msgstr ""
597
+
598
+ #: ../admin/class-testimonial.php:268
599
+ msgid "Add New Testimonial"
600
+ msgstr ""
601
+
602
+ #: ../admin/class-testimonial.php:269
603
+ msgid "Edit Testimonial"
604
+ msgstr ""
605
+
606
+ #: ../admin/class-testimonial.php:270
607
+ msgid "New Testimonial"
608
+ msgstr ""
609
+
610
+ #: ../admin/class-testimonial.php:271
611
+ msgid "View Testimonial"
612
+ msgstr ""
613
+
614
+ #: ../admin/class-testimonial.php:272
615
+ msgid "Search Testimonials"
616
+ msgstr ""
617
+
618
+ #: ../admin/class-testimonial.php:273
619
+ msgid "No Testimonials found"
620
+ msgstr ""
621
+
622
+ #: ../admin/class-testimonial.php:274
623
+ msgid "No Testimonials found in Trash"
624
+ msgstr ""
625
+
626
+ #: ../admin/class-testimonial.php:275
627
+ msgid "Filter Testimonials list"
628
+ msgstr ""
629
+
630
+ #: ../admin/class-testimonial.php:276
631
+ msgid "Testimonial list navigation"
632
+ msgstr ""
633
+
634
+ #: ../admin/class-testimonial.php:277
635
+ msgid "Testimonials list"
636
+ msgstr ""
637
+
638
+ #: ../admin/class-testimonial.php:312
639
+ #, php-format
640
+ msgid "Testimonial updated. <a href=\"%s\">View testimonial</a>"
641
+ msgstr ""
642
+
643
+ #: ../admin/class-testimonial.php:315
644
+ msgid "Testimonial updated."
645
+ msgstr ""
646
+
647
+ #: ../admin/class-testimonial.php:317
648
+ #, php-format
649
+ msgid "Testimonial restored to revision from %s"
650
+ msgstr ""
651
+
652
+ #: ../admin/class-testimonial.php:318
653
+ #, php-format
654
+ msgid "Testimonial published. <a href=\"%s\">View testimonial</a>"
655
+ msgstr ""
656
+
657
+ #: ../admin/class-testimonial.php:319
658
+ msgid "Testimonial saved."
659
+ msgstr ""
660
+
661
+ #: ../admin/class-testimonial.php:320
662
+ #, php-format
663
+ msgid ""
664
+ "Testimonial submitted. <a target=\"_blank\" href=\"%s\">Preview "
665
+ "testimonial</a>"
666
+ msgstr ""
667
+
668
+ #: ../admin/class-testimonial.php:321
669
+ #, php-format
670
+ msgid ""
671
+ "Testimonial scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" "
672
+ "href=\"%2$s\">Preview testimonial</a>"
673
+ msgstr ""
674
+
675
+ #: ../admin/class-testimonial.php:324
676
+ #, php-format
677
+ msgid ""
678
+ "Testimonial draft updated. <a target=\"_blank\" href=\"%s\">Preview "
679
+ "testimonial</a>"
680
+ msgstr ""
681
+
682
+ #: ../admin/class-testimonial.php:337
683
+ msgid "Enter the customer's name here"
684
+ msgstr ""
685
+
686
+ #: ../admin/class-testimonial.php:346
687
+ msgid "Customer Name"
688
+ msgstr ""
689
+
690
+ #: ../admin/class-testimonial.php:412
691
+ msgid "Customize Testimonials Archive"
692
+ msgstr ""
693
+
694
+ #: ../admin/class-testimonial.php:413
695
+ msgid "Customize"
696
+ msgstr ""
697
+
698
+ #: ../admin/class-testimonial.php:441
699
+ msgid "Testimonial Archive Title"
700
+ msgstr ""
701
+
702
+ #: ../admin/class-testimonial.php:453
703
+ msgid "Testimonial Archive Content"
704
+ msgstr ""
705
+
706
+ #: ../admin/class-testimonial.php:464
707
+ msgid "Testimonial Archive Featured Image"
708
+ msgstr ""
709
+
710
+ #: ../admin/class-testimonial.php:617
711
+ msgid ""
712
+ "Your Testimonial Archive currently has no entries. You can start creating "
713
+ "them on your dashboard."
714
+ msgstr ""
715
+
716
+ #: ../admin/partials/dashboard-display.php:25
717
+ msgid ""
718
+ "Essential Content Types allows you to feature the impressive content "
719
+ "through different content/post types on your website just the way you want "
720
+ "it. These content/post types are missed by the themes in WordPress Theme "
721
+ "Directory as the feature falls more towards the plugins’ territory."
722
+ msgstr ""
723
+
724
+ #: ../admin/partials/dashboard-display.php:34
725
+ msgid "Portfolios/Projects"
726
+ msgstr ""
727
+
728
+ #: ../admin/partials/dashboard-display.php:44
729
+ msgid "Portfolio – Create and display your portfolio on your website."
730
+ msgstr ""
731
+
732
+ #: ../admin/partials/dashboard-display.php:46
733
+ msgid ""
734
+ "Once enabled, Portfolio Post Type options will appear on Dashboard Menu"
735
+ msgstr ""
736
+
737
+ #: ../admin/partials/dashboard-display.php:48
738
+ #, php-format
739
+ msgid "%1$sClick here%2$s to view Portfolio Archive Options."
740
+ msgstr ""
741
+
742
+ #: ../admin/partials/dashboard-display.php:67
743
+ msgid "Testimonials – Add customer testimonials to your website."
744
+ msgstr ""
745
+
746
+ #: ../admin/partials/dashboard-display.php:69
747
+ msgid ""
748
+ "Once enabled, Testimonials Post Type options will appear on Dashboard Menu"
749
+ msgstr ""
750
+
751
+ #: ../admin/partials/dashboard-display.php:71
752
+ #, php-format
753
+ msgid "%1$sClick here%2$s to view Testimonial Achive Options."
754
+ msgstr ""
755
+
756
+ #: ../admin/partials/dashboard-display.php:91
757
+ msgid ""
758
+ "Featured Content – Display the content you want as featured content to "
759
+ "attract visitors' attention."
760
+ msgstr ""
761
+
762
+ #: ../admin/partials/dashboard-display.php:93
763
+ msgid ""
764
+ "Once enabled, Featured Content Post Type options will appear on Dashboard "
765
+ "Menu"
766
+ msgstr ""
767
+
768
+ #: ../admin/partials/dashboard-display.php:95
769
+ #, php-format
770
+ msgid "%1$sClick here%2$s to view Featured Content Archive Options."
771
+ msgstr ""
772
+
773
+ #: ../admin/partials/footer.php:22
774
+ msgid "Donate"
775
+ msgstr ""
776
+
777
+ #: ../admin/partials/footer.php:26
778
+ msgid "Support Forum"
779
+ msgstr ""
780
+
781
+ #: ../admin/partials/footer.php:30
782
+ msgid "Plugin Details"
783
+ msgstr ""
784
+
785
+ #: ../admin/partials/footer.php:34
786
+ msgid "Facebook"
787
+ msgstr ""
788
+
789
+ #: ../admin/partials/footer.php:38
790
+ msgid "Twitter"
791
+ msgstr ""
792
+
793
+ #: ../admin/partials/footer.php:42
794
+ msgid "5 Star Rating"
795
+ msgstr ""
796
+
797
+ #: ../admin/partials/other-products.php:21
798
+ #: ../admin/partials/other-products.php:25
799
+ msgid "View Premium Themes"
800
+ msgstr ""
801
+
802
+ #: ../admin/partials/other-products.php:22
803
+ #: ../admin/partials/other-products.php:25
804
+ msgid "Premium Themes"
805
+ msgstr ""
806
+
807
+ #: ../admin/partials/other-products.php:27
808
+ #: ../admin/partials/other-products.php:51
809
+ msgid "View Themes"
810
+ msgstr ""
811
+
812
+ #: ../admin/partials/other-products.php:33
813
+ #: ../admin/partials/other-products.php:39
814
+ msgid "View Plugins"
815
+ msgstr ""
816
+
817
+ #: ../admin/partials/other-products.php:34
818
+ #: ../admin/partials/other-products.php:37
819
+ msgid "Free Plugins"
820
+ msgstr ""
821
+
822
+ #: ../admin/partials/other-products.php:37
823
+ msgid "View Free Plugins"
824
+ msgstr ""
825
+
826
+ #: ../admin/partials/other-products.php:45
827
+ #: ../admin/partials/other-products.php:49
828
+ msgid "View Free Themes"
829
+ msgstr ""
830
+
831
+ #: ../admin/partials/other-products.php:46
832
+ #: ../admin/partials/other-products.php:49
833
+ msgid "Free Themes"
834
+ msgstr ""
uninstall.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Fired when the plugin is uninstalled.
5
+ *
6
+ * When populating this file, consider the following flow
7
+ * of control:
8
+ *
9
+ * - This method should be static
10
+ * - Check if the $_REQUEST content actually is the plugin name
11
+ * - Run an admin referrer check to make sure it goes through authentication
12
+ * - Verify the output of $_GET makes sense
13
+ * - Repeat with other user roles. Best directly by using the links/query string parameters.
14
+ * - Repeat things for multisite. Once for a single site in the network, once sitewide.
15
+ *
16
+ * This file may be updated more in future version of the Boilerplate; however, this is the
17
+ * general skeleton and outline for how the file should work.
18
+ *
19
+ * For more information, see the following discussion:
20
+ * https://github.com/tommcfarlin/WordPress-Plugin-Boilerplate/pull/123#issuecomment-28541913
21
+ *
22
+ * @link https://catchthemes.com
23
+ * @since 1.0.0
24
+ *
25
+ * @package Essential_Content_Types
26
+ */
27
+
28
+ // If uninstall not called from WordPress, then exit.
29
+ if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
30
+ exit;
31
+ }
32
+
33
+ $options = array(
34
+ 'ect_portfolio',
35
+ 'ect_testimonial',
36
+ 'ect_featured_content',
37
+ );
38
+
39
+ if ( !is_multisite() ) {
40
+ // For Single site
41
+ foreach ( $options as $option) {
42
+ delete_option( $option );
43
+ }
44
+ } else {
45
+ // For Multisite
46
+ global $wpdb;
47
+
48
+ $blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
49
+ $original_blog_id = get_current_blog_id();
50
+
51
+ foreach ( $blog_ids as $blog_id ) {
52
+ switch_to_blog( $blog_id );
53
+ foreach ( $options as $option) {
54
+ delete_site_option( $option );
55
+ }
56
+ }
57
+ switch_to_blog( $original_blog_id );
58
+ }