WP Show Posts - Version 0.7

Version Description

  • Prevent direct access to files
  • Add prefix to all column classes to avoid conflicts
  • Use wp_trim_words() function for excerpts
  • Fix conflict with Maintenance plugin
  • Make columns full width on mobile
  • Allow more tag usage when excerpt is set
  • Add blank option in widget to fix bug in Customizer/Elementor
Download this release

Release Info

Developer edge22
Plugin Icon 128x128 WP Show Posts
Version 0.7
Comparing to
See all releases

Code changes from version 0.6 to 0.7

Files changed (43) hide show
  1. admin/admin.php +82 -79
  2. admin/ajax.php +107 -104
  3. admin/butterbean/butterbean.php +17 -805
  4. admin/butterbean/changelog.md +3 -1
  5. admin/butterbean/class-butterbean.php +867 -0
  6. admin/butterbean/css/butterbean.css +2 -2
  7. admin/butterbean/css/butterbean.min.css +1 -1
  8. admin/butterbean/inc/class-manager.php +3 -3
  9. admin/butterbean/inc/class-setting.php +9 -0
  10. admin/butterbean/inc/controls/class-control-checkboxes.php +3 -3
  11. admin/butterbean/inc/controls/class-control-color.php +48 -19
  12. admin/butterbean/inc/controls/class-control-datetime.php +140 -0
  13. admin/butterbean/inc/controls/class-control-excerpt.php +9 -0
  14. admin/butterbean/inc/controls/class-control-image.php +12 -1
  15. admin/butterbean/inc/controls/class-control-multi-avatars.php +2 -1
  16. admin/butterbean/inc/controls/class-control-palette.php +10 -2
  17. admin/butterbean/inc/controls/class-control-radio-image.php +2 -1
  18. admin/butterbean/inc/controls/class-control-radio.php +1 -1
  19. admin/butterbean/inc/controls/class-control-select-group.php +2 -1
  20. admin/butterbean/inc/functions-core.php +20 -14
  21. admin/butterbean/inc/settings/class-setting-array.php +11 -73
  22. admin/butterbean/inc/settings/class-setting-datetime.php +105 -0
  23. admin/butterbean/inc/settings/class-setting-multiple.php +154 -0
  24. admin/butterbean/js/butterbean.js +617 -82
  25. admin/butterbean/js/butterbean.min.js +1 -1
  26. admin/butterbean/readme.md +95 -50
  27. admin/butterbean/tmpl/control-datetime.php +55 -0
  28. admin/butterbean/tmpl/control.php +2 -2
  29. admin/css/admin.css +36 -36
  30. admin/js/admin-scripts.js +207 -205
  31. admin/js/button.js +41 -41
  32. admin/metabox.php +899 -901
  33. admin/post-type.php +59 -56
  34. admin/widget.php +103 -99
  35. css/wp-show-posts-min.css +1 -1
  36. css/wp-show-posts.css +239 -235
  37. inc/defaults.php +81 -78
  38. inc/functions.php +381 -419
  39. inc/image-resizer.php +243 -240
  40. js/jquery.matchHeight.js +398 -398
  41. license.txt +28 -28
  42. readme.txt +239 -221
  43. wp-show-posts.php +492 -485
admin/admin.php CHANGED
@@ -1,80 +1,83 @@
1
- <?php
2
- if ( ! function_exists( 'wpsp_admin_scripts' ) ) :
3
- /**
4
- * Add our admin scripts and styles
5
- * @since 0.1
6
- */
7
- add_action( 'admin_print_scripts-post-new.php', 'wpsp_admin_scripts', 11 );
8
- add_action( 'admin_print_scripts-post.php', 'wpsp_admin_scripts', 11 );
9
- function wpsp_admin_scripts()
10
- {
11
- global $post_type, $post;
12
- if( 'wp_show_posts' == $post_type ) :
13
- wp_enqueue_script( 'wpsp-admin-scripts', plugin_dir_url( __FILE__ ) . "js/admin-scripts.js", array( 'jquery' ), '', true );
14
- wp_localize_script( 'wpsp-admin-scripts', 'wpsp_object', array (
15
- 'post_id' => ( isset( $post ) ) ? $post->ID : false,
16
- 'nonce' => wp_create_nonce( 'wpsp_nonce' )
17
- ));
18
- endif;
19
- wp_enqueue_style( 'wpsp-admin', plugin_dir_url( __FILE__ ) . "css/admin.css" );
20
- }
21
- endif;
22
-
23
- if ( ! function_exists( 'wpsp_translatable_strings' ) ) :
24
- /**
25
- * Add some javascript variables to the admin head
26
- * @since 0.1
27
- */
28
- add_action( 'admin_head','wpsp_translatable_strings', 0 );
29
- function wpsp_translatable_strings()
30
- {
31
- ?>
32
- <script type="text/javascript">
33
- var wpsp_add_posts = '<?php _e( 'WP Show Posts','wp-show-posts' );?>';
34
- var wpsp_nonce = '<?php echo wp_create_nonce( 'wpsp_nonce' ); ?>';
35
- </script>
36
- <?php
37
- }
38
- endif;
39
-
40
- if ( ! function_exists( 'wpsp_add_shortcode_button' ) ) :
41
- /*
42
- * Set it up so we can register our TinyMCE button
43
- * @since 0.1
44
- */
45
- add_action('admin_init', 'wpsp_add_shortcode_button');
46
- function wpsp_add_shortcode_button()
47
- {
48
- // check user permissions
49
- if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) )
50
- return;
51
-
52
- // check if WYSIWYG is enabled
53
- if ( get_user_option( 'rich_editing' ) == 'true') {
54
- add_filter( 'mce_external_plugins', 'wpsp_shortcodes_add_tinymce_plugin' );
55
- add_filter( 'mce_buttons', 'wpsp_shortcodes_register_button' );
56
- }
57
- }
58
- endif;
59
-
60
- if ( ! function_exists( 'wpsp_shortcodes_add_tinymce_plugin' ) ) :
61
- /*
62
- * Register our tinyMCE button javascript
63
- * @since 0.1
64
- */
65
- function wpsp_shortcodes_add_tinymce_plugin( $plugin_array ) {
66
- $plugin_array[ 'wpsp_shortcode_button' ] = plugin_dir_url( __FILE__ ) . '/js/button.js';
67
- return $plugin_array;
68
- }
69
- endif;
70
-
71
- if ( ! function_exists( 'wpsp_shortcodes_register_button' ) ) :
72
- /*
73
- * Register our TinyMCE button
74
- * @since 0.1
75
- */
76
- function wpsp_shortcodes_register_button( $buttons ) {
77
- array_push( $buttons, 'wpsp_shortcode_button' );
78
- return $buttons;
79
- }
 
 
 
80
  endif;
1
+ <?php
2
+ // No direct access, please
3
+ if ( ! defined( 'ABSPATH' ) ) exit;
4
+
5
+ if ( ! function_exists( 'wpsp_admin_scripts' ) ) :
6
+ /**
7
+ * Add our admin scripts and styles
8
+ * @since 0.1
9
+ */
10
+ add_action( 'admin_print_scripts-post-new.php', 'wpsp_admin_scripts', 11 );
11
+ add_action( 'admin_print_scripts-post.php', 'wpsp_admin_scripts', 11 );
12
+ function wpsp_admin_scripts()
13
+ {
14
+ global $post_type, $post;
15
+ if( 'wp_show_posts' == $post_type ) :
16
+ wp_enqueue_script( 'wpsp-admin-scripts', plugin_dir_url( __FILE__ ) . "js/admin-scripts.js", array( 'jquery' ), '', true );
17
+ wp_localize_script( 'wpsp-admin-scripts', 'wpsp_object', array (
18
+ 'post_id' => ( isset( $post ) ) ? $post->ID : false,
19
+ 'nonce' => wp_create_nonce( 'wpsp_nonce' )
20
+ ));
21
+ endif;
22
+ wp_enqueue_style( 'wpsp-admin', plugin_dir_url( __FILE__ ) . "css/admin.css" );
23
+ }
24
+ endif;
25
+
26
+ if ( ! function_exists( 'wpsp_translatable_strings' ) ) :
27
+ /**
28
+ * Add some javascript variables to the admin head
29
+ * @since 0.1
30
+ */
31
+ add_action( 'admin_head','wpsp_translatable_strings', 0 );
32
+ function wpsp_translatable_strings()
33
+ {
34
+ ?>
35
+ <script type="text/javascript">
36
+ var wpsp_add_posts = '<?php _e( 'WP Show Posts','wp-show-posts' );?>';
37
+ var wpsp_nonce = '<?php echo wp_create_nonce( 'wpsp_nonce' ); ?>';
38
+ </script>
39
+ <?php
40
+ }
41
+ endif;
42
+
43
+ if ( ! function_exists( 'wpsp_add_shortcode_button' ) ) :
44
+ /*
45
+ * Set it up so we can register our TinyMCE button
46
+ * @since 0.1
47
+ */
48
+ add_action('admin_init', 'wpsp_add_shortcode_button');
49
+ function wpsp_add_shortcode_button()
50
+ {
51
+ // check user permissions
52
+ if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) )
53
+ return;
54
+
55
+ // check if WYSIWYG is enabled
56
+ if ( get_user_option( 'rich_editing' ) == 'true') {
57
+ add_filter( 'mce_external_plugins', 'wpsp_shortcodes_add_tinymce_plugin' );
58
+ add_filter( 'mce_buttons', 'wpsp_shortcodes_register_button' );
59
+ }
60
+ }
61
+ endif;
62
+
63
+ if ( ! function_exists( 'wpsp_shortcodes_add_tinymce_plugin' ) ) :
64
+ /*
65
+ * Register our tinyMCE button javascript
66
+ * @since 0.1
67
+ */
68
+ function wpsp_shortcodes_add_tinymce_plugin( $plugin_array ) {
69
+ $plugin_array[ 'wpsp_shortcode_button' ] = plugin_dir_url( __FILE__ ) . '/js/button.js';
70
+ return $plugin_array;
71
+ }
72
+ endif;
73
+
74
+ if ( ! function_exists( 'wpsp_shortcodes_register_button' ) ) :
75
+ /*
76
+ * Register our TinyMCE button
77
+ * @since 0.1
78
+ */
79
+ function wpsp_shortcodes_register_button( $buttons ) {
80
+ array_push( $buttons, 'wpsp_shortcode_button' );
81
+ return $buttons;
82
+ }
83
  endif;
admin/ajax.php CHANGED
@@ -1,105 +1,108 @@
1
- <?php
2
- if ( ! function_exists( 'wpsp_get_json_option' ) ) :
3
- /**
4
- * Get the current option value
5
- * @since 0.1
6
- */
7
- add_action( 'wp_ajax_wpsp_get_json_option', 'wpsp_get_json_option' );
8
- function wpsp_get_json_option()
9
- {
10
- if ( ! isset( $_POST[ 'wpsp_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wpsp_nonce' ], 'wpsp_nonce' ) )
11
- wp_die( 'Permission declined' );
12
-
13
- $option = ( get_post_meta( intval( $_POST[ 'id' ] ), sanitize_text_field( $_POST[ 'key' ] ) ) ) ? get_post_meta( intval( $_POST[ 'id' ] ), sanitize_text_field( $_POST[ 'key' ] ), true ) : false;
14
-
15
- if ( $option )
16
- echo wp_json_encode( $option );
17
-
18
- die();
19
- }
20
- endif;
21
-
22
- if ( ! function_exists( 'wpsp_get_terms' ) ) :
23
- /**
24
- * Get all of our terms depending on the set taxonomy
25
- * @since 0.1
26
- */
27
- add_action( 'wp_ajax_wpsp_get_terms', 'wpsp_get_terms' );
28
- function wpsp_get_terms()
29
- {
30
- if ( ! isset( $_POST[ 'wpsp_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wpsp_nonce' ], 'wpsp_nonce' ) )
31
- wp_die( 'Permission declined' );
32
-
33
- $terms = get_terms( sanitize_text_field( $_POST[ 'taxonomy' ] ), 'orderby=count&hide_empty=1' );
34
- $count = count( $terms );
35
- $types = array();
36
- if ( $count > 0 ) {
37
- foreach ( $terms as $term ) {
38
- $types[] = $term->slug;
39
- }
40
- }
41
-
42
- echo wp_json_encode( $types );
43
-
44
- die();
45
- }
46
- endif;
47
-
48
- if ( ! function_exists( 'wpsp_get_taxonomies' ) ) :
49
- /**
50
- * Get out taxonomies based on the set post type
51
- * @since 0.1
52
- */
53
- add_action( 'wp_ajax_wpsp_get_taxonomies', 'wpsp_get_taxonomies' );
54
- function wpsp_get_taxonomies()
55
- {
56
- if ( ! isset( $_POST[ 'wpsp_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wpsp_nonce' ], 'wpsp_nonce' ) )
57
- wp_die( 'Permission declined' );
58
-
59
- $terms = get_object_taxonomies( sanitize_text_field( $_POST[ 'post_type' ] ) );
60
- $count = count( $terms );
61
- $types = array();
62
- if ( $count > 0 ) {
63
- foreach ( $terms as $term ) {
64
- $types[] = $term;
65
- }
66
- }
67
-
68
- echo wp_json_encode( $types );
69
-
70
- die();
71
- }
72
- endif;
73
-
74
- if ( ! function_exists( 'wpsp_get_post_lists' ) ) :
75
- /**
76
- * Get all of our post lists
77
- * @since 0.1
78
- */
79
- add_action( 'wp_ajax_wpsp_get_post_lists', 'wpsp_get_post_lists' );
80
- function wpsp_get_post_lists()
81
- {
82
- if ( ! isset( $_POST[ 'wpsp_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wpsp_nonce' ], 'wpsp_nonce' ) )
83
- wp_die( 'Permission declined' );
84
-
85
- $args = array(
86
- 'posts_per_page' => -1,
87
- 'post_type' => 'wp_show_posts',
88
- 'post_status' => 'publish',
89
- 'showposts' => -1
90
- );
91
- $posts = get_posts( $args );
92
-
93
- $count = count( $posts );
94
- $types = array();
95
- if ( $count > 0 ) {
96
- foreach ( $posts as $post ) {
97
- $types[] = array( 'text' => $post->post_title, 'value' => $post->ID );
98
- }
99
- }
100
-
101
- echo wp_json_encode( $types );
102
-
103
- die();
104
- }
 
 
 
105
  endif;
1
+ <?php
2
+ // No direct access, please
3
+ if ( ! defined( 'ABSPATH' ) ) exit;
4
+
5
+ if ( ! function_exists( 'wpsp_get_json_option' ) ) :
6
+ /**
7
+ * Get the current option value
8
+ * @since 0.1
9
+ */
10
+ add_action( 'wp_ajax_wpsp_get_json_option', 'wpsp_get_json_option' );
11
+ function wpsp_get_json_option()
12
+ {
13
+ if ( ! isset( $_POST[ 'wpsp_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wpsp_nonce' ], 'wpsp_nonce' ) )
14
+ wp_die( 'Permission declined' );
15
+
16
+ $option = ( get_post_meta( intval( $_POST[ 'id' ] ), sanitize_text_field( $_POST[ 'key' ] ) ) ) ? get_post_meta( intval( $_POST[ 'id' ] ), sanitize_text_field( $_POST[ 'key' ] ), true ) : false;
17
+
18
+ if ( $option )
19
+ echo wp_json_encode( $option );
20
+
21
+ die();
22
+ }
23
+ endif;
24
+
25
+ if ( ! function_exists( 'wpsp_get_terms' ) ) :
26
+ /**
27
+ * Get all of our terms depending on the set taxonomy
28
+ * @since 0.1
29
+ */
30
+ add_action( 'wp_ajax_wpsp_get_terms', 'wpsp_get_terms' );
31
+ function wpsp_get_terms()
32
+ {
33
+ if ( ! isset( $_POST[ 'wpsp_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wpsp_nonce' ], 'wpsp_nonce' ) )
34
+ wp_die( 'Permission declined' );
35
+
36
+ $terms = get_terms( sanitize_text_field( $_POST[ 'taxonomy' ] ), 'orderby=count&hide_empty=1' );
37
+ $count = count( $terms );
38
+ $types = array();
39
+ if ( $count > 0 ) {
40
+ foreach ( $terms as $term ) {
41
+ $types[] = $term->slug;
42
+ }
43
+ }
44
+
45
+ echo wp_json_encode( $types );
46
+
47
+ die();
48
+ }
49
+ endif;
50
+
51
+ if ( ! function_exists( 'wpsp_get_taxonomies' ) ) :
52
+ /**
53
+ * Get out taxonomies based on the set post type
54
+ * @since 0.1
55
+ */
56
+ add_action( 'wp_ajax_wpsp_get_taxonomies', 'wpsp_get_taxonomies' );
57
+ function wpsp_get_taxonomies()
58
+ {
59
+ if ( ! isset( $_POST[ 'wpsp_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wpsp_nonce' ], 'wpsp_nonce' ) )
60
+ wp_die( 'Permission declined' );
61
+
62
+ $terms = get_object_taxonomies( sanitize_text_field( $_POST[ 'post_type' ] ) );
63
+ $count = count( $terms );
64
+ $types = array();
65
+ if ( $count > 0 ) {
66
+ foreach ( $terms as $term ) {
67
+ $types[] = $term;
68
+ }
69
+ }
70
+
71
+ echo wp_json_encode( $types );
72
+
73
+ die();
74
+ }
75
+ endif;
76
+
77
+ if ( ! function_exists( 'wpsp_get_post_lists' ) ) :
78
+ /**
79
+ * Get all of our post lists
80
+ * @since 0.1
81
+ */
82
+ add_action( 'wp_ajax_wpsp_get_post_lists', 'wpsp_get_post_lists' );
83
+ function wpsp_get_post_lists()
84
+ {
85
+ if ( ! isset( $_POST[ 'wpsp_nonce' ] ) || ! wp_verify_nonce( $_POST[ 'wpsp_nonce' ], 'wpsp_nonce' ) )
86
+ wp_die( 'Permission declined' );
87
+
88
+ $args = array(
89
+ 'posts_per_page' => -1,
90
+ 'post_type' => 'wp_show_posts',
91
+ 'post_status' => 'publish',
92
+ 'showposts' => -1
93
+ );
94
+ $posts = get_posts( $args );
95
+
96
+ $count = count( $posts );
97
+ $types = array();
98
+ if ( $count > 0 ) {
99
+ foreach ( $posts as $post ) {
100
+ $types[] = array( 'text' => $post->post_title, 'value' => $post->ID );
101
+ }
102
+ }
103
+
104
+ echo wp_json_encode( $types );
105
+
106
+ die();
107
+ }
108
  endif;
admin/butterbean/butterbean.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: ButterBean
4
  * Plugin URI: https://github.com/justintadlock/butterbean
5
  * Description: A little post meta framework.
6
- * Version: 1.0.0-dev
7
  * Author: Justin Tadlock
8
  * Author URI: http://themehybrid.com
9
  *
@@ -14,819 +14,31 @@
14
  * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
15
  */
16
 
17
- if ( ! class_exists( 'ButterBean' ) ) {
 
 
 
 
18
 
19
  /**
20
- * Main ButterBean class. Runs the show.
 
21
  *
22
  * @since 1.0.0
23
  * @access public
 
24
  */
25
- final class ButterBean {
26
-
27
- /**
28
- * Directory path to the plugin folder.
29
- *
30
- * @since 1.0.0
31
- * @access public
32
- * @var string
33
- */
34
- public $dir_path = '';
35
-
36
- /**
37
- * Directory URI to the plugin folder.
38
- *
39
- * @since 1.0.0
40
- * @access public
41
- * @var string
42
- */
43
- public $dir_uri = '';
44
-
45
- /**
46
- * Directory path to the template folder.
47
- *
48
- * @since 1.0.0
49
- * @access public
50
- * @var string
51
- */
52
- public $tmpl_path = '';
53
-
54
- /**
55
- * Array of managers.
56
- *
57
- * @since 1.0.0
58
- * @access public
59
- * @var array
60
- */
61
- public $managers = array();
62
-
63
- /**
64
- * Array of manager types.
65
- *
66
- * @since 1.0.0
67
- * @access public
68
- * @var array
69
- */
70
- public $manager_types = array();
71
-
72
- /**
73
- * Array of section types.
74
- *
75
- * @since 1.0.0
76
- * @access public
77
- * @var array
78
- */
79
- public $section_types = array();
80
-
81
- /**
82
- * Array of control types.
83
- *
84
- * @since 1.0.0
85
- * @access public
86
- * @var array
87
- */
88
- public $control_types = array();
89
-
90
- /**
91
- * Array of setting types.
92
- *
93
- * @since 1.0.0
94
- * @access public
95
- * @var array
96
- */
97
- public $setting_types = array();
98
-
99
- /**
100
- * Whether this is a new post. Once the post is saved and we're
101
- * no longer on the `post-new.php` screen, this is going to be
102
- * `false`.
103
- *
104
- * @since 1.0.0
105
- * @access public
106
- * @var bool
107
- */
108
- public $is_new_post = false;
109
-
110
- /**
111
- * Returns the instance.
112
- *
113
- * @since 1.0.0
114
- * @access public
115
- * @return object
116
- */
117
- public static function get_instance() {
118
-
119
- static $instance = null;
120
-
121
- if ( is_null( $instance ) ) {
122
- $instance = new self;
123
- $instance->setup();
124
- $instance->includes();
125
- $instance->setup_actions();
126
- }
127
-
128
- return $instance;
129
- }
130
-
131
- /**
132
- * Constructor method.
133
- *
134
- * @since 1.0.0
135
- * @access private
136
- * @return void
137
- */
138
- private function __construct() {}
139
-
140
- /**
141
- * Initial plugin setup.
142
- *
143
- * @since 1.0.0
144
- * @access private
145
- * @return void
146
- */
147
- private function setup() {
148
-
149
- $this->dir_path = apply_filters( 'butterbean_dir_path', trailingslashit( plugin_dir_path( __FILE__ ) ) );
150
- $this->dir_uri = apply_filters( 'butterbean_dir_uri', trailingslashit( plugin_dir_url( __FILE__ ) ) );
151
-
152
- $this->tmpl_path = trailingslashit( $this->dir_path . 'tmpl' );
153
- }
154
-
155
- /**
156
- * Loads include and admin files for the plugin.
157
- *
158
- * @since 1.0.0
159
- * @access private
160
- * @return void
161
- */
162
- private function includes() {
163
-
164
- // If not in the admin, bail.
165
- if ( ! is_admin() )
166
- return;
167
 
168
- // Load base classes.
169
- require_once( $this->dir_path . 'inc/class-manager.php' );
170
- require_once( $this->dir_path . 'inc/class-section.php' );
171
- require_once( $this->dir_path . 'inc/class-control.php' );
172
- require_once( $this->dir_path . 'inc/class-setting.php' );
173
-
174
- // Load control sub-classes.
175
- require_once( $this->dir_path . 'inc/controls/class-control-checkboxes.php' );
176
- require_once( $this->dir_path . 'inc/controls/class-control-color.php' );
177
- require_once( $this->dir_path . 'inc/controls/class-control-date.php' );
178
- require_once( $this->dir_path . 'inc/controls/class-control-image.php' );
179
- require_once( $this->dir_path . 'inc/controls/class-control-palette.php' );
180
- require_once( $this->dir_path . 'inc/controls/class-control-radio.php' );
181
- require_once( $this->dir_path . 'inc/controls/class-control-radio-image.php' );
182
- require_once( $this->dir_path . 'inc/controls/class-control-select-group.php' );
183
- require_once( $this->dir_path . 'inc/controls/class-control-textarea.php' );
184
-
185
- require_once( $this->dir_path . 'inc/controls/class-control-excerpt.php' );
186
- require_once( $this->dir_path . 'inc/controls/class-control-multi-avatars.php' );
187
- require_once( $this->dir_path . 'inc/controls/class-control-parent.php' );
188
-
189
- // Load setting sub-classes.
190
- require_once( $this->dir_path . 'inc/settings/class-setting-date.php' );
191
- require_once( $this->dir_path . 'inc/settings/class-setting-array.php' );
192
-
193
- // Load functions.
194
- require_once( $this->dir_path . 'inc/functions-core.php' );
195
- }
196
-
197
- /**
198
- * Sets up initial actions.
199
- *
200
- * @since 1.0.0
201
- * @access private
202
- * @return void
203
- */
204
- private function setup_actions() {
205
-
206
- // Call the register function.
207
- add_action( 'load-post.php', array( $this, 'register' ), 95 );
208
- add_action( 'load-post-new.php', array( $this, 'register' ), 95 );
209
-
210
- // Register default types.
211
- add_action( 'butterbean_register', array( $this, 'register_manager_types' ), -95 );
212
- add_action( 'butterbean_register', array( $this, 'register_section_types' ), -95 );
213
- add_action( 'butterbean_register', array( $this, 'register_control_types' ), -95 );
214
- add_action( 'butterbean_register', array( $this, 'register_setting_types' ), -95 );
215
- }
216
-
217
- /**
218
- * Registration callback. Fires the `butterbean_register` action hook to
219
- * allow plugins to register their managers.
220
- *
221
- * @since 1.0.0
222
- * @access public
223
- * @return void
224
- */
225
- public function register() {
226
-
227
- // If this is a new post, set the new post boolean.
228
- if ( 'load-post-new.php' === current_action() )
229
- $this->is_new_post = true;
230
-
231
- // Get the current post type.
232
- $post_type = get_current_screen()->post_type;
233
-
234
- // Action hook for registering managers.
235
- do_action( 'butterbean_register', $this, $post_type );
236
-
237
- // Loop through the managers to see if we're using on on this screen.
238
- foreach ( $this->managers as $manager ) {
239
-
240
- // If we found a matching post type, add our actions/filters.
241
- if ( ! in_array( $post_type, (array) $manager->post_type ) ) {
242
- $this->unregister_manager( $manager->name );
243
- continue;
244
- }
245
-
246
- // Sort controls and sections by priority.
247
- uasort( $manager->controls, array( $this, 'priority_sort' ) );
248
- uasort( $manager->sections, array( $this, 'priority_sort' ) );
249
- }
250
-
251
- // If no managers registered, bail.
252
- if ( ! $this->managers )
253
- return;
254
-
255
- // Add meta boxes.
256
- add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
257
-
258
- // Save settings.
259
- add_action( 'save_post', array( $this, 'update' ) );
260
-
261
- // Load scripts and styles.
262
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ) );
263
-
264
- // Localize scripts and Undescore templates.
265
- add_action( 'admin_footer', array( $this, 'localize_scripts' ) );
266
- add_action( 'admin_footer', array( $this, 'print_templates' ) );
267
- }
268
-
269
- /**
270
- * Register a manager.
271
- *
272
- * @since 1.0.0
273
- * @access public
274
- * @param object|string $manager
275
- * @param array $args
276
- * @return void
277
- */
278
- public function register_manager( $manager, $args = array() ) {
279
-
280
- if ( ! is_object( $manager ) ) {
281
-
282
- $type = isset( $args['type'] ) ? $this->get_manager_type( $args['type'] ) : $this->get_manager_type( 'default' );
283
-
284
- $manager = new $type( $manager, $args );
285
- }
286
-
287
- if ( ! $this->manager_exists( $manager->name ) )
288
- $this->managers[ $manager->name ] = $manager;
289
-
290
- return $manager;
291
- }
292
-
293
- /**
294
- * Unregisters a manager object.
295
- *
296
- * @since 1.0.0
297
- * @access public
298
- * @param string $name
299
- * @return void
300
- */
301
- public function unregister_manager( $name ) {
302
-
303
- if ( $this->manager_exists( $name ) )
304
- unset( $this->managers[ $name ] );
305
- }
306
-
307
- /**
308
- * Returns a manager object.
309
- *
310
- * @since 1.0.0
311
- * @access public
312
- * @param string $name
313
- * @return object|bool
314
- */
315
- public function get_manager( $name ) {
316
-
317
- return $this->manager_exists( $name ) ? $this->managers[ $name ] : false;
318
- }
319
-
320
- /**
321
- * Checks if a manager exists.
322
- *
323
- * @since 1.0.0
324
- * @access public
325
- * @param string $name
326
- * @return bool
327
- */
328
- public function manager_exists( $name ) {
329
-
330
- return isset( $this->managers[ $name ] );
331
- }
332
-
333
- /**
334
- * Registers a manager type. This is just a method of telling ButterBean
335
- * the class of your custom manager type. It allows the manager to be
336
- * called without having to pass an object to `register_manager()`.
337
- *
338
- * @since 1.0.0
339
- * @access public
340
- * @param string $type
341
- * @param string $class
342
- * @return void
343
- */
344
- public function register_manager_type( $type, $class ) {
345
-
346
- if ( ! $this->manager_type_exists( $type ) )
347
- $this->manager_types[ $type ] = $class;
348
- }
349
-
350
- /**
351
- * Unregisters a manager type.
352
- *
353
- * @since 1.0.0
354
- * @access public
355
- * @param string $type
356
- * @return void
357
- */
358
- public function unregister_manager_type( $type ) {
359
-
360
- if ( $this->manager_type_exists( $type ) )
361
- unset( $this->manager_types[ $type ] );
362
- }
363
-
364
- /**
365
- * Returns the class name for the manager type.
366
- *
367
- * @since 1.0.0
368
- * @access public
369
- * @param string $type
370
- * @return string
371
- */
372
- public function get_manager_type( $type ) {
373
-
374
- return $this->manager_type_exists( $type ) ? $this->manager_types[ $type ] : $this->manager_types[ 'default' ];
375
- }
376
-
377
- /**
378
- * Checks if a manager type exists.
379
- *
380
- * @since 1.0.0
381
- * @access public
382
- * @param string $type
383
- * @return bool
384
- */
385
- public function manager_type_exists( $type ) {
386
-
387
- return isset( $this->manager_types[ $type ] );
388
- }
389
-
390
- /**
391
- * Registers a section type. This is just a method of telling ButterBean
392
- * the class of your custom section type. It allows the section to be
393
- * called without having to pass an object to `register_section()`.
394
- *
395
- * @since 1.0.0
396
- * @access public
397
- * @param string $type
398
- * @param string $class
399
- * @return void
400
- */
401
- public function register_section_type( $type, $class ) {
402
-
403
- if ( ! $this->section_type_exists( $type ) )
404
- $this->section_types[ $type ] = $class;
405
- }
406
-
407
- /**
408
- * Unregisters a section type.
409
- *
410
- * @since 1.0.0
411
- * @access public
412
- * @param string $type
413
- * @return void
414
- */
415
- public function unregister_section_type( $type ) {
416
-
417
- if ( $this->section_type_exists( $type ) )
418
- unset( $this->section_types[ $type ] );
419
- }
420
-
421
- /**
422
- * Returns the class name for the section type.
423
- *
424
- * @since 1.0.0
425
- * @access public
426
- * @param string $type
427
- * @return string
428
- */
429
- public function get_section_type( $type ) {
430
-
431
- return $this->section_type_exists( $type ) ? $this->section_types[ $type ] : $this->section_types[ 'default' ];
432
- }
433
-
434
- /**
435
- * Checks if a section type exists.
436
- *
437
- * @since 1.0.0
438
- * @access public
439
- * @param string $type
440
- * @return bool
441
- */
442
- public function section_type_exists( $type ) {
443
-
444
- return isset( $this->section_types[ $type ] );
445
- }
446
-
447
- /**
448
- * Registers a control type. This is just a method of telling ButterBean
449
- * the class of your custom control type. It allows the control to be
450
- * called without having to pass an object to `register_control()`.
451
- *
452
- * @since 1.0.0
453
- * @access public
454
- * @param string $type
455
- * @param string $class
456
- * @return void
457
- */
458
- public function register_control_type( $type, $class ) {
459
-
460
- if ( ! $this->control_type_exists( $type ) )
461
- $this->control_types[ $type ] = $class;
462
- }
463
 
464
- /**
465
- * Unregisters a control type.
466
- *
467
- * @since 1.0.0
468
- * @access public
469
- * @param string $type
470
- * @return void
471
- */
472
- public function unregister_control_type( $type ) {
473
 
474
- if ( $this->control_type_exists( $type ) )
475
- unset( $this->control_types[ $type ] );
476
  }
477
-
478
- /**
479
- * Returns the class name for the control type.
480
- *
481
- * @since 1.0.0
482
- * @access public
483
- * @param string $type
484
- * @return string
485
- */
486
- public function get_control_type( $type ) {
487
-
488
- return $this->control_type_exists( $type ) ? $this->control_types[ $type ] : $this->control_types[ 'default' ];
489
- }
490
-
491
- /**
492
- * Checks if a control type exists.
493
- *
494
- * @since 1.0.0
495
- * @access public
496
- * @param string $type
497
- * @return bool
498
- */
499
- public function control_type_exists( $type ) {
500
-
501
- return isset( $this->control_types[ $type ] );
502
- }
503
-
504
- /**
505
- * Registers a setting type. This is just a method of telling ButterBean
506
- * the class of your custom setting type. It allows the setting to be
507
- * called without having to pass an object to `register_setting()`.
508
- *
509
- * @since 1.0.0
510
- * @access public
511
- * @param string $type
512
- * @param string $class
513
- * @return void
514
- */
515
- public function register_setting_type( $type, $class ) {
516
-
517
- if ( ! $this->setting_type_exists( $type ) )
518
- $this->setting_types[ $type ] = $class;
519
- }
520
-
521
- /**
522
- * Unregisters a setting type.
523
- *
524
- * @since 1.0.0
525
- * @access public
526
- * @param string $type
527
- * @return void
528
- */
529
- public function unregister_setting_type( $type ) {
530
-
531
- if ( $this->setting_type_exists( $type ) )
532
- unset( $this->setting_types[ $type ] );
533
- }
534
-
535
- /**
536
- * Returns the class name for the setting type.
537
- *
538
- * @since 1.0.0
539
- * @access public
540
- * @param string $type
541
- * @return string
542
- */
543
- public function get_setting_type( $type ) {
544
-
545
- return $this->setting_type_exists( $type ) ? $this->setting_types[ $type ] : $this->setting_types[ 'default' ];
546
- }
547
-
548
- /**
549
- * Checks if a setting type exists.
550
- *
551
- * @since 1.0.0
552
- * @access public
553
- * @param string $type
554
- * @return bool
555
- */
556
- public function setting_type_exists( $type ) {
557
-
558
- return isset( $this->setting_types[ $type ] );
559
- }
560
-
561
- /**
562
- * Registers our manager types so that devs don't have to directly instantiate
563
- * the class each time they register a manager. Instead, they can use the
564
- * `type` argument.
565
- *
566
- * @since 1.0.0
567
- * @access public
568
- * @return void
569
- */
570
- public function register_manager_types() {
571
-
572
- $this->register_manager_type( 'default', 'ButterBean_Manager' );
573
- }
574
-
575
- /**
576
- * Registers our section types so that devs don't have to directly instantiate
577
- * the class each time they register a section. Instead, they can use the
578
- * `type` argument.
579
- *
580
- * @since 1.0.0
581
- * @access public
582
- * @return void
583
- */
584
- public function register_section_types() {
585
-
586
- $this->register_section_type( 'default', 'ButterBean_Section' );
587
- }
588
-
589
- /**
590
- * Registers our control types so that devs don't have to directly instantiate
591
- * the class each time they register a control. Instead, they can use the
592
- * `type` argument.
593
- *
594
- * @since 1.0.0
595
- * @access public
596
- * @return void
597
- */
598
- public function register_control_types() {
599
-
600
- $this->register_control_type( 'default', 'ButterBean_Control' );
601
- $this->register_control_type( 'checkboxes', 'ButterBean_Control_Checkboxes' );
602
- $this->register_control_type( 'color', 'ButterBean_Control_Color' );
603
- $this->register_control_type( 'date', 'ButterBean_Control_Date' );
604
- $this->register_control_type( 'image', 'ButterBean_Control_Image' );
605
- $this->register_control_type( 'palette', 'ButterBean_Control_Palette' );
606
- $this->register_control_type( 'radio', 'ButterBean_Control_Radio' );
607
- $this->register_control_type( 'radio-image', 'ButterBean_Control_Radio_Image' );
608
- $this->register_control_type( 'select-group', 'ButterBean_Control_Select_Group' );
609
- $this->register_control_type( 'textarea', 'ButterBean_Control_Textarea' );
610
- $this->register_control_type( 'multi-avatars', 'ButterBean_Control_Multi_Avatars' );
611
- $this->register_control_type( 'parent', 'ButterBean_Control_Parent' );
612
- }
613
-
614
- /**
615
- * Registers our setting types so that devs don't have to directly instantiate
616
- * the class each time they register a setting. Instead, they can use the
617
- * `type` argument.
618
- *
619
- * @since 1.0.0
620
- * @access public
621
- * @return void
622
- */
623
- public function register_setting_types() {
624
-
625
- $this->register_setting_type( 'default', 'ButterBean_Setting' );
626
- $this->register_setting_type( 'array', 'ButterBean_Setting_Array' );
627
- $this->register_setting_type( 'date', 'ButterBean_Setting_Date' );
628
- }
629
-
630
- /**
631
- * Loads scripts and styles.
632
- *
633
- * @since 1.0.0
634
- * @access public
635
- * @return void
636
- */
637
- public function enqueue() {
638
- $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
639
-
640
- // Enqueue the main plugin script.
641
- wp_enqueue_script( 'butterbean', $this->dir_uri . "js/butterbean{$min}.js", array( 'backbone', 'wp-util' ), '', true );
642
-
643
- // Enqueue the main plugin style.
644
- wp_enqueue_style( 'butterbean', $this->dir_uri . "css/butterbean{$min}.css" );
645
-
646
- // Loop through the manager and its controls and call each control's `enqueue()` method.
647
- foreach ( $this->managers as $manager ) {
648
-
649
- $manager->enqueue();
650
-
651
- foreach ( $manager->sections as $section )
652
- $section->enqueue();
653
-
654
- foreach ( $manager->controls as $control )
655
- $control->enqueue();
656
- }
657
- }
658
-
659
- /**
660
- * Callback function for adding meta boxes. This function adds a meta box
661
- * for each of the managers.
662
- *
663
- * @since 1.0.0
664
- * @access public
665
- * @param string $post_type
666
- * @return void
667
- */
668
- public function add_meta_boxes( $post_type ) {
669
-
670
- foreach ( $this->managers as $manager ) {
671
-
672
- // If the manager is registered for the current post type, add a meta box.
673
- if ( in_array( $post_type, (array) $manager->post_type ) && $manager->check_capabilities() ) {
674
-
675
- add_meta_box(
676
- "butterbean-ui-{$manager->name}",
677
- $manager->label,
678
- array( $this, 'meta_box' ),
679
- $post_type,
680
- $manager->context,
681
- $manager->priority,
682
- array( 'manager' => $manager )
683
- );
684
- }
685
- }
686
- }
687
-
688
- /**
689
- * Displays the meta box. Note that the actual content of the meta box is
690
- * handled via Underscore.js templates. The only thing we're outputting here
691
- * is the nonce field.
692
- *
693
- * @since 1.0.0
694
- * @access public
695
- * @param object $post
696
- * @param array $metabox
697
- * @return void
698
- */
699
- public function meta_box( $post, $metabox ) {
700
-
701
- $manager = $metabox['args']['manager'];
702
-
703
- $manager->post_id = $this->post_id = $post->ID;
704
-
705
- // Nonce field to validate on save.
706
- wp_nonce_field( "butterbean_{$manager->name}_nonce", "butterbean_{$manager->name}" );
707
- }
708
-
709
- /**
710
- * Passes the appropriate section and control json data to the JS file.
711
- *
712
- * @since 1.0.0
713
- * @access public
714
- * @return void
715
- */
716
- public function localize_scripts() {
717
-
718
- $json = array( 'managers' => array() );
719
-
720
- foreach ( $this->managers as $manager ) {
721
-
722
- if ( $manager->check_capabilities() )
723
- $json['managers'][] = $manager->get_json();
724
- }
725
-
726
- wp_localize_script( 'butterbean', 'butterbean_data', $json );
727
- }
728
-
729
- /**
730
- * Prints the Underscore.js templates.
731
- *
732
- * @since 1.0.0
733
- * @access public
734
- * @return void
735
- */
736
- public function print_templates() {
737
-
738
- $m_templates = array();
739
- $s_templates = array();
740
- $c_templates = array(); ?>
741
-
742
- <script type="text/html" id="tmpl-butterbean-nav">
743
- <?php butterbean_get_nav_template(); ?>
744
- </script>
745
-
746
- <?php foreach ( $this->managers as $manager ) {
747
-
748
- if ( ! $manager->check_capabilities() )
749
- continue;
750
-
751
- if ( ! in_array( $manager->type, $m_templates ) ) {
752
- $m_templates[] = $manager->type;
753
-
754
- $manager->print_template();
755
- }
756
-
757
- foreach ( $manager->sections as $section ) {
758
-
759
- if ( ! in_array( $section->type, $s_templates ) ) {
760
- $s_templates[] = $section->type;
761
-
762
- $section->print_template();
763
- }
764
- }
765
-
766
- foreach ( $manager->controls as $control ) {
767
-
768
- if ( ! in_array( $control->type, $c_templates ) ) {
769
- $c_templates[] = $control->type;
770
-
771
- $control->print_template();
772
- }
773
- }
774
- }
775
- }
776
-
777
- /**
778
- * Saves the settings.
779
- *
780
- * @since 1.0.0
781
- * @access public
782
- * @return void
783
- */
784
- public function update( $post_id ) {
785
-
786
- $do_autosave = defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE;
787
- $is_autosave = wp_is_post_autosave( $post_id );
788
- $is_revision = wp_is_post_revision( $post_id );
789
-
790
- if ( $do_autosave || $is_autosave || $is_revision )
791
- return;
792
-
793
- foreach ( $this->managers as $manager ) {
794
-
795
- if ( $manager->check_capabilities() )
796
- $manager->save( $post_id );
797
- }
798
- }
799
-
800
- /**
801
- * Helper method for sorting sections and controls by priority.
802
- *
803
- * @since 1.0.0
804
- * @access protected
805
- * @param object $a
806
- * @param object $b
807
- * @return int
808
- */
809
- protected function priority_sort( $a, $b ) {
810
-
811
- if ( $a->priority === $b->priority )
812
- return $a->instance_number - $b->instance_number;
813
-
814
- return $a->priority - $b->priority;
815
- }
816
- }
817
-
818
- /**
819
- * Gets the instance of the `ButterBean` class. This function is useful for quickly grabbing data
820
- * used throughout the plugin.
821
- *
822
- * @since 1.0.0
823
- * @access public
824
- * @return object
825
- */
826
- function butterbean() {
827
- return ButterBean::get_instance();
828
  }
829
-
830
- // Let's do this thang!
831
- butterbean();
832
  }
3
  * Plugin Name: ButterBean
4
  * Plugin URI: https://github.com/justintadlock/butterbean
5
  * Description: A little post meta framework.
6
+ * Version: 1.0.0
7
  * Author: Justin Tadlock
8
  * Author URI: http://themehybrid.com
9
  *
14
  * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
15
  */
16
 
17
+ // For each version release, the priority needs to decrement by 1. This is so that
18
+ // we can load newer versions earlier than older versions when there's a conflict.
19
+ add_action( 'init', 'butterbean_loader_100', 9999 );
20
+
21
+ if ( ! function_exists( 'butterbean_loader_100' ) ) {
22
 
23
  /**
24
+ * Loader function. Note to change the name of this function to use the
25
+ * current version number of the plugin. `1.0.0` is `100`, `1.3.4` = `134`.
26
  *
27
  * @since 1.0.0
28
  * @access public
29
+ * @return void
30
  */
31
+ function butterbean_loader_100() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ // If not in the admin, bail.
34
+ if ( ! is_admin() )
35
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
+ // If ButterBean hasn't been loaded, let's load it.
38
+ if ( ! defined( 'BUTTERBEAN_LOADED' ) ) {
39
+ define( 'BUTTERBEAN_LOADED', true );
 
 
 
 
 
 
40
 
41
+ require_once( trailingslashit( plugin_dir_path( __FILE__ ) ) . 'class-butterbean.php' );
 
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
 
 
 
44
  }
admin/butterbean/changelog.md CHANGED
@@ -1,3 +1,5 @@
1
  # Change Log
2
 
3
- Work in progress...
 
 
1
  # Change Log
2
 
3
+ ## [1.0.0] - 2016-08-29
4
+
5
+ * Plugin launch. Everything's new!
admin/butterbean/class-butterbean.php ADDED
@@ -0,0 +1,867 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Primary plugin class. This sets up and runs the show.
4
+ *
5
+ * @package ButterBean
6
+ * @author Justin Tadlock <justin@justintadlock.com>
7
+ * @copyright Copyright (c) 2015-2016, Justin Tadlock
8
+ * @link https://github.com/justintadlock/butterbean
9
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10
+ */
11
+
12
+ if ( ! class_exists( 'ButterBean' ) ) {
13
+
14
+ /**
15
+ * Main ButterBean class. Runs the show.
16
+ *
17
+ * @since 1.0.0
18
+ * @access public
19
+ */
20
+ final class ButterBean {
21
+
22
+ /**
23
+ * Directory path to the plugin folder.
24
+ *
25
+ * @since 1.0.0
26
+ * @access public
27
+ * @var string
28
+ */
29
+ public $dir_path = '';
30
+
31
+ /**
32
+ * Directory URI to the plugin folder.
33
+ *
34
+ * @since 1.0.0
35
+ * @access public
36
+ * @var string
37
+ */
38
+ public $dir_uri = '';
39
+
40
+ /**
41
+ * Directory path to the template folder.
42
+ *
43
+ * @since 1.0.0
44
+ * @access public
45
+ * @var string
46
+ */
47
+ public $tmpl_path = '';
48
+
49
+ /**
50
+ * Array of managers.
51
+ *
52
+ * @since 1.0.0
53
+ * @access public
54
+ * @var array
55
+ */
56
+ public $managers = array();
57
+
58
+ /**
59
+ * Array of manager types.
60
+ *
61
+ * @since 1.0.0
62
+ * @access public
63
+ * @var array
64
+ */
65
+ public $manager_types = array();
66
+
67
+ /**
68
+ * Array of section types.
69
+ *
70
+ * @since 1.0.0
71
+ * @access public
72
+ * @var array
73
+ */
74
+ public $section_types = array();
75
+
76
+ /**
77
+ * Array of control types.
78
+ *
79
+ * @since 1.0.0
80
+ * @access public
81
+ * @var array
82
+ */
83
+ public $control_types = array();
84
+
85
+ /**
86
+ * Array of setting types.
87
+ *
88
+ * @since 1.0.0
89
+ * @access public
90
+ * @var array
91
+ */
92
+ public $setting_types = array();
93
+
94
+ /**
95
+ * Whether this is a new post. Once the post is saved and we're
96
+ * no longer on the `post-new.php` screen, this is going to be
97
+ * `false`.
98
+ *
99
+ * @since 1.0.0
100
+ * @access public
101
+ * @var bool
102
+ */
103
+ public $is_new_post = false;
104
+
105
+ /**
106
+ * Returns the instance.
107
+ *
108
+ * @since 1.0.0
109
+ * @access public
110
+ * @return object
111
+ */
112
+ public static function get_instance() {
113
+
114
+ static $instance = null;
115
+
116
+ if ( is_null( $instance ) ) {
117
+ $instance = new self;
118
+ $instance->setup();
119
+ $instance->includes();
120
+ $instance->setup_actions();
121
+ }
122
+
123
+ return $instance;
124
+ }
125
+
126
+ /**
127
+ * Constructor method.
128
+ *
129
+ * @since 1.0.0
130
+ * @access private
131
+ * @return void
132
+ */
133
+ private function __construct() {}
134
+
135
+ /**
136
+ * Initial plugin setup.
137
+ *
138
+ * @since 1.0.0
139
+ * @access private
140
+ * @return void
141
+ */
142
+ private function setup() {
143
+
144
+ $this->dir_path = apply_filters( 'butterbean_dir_path', trailingslashit( plugin_dir_path( __FILE__ ) ) );
145
+ $this->dir_uri = apply_filters( 'butterbean_dir_uri', trailingslashit( plugin_dir_url( __FILE__ ) ) );
146
+
147
+ $this->tmpl_path = trailingslashit( $this->dir_path . 'tmpl' );
148
+ }
149
+
150
+ /**
151
+ * Loads include and admin files for the plugin.
152
+ *
153
+ * @since 1.0.0
154
+ * @access private
155
+ * @return void
156
+ */
157
+ private function includes() {
158
+
159
+ // If not in the admin, bail.
160
+ if ( ! is_admin() )
161
+ return;
162
+
163
+ // Load base classes.
164
+ require_once( $this->dir_path . 'inc/class-manager.php' );
165
+ require_once( $this->dir_path . 'inc/class-section.php' );
166
+ require_once( $this->dir_path . 'inc/class-control.php' );
167
+ require_once( $this->dir_path . 'inc/class-setting.php' );
168
+
169
+ // Load control sub-classes.
170
+ require_once( $this->dir_path . 'inc/controls/class-control-checkboxes.php' );
171
+ require_once( $this->dir_path . 'inc/controls/class-control-color.php' );
172
+ require_once( $this->dir_path . 'inc/controls/class-control-datetime.php' );
173
+ require_once( $this->dir_path . 'inc/controls/class-control-image.php' );
174
+ require_once( $this->dir_path . 'inc/controls/class-control-palette.php' );
175
+ require_once( $this->dir_path . 'inc/controls/class-control-radio.php' );
176
+ require_once( $this->dir_path . 'inc/controls/class-control-radio-image.php' );
177
+ require_once( $this->dir_path . 'inc/controls/class-control-select-group.php' );
178
+ require_once( $this->dir_path . 'inc/controls/class-control-textarea.php' );
179
+
180
+ require_once( $this->dir_path . 'inc/controls/class-control-excerpt.php' );
181
+ require_once( $this->dir_path . 'inc/controls/class-control-multi-avatars.php' );
182
+ require_once( $this->dir_path . 'inc/controls/class-control-parent.php' );
183
+
184
+ // Load setting sub-classes.
185
+ require_once( $this->dir_path . 'inc/settings/class-setting-multiple.php' );
186
+ require_once( $this->dir_path . 'inc/settings/class-setting-datetime.php' );
187
+ require_once( $this->dir_path . 'inc/settings/class-setting-array.php' );
188
+
189
+ // Load functions.
190
+ require_once( $this->dir_path . 'inc/functions-core.php' );
191
+ }
192
+
193
+ /**
194
+ * Sets up initial actions.
195
+ *
196
+ * @since 1.0.0
197
+ * @access private
198
+ * @return void
199
+ */
200
+ private function setup_actions() {
201
+
202
+ // Call the register function.
203
+ add_action( 'load-post.php', array( $this, 'register' ), 95 );
204
+ add_action( 'load-post-new.php', array( $this, 'register' ), 95 );
205
+
206
+ // Register default types.
207
+ add_action( 'butterbean_register', array( $this, 'register_manager_types' ), -95 );
208
+ add_action( 'butterbean_register', array( $this, 'register_section_types' ), -95 );
209
+ add_action( 'butterbean_register', array( $this, 'register_control_types' ), -95 );
210
+ add_action( 'butterbean_register', array( $this, 'register_setting_types' ), -95 );
211
+ }
212
+
213
+ /**
214
+ * Registration callback. Fires the `butterbean_register` action hook to
215
+ * allow plugins to register their managers.
216
+ *
217
+ * @since 1.0.0
218
+ * @access public
219
+ * @return void
220
+ */
221
+ public function register() {
222
+
223
+ // If this is a new post, set the new post boolean.
224
+ if ( 'load-post-new.php' === current_action() )
225
+ $this->is_new_post = true;
226
+
227
+ // Get the current post type.
228
+ $post_type = get_current_screen()->post_type;
229
+
230
+ // Action hook for registering managers.
231
+ do_action( 'butterbean_register', $this, $post_type );
232
+
233
+ // Loop through the managers to see if we're using on on this screen.
234
+ foreach ( $this->managers as $manager ) {
235
+
236
+ // If we found a matching post type, add our actions/filters.
237
+ if ( ! in_array( $post_type, (array) $manager->post_type ) ) {
238
+ $this->unregister_manager( $manager->name );
239
+ continue;
240
+ }
241
+
242
+ // Sort controls and sections by priority.
243
+ uasort( $manager->controls, array( $this, 'priority_sort' ) );
244
+ uasort( $manager->sections, array( $this, 'priority_sort' ) );
245
+ }
246
+
247
+ // If no managers registered, bail.
248
+ if ( ! $this->managers )
249
+ return;
250
+
251
+ // Add meta boxes.
252
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 5 );
253
+
254
+ // Save settings.
255
+ add_action( 'save_post', array( $this, 'update' ) );
256
+
257
+ // Load scripts and styles.
258
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
259
+ add_action( 'butterbean_enqueue_scripts', array( $this, 'enqueue' ) );
260
+
261
+ // Localize scripts and Undescore templates.
262
+ add_action( 'admin_footer', array( $this, 'localize_scripts' ) );
263
+ add_action( 'admin_footer', array( $this, 'print_templates' ) );
264
+
265
+ // Renders our Backbone views.
266
+ add_action( 'admin_print_footer_scripts', array( $this, 'render_views' ), 95 );
267
+ }
268
+
269
+ /**
270
+ * Register a manager.
271
+ *
272
+ * @since 1.0.0
273
+ * @access public
274
+ * @param object|string $manager
275
+ * @param array $args
276
+ * @return void
277
+ */
278
+ public function register_manager( $manager, $args = array() ) {
279
+
280
+ if ( ! is_object( $manager ) ) {
281
+
282
+ $type = isset( $args['type'] ) ? $this->get_manager_type( $args['type'] ) : $this->get_manager_type( 'default' );
283
+
284
+ $manager = new $type( $manager, $args );
285
+ }
286
+
287
+ if ( ! $this->manager_exists( $manager->name ) )
288
+ $this->managers[ $manager->name ] = $manager;
289
+
290
+ return $manager;
291
+ }
292
+
293
+ /**
294
+ * Unregisters a manager object.
295
+ *
296
+ * @since 1.0.0
297
+ * @access public
298
+ * @param string $name
299
+ * @return void
300
+ */
301
+ public function unregister_manager( $name ) {
302
+
303
+ if ( $this->manager_exists( $name ) )
304
+ unset( $this->managers[ $name ] );
305
+ }
306
+
307
+ /**
308
+ * Returns a manager object.
309
+ *
310
+ * @since 1.0.0
311
+ * @access public
312
+ * @param string $name
313
+ * @return object|bool
314
+ */
315
+ public function get_manager( $name ) {
316
+
317
+ return $this->manager_exists( $name ) ? $this->managers[ $name ] : false;
318
+ }
319
+
320
+ /**
321
+ * Checks if a manager exists.
322
+ *
323
+ * @since 1.0.0
324
+ * @access public
325
+ * @param string $name
326
+ * @return bool
327
+ */
328
+ public function manager_exists( $name ) {
329
+
330
+ return isset( $this->managers[ $name ] );
331
+ }
332
+
333
+ /**
334
+ * Registers a manager type. This is just a method of telling ButterBean
335
+ * the class of your custom manager type. It allows the manager to be
336
+ * called without having to pass an object to `register_manager()`.
337
+ *
338
+ * @since 1.0.0
339
+ * @access public
340
+ * @param string $type
341
+ * @param string $class
342
+ * @return void
343
+ */
344
+ public function register_manager_type( $type, $class ) {
345
+
346
+ if ( ! $this->manager_type_exists( $type ) )
347
+ $this->manager_types[ $type ] = $class;
348
+ }
349
+
350
+ /**
351
+ * Unregisters a manager type.
352
+ *
353
+ * @since 1.0.0
354
+ * @access public
355
+ * @param string $type
356
+ * @return void
357
+ */
358
+ public function unregister_manager_type( $type ) {
359
+
360
+ if ( $this->manager_type_exists( $type ) )
361
+ unset( $this->manager_types[ $type ] );
362
+ }
363
+
364
+ /**
365
+ * Returns the class name for the manager type.
366
+ *
367
+ * @since 1.0.0
368
+ * @access public
369
+ * @param string $type
370
+ * @return string
371
+ */
372
+ public function get_manager_type( $type ) {
373
+
374
+ return $this->manager_type_exists( $type ) ? $this->manager_types[ $type ] : $this->manager_types[ 'default' ];
375
+ }
376
+
377
+ /**
378
+ * Checks if a manager type exists.
379
+ *
380
+ * @since 1.0.0
381
+ * @access public
382
+ * @param string $type
383
+ * @return bool
384
+ */
385
+ public function manager_type_exists( $type ) {
386
+
387
+ return isset( $this->manager_types[ $type ] );
388
+ }
389
+
390
+ /**
391
+ * Registers a section type. This is just a method of telling ButterBean
392
+ * the class of your custom section type. It allows the section to be
393
+ * called without having to pass an object to `register_section()`.
394
+ *
395
+ * @since 1.0.0
396
+ * @access public
397
+ * @param string $type
398
+ * @param string $class
399
+ * @return void
400
+ */
401
+ public function register_section_type( $type, $class ) {
402
+
403
+ if ( ! $this->section_type_exists( $type ) )
404
+ $this->section_types[ $type ] = $class;
405
+ }
406
+
407
+ /**
408
+ * Unregisters a section type.
409
+ *
410
+ * @since 1.0.0
411
+ * @access public
412
+ * @param string $type
413
+ * @return void
414
+ */
415
+ public function unregister_section_type( $type ) {
416
+
417
+ if ( $this->section_type_exists( $type ) )
418
+ unset( $this->section_types[ $type ] );
419
+ }
420
+
421
+ /**
422
+ * Returns the class name for the section type.
423
+ *
424
+ * @since 1.0.0
425
+ * @access public
426
+ * @param string $type
427
+ * @return string
428
+ */
429
+ public function get_section_type( $type ) {
430
+
431
+ return $this->section_type_exists( $type ) ? $this->section_types[ $type ] : $this->section_types[ 'default' ];
432
+ }
433
+
434
+ /**
435
+ * Checks if a section type exists.
436
+ *
437
+ * @since 1.0.0
438
+ * @access public
439
+ * @param string $type
440
+ * @return bool
441
+ */
442
+ public function section_type_exists( $type ) {
443
+
444
+ return isset( $this->section_types[ $type ] );
445
+ }
446
+
447
+ /**
448
+ * Registers a control type. This is just a method of telling ButterBean
449
+ * the class of your custom control type. It allows the control to be
450
+ * called without having to pass an object to `register_control()`.
451
+ *
452
+ * @since 1.0.0
453
+ * @access public
454
+ * @param string $type
455
+ * @param string $class
456
+ * @return void
457
+ */
458
+ public function register_control_type( $type, $class ) {
459
+
460
+ if ( ! $this->control_type_exists( $type ) )
461
+ $this->control_types[ $type ] = $class;
462
+ }
463
+
464
+ /**
465
+ * Unregisters a control type.
466
+ *
467
+ * @since 1.0.0
468
+ * @access public
469
+ * @param string $type
470
+ * @return void
471
+ */
472
+ public function unregister_control_type( $type ) {
473
+
474
+ if ( $this->control_type_exists( $type ) )
475
+ unset( $this->control_types[ $type ] );
476
+ }
477
+
478
+ /**
479
+ * Returns the class name for the control type.
480
+ *
481
+ * @since 1.0.0
482
+ * @access public
483
+ * @param string $type
484
+ * @return string
485
+ */
486
+ public function get_control_type( $type ) {
487
+
488
+ return $this->control_type_exists( $type ) ? $this->control_types[ $type ] : $this->control_types[ 'default' ];
489
+ }
490
+
491
+ /**
492
+ * Checks if a control type exists.
493
+ *
494
+ * @since 1.0.0
495
+ * @access public
496
+ * @param string $type
497
+ * @return bool
498
+ */
499
+ public function control_type_exists( $type ) {
500
+
501
+ return isset( $this->control_types[ $type ] );
502
+ }
503
+
504
+ /**
505
+ * Registers a setting type. This is just a method of telling ButterBean
506
+ * the class of your custom setting type. It allows the setting to be
507
+ * called without having to pass an object to `register_setting()`.
508
+ *
509
+ * @since 1.0.0
510
+ * @access public
511
+ * @param string $type
512
+ * @param string $class
513
+ * @return void
514
+ */
515
+ public function register_setting_type( $type, $class ) {
516
+
517
+ if ( ! $this->setting_type_exists( $type ) )
518
+ $this->setting_types[ $type ] = $class;
519
+ }
520
+
521
+ /**
522
+ * Unregisters a setting type.
523
+ *
524
+ * @since 1.0.0
525
+ * @access public
526
+ * @param string $type
527
+ * @return void
528
+ */
529
+ public function unregister_setting_type( $type ) {
530
+
531
+ if ( $this->setting_type_exists( $type ) )
532
+ unset( $this->setting_types[ $type ] );
533
+ }
534
+
535
+ /**
536
+ * Returns the class name for the setting type.
537
+ *
538
+ * @since 1.0.0
539
+ * @access public
540
+ * @param string $type
541
+ * @return string
542
+ */
543
+ public function get_setting_type( $type ) {
544
+
545
+ return $this->setting_type_exists( $type ) ? $this->setting_types[ $type ] : $this->setting_types[ 'default' ];
546
+ }
547
+
548
+ /**
549
+ * Checks if a setting type exists.
550
+ *
551
+ * @since 1.0.0
552
+ * @access public
553
+ * @param string $type
554
+ * @return bool
555
+ */
556
+ public function setting_type_exists( $type ) {
557
+
558
+ return isset( $this->setting_types[ $type ] );
559
+ }
560
+
561
+ /**
562
+ * Registers our manager types so that devs don't have to directly instantiate
563
+ * the class each time they register a manager. Instead, they can use the
564
+ * `type` argument.
565
+ *
566
+ * @since 1.0.0
567
+ * @access public
568
+ * @return void
569
+ */
570
+ public function register_manager_types() {
571
+
572
+ $this->register_manager_type( 'default', 'ButterBean_Manager' );
573
+ }
574
+
575
+ /**
576
+ * Registers our section types so that devs don't have to directly instantiate
577
+ * the class each time they register a section. Instead, they can use the
578
+ * `type` argument.
579
+ *
580
+ * @since 1.0.0
581
+ * @access public
582
+ * @return void
583
+ */
584
+ public function register_section_types() {
585
+
586
+ $this->register_section_type( 'default', 'ButterBean_Section' );
587
+ }
588
+
589
+ /**
590
+ * Registers our control types so that devs don't have to directly instantiate
591
+ * the class each time they register a control. Instead, they can use the
592
+ * `type` argument.
593
+ *
594
+ * @since 1.0.0
595
+ * @access public
596
+ * @return void
597
+ */
598
+ public function register_control_types() {
599
+
600
+ $this->register_control_type( 'default', 'ButterBean_Control' );
601
+ $this->register_control_type( 'checkboxes', 'ButterBean_Control_Checkboxes' );
602
+ $this->register_control_type( 'color', 'ButterBean_Control_Color' );
603
+ $this->register_control_type( 'datetime', 'ButterBean_Control_Datetime' );
604
+ $this->register_control_type( 'excerpt', 'ButterBean_Control_Excerpt' );
605
+ $this->register_control_type( 'image', 'ButterBean_Control_Image' );
606
+ $this->register_control_type( 'palette', 'ButterBean_Control_Palette' );
607
+ $this->register_control_type( 'radio', 'ButterBean_Control_Radio' );
608
+ $this->register_control_type( 'radio-image', 'ButterBean_Control_Radio_Image' );
609
+ $this->register_control_type( 'select-group', 'ButterBean_Control_Select_Group' );
610
+ $this->register_control_type( 'textarea', 'ButterBean_Control_Textarea' );
611
+ $this->register_control_type( 'multi-avatars', 'ButterBean_Control_Multi_Avatars' );
612
+ $this->register_control_type( 'parent', 'ButterBean_Control_Parent' );
613
+ }
614
+
615
+ /**
616
+ * Registers our setting types so that devs don't have to directly instantiate
617
+ * the class each time they register a setting. Instead, they can use the
618
+ * `type` argument.
619
+ *
620
+ * @since 1.0.0
621
+ * @access public
622
+ * @return void
623
+ */
624
+ public function register_setting_types() {
625
+
626
+ $this->register_setting_type( 'default', 'ButterBean_Setting' );
627
+ $this->register_setting_type( 'single', 'ButterBean_Setting' );
628
+ $this->register_setting_type( 'multiple', 'ButterBean_Setting_Multiple' );
629
+ $this->register_setting_type( 'array', 'ButterBean_Setting_Array' );
630
+ $this->register_setting_type( 'datetime', 'ButterBean_Setting_Datetime' );
631
+ }
632
+
633
+ /**
634
+ * Fires an action hook to register/enqueue scripts/styles.
635
+ *
636
+ * @since 1.0.0
637
+ * @access public
638
+ * @return void
639
+ */
640
+ public function enqueue_scripts() {
641
+
642
+ do_action( 'butterbean_enqueue_scripts' );
643
+ }
644
+
645
+ /**
646
+ * Loads scripts and styles.
647
+ *
648
+ * @since 1.0.0
649
+ * @access public
650
+ * @return void
651
+ */
652
+ public function enqueue() {
653
+ $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
654
+
655
+ // Enqueue the main plugin script.
656
+ wp_enqueue_script( 'butterbean', $this->dir_uri . "js/butterbean{$min}.js", array( 'backbone', 'wp-util' ), '', true );
657
+
658
+ // Enqueue the main plugin style.
659
+ wp_enqueue_style( 'butterbean', $this->dir_uri . "css/butterbean{$min}.css" );
660
+
661
+ // Loop through the manager and its controls and call each control's `enqueue()` method.
662
+ foreach ( $this->managers as $manager ) {
663
+
664
+ $manager->enqueue();
665
+
666
+ foreach ( $manager->sections as $section )
667
+ $section->enqueue();
668
+
669
+ foreach ( $manager->controls as $control )
670
+ $control->enqueue();
671
+ }
672
+ }
673
+
674
+ /**
675
+ * Callback function for adding meta boxes. This function adds a meta box
676
+ * for each of the managers.
677
+ *
678
+ * @since 1.0.0
679
+ * @access public
680
+ * @param string $post_type
681
+ * @return void
682
+ */
683
+ public function add_meta_boxes( $post_type ) {
684
+
685
+ foreach ( $this->managers as $manager ) {
686
+
687
+ // If the manager is registered for the current post type, add a meta box.
688
+ if ( in_array( $post_type, (array) $manager->post_type ) && $manager->check_capabilities() ) {
689
+
690
+ add_meta_box(
691
+ "butterbean-ui-{$manager->name}",
692
+ $manager->label,
693
+ array( $this, 'meta_box' ),
694
+ $post_type,
695
+ $manager->context,
696
+ $manager->priority,
697
+ array( 'manager' => $manager )
698
+ );
699
+ }
700
+ }
701
+ }
702
+
703
+ /**
704
+ * Displays the meta box. Note that the actual content of the meta box is
705
+ * handled via Underscore.js templates. The only thing we're outputting here
706
+ * is the nonce field.
707
+ *
708
+ * @since 1.0.0
709
+ * @access public
710
+ * @param object $post
711
+ * @param array $metabox
712
+ * @return void
713
+ */
714
+ public function meta_box( $post, $metabox ) {
715
+
716
+ $manager = $metabox['args']['manager'];
717
+
718
+ $manager->post_id = $this->post_id = $post->ID;
719
+
720
+ // Nonce field to validate on save.
721
+ wp_nonce_field( "butterbean_{$manager->name}_nonce", "butterbean_{$manager->name}" );
722
+ }
723
+
724
+ /**
725
+ * Passes the appropriate section and control json data to the JS file.
726
+ *
727
+ * @since 1.0.0
728
+ * @access public
729
+ * @return void
730
+ */
731
+ public function localize_scripts() {
732
+
733
+ $json = array( 'managers' => array() );
734
+
735
+ foreach ( $this->managers as $manager ) {
736
+
737
+ if ( $manager->check_capabilities() )
738
+ $json['managers'][] = $manager->get_json();
739
+ }
740
+
741
+ wp_localize_script( 'butterbean', 'butterbean_data', $json );
742
+ }
743
+
744
+ /**
745
+ * Prints the Underscore.js templates.
746
+ *
747
+ * @since 1.0.0
748
+ * @access public
749
+ * @return void
750
+ */
751
+ public function print_templates() {
752
+
753
+ $m_templates = array();
754
+ $s_templates = array();
755
+ $c_templates = array(); ?>
756
+
757
+ <script type="text/html" id="tmpl-butterbean-nav">
758
+ <?php butterbean_get_nav_template(); ?>
759
+ </script>
760
+
761
+ <?php foreach ( $this->managers as $manager ) {
762
+
763
+ if ( ! $manager->check_capabilities() )
764
+ continue;
765
+
766
+ if ( ! in_array( $manager->type, $m_templates ) ) {
767
+ $m_templates[] = $manager->type;
768
+
769
+ $manager->print_template();
770
+ }
771
+
772
+ foreach ( $manager->sections as $section ) {
773
+
774
+ if ( ! in_array( $section->type, $s_templates ) ) {
775
+ $s_templates[] = $section->type;
776
+
777
+ $section->print_template();
778
+ }
779
+ }
780
+
781
+ foreach ( $manager->controls as $control ) {
782
+
783
+ if ( ! in_array( $control->type, $c_templates ) ) {
784
+ $c_templates[] = $control->type;
785
+
786
+ $control->print_template();
787
+ }
788
+ }
789
+ }
790
+ }
791
+
792
+ /**
793
+ * Renders our Backbone views. We're calling this late in the page load so
794
+ * that other scripts have an opportunity to extend with their own, custom
795
+ * views for custom controls and such.
796
+ *
797
+ * @since 1.0.0
798
+ * @access public
799
+ * @return void
800
+ */
801
+ public function render_views() { ?>
802
+
803
+ <script type="text/javascript">
804
+ ( function( api ) {
805
+ if ( _.isObject( api ) && _.isFunction( api.render ) ) {
806
+ api.render();
807
+ }
808
+ }( butterbean ) );
809
+ </script>
810
+ <?php }
811
+
812
+ /**
813
+ * Saves the settings.
814
+ *
815
+ * @since 1.0.0
816
+ * @access public
817
+ * @return void
818
+ */
819
+ public function update( $post_id ) {
820
+
821
+ $do_autosave = defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE;
822
+ $is_autosave = wp_is_post_autosave( $post_id );
823
+ $is_revision = wp_is_post_revision( $post_id );
824
+
825
+ if ( $do_autosave || $is_autosave || $is_revision )
826
+ return;
827
+
828
+ foreach ( $this->managers as $manager ) {
829
+
830
+ if ( $manager->check_capabilities() )
831
+ $manager->save( $post_id );
832
+ }
833
+ }
834
+
835
+ /**
836
+ * Helper method for sorting sections and controls by priority.
837
+ *
838
+ * @since 1.0.0
839
+ * @access protected
840
+ * @param object $a
841
+ * @param object $b
842
+ * @return int
843
+ */
844
+ protected function priority_sort( $a, $b ) {
845
+
846
+ if ( $a->priority === $b->priority )
847
+ return $a->instance_number - $b->instance_number;
848
+
849
+ return $a->priority - $b->priority;
850
+ }
851
+ }
852
+
853
+ /**
854
+ * Gets the instance of the `ButterBean` class. This function is useful for quickly grabbing data
855
+ * used throughout the plugin.
856
+ *
857
+ * @since 1.0.0
858
+ * @access public
859
+ * @return object
860
+ */
861
+ function butterbean() {
862
+ return ButterBean::get_instance();
863
+ }
864
+
865
+ // Let's do this thang!
866
+ butterbean();
867
+ }
admin/butterbean/css/butterbean.css CHANGED
@@ -232,7 +232,7 @@
232
 
233
  /* === Date Control === */
234
 
235
- .butterbean-control-date select {
236
  vertical-align: top;
237
  }
238
 
@@ -327,4 +327,4 @@
327
 
328
  .butterbean-multi-avatars-wrap input:checked + span + img {
329
  border-color: #00a0d2;
330
- }
232
 
233
  /* === Date Control === */
234
 
235
+ .butterbean-control-datetime select {
236
  vertical-align: top;
237
  }
238
 
327
 
328
  .butterbean-multi-avatars-wrap input:checked + span + img {
329
  border-color: #00a0d2;
330
+ }
admin/butterbean/css/butterbean.min.css CHANGED
@@ -1 +1 @@
1
- .butterbean-ui>.hndle{padding:10px!important;border-bottom:1px solid #eee}.butterbean-ui .inside{margin:0!important;padding:0}.butterbean-manager-default{overflow:hidden;background:#fff;background:linear-gradient(90deg,#fafafa 0,#fafafa 180px,#fff 180px,#fff 100%)}#side-sortables .butterbean-manager-default{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}@media only screen and (max-width:782px),(max-width:980px) and (min-width:851px){.butterbean-manager-default{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}}.butterbean-manager-default .butterbean-nav{position:relative;float:left;list-style:none;width:180px;line-height:1em;margin:0 0 -1px 0;padding:0;background-color:#fafafa;border-right:1px solid #eee;box-sizing:border-box}.butterbean-manager-default .butterbean-nav li{display:block;position:relative;margin:0;padding:0;line-height:20px}.butterbean-manager-default .butterbean-nav li a{display:block;margin:0;padding:10px;line-height:20px!important;text-decoration:none;border-bottom:1px solid #eee;box-shadow:none}.butterbean-manager-default .butterbean-nav .dashicons{line-height:20px;margin-right:3px}.butterbean-manager-default .butterbean-nav li[aria-selected=true] a{position:relative;font-weight:700;color:#555;background-color:#e0e0e0}@media only screen and (max-width:782px),(max-width:980px) and (min-width:851px){.butterbean-manager-default .butterbean-nav{width:48px}.butterbean-manager-default .butterbean-nav .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}.butterbean-manager-default .butterbean-nav .dashicons::before{width:24px;height:24px}.butterbean-manager-default .butterbean-nav .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.butterbean-manager-default .butterbean-content{float:left;width:calc(100% - 180px);margin-left:-1px;border-left:1px solid #eee}@media only screen and (max-width:782px),(max-width:980px) and (min-width:851px){.butterbean-manager-default .butterbean-content{width:calc(100% - 48px)}}@media only screen and (min-width:850px){#side-sortables .butterbean-manager-default{background:#fff}#side-sortables .butterbean-manager-default .butterbean-content{width:100%}#side-sortables .butterbean-manager-default .butterbean-nav{display:table;width:100%}#side-sortables .butterbean-manager-default .butterbean-nav li{display:table-cell;text-align:center;border-right:1px solid #eee}#side-sortables .butterbean-manager-default .butterbean-nav li:last-of-type{border-right:0}#side-sortables .butterbean-manager-default .butterbean-nav li a{padding:10px 0}#side-sortables .butterbean-manager-default .butterbean-nav .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}#side-sortables .butterbean-manager-default .butterbean-nav .dashicons::before{width:24px;height:24px}#side-sortables .butterbean-manager-default .butterbean-nav .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.butterbean-manager-default .butterbean-section{padding:12px 12px 0;box-sizing:border-box}.butterbean-manager-default .butterbean-section[aria-hidden=true]{display:none}.butterbean-manager-default .butterbean-section[aria-hidden=false]{display:block}.butterbean-manager-default .butterbean-control{margin-bottom:20px}.butterbean-manager-default .butterbean-label{display:block!important;font-weight:700;display:inline-block;margin-bottom:4px}.butterbean-manager-default .butterbean-control-checkbox .butterbean-label{display:inline!important}.butterbean-manager-default .butterbean-description{display:block;font-style:italic;margin-top:4px}.butterbean-manager-default .butterbean-label+.butterbean-description{margin-top:0;margin-bottom:4px}.butterbean-control-image .butterbean-img{display:block;max-width:100%;max-height:300px;height:auto}.butterbean-placeholder{width:100%;position:relative;text-align:center;padding:9px 0;line-height:20px;border:1px dashed #b4b9be;box-sizing:border-box}.butterbean-control-textarea textarea,.butterbean-control-excerpt textarea{display:block;width:100%;height:105px}.butterbean-control-date select{vertical-align:top}.butterbean-control-palette label{display:block;padding:0 10px 10px}.butterbean-control-palette label[aria-selected=true]{padding-top:5px;background-color:#ddd}.butterbean-palette-label{line-height:28px}.butterbean-palette-block{display:table;width:100%;height:45px;border:1px solid #eee;box-sizing:border-box}.butterbean-palette-color{display:table-cell;height:100%}.butterbean-control-radio-image input[type=radio]{clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute!important;width:1px}.butterbean-control-radio-image img{box-sizing:border-box;max-width:100%;height:auto;padding:1px;border:4px solid transparent}.butterbean-control-radio-image img:hover,.butterbean-control-radio-image img:focus{border-color:#ccc}.butterbean-control-radio-image input:checked+span+img{border-color:#00a0d2}.butterbean-multi-avatars-wrap label{display:inline-block;margin-top:8px}.butterbean-multi-avatars-wrap input[type=checkbox]{clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute!important;width:1px}.butterbean-multi-avatars-wrap .avatar{box-sizing:border-box;max-width:100%;height:auto;padding:1px;border:4px solid transparent}#side-sortables .butterbean-multi-avatars-wrap .avatar{max-width:60px;max-height:60px}.butterbean-multi-avatars-wrap img:hover,.butterbean-multi-avatars-wrap img:focus{border-color:#ccc}.butterbean-multi-avatars-wrap input:checked+span+img{border-color:#00a0d2}
1
+ .butterbean-ui>.hndle{padding:10px!important;border-bottom:1px solid #eee}.butterbean-ui .inside{margin:0!important;padding:0}.butterbean-manager-default{overflow:hidden;background:#fff;background:linear-gradient(90deg,#fafafa 0,#fafafa 180px,#fff 180px,#fff 100%)}#side-sortables .butterbean-manager-default{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}@media only screen and (max-width:782px),(max-width:980px) and (min-width:851px){.butterbean-manager-default{background:linear-gradient(90deg,#fafafa 0,#fafafa 48px,#fff 48px,#fff 100%)}}.butterbean-manager-default .butterbean-nav{position:relative;float:left;list-style:none;width:180px;line-height:1em;margin:0 0 -1px 0;padding:0;background-color:#fafafa;border-right:1px solid #eee;box-sizing:border-box}.butterbean-manager-default .butterbean-nav li{display:block;position:relative;margin:0;padding:0;line-height:20px}.butterbean-manager-default .butterbean-nav li a{display:block;margin:0;padding:10px;line-height:20px!important;text-decoration:none;border-bottom:1px solid #eee;box-shadow:none}.butterbean-manager-default .butterbean-nav .dashicons{line-height:20px;margin-right:3px}.butterbean-manager-default .butterbean-nav li[aria-selected=true] a{position:relative;font-weight:700;color:#555;background-color:#e0e0e0}@media only screen and (max-width:782px),(max-width:980px) and (min-width:851px){.butterbean-manager-default .butterbean-nav{width:48px}.butterbean-manager-default .butterbean-nav .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}.butterbean-manager-default .butterbean-nav .dashicons::before{width:24px;height:24px}.butterbean-manager-default .butterbean-nav .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.butterbean-manager-default .butterbean-content{float:left;width:calc(100% - 180px);margin-left:-1px;border-left:1px solid #eee}@media only screen and (max-width:782px),(max-width:980px) and (min-width:851px){.butterbean-manager-default .butterbean-content{width:calc(100% - 48px)}}@media only screen and (min-width:850px){#side-sortables .butterbean-manager-default{background:#fff}#side-sortables .butterbean-manager-default .butterbean-content{width:100%}#side-sortables .butterbean-manager-default .butterbean-nav{display:table;width:100%}#side-sortables .butterbean-manager-default .butterbean-nav li{display:table-cell;text-align:center;border-right:1px solid #eee}#side-sortables .butterbean-manager-default .butterbean-nav li:last-of-type{border-right:0}#side-sortables .butterbean-manager-default .butterbean-nav li a{padding:10px 0}#side-sortables .butterbean-manager-default .butterbean-nav .dashicons{width:24px;height:24px;font-size:24px;line-height:24px}#side-sortables .butterbean-manager-default .butterbean-nav .dashicons::before{width:24px;height:24px}#side-sortables .butterbean-manager-default .butterbean-nav .label{overflow:hidden;position:absolute;top:-1000em;left:-1000em;width:1px;height:1px}}.butterbean-manager-default .butterbean-section{padding:12px 12px 0;box-sizing:border-box}.butterbean-manager-default .butterbean-section[aria-hidden=true]{display:none}.butterbean-manager-default .butterbean-section[aria-hidden=false]{display:block}.butterbean-manager-default .butterbean-control{margin-bottom:20px}.butterbean-manager-default .butterbean-label{display:block!important;font-weight:700;display:inline-block;margin-bottom:4px}.butterbean-manager-default .butterbean-control-checkbox .butterbean-label{display:inline!important}.butterbean-manager-default .butterbean-description{display:block;font-style:italic;margin-top:4px}.butterbean-manager-default .butterbean-label+.butterbean-description{margin-top:0;margin-bottom:4px}.butterbean-control-image .butterbean-img{display:block;max-width:100%;max-height:300px;height:auto}.butterbean-placeholder{width:100%;position:relative;text-align:center;padding:9px 0;line-height:20px;border:1px dashed #b4b9be;box-sizing:border-box}.butterbean-control-textarea textarea,.butterbean-control-excerpt textarea{display:block;width:100%;height:105px}.butterbean-control-datetime select{vertical-align:top}.butterbean-control-palette label{display:block;padding:0 10px 10px}.butterbean-control-palette label[aria-selected=true]{padding-top:5px;background-color:#ddd}.butterbean-palette-label{line-height:28px}.butterbean-palette-block{display:table;width:100%;height:45px;border:1px solid #eee;box-sizing:border-box}.butterbean-palette-color{display:table-cell;height:100%}.butterbean-control-radio-image input[type=radio]{clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute!important;width:1px}.butterbean-control-radio-image img{box-sizing:border-box;max-width:100%;height:auto;padding:1px;border:4px solid transparent}.butterbean-control-radio-image img:hover,.butterbean-control-radio-image img:focus{border-color:#ccc}.butterbean-control-radio-image input:checked+span+img{border-color:#00a0d2}.butterbean-multi-avatars-wrap label{display:inline-block;margin-top:8px}.butterbean-multi-avatars-wrap input[type=checkbox]{clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute!important;width:1px}.butterbean-multi-avatars-wrap .avatar{box-sizing:border-box;max-width:100%;height:auto;padding:1px;border:4px solid transparent}#side-sortables .butterbean-multi-avatars-wrap .avatar{max-width:60px;max-height:60px}.butterbean-multi-avatars-wrap img:hover,.butterbean-multi-avatars-wrap img:focus{border-color:#ccc}.butterbean-multi-avatars-wrap input:checked+span+img{border-color:#00a0d2}
admin/butterbean/inc/class-manager.php CHANGED
@@ -38,7 +38,7 @@ class ButterBean_Manager {
38
  public $name = '';
39
 
40
  /**
41
- * Label for the control.
42
  *
43
  * @since 1.0.0
44
  * @access public
@@ -56,7 +56,7 @@ class ButterBean_Manager {
56
  public $post_type = 'post';
57
 
58
  /**
59
- * Location of the meta box.
60
  *
61
  * @link https://developer.wordpress.org/reference/functions/add_meta_box/
62
  * @since 1.0.0
@@ -66,7 +66,7 @@ class ButterBean_Manager {
66
  public $context = 'advanced';
67
 
68
  /**
69
- * Priority of the meta box.
70
  *
71
  * @link https://developer.wordpress.org/reference/functions/add_meta_box/
72
  * @since 1.0.0
38
  public $name = '';
39
 
40
  /**
41
+ * Label for the manager.
42
  *
43
  * @since 1.0.0
44
  * @access public
56
  public $post_type = 'post';
57
 
58
  /**
59
+ * Location of the meta box. Accepted values: 'normal', 'advanced', 'side'.
60
  *
61
  * @link https://developer.wordpress.org/reference/functions/add_meta_box/
62
  * @since 1.0.0
66
  public $context = 'advanced';
67
 
68
  /**
69
+ * Priority of the meta box. Accepted values: 'high', 'core', 'default', 'low'.
70
  *
71
  * @link https://developer.wordpress.org/reference/functions/add_meta_box/
72
  * @since 1.0.0
admin/butterbean/inc/class-setting.php CHANGED
@@ -18,6 +18,15 @@
18
  */
19
  class ButterBean_Setting {
20
 
 
 
 
 
 
 
 
 
 
21
  /**
22
  * Stores the manager object.
23
  *
18
  */
19
  class ButterBean_Setting {
20
 
21
+ /**
22
+ * The type of setting.
23
+ *
24
+ * @since 1.0.0
25
+ * @access public
26
+ * @var string
27
+ */
28
+ public $type = 'default';
29
+
30
  /**
31
  * Stores the manager object.
32
  *
admin/butterbean/inc/controls/class-control-checkboxes.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
  /**
3
- * Multiple checkbox control class. This is for array-type settings, so you'll need to
4
- * use it with either the `ButterBean_Setting_Array` class or a class that handles
5
- * arrays.
6
  *
7
  * @package ButterBean
8
  * @author Justin Tadlock <justin@justintadlock.com>
1
  <?php
2
  /**
3
+ * Multiple checkbox control class. This is for array-type settings, so you'll need
4
+ * to utilize a setting type that handles arrays. Both the `array` and `multiple`
5
+ * setting types will do this.
6
  *
7
  * @package ButterBean
8
  * @author Justin Tadlock <justin@justintadlock.com>
admin/butterbean/inc/controls/class-control-color.php CHANGED
@@ -1,6 +1,8 @@
1
  <?php
2
  /**
3
- * Text control class.
 
 
4
  *
5
  * @package ButterBean
6
  * @author Justin Tadlock <justin@justintadlock.com>
@@ -10,7 +12,7 @@
10
  */
11
 
12
  /**
13
- * Text control class.
14
  *
15
  * @since 1.0.0
16
  * @access public
@@ -26,10 +28,39 @@ class ButterBean_Control_Color extends ButterBean_Control {
26
  */
27
  public $type = 'color';
28
 
29
- public function __construct( $manager, $name, $args = array() ) {
30
- parent::__construct( $manager, $name, $args );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
 
 
 
 
 
 
 
 
33
  public function get_attr() {
34
  $attr = parent::get_attr();
35
 
@@ -43,21 +74,6 @@ class ButterBean_Control_Color extends ButterBean_Control {
43
  return $attr;
44
  }
45
 
46
- public function enqueue() {
47
- wp_enqueue_script( 'wp-color-picker' );
48
- wp_enqueue_style( 'wp-color-picker' );
49
-
50
- add_action( 'admin_footer', array( $this, 'print_scripts' ) );
51
- }
52
-
53
- public function print_scripts() { ?>
54
- <script type="text/javascript">
55
- jQuery( document ).ready( function( $ ) {
56
- $( '.butterbean-color-picker' ).wpColorPicker();
57
- } );
58
- </script>
59
- <?php }
60
-
61
  /**
62
  * Get the value for the setting.
63
  *
@@ -72,4 +88,17 @@ class ButterBean_Control_Color extends ButterBean_Control {
72
 
73
  return ltrim( $value, '#' );
74
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  }
1
  <?php
2
  /**
3
+ * Color control class. This class uses the core WordPress color picker. Expected
4
+ * values are hex colors. This class also attempts to strip `#` from the hex color.
5
+ * By design, it's recommended to add the `#` on output.
6
  *
7
  * @package ButterBean
8
  * @author Justin Tadlock <justin@justintadlock.com>
12
  */
13
 
14
  /**
15
+ * Color control class.
16
  *
17
  * @since 1.0.0
18
  * @access public
28
  */
29
  public $type = 'color';
30
 
31
+ /**
32
+ * Custom options to pass to the color picker. Mostly, this is a wrapper for
33
+ * `iris()`, which is bundled with core WP. However, if they change pickers
34
+ * in the future, it may correspond to a different script.
35
+ *
36
+ * @link http://automattic.github.io/Iris/#options
37
+ * @link https://make.wordpress.org/core/2012/11/30/new-color-picker-in-wp-3-5/
38
+ * @since 1.0.0
39
+ * @access public
40
+ * @var array
41
+ */
42
+ public $options = array();
43
+
44
+ /**
45
+ * Enqueue scripts/styles for the control.
46
+ *
47
+ * @since 1.0.0
48
+ * @access public
49
+ * @return void
50
+ */
51
+ public function enqueue() {
52
+
53
+ wp_enqueue_script( 'wp-color-picker' );
54
+ wp_enqueue_style( 'wp-color-picker' );
55
  }
56
 
57
+ /**
58
+ * Gets the attributes for the control.
59
+ *
60
+ * @since 1.0.0
61
+ * @access public
62
+ * @return array
63
+ */
64
  public function get_attr() {
65
  $attr = parent::get_attr();
66
 
74
  return $attr;
75
  }
76
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  /**
78
  * Get the value for the setting.
79
  *
88
 
89
  return ltrim( $value, '#' );
90
  }
91
+
92
+ /**
93
+ * Adds custom data to the json array. This data is passed to the Underscore template.
94
+ *
95
+ * @since 1.0.0
96
+ * @access public
97
+ * @return void
98
+ */
99
+ public function to_json() {
100
+ parent::to_json();
101
+
102
+ $this->json['options'] = $this->options;
103
+ }
104
  }
admin/butterbean/inc/controls/class-control-datetime.php ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Datetime control class. This class is meant for storing a datetime in the format
4
+ * of `YYYY-MM-DD HH:MM:SS` or `0000-00-00 00:00:00`. You can set the `$show_time`
5
+ * property to `false`.
6
+ *
7
+ * Note that this control should be used in conjunction with the `datetime` setting
8
+ * type or another custom class that can handle the datetime.
9
+ *
10
+ * @package ButterBean
11
+ * @subpackage Admin
12
+ * @author Justin Tadlock <justin@justintadlock.com>
13
+ * @copyright Copyright (c) 2015-2016, Justin Tadlock
14
+ * @link https://github.com/justintadlock/butterbean
15
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
16
+ */
17
+
18
+ /**
19
+ * Datetime control class.
20
+ *
21
+ * @since 1.0.0
22
+ * @access public
23
+ */
24
+ class ButterBean_Control_Datetime extends ButterBean_Control {
25
+
26
+ /**
27
+ * The type of control.
28
+ *
29
+ * @since 1.0.0
30
+ * @access public
31
+ * @var string
32
+ */
33
+ public $type = 'datetime';
34
+
35
+ /**
36
+ * Whether to show the time. Note that settings, particularly the
37
+ * `ButterBean_Setting_Date` class will store the time as `00:00:00` if
38
+ * no time is provided.
39
+ *
40
+ * @since 1.0.0
41
+ * @access public
42
+ * @var bool
43
+ */
44
+ public $show_time = true;
45
+
46
+ /**
47
+ * Adds custom data to the json array. This data is passed to the Underscore template.
48
+ *
49
+ * @since 1.0.0
50
+ * @access public
51
+ * @globl object $wp_locale
52
+ * @return void
53
+ */
54
+ public function to_json() {
55
+ global $wp_locale;
56
+
57
+ parent::to_json();
58
+
59
+ $this->json['show_time'] = $this->show_time;
60
+
61
+ $field_name = $this->get_field_name();
62
+
63
+ // Get project start/end dates.
64
+ $date = $this->get_value();
65
+
66
+ // Get the year, month, and day.
67
+ $year = $date ? mysql2date( 'Y', $date, false ) : '';
68
+ $month = $date ? mysql2date( 'm', $date, false ) : '';
69
+ $day = $date ? mysql2date( 'd', $date, false ) : '';
70
+
71
+ // Get the hour, minute, and second.
72
+ $hour = $date ? mysql2date( 'H', $date, false ) : '';
73
+ $minute = $date ? mysql2date( 'i', $date, false ) : '';
74
+ $second = $date ? mysql2date( 's', $date, false ) : '';
75
+
76
+ // Year
77
+ $this->json['year'] = array(
78
+ 'value' => esc_attr( $year ),
79
+ 'label' => esc_html__( 'Year', 'butterbean' ),
80
+ 'name' => esc_attr( "{$field_name}_year" ),
81
+ 'attr' => sprintf( 'placeholder="%s" size="4" maxlength="4" autocomplete="off"', esc_attr( date_i18n( 'Y' ) ) )
82
+ );
83
+
84
+ // Month
85
+ $this->json['month'] = array(
86
+ 'value' => esc_attr( $month ),
87
+ 'name' => esc_attr( "{$field_name}_month" ),
88
+ 'label' => esc_html__( 'Month', 'butterbean' ),
89
+ 'choices' => array(
90
+ array(
91
+ 'num' => '',
92
+ 'label' => ''
93
+ )
94
+ )
95
+ );
96
+
97
+ for ( $i = 1; $i < 13; $i = $i +1 ) {
98
+
99
+ $monthnum = zeroise( $i, 2 );
100
+ $monthtext = $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) );
101
+
102
+ $this->json['month']['choices'][] = array(
103
+ 'num' => $monthnum,
104
+ 'label' => $monthtext
105
+ );
106
+ }
107
+
108
+ // Day
109
+ $this->json['day'] = array(
110
+ 'value' => esc_attr( $day ),
111
+ 'name' => esc_attr( "{$field_name}_day" ),
112
+ 'label' => esc_html__( 'Day', 'butterbean' ),
113
+ 'attr' => sprintf( 'placeholder="%s" size="2" maxlength="2" autocomplete="off"', esc_attr( date_i18n( 'd' ) ) )
114
+ );
115
+
116
+ // Hour
117
+ $this->json['hour'] = array(
118
+ 'value' => esc_attr( $hour ),
119
+ 'name' => esc_attr( "{$field_name}_hour" ),
120
+ 'label' => esc_html__( 'Hour', 'butterbean' ),
121
+ 'attr' => 'placeholder="00" size="2" maxlength="2" autocomplete="off"'
122
+ );
123
+
124
+ // Minute
125
+ $this->json['minute'] = array(
126
+ 'value' => esc_attr( $minute ),
127
+ 'name' => esc_attr( "{$field_name}_minute" ),
128
+ 'label' => esc_html__( 'Minute', 'butterbean' ),
129
+ 'attr' => 'placeholder="00" size="2" maxlength="2" autocomplete="off"'
130
+ );
131
+
132
+ // Second
133
+ $this->json['second'] = array(
134
+ 'value' => esc_attr( $second ),
135
+ 'name' => esc_attr( "{$field_name}_second" ),
136
+ 'label' => esc_html__( 'Second', 'butterbean' ),
137
+ 'attr' => 'placeholder="00" size="2" maxlength="2" autocomplete="off"'
138
+ );
139
+ }
140
+ }
admin/butterbean/inc/controls/class-control-excerpt.php CHANGED
@@ -20,6 +20,15 @@
20
  */
21
  class ButterBean_Control_Excerpt extends ButterBean_Control_Textarea {
22
 
 
 
 
 
 
 
 
 
 
23
  /**
24
  * Gets the attributes for the control.
25
  *
20
  */
21
  class ButterBean_Control_Excerpt extends ButterBean_Control_Textarea {
22
 
23
+ /**
24
+ * The type of control.
25
+ *
26
+ * @since 1.0.0
27
+ * @access public
28
+ * @var string
29
+ */
30
+ public $type = 'excerpt';
31
+
32
  /**
33
  * Gets the attributes for the control.
34
  *
admin/butterbean/inc/controls/class-control-image.php CHANGED
@@ -37,6 +37,16 @@ class ButterBean_Control_Image extends ButterBean_Control {
37
  */
38
  public $l10n = array();
39
 
 
 
 
 
 
 
 
 
 
 
40
  /**
41
  * Creates a new control object.
42
  *
@@ -86,12 +96,13 @@ class ButterBean_Control_Image extends ButterBean_Control {
86
  parent::to_json();
87
 
88
  $this->json['l10n'] = $this->l10n;
 
89
 
90
  $value = $this->get_value();
91
  $image = $alt = '';
92
 
93
  if ( $value ) {
94
- $image = wp_get_attachment_image_src( absint( $value ), 'large' );
95
  $alt = get_post_meta( absint( $value ), '_wp_attachment_image_alt', true );
96
  }
97
 
37
  */
38
  public $l10n = array();
39
 
40
+ /**
41
+ * Image size to display. If the size isn't found for the image,
42
+ * the full size of the image will be output.
43
+ *
44
+ * @since 1.0.0
45
+ * @access public
46
+ * @var string
47
+ */
48
+ public $size = 'large';
49
+
50
  /**
51
  * Creates a new control object.
52
  *
96
  parent::to_json();
97
 
98
  $this->json['l10n'] = $this->l10n;
99
+ $this->json['size'] = $this->size;
100
 
101
  $value = $this->get_value();
102
  $image = $alt = '';
103
 
104
  if ( $value ) {
105
+ $image = wp_get_attachment_image_src( absint( $value ), $this->size );
106
  $alt = get_post_meta( absint( $value ), '_wp_attachment_image_alt', true );
107
  }
108
 
admin/butterbean/inc/controls/class-control-multi-avatars.php CHANGED
@@ -2,7 +2,8 @@
2
  /**
3
  * Multi-avatars control. This control is for outputting multiple users who can create,
4
  * edit, or publish posts of the given post type. Multiple users can be selected. The
5
- * data is expected to be an array. For use with the `Butterbean_Setting_Array` class.
 
6
  *
7
  * @package ButterBean
8
  * @author Justin Tadlock <justin@justintadlock.com>
2
  /**
3
  * Multi-avatars control. This control is for outputting multiple users who can create,
4
  * edit, or publish posts of the given post type. Multiple users can be selected. The
5
+ * data is expected to be an array. This control should be used with a setting type that
6
+ * handles arrays, such as the built-in `array` or `multiple` types.
7
  *
8
  * @package ButterBean
9
  * @author Justin Tadlock <justin@justintadlock.com>
admin/butterbean/inc/controls/class-control-palette.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
  /**
3
- * Radio control class.
 
4
  *
5
  * @package ButterBean
6
  * @author Justin Tadlock <justin@justintadlock.com>
@@ -10,7 +11,7 @@
10
  */
11
 
12
  /**
13
- * Radio control class.
14
  *
15
  * @since 1.0.0
16
  * @access public
@@ -26,6 +27,13 @@ class ButterBean_Control_Palette extends ButterBean_Control {
26
  */
27
  public $type = 'palette';
28
 
 
 
 
 
 
 
 
29
  public function to_json() {
30
  parent::to_json();
31
 
1
  <?php
2
  /**
3
+ * Color palette control class. The purpose of this class is to give users a choice
4
+ * of color palettes. The actual data that is stored is a key of your choosing.
5
  *
6
  * @package ButterBean
7
  * @author Justin Tadlock <justin@justintadlock.com>
11
  */
12
 
13
  /**
14
+ * Color palette control class.
15
  *
16
  * @since 1.0.0
17
  * @access public
27
  */
28
  public $type = 'palette';
29
 
30
+ /**
31
+ * Adds custom data to the json array. This data is passed to the Underscore template.
32
+ *
33
+ * @since 1.0.0
34
+ * @access public
35
+ * @return void
36
+ */
37
  public function to_json() {
38
  parent::to_json();
39
 
admin/butterbean/inc/controls/class-control-radio-image.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
  /**
3
- * Radio image control class.
 
4
  *
5
  * @package ButterBean
6
  * @subpackage Admin
1
  <?php
2
  /**
3
+ * Radio image control class extends the built-in radio control. This control is
4
+ * meant for displaying an image instead of the radio fields.
5
  *
6
  * @package ButterBean
7
  * @subpackage Admin
admin/butterbean/inc/controls/class-control-radio.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /**
3
- * Radio control class.
4
  *
5
  * @package ButterBean
6
  * @subpackage Admin
1
  <?php
2
  /**
3
+ * Radio control class that creates a list of radio inputs to choose from.
4
  *
5
  * @package ButterBean
6
  * @subpackage Admin
admin/butterbean/inc/controls/class-control-select-group.php CHANGED
@@ -1,6 +1,7 @@
1
  <?php
2
  /**
3
- * Select group control class.
 
4
  *
5
  * @package ButterBean
6
  * @author Justin Tadlock <justin@justintadlock.com>
1
  <?php
2
  /**
3
+ * Select group control class. This works just like a normal select. However, it
4
+ * allows for `<optgroup>` to be added.
5
  *
6
  * @package ButterBean
7
  * @author Justin Tadlock <justin@justintadlock.com>
admin/butterbean/inc/functions-core.php CHANGED
@@ -71,8 +71,8 @@ function butterbean_sanitize_hex_color_no_hash( $color ) {
71
  */
72
  function butterbean_maybe_hash_hex_color( $color ) {
73
 
74
- if ( function_exists( 'maybe_has_hex_color' ) )
75
- return maybe_has_hex_color( $color );
76
 
77
  if ( $unhashed = butterbean_sanitize_hex_color_no_hash( $color ) )
78
  return '#' . $unhashed;
@@ -134,23 +134,29 @@ function butterbean_get_control_template( $slug = '' ) {
134
  */
135
  function butterbean_get_template( $name, $slug = '' ) {
136
 
137
- $templates = array();
138
- $located = '';
139
 
140
- if ( $slug )
141
- $templates[] = "{$name}-{$slug}.php";
142
 
143
- $templates[] = "{$name}.php";
144
 
145
- // Allow devs to filter the template hierarchy.
146
- $templates = apply_filters( "butterbean_{$name}_template_hierarchy", $templates, $slug );
147
 
148
- // Loop through the templates and locate one.
149
- foreach ( $templates as $template ) {
150
 
151
- if ( file_exists( butterbean()->tmpl_path . $template ) ) {
152
- $located = butterbean()->tmpl_path . $template;
153
- break;
 
 
 
 
 
 
 
154
  }
155
  }
156
 
71
  */
72
  function butterbean_maybe_hash_hex_color( $color ) {
73
 
74
+ if ( function_exists( 'maybe_hash_hex_color' ) )
75
+ return maybe_hash_hex_color( $color );
76
 
77
  if ( $unhashed = butterbean_sanitize_hex_color_no_hash( $color ) )
78
  return '#' . $unhashed;
134
  */
135
  function butterbean_get_template( $name, $slug = '' ) {
136
 
137
+ // Allow devs to hook in early to bypass template checking.
138
+ $located = apply_filters( "butterbean_pre_{$name}_template", '', $slug );
139
 
140
+ // If there's no template, let's try to find one.
141
+ if ( ! $located ) {
142
 
143
+ $templates = array();
144
 
145
+ if ( $slug )
146
+ $templates[] = "{$name}-{$slug}.php";
147
 
148
+ $templates[] = "{$name}.php";
 
149
 
150
+ // Allow devs to filter the template hierarchy.
151
+ $templates = apply_filters( "butterbean_{$name}_template_hierarchy", $templates, $slug );
152
+
153
+ // Loop through the templates and locate one.
154
+ foreach ( $templates as $template ) {
155
+
156
+ if ( file_exists( butterbean()->tmpl_path . $template ) ) {
157
+ $located = butterbean()->tmpl_path . $template;
158
+ break;
159
+ }
160
  }
161
  }
162
 
admin/butterbean/inc/settings/class-setting-array.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /**
3
- * Setting class for storing multiple post meta values for a single key.
4
  *
5
  * @package ButterBean
6
  * @author Justin Tadlock <justin@justintadlock.com>
@@ -18,16 +18,13 @@
18
  class ButterBean_Setting_Array extends ButterBean_Setting {
19
 
20
  /**
21
- * Gets the value of the setting.
22
  *
23
  * @since 1.0.0
24
  * @access public
25
- * @return mixed
26
  */
27
- public function get_value() {
28
-
29
- return get_post_meta( $this->manager->post_id, $this->name );
30
- }
31
 
32
  /**
33
  * Sanitizes the value of the setting.
@@ -66,77 +63,18 @@ class ButterBean_Setting_Array extends ButterBean_Setting {
66
  */
67
  public function save() {
68
 
 
 
 
69
  $old_values = $this->get_value();
70
  $new_values = $this->get_posted_value();
71
 
72
  // If there's an array of posted values, set them.
73
- if ( is_array( $new_values ) )
74
- $this->set_values( $new_values, $old_values );
75
 
76
  // If no array of posted values but we have old values, delete them.
77
- else if ( $old_values )
78
- $this->delete_values();
79
- }
80
-
81
- /**
82
- * Loops through new and old meta values and updates.
83
- *
84
- * @since 1.0.0
85
- * @access public
86
- * @param array $new_values
87
- * @param array $old_values
88
- * @return void
89
- */
90
- public function set_values( $new_values, $old_values ) {
91
-
92
- foreach ( $new_values as $new ) {
93
-
94
- if ( ! in_array( $new, $old_values ) )
95
- $this->add_value( $new );
96
- }
97
-
98
- foreach ( $old_values as $old ) {
99
-
100
- if ( ! in_array( $old, $new_values ) )
101
- $this->remove_value( $old );
102
- }
103
- }
104
-
105
- /**
106
- * Deletes old meta values.
107
- *
108
- * @since 1.0.0
109
- * @access public
110
- * @return void
111
- */
112
- public function delete_values() {
113
-
114
- return delete_post_meta( $this->manager->post_id, $this->name );
115
- }
116
-
117
- /**
118
- * Adds a single meta value.
119
- *
120
- * @since 1.0.0
121
- * @access public
122
- * @param mixed $value
123
- * @return bool
124
- */
125
- public function add_value( $value ) {
126
-
127
- return add_post_meta( $this->manager->post_id, $this->name, $value, false );
128
- }
129
-
130
- /**
131
- * Deletes a single meta value.
132
- *
133
- * @since 1.0.0
134
- * @access public
135
- * @param mixed $value
136
- * @return bool
137
- */
138
- public function remove_value( $value ) {
139
-
140
- return delete_post_meta( $this->manager->post_id, $this->name, $value );
141
  }
142
  }
1
  <?php
2
  /**
3
+ * Setting class for storing a single meta value as an array.
4
  *
5
  * @package ButterBean
6
  * @author Justin Tadlock <justin@justintadlock.com>
18
  class ButterBean_Setting_Array extends ButterBean_Setting {
19
 
20
  /**
21
+ * The type of setting.
22
  *
23
  * @since 1.0.0
24
  * @access public
25
+ * @var string
26
  */
27
+ public $type = 'array';
 
 
 
28
 
29
  /**
30
  * Sanitizes the value of the setting.
63
  */
64
  public function save() {
65
 
66
+ if ( ! $this->check_capabilities() )
67
+ return;
68
+
69
  $old_values = $this->get_value();
70
  $new_values = $this->get_posted_value();
71
 
72
  // If there's an array of posted values, set them.
73
+ if ( $new_values && is_array( $new_values ) && $new_values !== $old_values )
74
+ return update_post_meta( $this->manager->post_id, $this->name, $new_values );
75
 
76
  // If no array of posted values but we have old values, delete them.
77
+ else if ( $old_values && ! $new_values )
78
+ return delete_post_meta( $this->manager->post_id, $this->name );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
  }
admin/butterbean/inc/settings/class-setting-datetime.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Datetime setting class. This is meant to be used in conjunction with the built-in
4
+ * `ButterBean_Datetime_Control` or a sub-class that passes the appropriate values.
5
+ *
6
+ * @package ButterBean
7
+ * @subpackage Admin
8
+ * @author Justin Tadlock <justin@justintadlock.com>
9
+ * @copyright Copyright (c) 2015-2016, Justin Tadlock
10
+ * @link https://github.com/justintadlock/butterbean
11
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
12
+ */
13
+
14
+ /**
15
+ * Date setting class.
16
+ *
17
+ * @since 1.0.0
18
+ * @access public
19
+ */
20
+ class ButterBean_Setting_Datetime extends ButterBean_Setting {
21
+
22
+ /**
23
+ * The type of setting.
24
+ *
25
+ * @since 1.0.0
26
+ * @access public
27
+ * @var string
28
+ */
29
+ public $type = 'datetime';
30
+
31
+ /**
32
+ * Gets the posted value of the setting.
33
+ *
34
+ * @since 1.0.0
35
+ * @access public
36
+ * @return mixed
37
+ */
38
+ public function get_posted_value() {
39
+
40
+ $field_name = $this->get_field_name();
41
+
42
+ // Get the posted date.
43
+ $year = ! empty( $_POST[ "{$field_name}_year" ] ) ? zeroise( absint( $_POST[ "{$field_name}_year" ] ), 4 ) : '';
44
+ $month = ! empty( $_POST[ "{$field_name}_month" ] ) ? zeroise( absint( $_POST[ "{$field_name}_month" ] ), 2 ) : '';
45
+ $day = ! empty( $_POST[ "{$field_name}_day" ] ) ? zeroise( absint( $_POST[ "{$field_name}_day" ] ), 2 ) : '';
46
+
47
+ // Get the posted time.
48
+ $hour = ! empty( $_POST[ "{$field_name}_hour" ] ) ? $this->validate_hour( $_POST[ "{$field_name}_hour" ] ) : '00';
49
+ $minute = ! empty( $_POST[ "{$field_name}_minute" ] ) ? $this->validate_minute( $_POST[ "{$field_name}_minute" ] ) : '00';
50
+ $second = ! empty( $_POST[ "{$field_name}_second" ] ) ? $this->validate_second( $_POST[ "{$field_name}_second" ] ) : '00';
51
+
52
+ $date = "{$year}-{$month}-{$day}";
53
+ $time = "{$hour}:{$minute}:{$second}";
54
+
55
+ if ( $year && $month && $day && wp_checkdate( absint( $month ), absint( $day ), absint( $year ), $date ) )
56
+ return "{$date} {$time}";
57
+
58
+ return '';
59
+ }
60
+
61
+ /**
62
+ * Validates the hour.
63
+ *
64
+ * @since 1.0.0
65
+ * @access public
66
+ * @param int|string $hour
67
+ * @return string
68
+ */
69
+ public function validate_hour( $hour ) {
70
+
71
+ $hour = absint( $hour );
72
+
73
+ return $hour < 0 || $hour > 23 ? zeroise( $hour, 2 ) : '00';
74
+ }
75
+
76
+ /**
77
+ * Validates the minute.
78
+ *
79
+ * @since 1.0.0
80
+ * @access public
81
+ * @param int|string $minute
82
+ * @return string
83
+ */
84
+ public function validate_minute( $minute ) {
85
+
86
+ $minute = absint( $minute );
87
+
88
+ return $minute < 0 || $minute > 59 ? zeroise( $minute, 2 ) : '00';
89
+ }
90
+
91
+ /**
92
+ * Validates the second.
93
+ *
94
+ * @since 1.0.0
95
+ * @access public
96
+ * @param int|string $second
97
+ * @return string
98
+ */
99
+ public function validate_second( $second ) {
100
+
101
+ $second = absint( $second );
102
+
103
+ return $second < 0 || $second > 59 ? zeroise( $second, 2 ) : '00';
104
+ }
105
+ }
admin/butterbean/inc/settings/class-setting-multiple.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Setting class for storing multiple post meta values for a single key.
4
+ *
5
+ * @package ButterBean
6
+ * @author Justin Tadlock <justin@justintadlock.com>
7
+ * @copyright Copyright (c) 2015-2016, Justin Tadlock
8
+ * @link https://github.com/justintadlock/butterbean
9
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10
+ */
11
+
12
+ /**
13
+ * Multiple setting class.
14
+ *
15
+ * @since 1.0.0
16
+ * @access public
17
+ */
18
+ class ButterBean_Setting_Multiple extends ButterBean_Setting {
19
+
20
+ /**
21
+ * The type of setting.
22
+ *
23
+ * @since 1.0.0
24
+ * @access public
25
+ * @var string
26
+ */
27
+ public $type = 'multiple';
28
+
29
+ /**
30
+ * Gets the value of the setting.
31
+ *
32
+ * @since 1.0.0
33
+ * @access public
34
+ * @return mixed
35
+ */
36
+ public function get_value() {
37
+
38
+ return get_post_meta( $this->manager->post_id, $this->name );
39
+ }
40
+
41
+ /**
42
+ * Sanitizes the value of the setting.
43
+ *
44
+ * @since 1.0.0
45
+ * @access public
46
+ * @param array $value
47
+ * @return array
48
+ */
49
+ public function sanitize( $values ) {
50
+
51
+ $multi_values = $values && ! is_array( $values ) ? explode( ',', $values ) : $values;
52
+
53
+ return $multi_values ? array_map( array( $this, 'map' ), $multi_values ) : array();
54
+ }
55
+
56
+ /**
57
+ * Helper function for sanitizing each value of the array.
58
+ *
59
+ * @since 1.0.0
60
+ * @access public
61
+ * @param mixed $value
62
+ * @return mixed
63
+ */
64
+ public function map( $value ) {
65
+
66
+ return apply_filters( "butterbean_{$this->manager->name}_sanitize_{$this->name}", $value, $this );
67
+ }
68
+
69
+ /**
70
+ * Saves the value of the setting.
71
+ *
72
+ * @since 1.0.0
73
+ * @access public
74
+ * @return void
75
+ */
76
+ public function save() {
77
+
78
+ if ( ! $this->check_capabilities() )
79
+ return;
80
+
81
+ $old_values = $this->get_value();
82
+ $new_values = $this->get_posted_value();
83
+
84
+ // If there's an array of posted values, set them.
85
+ if ( is_array( $new_values ) )
86
+ $this->set_values( $new_values, $old_values );
87
+
88
+ // If no array of posted values but we have old values, delete them.
89
+ else if ( $old_values )
90
+ $this->delete_values();
91
+ }
92
+
93
+ /**
94
+ * Loops through new and old meta values and updates.
95
+ *
96
+ * @since 1.0.0
97
+ * @access public
98
+ * @param array $new_values
99
+ * @param array $old_values
100
+ * @return void
101
+ */
102
+ public function set_values( $new_values, $old_values ) {
103
+
104
+ foreach ( $new_values as $new ) {
105
+
106
+ if ( ! in_array( $new, $old_values ) )
107
+ $this->add_value( $new );
108
+ }
109
+
110
+ foreach ( $old_values as $old ) {
111
+
112
+ if ( ! in_array( $old, $new_values ) )
113
+ $this->remove_value( $old );
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Deletes old meta values.
119
+ *
120
+ * @since 1.0.0
121
+ * @access public
122
+ * @return void
123
+ */
124
+ public function delete_values() {
125
+
126
+ return delete_post_meta( $this->manager->post_id, $this->name );
127
+ }
128
+
129
+ /**
130
+ * Adds a single meta value.
131
+ *
132
+ * @since 1.0.0
133
+ * @access public
134
+ * @param mixed $value
135
+ * @return bool
136
+ */
137
+ public function add_value( $value ) {
138
+
139
+ return add_post_meta( $this->manager->post_id, $this->name, $value, false );
140
+ }
141
+
142
+ /**
143
+ * Deletes a single meta value.
144
+ *
145
+ * @since 1.0.0
146
+ * @access public
147
+ * @param mixed $value
148
+ * @return bool
149
+ */
150
+ public function remove_value( $value ) {
151
+
152
+ return delete_post_meta( $this->manager->post_id, $this->name, $value );
153
+ }
154
+ }
admin/butterbean/js/butterbean.js CHANGED
@@ -1,3 +1,5 @@
 
 
1
  ( function() {
2
 
3
  // Bail if we don't have the JSON, which is passed in via `wp_localize_script()`.
@@ -5,13 +7,410 @@
5
  return;
6
  }
7
 
8
- /* === Backbone + Underscore === */
9
-
10
- // Set up a variable to house our views.
11
- var views = { managers : {}, sections : {}, controls : {} };
12
-
13
- // Set up a variable to house our templates.
14
- var templates = { managers : {}, sections : {}, controls : {} };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  // Nav template.
17
  var nav_template = wp.template( 'butterbean-nav' );
@@ -62,36 +461,63 @@
62
 
63
  /* === Collections === */
64
 
65
- // Collection of sections.
 
 
 
 
 
 
66
  var Sections = Backbone.Collection.extend( {
67
  model : Section
68
  } );
69
 
70
  /* === Views === */
71
 
72
- // Manager view. Handles the output of a manager.
73
- views.managers.default = Backbone.View.extend( {
 
 
 
 
 
 
 
 
 
74
  tagName : 'div',
 
 
75
  attributes : function() {
76
  return {
77
  'id' : 'butterbean-manager-' + this.model.get( 'name' ),
78
  'class' : 'butterbean-manager butterbean-manager-' + this.model.get( 'type' )
79
  };
80
  },
 
 
81
  initialize : function() {
82
 
83
  var type = this.model.get( 'type' );
84
 
85
- if ( _.isUndefined( templates.managers[ type ] ) ) {
86
- templates.managers[ type ] = wp.template( 'butterbean-manager-' + type );
87
- }
88
 
89
- this.template = templates.managers[ type ];
 
90
  },
 
 
91
  render : function() {
92
  this.el.innerHTML = this.template( this.model.toJSON() );
93
  return this;
94
  },
 
 
 
 
 
95
  subview_render : function() {
96
 
97
  // Create a new section collection.
@@ -103,14 +529,26 @@
103
  sections.add( new Section( data ) );
104
  } );
105
 
106
- // Loop through each manager in the collection and render its view.
107
  sections.forEach( function( section, i ) {
108
 
109
- var nav_view = new Nav_View( { model : section } );
110
- var section_view = new views.sections.default( { model : section } );
111
 
 
112
  document.querySelector( '#butterbean-ui-' + section.get( 'manager' ) + ' .butterbean-nav' ).appendChild( nav_view.render().el );
113
- document.querySelector( '#butterbean-ui-' + section.get( 'manager' ) + ' .butterbean-content' ).appendChild( section_view.render().el );
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  // If the first model, set it to selected.
116
  section.set( 'selected', 0 === i );
@@ -119,22 +557,44 @@
119
  // Loop through each control for the manager and render its view.
120
  _.each( this.model.get( 'controls' ), function( data ) {
121
 
 
122
  var control = new Control( data );
123
 
124
- var callback = _.isUndefined( views.controls[ data.type ] ) ? views.controls.default : views.controls[ data.type ];
 
125
 
 
126
  var view = new callback( { model : control } );
127
 
 
128
  document.getElementById( 'butterbean-' + control.get( 'manager' ) + '-section-' + control.get( 'section' ) ).appendChild( view.render().el );
 
 
 
129
  } );
130
 
131
  return this;
132
- }
 
 
 
 
133
  } );
134
 
135
- // Section view. Handles the output of a section.
136
- views.sections.default = Backbone.View.extend( {
 
 
 
 
 
 
 
 
 
137
  tagName : 'div',
 
 
138
  attributes : function() {
139
  return {
140
  'id' : 'butterbean-' + this.model.get( 'manager' ) + '-section-' + this.model.get( 'name' ),
@@ -142,63 +602,97 @@
142
  'aria-hidden' : ! this.model.get( 'selected' )
143
  };
144
  },
 
 
145
  initialize : function() {
146
- this.model.on('change', this.onchange, this);
147
 
 
 
 
 
148
  var type = this.model.get( 'type' );
149
 
150
- if ( _.isUndefined( templates.sections[ type ] ) ) {
151
- templates.sections[ type ] = wp.template( 'butterbean-section-' + type );
152
- }
153
 
154
- this.template = templates.sections[ type ];
 
155
  },
 
 
156
  render : function() {
157
 
158
  // Only render template if model is active.
159
- if ( this.model.get( 'active' ) ) {
160
  this.el.innerHTML = this.template( this.model.toJSON() );
161
- }
162
 
163
  return this;
164
  },
 
 
165
  onchange : function() {
166
 
167
  // Set the view's `aria-hidden` attribute based on whether the model is selected.
168
  this.el.setAttribute( 'aria-hidden', ! this.model.get( 'selected' ) );
169
- }
 
 
 
 
170
  } );
171
 
172
- // Nav view.
 
 
 
 
 
 
173
  var Nav_View = Backbone.View.extend( {
 
 
174
  template : nav_template,
 
 
175
  tagName : 'li',
 
 
176
  attributes : function() {
177
  return {
178
  'aria-selected' : this.model.get( 'selected' )
179
  };
180
  },
 
 
181
  initialize : function() {
182
- this.model.on('change', this.render, this);
183
- this.model.on('change', this.onchange, this);
184
  },
 
 
185
  render : function() {
186
 
187
  // Only render template if model is active.
188
- if ( this.model.get( 'active' ) ) {
189
  this.el.innerHTML = this.template( this.model.toJSON() );
190
- }
191
 
192
  return this;
193
  },
 
 
194
  events : {
195
  'click a' : 'onselect'
196
  },
 
 
197
  onchange : function() {
198
 
199
  // Set the `aria-selected` attibute based on the model selected state.
200
  this.el.setAttribute( 'aria-selected', this.model.get( 'selected' ) );
201
  },
 
 
202
  onselect : function( event ) {
203
  event.preventDefault();
204
 
@@ -213,84 +707,134 @@
213
  }
214
  } );
215
 
216
- // Control view. Handles the output of a control.
217
- views.controls.default = Backbone.View.extend( {
 
 
 
 
 
 
 
 
 
218
  tagName : 'div',
 
 
219
  attributes : function() {
220
  return {
221
  'id' : 'butterbean-control-' + this.model.get( 'name' ),
222
  'class' : 'butterbean-control butterbean-control-' + this.model.get( 'type' )
223
  };
224
  },
 
 
225
  initialize : function() {
226
  var type = this.model.get( 'type' );
227
 
228
  // Only add a new control template if we have a different control type.
229
- if ( _.isUndefined( templates.controls[ type ] ) ) {
230
- templates.controls[ type ] = wp.template( 'butterbean-control-' + type );
231
- }
232
 
233
- this.template = templates.controls[ type ];
 
234
 
235
- this.ready();
 
 
236
  },
 
 
237
  render : function() {
238
 
239
  // Only render template if model is active.
240
- if ( this.model.get( 'active' ) ) {
241
  this.el.innerHTML = this.template( this.model.toJSON() );
242
- }
243
 
244
  return this;
245
  },
 
 
 
246
  ready : function() {}
247
  } );
248
 
249
- // Palette control view.
250
- views.controls.palette = views.controls.default.extend( {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  events : {
252
  'change input' : 'onselect'
253
  },
254
- ready : function() {
255
 
256
- _.bindAll( this, 'render' );
257
- this.model.bind( 'change', this.render );
258
- },
259
  onselect : function() {
260
 
 
261
  var value = document.querySelector( '#' + this.el.id + ' input:checked' ).getAttribute( 'value' );
262
 
 
263
  var choices = this.model.get( 'choices' );
264
 
 
265
  _.each( choices, function( choice, key ) {
266
  choice.selected = key === value;
267
  } );
268
 
 
 
269
  this.model.set( 'choices', choices ).trigger( 'change', this.model );
270
  }
271
  } );
272
 
273
- // Image control view.
274
- views.controls.image = views.controls.default.extend( {
 
 
 
 
 
 
275
  events : {
276
  'click .butterbean-add-media' : 'showmodal',
277
  'click .butterbean-change-media' : 'showmodal',
278
  'click .butterbean-remove-media' : 'removemedia'
279
  },
280
- ready : function() {
281
 
282
- _.bindAll( this, 'render' );
283
- this.model.bind( 'change', this.render );
284
- },
285
  showmodal : function() {
286
 
287
- if ( ! _.isUndefined( this.modal ) ) {
288
 
289
- this.modal.open();
 
 
 
290
  return;
291
  }
292
 
293
- this.modal = wp.media( {
 
294
  frame : 'select',
295
  multiple : false,
296
  editing : true,
@@ -299,42 +843,33 @@
299
  button : { text: this.model.get( 'l10n' ).set }
300
  } );
301
 
302
- this.modal.on( 'select', function() {
 
303
 
304
- var media = this.modal.state().get( 'selection' ).first().toJSON();
 
305
 
 
 
 
 
306
  this.model.set( {
307
- src : media.sizes.large ? media.sizes.large.url : media.url,
308
  alt : media.alt,
309
  value : media.id
310
  } );
311
  }, this );
312
 
313
- this.modal.open();
 
314
  },
 
 
315
  removemedia : function() {
316
 
 
317
  this.model.set( { src : '', alt : '', value : '' } );
318
  }
319
  } );
320
 
321
- // Loop through each of the managers and render their views.
322
- _.each( butterbean_data.managers, function( data ) {
323
-
324
- // Create a new manager model.
325
- var manager = new Manager( data );
326
-
327
- // Create a new manager view.
328
- var view = new views.managers.default( { model : manager } );
329
-
330
- // Add the `.butterbean-ui` class to the meta box.
331
- document.getElementById( 'butterbean-ui-' + manager.get( 'name' ) ).className += ' butterbean-ui';
332
-
333
- // Render the manager view.
334
- document.querySelector( '#butterbean-ui-' + manager.get( 'name' ) + ' .inside' ).appendChild( view.render().el );
335
-
336
- // Render the manager subviews.
337
- view.subview_render();
338
- } );
339
-
340
  }() );
1
+ window.butterbean = window.butterbean || {};
2
+
3
  ( function() {
4
 
5
  // Bail if we don't have the JSON, which is passed in via `wp_localize_script()`.
7
  return;
8
  }
9
 
10
+ /**
11
+ * Our global object. The `butterbean` object is just a wrapper to house everything
12
+ * in a single namespace.
13
+ *
14
+ * @since 1.0.0
15
+ * @access public
16
+ * @var object
17
+ */
18
+ var api = butterbean = {
19
+
20
+ /**
21
+ * Houses the manager, section, and control views based on the `type`.
22
+ *
23
+ * @since 1.0.0
24
+ * @access public
25
+ * @var object
26
+ */
27
+ views : { managers : {}, sections : {}, controls : {} },
28
+
29
+ /**
30
+ * Houses the manager, section, and control templates based on the `type`.
31
+ *
32
+ * @since 1.0.0
33
+ * @access public
34
+ * @var object
35
+ */
36
+ templates : { managers : {}, sections : {}, controls : {} }
37
+ };
38
+
39
+ /**
40
+ * Creates a new manager view.
41
+ *
42
+ * @since 1.0.0
43
+ * @access public
44
+ * @param string $type
45
+ * @param object $args
46
+ * @return void
47
+ */
48
+ api.views.register_manager = function( type, args ) {
49
+
50
+ if ( 'default' !== type )
51
+ this.managers[ type ] = this.managers.default.extend( args );
52
+ };
53
+
54
+ /**
55
+ * Returns a manager view.
56
+ *
57
+ * @since 1.0.0
58
+ * @access public
59
+ * @param string $type
60
+ * @return object
61
+ */
62
+ api.views.get_manager = function( type ) {
63
+
64
+ if ( this.manager_exists( type ) )
65
+ return this.managers[ type ];
66
+
67
+ return this.managers.default;
68
+ };
69
+
70
+ /**
71
+ * Removes a manager view.
72
+ *
73
+ * @since 1.0.0
74
+ * @access public
75
+ * @param string $type
76
+ * @return void
77
+ */
78
+ api.views.unregister_manager = function( type ) {
79
+
80
+ if ( 'default' !== type && this.manager_exists( type ) )
81
+ delete this.managers[ type ];
82
+ };
83
+
84
+ /**
85
+ * Checks if a manager view exists.
86
+ *
87
+ * @since 1.0.0
88
+ * @access public
89
+ * @param string $type
90
+ * @return bool
91
+ */
92
+ api.views.manager_exists = function( type ) {
93
+
94
+ return this.managers.hasOwnProperty( type );
95
+ };
96
+
97
+ /**
98
+ * Creates a new section view.
99
+ *
100
+ * @since 1.0.0
101
+ * @access public
102
+ * @param string $type
103
+ * @param object $args
104
+ * @return void
105
+ */
106
+ api.views.register_section = function( type, args ) {
107
+
108
+ if ( 'default' !== type )
109
+ this.sections[ type ] = this.sections.default.extend( args );
110
+ };
111
+
112
+ /**
113
+ * Returns a section view.
114
+ *
115
+ * @since 1.0.0
116
+ * @access public
117
+ * @param string $type
118
+ * @return object
119
+ */
120
+ api.views.get_section = function( type ) {
121
+
122
+ if ( this.section_exists( type ) )
123
+ return this.sections[ type ];
124
+
125
+ return this.sections.default;
126
+ };
127
+
128
+ /**
129
+ * Removes a section view.
130
+ *
131
+ * @since 1.0.0
132
+ * @access public
133
+ * @param string $type
134
+ * @return void
135
+ */
136
+ api.views.unregister_section = function( type ) {
137
+
138
+ if ( 'default' !== type && this.section_exists( type ) )
139
+ delete this.sections[ type ];
140
+ };
141
+
142
+ /**
143
+ * Checks if a section view exists.
144
+ *
145
+ * @since 1.0.0
146
+ * @access public
147
+ * @param string $type
148
+ * @return bool
149
+ */
150
+ api.views.section_exists = function( type ) {
151
+
152
+ return this.sections.hasOwnProperty( type );
153
+ };
154
+
155
+ /**
156
+ * Creates a new control view.
157
+ *
158
+ * @since 1.0.0
159
+ * @access public
160
+ * @param string $type
161
+ * @param object $args
162
+ * @return void
163
+ */
164
+ api.views.register_control = function( type, args ) {
165
+
166
+ if ( 'default' !== type )
167
+ this.controls[ type ] = this.controls.default.extend( args );
168
+ };
169
+
170
+ /**
171
+ * Returns a control view.
172
+ *
173
+ * @since 1.0.0
174
+ * @access public
175
+ * @param string $type
176
+ * @return object
177
+ */
178
+ api.views.get_control = function( type ) {
179
+
180
+ if ( this.control_exists( type ) )
181
+ return this.controls[ type ];
182
+
183
+ return this.controls.default;
184
+ };
185
+
186
+ /**
187
+ * Removes a control view.
188
+ *
189
+ * @since 1.0.0
190
+ * @access public
191
+ * @param string $type
192
+ * @return void
193
+ */
194
+ api.views.unregister_control = function( type ) {
195
+
196
+ if ( 'default' !== type && this.control_exists( type ) )
197
+ delete this.controls[ type ];
198
+ };
199
+
200
+ /**
201
+ * Checks if a control view exists.
202
+ *
203
+ * @since 1.0.0
204
+ * @access public
205
+ * @param string $type
206
+ * @return bool
207
+ */
208
+ api.views.control_exists = function( type ) {
209
+
210
+ return this.controls.hasOwnProperty( type );
211
+ };
212
+
213
+ /**
214
+ * Creates a new manager template.
215
+ *
216
+ * @since 1.0.0
217
+ * @access public
218
+ * @param string $type
219
+ * @param object $args
220
+ * @return void
221
+ */
222
+ api.templates.register_manager = function( type ) {
223
+
224
+ this.managers[ type ] = wp.template( 'butterbean-manager-' + type );
225
+ };
226
+
227
+ /**
228
+ * Returns a manager template.
229
+ *
230
+ * @since 1.0.0
231
+ * @access public
232
+ * @param string $type
233
+ * @return function
234
+ */
235
+ api.templates.get_manager = function( type ) {
236
+
237
+ return this.manager_exists( type ) ? this.managers[ type ] : false;
238
+ };
239
+
240
+ /**
241
+ * Removes a manager template.
242
+ *
243
+ * @since 1.0.0
244
+ * @access public
245
+ * @param string $type
246
+ * @return void
247
+ */
248
+ api.templates.unregister_manager = function( type ) {
249
+
250
+ if ( this.manager_exists( type ) )
251
+ delete this.managers[ type ];
252
+ };
253
+
254
+ /**
255
+ * Checks if a manager template exists.
256
+ *
257
+ * @since 1.0.0
258
+ * @access public
259
+ * @param string $type
260
+ * @return bool
261
+ */
262
+ api.templates.manager_exists = function( type ) {
263
+
264
+ return this.managers.hasOwnProperty( type );
265
+ };
266
+
267
+ /**
268
+ * Creates a new section template.
269
+ *
270
+ * @since 1.0.0
271
+ * @access public
272
+ * @param string $type
273
+ * @param object $args
274
+ * @return void
275
+ */
276
+ api.templates.register_section = function( type ) {
277
+
278
+ this.sections[ type ] = wp.template( 'butterbean-section-' + type );
279
+ };
280
+
281
+ /**
282
+ * Returns a section template.
283
+ *
284
+ * @since 1.0.0
285
+ * @access public
286
+ * @param string $type
287
+ * @return function
288
+ */
289
+ api.templates.get_section = function( type ) {
290
+
291
+ return this.section_exists( type ) ? this.sections[ type ] : false;
292
+ };
293
+
294
+ /**
295
+ * Removes a section template.
296
+ *
297
+ * @since 1.0.0
298
+ * @access public
299
+ * @param string $type
300
+ * @return void
301
+ */
302
+ api.templates.unregister_section = function( type ) {
303
+
304
+ if ( this.section_exists( type ) )
305
+ delete this.sections[ type ];
306
+ };
307
+
308
+ /**
309
+ * Checks if a section template exists.
310
+ *
311
+ * @since 1.0.0
312
+ * @access public
313
+ * @param string $type
314
+ * @return bool
315
+ */
316
+ api.templates.section_exists = function( type ) {
317
+
318
+ return this.sections.hasOwnProperty( type );
319
+ };
320
+
321
+ /**
322
+ * Creates a new control template.
323
+ *
324
+ * @since 1.0.0
325
+ * @access public
326
+ * @param string $type
327
+ * @param object $args
328
+ * @return void
329
+ */
330
+ api.templates.register_control = function( type ) {
331
+
332
+ this.controls[ type ] = wp.template( 'butterbean-control-' + type );
333
+ };
334
+
335
+ /**
336
+ * Returns a control template.
337
+ *
338
+ * @since 1.0.0
339
+ * @access public
340
+ * @param string $type
341
+ * @return function
342
+ */
343
+ api.templates.get_control = function( type ) {
344
+
345
+ return this.control_exists( type ) ? this.controls[ type ] : false;
346
+ };
347
+
348
+ /**
349
+ * Removes a control template.
350
+ *
351
+ * @since 1.0.0
352
+ * @access public
353
+ * @param string $type
354
+ * @return void
355
+ */
356
+ api.templates.unregister_control = function( type ) {
357
+
358
+ if ( this.control_exists( type ) )
359
+ delete this.controls[ type ];
360
+ };
361
+
362
+ /**
363
+ * Checks if a control template exists.
364
+ *
365
+ * @since 1.0.0
366
+ * @access public
367
+ * @param string $type
368
+ * @return bool
369
+ */
370
+ api.templates.control_exists = function( type ) {
371
+
372
+ return this.controls.hasOwnProperty( type );
373
+ };
374
+
375
+ /**
376
+ * Renders our managers, sections, and controls.
377
+ *
378
+ * @since 1.0.0
379
+ * @access private
380
+ * @return void
381
+ */
382
+ api.render = function() {
383
+
384
+ // Loop through each of the managers and render their api.views.
385
+ _.each( butterbean_data.managers, function( data ) {
386
+
387
+ // Create a new manager model with the JSON data for the manager.
388
+ var manager = new Manager( data );
389
+
390
+ // Get the manager view callback.
391
+ var callback = api.views.get_manager( data.type );
392
+
393
+ // Create a new manager view.
394
+ var view = new callback( { model : manager } );
395
+
396
+ // Get the meta box element.
397
+ var metabox = document.getElementById( 'butterbean-ui-' + manager.get( 'name' ) );
398
+
399
+ // Add the `.butterbean-ui` class to the meta box.
400
+ metabox.className += ' butterbean-ui';
401
+
402
+ // Render the manager view.
403
+ metabox.querySelector( '.inside' ).appendChild( view.render().el );
404
+
405
+ // Render the manager subviews.
406
+ view.subview_render();
407
+
408
+ // Call the view's ready method.
409
+ view.ready();
410
+ } );
411
+ };
412
+
413
+ /* === Templates === */
414
 
415
  // Nav template.
416
  var nav_template = wp.template( 'butterbean-nav' );
461
 
462
  /* === Collections === */
463
 
464
+ /**
465
+ * Stores our collection of section models.
466
+ *
467
+ * @since 1.0.0
468
+ * @access private
469
+ * @var object
470
+ */
471
  var Sections = Backbone.Collection.extend( {
472
  model : Section
473
  } );
474
 
475
  /* === Views === */
476
 
477
+ /**
478
+ * The default manager view. Other views can extend this using the
479
+ * `butterbean.views.register_manager()` function.
480
+ *
481
+ * @since 1.0.0
482
+ * @access public
483
+ * @var object
484
+ */
485
+ api.views.managers[ 'default' ] = Backbone.View.extend( {
486
+
487
+ // Wrapper element for the manager view.
488
  tagName : 'div',
489
+
490
+ // Adds some custom attributes to the wrapper.
491
  attributes : function() {
492
  return {
493
  'id' : 'butterbean-manager-' + this.model.get( 'name' ),
494
  'class' : 'butterbean-manager butterbean-manager-' + this.model.get( 'type' )
495
  };
496
  },
497
+
498
+ // Initializes the view.
499
  initialize : function() {
500
 
501
  var type = this.model.get( 'type' );
502
 
503
+ // If there's not yet a template for this manager type, create it.
504
+ if ( ! api.templates.manager_exists( type ) )
505
+ api.templates.register_manager( type );
506
 
507
+ // Get the manager template.
508
+ this.template = api.templates.get_manager( type );
509
  },
510
+
511
+ // Renders the manager.
512
  render : function() {
513
  this.el.innerHTML = this.template( this.model.toJSON() );
514
  return this;
515
  },
516
+
517
+ // Renders the manager's sections and controls.
518
+ // Important! This may change drastically in the future, possibly even
519
+ // taken out of the manager view altogether. It's for this reason that
520
+ // it's not recommended to create custom views for managers right now.
521
  subview_render : function() {
522
 
523
  // Create a new section collection.
529
  sections.add( new Section( data ) );
530
  } );
531
 
532
+ // Loop through each section in the collection and render its view.
533
  sections.forEach( function( section, i ) {
534
 
535
+ // Create a new nav item view for the section.
536
+ var nav_view = new Nav_View( { model : section } );
537
 
538
+ // Render the nav item view.
539
  document.querySelector( '#butterbean-ui-' + section.get( 'manager' ) + ' .butterbean-nav' ).appendChild( nav_view.render().el );
540
+
541
+ // Get the section view callback.
542
+ var callback = api.views.get_section( section.attributes.type );
543
+
544
+ // Create a new section view.
545
+ var view = new callback( { model : section } );
546
+
547
+ // Render the section view.
548
+ document.querySelector( '#butterbean-ui-' + section.get( 'manager' ) + ' .butterbean-content' ).appendChild( view.render().el );
549
+
550
+ // Call the section view's ready method.
551
+ view.ready();
552
 
553
  // If the first model, set it to selected.
554
  section.set( 'selected', 0 === i );
557
  // Loop through each control for the manager and render its view.
558
  _.each( this.model.get( 'controls' ), function( data ) {
559
 
560
+ // Create a new control model.
561
  var control = new Control( data );
562
 
563
+ // Get the control view callback.
564
+ var callback = api.views.get_control( data.type );
565
 
566
+ // Create a new control view.
567
  var view = new callback( { model : control } );
568
 
569
+ // Render the view.
570
  document.getElementById( 'butterbean-' + control.get( 'manager' ) + '-section-' + control.get( 'section' ) ).appendChild( view.render().el );
571
+
572
+ // Call the view's ready method.
573
+ view.ready();
574
  } );
575
 
576
  return this;
577
+ },
578
+
579
+ // Function that is executed *after* the view has been rendered.
580
+ // This is meant to be overwritten in sub-views.
581
+ ready : function() {}
582
  } );
583
 
584
+ /**
585
+ * The default section view. Other views can extend this using the
586
+ * `butterbean.views.register_section()` function.
587
+ *
588
+ * @since 1.0.0
589
+ * @access public
590
+ * @var object
591
+ */
592
+ api.views.sections[ 'default' ] = Backbone.View.extend( {
593
+
594
+ // Wrapper element for the section.
595
  tagName : 'div',
596
+
597
+ // Adds custom attributes for the section wrapper.
598
  attributes : function() {
599
  return {
600
  'id' : 'butterbean-' + this.model.get( 'manager' ) + '-section-' + this.model.get( 'name' ),
602
  'aria-hidden' : ! this.model.get( 'selected' )
603
  };
604
  },
605
+
606
+ // Initializes the view.
607
  initialize : function() {
 
608
 
609
+ // Add an event for when the model changes.
610
+ this.model.on( 'change', this.onchange, this );
611
+
612
+ // Get the section type.
613
  var type = this.model.get( 'type' );
614
 
615
+ // If there's no template for this section type, create it.
616
+ if ( ! api.templates.section_exists( type ) )
617
+ api.templates.register_section( type );
618
 
619
+ // Gets the section template.
620
+ this.template = api.templates.get_section( type );
621
  },
622
+
623
+ // Renders the section.
624
  render : function() {
625
 
626
  // Only render template if model is active.
627
+ if ( this.model.get( 'active' ) )
628
  this.el.innerHTML = this.template( this.model.toJSON() );
 
629
 
630
  return this;
631
  },
632
+
633
+ // Executed when the model changes.
634
  onchange : function() {
635
 
636
  // Set the view's `aria-hidden` attribute based on whether the model is selected.
637
  this.el.setAttribute( 'aria-hidden', ! this.model.get( 'selected' ) );
638
+ },
639
+
640
+ // Function that is executed *after* the view has been rendered.
641
+ // This is meant to be overwritten in sub-views.
642
+ ready : function() {}
643
  } );
644
 
645
+ /**
646
+ * The nav item view for each section.
647
+ *
648
+ * @since 1.0.0
649
+ * @access public
650
+ * @var object
651
+ */
652
  var Nav_View = Backbone.View.extend( {
653
+
654
+ // Sets the template used.
655
  template : nav_template,
656
+
657
+ // Wrapper element for the nav item.
658
  tagName : 'li',
659
+
660
+ // Sets some custom attributes for the nav item wrapper.
661
  attributes : function() {
662
  return {
663
  'aria-selected' : this.model.get( 'selected' )
664
  };
665
  },
666
+
667
+ // Initializes the nav item view.
668
  initialize : function() {
669
+ this.model.on( 'change', this.render, this );
670
+ this.model.on( 'change', this.onchange, this );
671
  },
672
+
673
+ // Renders the nav item.
674
  render : function() {
675
 
676
  // Only render template if model is active.
677
+ if ( this.model.get( 'active' ) )
678
  this.el.innerHTML = this.template( this.model.toJSON() );
 
679
 
680
  return this;
681
  },
682
+
683
+ // Custom events.
684
  events : {
685
  'click a' : 'onselect'
686
  },
687
+
688
+ // Executed when the section model changes.
689
  onchange : function() {
690
 
691
  // Set the `aria-selected` attibute based on the model selected state.
692
  this.el.setAttribute( 'aria-selected', this.model.get( 'selected' ) );
693
  },
694
+
695
+ // Executed when the link for the nav item is clicked.
696
  onselect : function( event ) {
697
  event.preventDefault();
698
 
707
  }
708
  } );
709
 
710
+ /**
711
+ * The default control view. Other views can extend this using the
712
+ * `butterbean.views.register_control()` function.
713
+ *
714
+ * @since 1.0.0
715
+ * @access public
716
+ * @var object
717
+ */
718
+ api.views.controls[ 'default' ] = Backbone.View.extend( {
719
+
720
+ // Wrapper element for the control.
721
  tagName : 'div',
722
+
723
+ // Custom attributes for the control wrapper.
724
  attributes : function() {
725
  return {
726
  'id' : 'butterbean-control-' + this.model.get( 'name' ),
727
  'class' : 'butterbean-control butterbean-control-' + this.model.get( 'type' )
728
  };
729
  },
730
+
731
+ // Initiazlies the control view.
732
  initialize : function() {
733
  var type = this.model.get( 'type' );
734
 
735
  // Only add a new control template if we have a different control type.
736
+ if ( ! api.templates.control_exists( type ) )
737
+ api.templates.register_control( type );
 
738
 
739
+ // Get the control template.
740
+ this.template = api.templates.get_control( type );
741
 
742
+ // Bind changes so that the view is re-rendered when the model changes.
743
+ _.bindAll( this, 'render' );
744
+ this.model.bind( 'change', this.render );
745
  },
746
+
747
+ // Renders the control template.
748
  render : function() {
749
 
750
  // Only render template if model is active.
751
+ if ( this.model.get( 'active' ) )
752
  this.el.innerHTML = this.template( this.model.toJSON() );
 
753
 
754
  return this;
755
  },
756
+
757
+ // Function that is executed *after* the view has been rendered.
758
+ // This is meant to be overwritten in sub-views.
759
  ready : function() {}
760
  } );
761
 
762
+ /**
763
+ * Adds the color control view.
764
+ *
765
+ * @since 1.0.0
766
+ */
767
+ api.views.register_control( 'color', {
768
+
769
+ // Calls the core WP color picker for the control's input.
770
+ ready : function() {
771
+
772
+ var options = this.model.attributes.options;
773
+
774
+ jQuery( this.$el ).find( '.butterbean-color-picker' ).wpColorPicker( options );
775
+ }
776
+ } );
777
+
778
+ /**
779
+ * Adds the color palette view.
780
+ *
781
+ * @since 1.0.0
782
+ */
783
+ api.views.register_control( 'palette', {
784
+
785
+ // Adds custom events.
786
  events : {
787
  'change input' : 'onselect'
788
  },
 
789
 
790
+ // Executed when one of the color palette's value has changed.
791
+ // These are radio inputs.
 
792
  onselect : function() {
793
 
794
+ // Get the value of the input.
795
  var value = document.querySelector( '#' + this.el.id + ' input:checked' ).getAttribute( 'value' );
796
 
797
+ // Get all choices.
798
  var choices = this.model.get( 'choices' );
799
 
800
+ // Loop through choices and change the selected value.
801
  _.each( choices, function( choice, key ) {
802
  choice.selected = key === value;
803
  } );
804
 
805
+ // Because `choices` is an array, it's not recognized as a change. So, we
806
+ // have to manually trigger a change here so that the view gets re-rendered.
807
  this.model.set( 'choices', choices ).trigger( 'change', this.model );
808
  }
809
  } );
810
 
811
+ /**
812
+ * Adds the image control view.
813
+ *
814
+ * @since 1.0.0
815
+ */
816
+ api.views.register_control( 'image', {
817
+
818
+ // Adds custom events.
819
  events : {
820
  'click .butterbean-add-media' : 'showmodal',
821
  'click .butterbean-change-media' : 'showmodal',
822
  'click .butterbean-remove-media' : 'removemedia'
823
  },
 
824
 
825
+ // Executed when the show modal button is clicked.
 
 
826
  showmodal : function() {
827
 
 
828
 
829
+ // If we already have a media modal, open it.
830
+ if ( ! _.isUndefined( this.media_modal ) ) {
831
+
832
+ this.media_modal.open();
833
  return;
834
  }
835
 
836
+ // Create a new media modal.
837
+ this.media_modal = wp.media( {
838
  frame : 'select',
839
  multiple : false,
840
  editing : true,
843
  button : { text: this.model.get( 'l10n' ).set }
844
  } );
845
 
846
+ // Runs when an image is selected in the media modal.
847
+ this.media_modal.on( 'select', function() {
848
 
849
+ // Gets the JSON data for the first selection.
850
+ var media = this.media_modal.state().get( 'selection' ).first().toJSON();
851
 
852
+ // Size of image to display.
853
+ var size = this.model.attributes.size;
854
+
855
+ // Updates the model for the view.
856
  this.model.set( {
857
+ src : media.sizes[ size ] ? media.sizes[ size ]['url'] : media.url,
858
  alt : media.alt,
859
  value : media.id
860
  } );
861
  }, this );
862
 
863
+ // Opens the media modal.
864
+ this.media_modal.open();
865
  },
866
+
867
+ // Executed when the remove media button is clicked.
868
  removemedia : function() {
869
 
870
+ // Updates the model for the view.
871
  this.model.set( { src : '', alt : '', value : '' } );
872
  }
873
  } );
874
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
875
  }() );
admin/butterbean/js/butterbean.min.js CHANGED
@@ -1 +1 @@
1
- !function(){if(!_.isUndefined(butterbean_data)){var e={managers:{},sections:{},controls:{}},t={managers:{},sections:{},controls:{}},n=wp.template("butterbean-nav"),i=Backbone.Model.extend({defaults:{name:"",type:"",sections:{},controls:{}}}),a=Backbone.Model.extend({defaults:{name:"",type:"",label:"",description:"",icon:"",manager:"",active:"",selected:!1}}),o=Backbone.Model.extend({defaults:{name:"",type:"",label:"",description:"",icon:"",value:"",choices:{},attr:"",active:"",manager:"",section:"",setting:""}}),s=Backbone.Collection.extend({model:a});e.managers.default=Backbone.View.extend({tagName:"div",attributes:function(){return{id:"butterbean-manager-"+this.model.get("name"),"class":"butterbean-manager butterbean-manager-"+this.model.get("type")}},initialize:function(){var e=this.model.get("type");_.isUndefined(t.managers[e])&&(t.managers[e]=wp.template("butterbean-manager-"+e)),this.template=t.managers[e]},render:function(){return this.el.innerHTML=this.template(this.model.toJSON()),this},subview_render:function(){var t=new s;return _.each(this.model.get("sections"),function(e){t.add(new a(e))}),t.forEach(function(t,n){var i=new l({model:t}),a=new e.sections.default({model:t});document.querySelector("#butterbean-ui-"+t.get("manager")+" .butterbean-nav").appendChild(i.render().el),document.querySelector("#butterbean-ui-"+t.get("manager")+" .butterbean-content").appendChild(a.render().el),t.set("selected",0===n)},this),_.each(this.model.get("controls"),function(t){var n=new o(t),i=_.isUndefined(e.controls[t.type])?e.controls.default:e.controls[t.type],a=new i({model:n});document.getElementById("butterbean-"+n.get("manager")+"-section-"+n.get("section")).appendChild(a.render().el)}),this}}),e.sections.default=Backbone.View.extend({tagName:"div",attributes:function(){return{id:"butterbean-"+this.model.get("manager")+"-section-"+this.model.get("name"),"class":"butterbean-section butterbean-section-"+this.model.get("type"),"aria-hidden":!this.model.get("selected")}},initialize:function(){this.model.on("change",this.onchange,this);var e=this.model.get("type");_.isUndefined(t.sections[e])&&(t.sections[e]=wp.template("butterbean-section-"+e)),this.template=t.sections[e]},render:function(){return this.model.get("active")&&(this.el.innerHTML=this.template(this.model.toJSON())),this},onchange:function(){this.el.setAttribute("aria-hidden",!this.model.get("selected"))}});var l=Backbone.View.extend({template:n,tagName:"li",attributes:function(){return{"aria-selected":this.model.get("selected")}},initialize:function(){this.model.on("change",this.render,this),this.model.on("change",this.onchange,this)},render:function(){return this.model.get("active")&&(this.el.innerHTML=this.template(this.model.toJSON())),this},events:{"click a":"onselect"},onchange:function(){this.el.setAttribute("aria-selected",this.model.get("selected"))},onselect:function(e){e.preventDefault(),_.each(this.model.collection.models,function(e){e.set("selected",!1)},this),this.model.set("selected",!0)}});e.controls.default=Backbone.View.extend({tagName:"div",attributes:function(){return{id:"butterbean-control-"+this.model.get("name"),"class":"butterbean-control butterbean-control-"+this.model.get("type")}},initialize:function(){var e=this.model.get("type");_.isUndefined(t.controls[e])&&(t.controls[e]=wp.template("butterbean-control-"+e)),this.template=t.controls[e],this.ready()},render:function(){return this.model.get("active")&&(this.el.innerHTML=this.template(this.model.toJSON())),this},ready:function(){}}),e.controls.palette=e.controls.default.extend({events:{"change input":"onselect"},ready:function(){_.bindAll(this,"render"),this.model.bind("change",this.render)},onselect:function(){var e=document.querySelector("#"+this.el.id+" input:checked").getAttribute("value"),t=this.model.get("choices");_.each(t,function(t,n){t.selected=n===e}),this.model.set("choices",t).trigger("change",this.model)}}),e.controls.image=e.controls.default.extend({events:{"click .butterbean-add-media":"showmodal","click .butterbean-change-media":"showmodal","click .butterbean-remove-media":"removemedia"},ready:function(){_.bindAll(this,"render"),this.model.bind("change",this.render)},showmodal:function(){return _.isUndefined(this.modal)?(this.modal=wp.media({frame:"select",multiple:!1,editing:!0,title:this.model.get("l10n").choose,library:{type:"image"},button:{text:this.model.get("l10n").set}}),this.modal.on("select",function(){var e=this.modal.state().get("selection").first().toJSON();this.model.set({src:e.sizes.large?e.sizes.large.url:e.url,alt:e.alt,value:e.id})},this),this.modal.open(),void 0):(this.modal.open(),void 0)},removemedia:function(){this.model.set({src:"",alt:"",value:""})}}),_.each(butterbean_data.managers,function(t){var n=new i(t),a=new e.managers.default({model:n});document.getElementById("butterbean-ui-"+n.get("name")).className+=" butterbean-ui",document.querySelector("#butterbean-ui-"+n.get("name")+" .inside").appendChild(a.render().el),a.subview_render()})}}();
1
+ window.butterbean=window.butterbean||{},function(){if(!_.isUndefined(butterbean_data)){var e=butterbean={views:{managers:{},sections:{},controls:{}},templates:{managers:{},sections:{},controls:{}}};e.views.register_manager=function(e,t){"default"!==e&&(this.managers[e]=this.managers.default.extend(t))},e.views.get_manager=function(e){return this.manager_exists(e)?this.managers[e]:this.managers.default},e.views.unregister_manager=function(e){"default"!==e&&this.manager_exists(e)&&delete this.managers[e]},e.views.manager_exists=function(e){return this.managers.hasOwnProperty(e)},e.views.register_section=function(e,t){"default"!==e&&(this.sections[e]=this.sections.default.extend(t))},e.views.get_section=function(e){return this.section_exists(e)?this.sections[e]:this.sections.default},e.views.unregister_section=function(e){"default"!==e&&this.section_exists(e)&&delete this.sections[e]},e.views.section_exists=function(e){return this.sections.hasOwnProperty(e)},e.views.register_control=function(e,t){"default"!==e&&(this.controls[e]=this.controls.default.extend(t))},e.views.get_control=function(e){return this.control_exists(e)?this.controls[e]:this.controls.default},e.views.unregister_control=function(e){"default"!==e&&this.control_exists(e)&&delete this.controls[e]},e.views.control_exists=function(e){return this.controls.hasOwnProperty(e)},e.templates.register_manager=function(e){this.managers[e]=wp.template("butterbean-manager-"+e)},e.templates.get_manager=function(e){return this.manager_exists(e)?this.managers[e]:!1},e.templates.unregister_manager=function(e){this.manager_exists(e)&&delete this.managers[e]},e.templates.manager_exists=function(e){return this.managers.hasOwnProperty(e)},e.templates.register_section=function(e){this.sections[e]=wp.template("butterbean-section-"+e)},e.templates.get_section=function(e){return this.section_exists(e)?this.sections[e]:!1},e.templates.unregister_section=function(e){this.section_exists(e)&&delete this.sections[e]},e.templates.section_exists=function(e){return this.sections.hasOwnProperty(e)},e.templates.register_control=function(e){this.controls[e]=wp.template("butterbean-control-"+e)},e.templates.get_control=function(e){return this.control_exists(e)?this.controls[e]:!1},e.templates.unregister_control=function(e){this.control_exists(e)&&delete this.controls[e]},e.templates.control_exists=function(e){return this.controls.hasOwnProperty(e)},e.render=function(){_.each(butterbean_data.managers,function(t){var i=new n(t),s=e.views.get_manager(t.type),a=new s({model:i}),o=document.getElementById("butterbean-ui-"+i.get("name"));o.className+=" butterbean-ui",o.querySelector(".inside").appendChild(a.render().el),a.subview_render(),a.ready()})};var t=wp.template("butterbean-nav"),n=Backbone.Model.extend({defaults:{name:"",type:"",sections:{},controls:{}}}),i=Backbone.Model.extend({defaults:{name:"",type:"",label:"",description:"",icon:"",manager:"",active:"",selected:!1}}),s=Backbone.Model.extend({defaults:{name:"",type:"",label:"",description:"",icon:"",value:"",choices:{},attr:"",active:"",manager:"",section:"",setting:""}}),a=Backbone.Collection.extend({model:i});e.views.managers["default"]=Backbone.View.extend({tagName:"div",attributes:function(){return{id:"butterbean-manager-"+this.model.get("name"),"class":"butterbean-manager butterbean-manager-"+this.model.get("type")}},initialize:function(){var t=this.model.get("type");e.templates.manager_exists(t)||e.templates.register_manager(t),this.template=e.templates.get_manager(t)},render:function(){return this.el.innerHTML=this.template(this.model.toJSON()),this},subview_render:function(){var t=new a;return _.each(this.model.get("sections"),function(e){t.add(new i(e))}),t.forEach(function(t,n){var i=new o({model:t});document.querySelector("#butterbean-ui-"+t.get("manager")+" .butterbean-nav").appendChild(i.render().el);var s=e.views.get_section(t.attributes.type),a=new s({model:t});document.querySelector("#butterbean-ui-"+t.get("manager")+" .butterbean-content").appendChild(a.render().el),a.ready(),t.set("selected",0===n)},this),_.each(this.model.get("controls"),function(t){var n=new s(t),i=e.views.get_control(t.type),a=new i({model:n});document.getElementById("butterbean-"+n.get("manager")+"-section-"+n.get("section")).appendChild(a.render().el),a.ready()}),this},ready:function(){}}),e.views.sections["default"]=Backbone.View.extend({tagName:"div",attributes:function(){return{id:"butterbean-"+this.model.get("manager")+"-section-"+this.model.get("name"),"class":"butterbean-section butterbean-section-"+this.model.get("type"),"aria-hidden":!this.model.get("selected")}},initialize:function(){this.model.on("change",this.onchange,this);var t=this.model.get("type");e.templates.section_exists(t)||e.templates.register_section(t),this.template=e.templates.get_section(t)},render:function(){return this.model.get("active")&&(this.el.innerHTML=this.template(this.model.toJSON())),this},onchange:function(){this.el.setAttribute("aria-hidden",!this.model.get("selected"))},ready:function(){}});var o=Backbone.View.extend({template:t,tagName:"li",attributes:function(){return{"aria-selected":this.model.get("selected")}},initialize:function(){this.model.on("change",this.render,this),this.model.on("change",this.onchange,this)},render:function(){return this.model.get("active")&&(this.el.innerHTML=this.template(this.model.toJSON())),this},events:{"click a":"onselect"},onchange:function(){this.el.setAttribute("aria-selected",this.model.get("selected"))},onselect:function(e){e.preventDefault(),_.each(this.model.collection.models,function(e){e.set("selected",!1)},this),this.model.set("selected",!0)}});e.views.controls["default"]=Backbone.View.extend({tagName:"div",attributes:function(){return{id:"butterbean-control-"+this.model.get("name"),"class":"butterbean-control butterbean-control-"+this.model.get("type")}},initialize:function(){var t=this.model.get("type");e.templates.control_exists(t)||e.templates.register_control(t),this.template=e.templates.get_control(t),_.bindAll(this,"render"),this.model.bind("change",this.render)},render:function(){return this.model.get("active")&&(this.el.innerHTML=this.template(this.model.toJSON())),this},ready:function(){}}),e.views.register_control("color",{ready:function(){var e=this.model.attributes.options;jQuery(this.$el).find(".butterbean-color-picker").wpColorPicker(e)}}),e.views.register_control("palette",{events:{"change input":"onselect"},onselect:function(){var e=document.querySelector("#"+this.el.id+" input:checked").getAttribute("value"),t=this.model.get("choices");_.each(t,function(t,n){t.selected=n===e}),this.model.set("choices",t).trigger("change",this.model)}}),e.views.register_control("image",{events:{"click .butterbean-add-media":"showmodal","click .butterbean-change-media":"showmodal","click .butterbean-remove-media":"removemedia"},showmodal:function(){return _.isUndefined(this.media_modal)?(this.media_modal=wp.media({frame:"select",multiple:!1,editing:!0,title:this.model.get("l10n").choose,library:{type:"image"},button:{text:this.model.get("l10n").set}}),this.media_modal.on("select",function(){var e=this.media_modal.state().get("selection").first().toJSON(),t=this.model.attributes.size;this.model.set({src:e.sizes[t]?e.sizes[t].url:e.url,alt:e.alt,value:e.id})},this),this.media_modal.open(),void 0):(this.media_modal.open(),void 0)},removemedia:function(){this.model.set({src:"",alt:"",value:""})}})}}();
admin/butterbean/readme.md CHANGED
@@ -1,10 +1,18 @@
1
  # ButterBean
2
 
3
- ButterBean is a framework for creating cool post meta boxes.
4
 
5
- **Development environments only:** Please note that this is a development version of the code. Don't use on a live site yet.
6
 
7
- ## Usage
 
 
 
 
 
 
 
 
8
 
9
  This is a quick guide. If you're familiar with the WordPress Customization API, you should probably pick this up fairly quickly. A lot of the same concepts are used here.
10
 
@@ -12,87 +20,124 @@ This is a quick guide. If you're familiar with the WordPress Customization API,
12
 
13
  Drop the `butterbean` folder into your plugin. That's the simple part.
14
 
15
- You're only going to want to load this on the edit post screen for whatever post type you're using it on.
16
-
17
- add_action( 'load-post.php', 'th_load' );
18
- add_action( 'load-post-new.php', 'th_load' );
19
 
20
- function th_load() {
 
21
 
22
- // Bail if not our post type.
23
- if ( 'your_post_type' !== get_current_screen()->post_type )
24
- return;
25
 
26
- require_once( 'path/to/butterbean/butterbean.php' );
27
- }
 
28
 
29
  ### Registration
30
 
31
  There's a built-in action hook called `butterbean_register`. You're going to use that to register everything. So, you need to set up a callback function for that.
32
 
33
- add_action( 'butterbean_register', 'th_register', 10, 2 );
 
34
 
35
- function th_register( $butterbean, $post_type ) {
36
 
37
- // Register managers, sections, controls, and settings here.
38
- }
 
39
 
40
  #### Registering a manager
41
 
42
  A **manager** is a group of sections, controls, and settings. It's displayed as a single meta box. There can be multiple managers per screen (don't try multiples yet).
43
 
44
- $butterbean->register_manager(
45
- 'example',
46
- array(
47
- 'label' => esc_html__( 'Example', 'your-textdomain' ),
48
- 'post_type' => 'your_post_type',
49
- 'context' => 'normal',
50
- 'priority' => 'high'
51
- )
52
- );
 
53
 
54
- $manager = $butterbean->get_manager( 'example' );
 
55
 
56
  #### Registering a section
57
 
58
  A **section** is a group of controls within a manager. They are presented as "tabbed" sections in the UI.
59
 
60
- $manager->register_section(
61
- 'section_1',
62
- array(
63
- 'label' => esc_html__( 'Section 1', 'your-textdomain' ),
64
- 'icon' => 'dashicons-admin-generic'
65
- )
66
- );
 
 
67
 
68
  #### Registering a control
69
 
70
  A **control** is essentially a form field. It's the field(s) that a user enters data into. Each control belongs to a section. Each control should also be tied to a setting (below).
71
 
72
- $manager->register_control(
73
- 'abc_xyz', // Same as setting name.
74
- array(
75
- 'type' => 'text',
76
- 'section' => 'section_1',
77
- 'label' => esc_html__( 'Control ABC', 'your-textdomain' ),
78
- 'attr' => array( 'class' => 'widefat' )
79
- )
80
- );
 
 
81
 
82
  #### Registering a setting
83
 
84
  A **setting** is nothing more than some post metadata and how it gets stored. A setting belongs to a specific control.
85
 
86
- $manager->register_setting(
87
- 'abc_xyz', // Same as control name.
88
- array(
89
- 'sanitize_callback' => 'wp_filter_nohtml_kses'
90
- )
91
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  ## Professional Support
94
 
95
- If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](http://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 60,000+ users (and growing).
96
 
97
  ## Copyright and License
98
 
1
  # ButterBean
2
 
3
+ ButterBean is a neat little post meta box framework built on [Backbone.js](http://backbonejs.org) and [Underscore.js](http://underscorejs.org). You can run it as a standalone plugin or drop it into your own plugins.
4
 
5
+ The idea behind ButterBean came about because I often build custom post types that need quite a bit of custom metadata attached to the posts. Separating this into multiple meta boxes wasn't fun or user friendly. So, I decided to go with a single tabbed meta box instead.
6
 
7
+ And, that's what ButterBean is. It's essentially a meta box with tabs for lots of content.
8
+
9
+ ## Just the interface
10
+
11
+ A lot of meta box frameworks try to do everything. They handle backend output, frontend output, and everything else you can think of. ButterBean is meant to be an interface only. Because every project's needs are vastly different, it doesn't make sense to stick you with a bunch of things you don't need. This means that the code can stay relatively lean and flexible, which makes it perfect for bundling in your plugins.
12
+
13
+ So, don't go looking for functions for outputting metadata on the front end from ButterBean. It doesn't have any. Use the core WordPress functionality or build your own wrapper functions.
14
+
15
+ ## Documentation
16
 
17
  This is a quick guide. If you're familiar with the WordPress Customization API, you should probably pick this up fairly quickly. A lot of the same concepts are used here.
18
 
20
 
21
  Drop the `butterbean` folder into your plugin. That's the simple part.
22
 
23
+ The script will auto-load itself on the correct admin hooks. You just need to load it like so:
 
 
 
24
 
25
+ ```
26
+ add_action( 'plugins_loaded', 'th_load' );
27
 
28
+ function th_load() {
 
 
29
 
30
+ require_once( 'path/to/butterbean/butterbean.php' );
31
+ }
32
+ ```
33
 
34
  ### Registration
35
 
36
  There's a built-in action hook called `butterbean_register`. You're going to use that to register everything. So, you need to set up a callback function for that.
37
 
38
+ ```
39
+ add_action( 'butterbean_register', 'th_register', 10, 2 );
40
 
41
+ function th_register( $butterbean, $post_type ) {
42
 
43
+ // Register managers, sections, controls, and settings here.
44
+ }
45
+ ```
46
 
47
  #### Registering a manager
48
 
49
  A **manager** is a group of sections, controls, and settings. It's displayed as a single meta box. There can be multiple managers per screen (don't try multiples yet).
50
 
51
+ ```
52
+ $butterbean->register_manager(
53
+ 'example',
54
+ array(
55
+ 'label' => esc_html__( 'Example', 'your-textdomain' ),
56
+ 'post_type' => 'your_post_type',
57
+ 'context' => 'normal',
58
+ 'priority' => 'high'
59
+ )
60
+ );
61
 
62
+ $manager = $butterbean->get_manager( 'example' );
63
+ ```
64
 
65
  #### Registering a section
66
 
67
  A **section** is a group of controls within a manager. They are presented as "tabbed" sections in the UI.
68
 
69
+ ```
70
+ $manager->register_section(
71
+ 'section_1',
72
+ array(
73
+ 'label' => esc_html__( 'Section 1', 'your-textdomain' ),
74
+ 'icon' => 'dashicons-admin-generic'
75
+ )
76
+ );
77
+ ```
78
 
79
  #### Registering a control
80
 
81
  A **control** is essentially a form field. It's the field(s) that a user enters data into. Each control belongs to a section. Each control should also be tied to a setting (below).
82
 
83
+ ```
84
+ $manager->register_control(
85
+ 'abc_xyz', // Same as setting name.
86
+ array(
87
+ 'type' => 'text',
88
+ 'section' => 'section_1',
89
+ 'label' => esc_html__( 'Control ABC', 'your-textdomain' ),
90
+ 'attr' => array( 'class' => 'widefat' )
91
+ )
92
+ );
93
+ ```
94
 
95
  #### Registering a setting
96
 
97
  A **setting** is nothing more than some post metadata and how it gets stored. A setting belongs to a specific control.
98
 
99
+ ```
100
+ $manager->register_setting(
101
+ 'abc_xyz', // Same as control name.
102
+ array(
103
+ 'sanitize_callback' => 'wp_filter_nohtml_kses'
104
+ )
105
+ );
106
+ ```
107
+
108
+ ### JavaScript API
109
+
110
+ ButterBean was built using [Backbone](http://backbonejs.org) for handling models, collections, and views. It uses [Underscore](http://underscorejs.org) for rendering templates for the views. All output is handled via JavaScript rather than PHP so that we can do cool stuff on the fly without having to reload the page. This is particularly useful when you start building more complex controls.
111
+
112
+ You'll never need to touch JavaScript until you need to build a control that relies on JavaScript.
113
+
114
+ #### The butterbean object
115
+
116
+ `butterbean` is the global object that houses everything you ever want to touch on the JavaScript side of things. It's located in the `js/butterbean.js` file. This file is well-documented, so you'll want to dive into it for doing more advanced stuff.
117
+
118
+ `butterbean.views.register_control()` is what most people will end up using. It's a function for registering a custom control view. New views can be created for each `type` of control.
119
+
120
+ Here's a quick example of registering a view for a color control where we need to call the core WordPress `wpColorPicker()` function. It uses the `ready()` function, which is fired after the HTML has been rendered for the view.
121
+
122
+ ```
123
+ ( function() {
124
+
125
+ butterbean.views.register_control( 'color', {
126
+
127
+ // Calls the core WP color picker for the control's input.
128
+ ready : function() {
129
+
130
+ var options = this.model.attributes.options;
131
+
132
+ jQuery( this.$el ).find( '.butterbean-color-picker' ).wpColorPicker( options );
133
+ }
134
+ } );
135
+ }() );
136
+ ```
137
 
138
  ## Professional Support
139
 
140
+ If you need professional plugin support from me, the plugin author, you can access the support forums at [Theme Hybrid](http://themehybrid.com/board/topics), which is a professional WordPress help/support site where I handle support for all my plugins and themes for a community of 70,000+ users (and growing).
141
 
142
  ## Copyright and License
143
 
admin/butterbean/tmpl/control-datetime.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <# if ( data.label ) { #>
2
+ <span class="butterbean-label">{{ data.label }}</span>
3
+ <# } #>
4
+
5
+ <# if ( data.description ) { #>
6
+ <span class="butterbean-description">{{{ data.description }}}</span>
7
+ <# } #>
8
+
9
+ <?php $month = '<label>
10
+ <span class="screen-reader-text">{{ data.month.label }}</span>
11
+ <select name="{{ data.month.name }}">
12
+ <# _.each( data.month.choices, function( choice ) { #>
13
+ <option value="{{ choice.num }}" <# if ( choice.num === data.month.value ) { #> selected="selected" <# } #>>{{ choice.label }}</option>
14
+ <# } ) #>
15
+ </select>
16
+ </label>';
17
+
18
+ $day = '<label>
19
+ <span class="screen-reader-text">{{ data.day.label }}</span>
20
+ <input type="text" name="{{ data.day.name }}" value="{{ data.day.value }}" {{{ data.day.attr }}} />
21
+ </label>';
22
+
23
+ $year = '<label>
24
+ <span class="screen-reader-text">{{ data.year.label }}</span>
25
+ <input type="text" name="{{ data.year.name }}" value="{{ data.year.value }}" {{{ data.year.attr }}} />
26
+ </label>';
27
+
28
+ $hour = '<label>
29
+ <span class="screen-reader-text">{{ data.hour.label }}</span>
30
+ <input type="text" name="{{ data.hour.name }}" value="{{ data.hour.value }}" {{{ data.hour.attr }}} />
31
+ </label>';
32
+
33
+ $minute = '<label>
34
+ <span class="screen-reader-text">{{ data.minute.label }}</span>
35
+ <input type="text" name="{{ data.minute.name }}" value="{{ data.minute.value }}" {{{ data.minute.attr }}} />
36
+ </label>';
37
+
38
+ $second = '<label>
39
+ <span class="screen-reader-text">{{ data.second.label }}</span>
40
+ <input type="text" name="{{ data.second.name }}" value="{{ data.second.value }}" {{{ data.second.attr }}} />
41
+ </label>'; ?>
42
+
43
+ <# if ( data.show_time ) { #>
44
+
45
+ <?php // Translators: 1: month, 2: day, 3: year, 4: hour, 5: minute, 6: second.
46
+ printf( __( '%1$s %2$s, %3$s @ %4$s:%5$s:%6$s', 'butterbean' ), $month, $day, $year, $hour, $minute, $second );
47
+ ?>
48
+
49
+ <# } else { #>
50
+
51
+ <?php // Translators: 1: month, 2: day, 3: year.
52
+ printf( __( '%1$s %2$s, %3$s', 'butterbean' ), $month, $day, $year );
53
+ ?>
54
+
55
+ <# } #>
admin/butterbean/tmpl/control.php CHANGED
@@ -3,9 +3,9 @@
3
  <span class="butterbean-label">{{ data.label }}</span>
4
  <# } #>
5
 
6
- <input type="{{ data.type }}" value="{{ data.value }}" {{{ data.attr }}} />
7
-
8
  <# if ( data.description ) { #>
9
  <span class="butterbean-description">{{{ data.description }}}</span>
10
  <# } #>
 
 
11
  </label>
3
  <span class="butterbean-label">{{ data.label }}</span>
4
  <# } #>
5
 
 
 
6
  <# if ( data.description ) { #>
7
  <span class="butterbean-description">{{{ data.description }}}</span>
8
  <# } #>
9
+
10
+ <input type="{{ data.type }}" value="{{ data.value }}" {{{ data.attr }}} />
11
  </label>
admin/css/admin.css CHANGED
@@ -1,37 +1,37 @@
1
- #butterbean-control-taxonomy,
2
- #butterbean-control-terms {
3
- display: none;
4
- }
5
-
6
- #butterbean-ui-wp_show_posts input,
7
- #butterbean-ui-wp_show_posts select,
8
- #butterbean-ui-wp_show_posts textarea {
9
- padding: 10px;
10
- width: 100%;
11
- height: auto;
12
- }
13
-
14
- .wpsp-pro {
15
- background: orange;
16
- padding: 5px;
17
- color: white;
18
- font-size: 80%;
19
- }
20
-
21
- #butterbean-ui-wp_show_posts .butterbean-control-color input {
22
- width: 80px;
23
- padding: 3px 5px;
24
- line-height: 16px;
25
- }
26
-
27
- #butterbean-ui-wp_show_posts input[type="checkbox"] {
28
- width: initial;
29
- height: 16px;
30
- }
31
-
32
- .mce-i-wpsp-add-icon:before {
33
- content: "\f163";
34
- font: normal 20px/1 'dashicons';
35
- -webkit-font-smoothing: antialiased;
36
- -moz-osx-font-smoothing: grayscale;
37
  }
1
+ #butterbean-control-taxonomy,
2
+ #butterbean-control-terms {
3
+ display: none;
4
+ }
5
+
6
+ #butterbean-ui-wp_show_posts input,
7
+ #butterbean-ui-wp_show_posts select,
8
+ #butterbean-ui-wp_show_posts textarea {
9
+ padding: 10px;
10
+ width: 100%;
11
+ height: auto;
12
+ }
13
+
14
+ .wpsp-pro {
15
+ background: orange;
16
+ padding: 5px;
17
+ color: white;
18
+ font-size: 80%;
19
+ }
20
+
21
+ #butterbean-ui-wp_show_posts .butterbean-control-color input {
22
+ width: 80px;
23
+ padding: 3px 5px;
24
+ line-height: 16px;
25
+ }
26
+
27
+ #butterbean-ui-wp_show_posts input[type="checkbox"] {
28
+ width: initial;
29
+ height: 16px;
30
+ }
31
+
32
+ .mce-i-wpsp-add-icon:before {
33
+ content: "\f163";
34
+ font: normal 20px/1 'dashicons';
35
+ -webkit-font-smoothing: antialiased;
36
+ -moz-osx-font-smoothing: grayscale;
37
  }
admin/js/admin-scripts.js CHANGED
@@ -1,206 +1,208 @@
1
- function wpsp_get_taxonomy( type = 'post' ) {
2
- var response = jQuery.getJSON({
3
- type: 'POST',
4
- url: ajaxurl,
5
- data: {
6
- action: 'wpsp_get_taxonomies',
7
- wpsp_nonce: wpsp_object.nonce,
8
- post_type: type
9
- },
10
- async: false,
11
- dataType: 'json'
12
- });
13
-
14
- return response.responseJSON;
15
- }
16
-
17
- function wpsp_get_terms( type = 'post' ) {
18
- var response = jQuery.getJSON({
19
- type: 'POST',
20
- url: ajaxurl,
21
- data: {
22
- action: 'wpsp_get_terms',
23
- wpsp_nonce: wpsp_object.nonce,
24
- taxonomy: type
25
- },
26
- async: false,
27
- dataType: 'json'
28
- });
29
-
30
- return response.responseJSON;
31
- }
32
-
33
- function wpsp_get_option( key = 'wpsp_taxonomy' ) {
34
- var response = jQuery.getJSON({
35
- type: 'POST',
36
- url: ajaxurl,
37
- data: {
38
- action: 'wpsp_get_json_option',
39
- wpsp_nonce: wpsp_object.nonce,
40
- key: key,
41
- id: wpsp_object.post_id
42
- },
43
- async: false,
44
- dataType: 'json',
45
- }).done( function() {
46
- jQuery( '#butterbean-control-wpsp_taxonomy' ).css( 'display', 'block' );
47
- jQuery( '#butterbean-control-wpsp_tax_term' ).css( 'display', 'block' );
48
- });
49
-
50
- return response.responseJSON;
51
- }
52
-
53
- jQuery( document ).ready( function( $ ) {
54
-
55
- // Populate taxonomy select based on current post type value
56
- var taxonomies = wpsp_get_taxonomy( $( '#wpsp-post-type' ).val() );
57
-
58
- $('#wpsp-taxonomy').append( $( '<option></option>' ) );
59
- $.each(taxonomies, function(key, value) {
60
- $('#wpsp-taxonomy').append( $( '<option></option>' ).attr( 'value', value ).text( value ) );
61
- });
62
-
63
- // Set the selected taxonomy value on load
64
- $( '#wpsp-taxonomy' ).val( wpsp_get_option( 'wpsp_taxonomy' ) );
65
-
66
- var terms = wpsp_get_terms( $( '#wpsp-taxonomy' ).val() );
67
- $('#wpsp-terms').append( $( '<option></option>' ) );
68
- $.each(terms, function(key, value) {
69
- $('#wpsp-terms').append( $( '<option></option>' ).attr( 'value', value ).text( value ) );
70
- });
71
-
72
- // Set the selected term value on load
73
- $( '#wpsp-terms' ).val( wpsp_get_option( 'wpsp_tax_term' ) );
74
-
75
- // Hide the terms of taxonomy is empty on load
76
- if ( '' == $( '#wpsp-taxonomy' ).val() )
77
- $( '#butterbean-control-wpsp_tax_term' ).hide();
78
-
79
- // When changing the post type option
80
- $( '#wpsp-post-type' ).change(function() {
81
-
82
- $( '#butterbean-control-wpsp_tax_term' ).hide();
83
-
84
- $( '#wpsp-taxonomy' ).empty();
85
-
86
- $( '#wpsp-terms' ).empty();
87
- $( '#wpsp-terms' ).append( $( '<option></option>' ) );
88
-
89
- var selectValues = wpsp_get_taxonomy( $(this).val(), false );
90
-
91
- $('#wpsp-taxonomy').append( $( '<option></option>' ) );
92
- $.each(selectValues, function(key, value) {
93
- $('#wpsp-taxonomy').append( $( '<option></option>' ).attr( 'value', value ).text( value ) );
94
- });
95
- if ( '' == selectValues ) {
96
- $( '#butterbean-control-wpsp_taxonomy' ).hide();
97
- } else {
98
- $( '#butterbean-control-wpsp_taxonomy' ).show();
99
- }
100
- });
101
-
102
- // When changing the taxonomy option
103
- $( '#wpsp-taxonomy' ).change(function() {
104
-
105
- $( '#wpsp-terms' ).empty();
106
- var selectValues = wpsp_get_terms( $(this).val() );
107
-
108
- $('#wpsp-terms').append( $( '<option></option>' ) );
109
- $.each(selectValues, function(key, value) {
110
- $('#wpsp-terms').append( $( '<option></option>' ).attr( 'value', value ).text( value ) );
111
- });
112
-
113
- if ( '' == selectValues || ',' == selectValues )
114
- $( '#butterbean-control-wpsp_tax_term' ).hide();
115
- else
116
- $( '#butterbean-control-wpsp_tax_term' ).show();
117
- });
118
-
119
- // Dealing with the image options
120
- if ( ! $( '#wpsp-image' ).is( ':checked' ) ) {
121
- $( this ).parent().parent().siblings().hide();
122
- }
123
-
124
- $( '#wpsp-image' ).change(function() {
125
- if ( ! this.checked ) {
126
- $( this ).parent().parent().siblings().hide();
127
- } else {
128
- $( this ).parent().parent().siblings().show();
129
- }
130
- });
131
-
132
- // Excerpt or full content
133
- $( '#wpsp-content-type' ).change(function() {
134
- if ( 'excerpt' == $( this ).val() ) {
135
- $( '#butterbean-control-wpsp_excerpt_length' ).show();
136
- } else {
137
- $( '#butterbean-control-wpsp_excerpt_length' ).hide();
138
- }
139
- });
140
-
141
- // Author location
142
- if ( ! $( '#wpsp-include-author' ).is( ':checked' ) ) {
143
- $( '#butterbean-control-wpsp_author_location' ).hide();
144
- }
145
-
146
- $( '#wpsp-include-author' ).change(function() {
147
- if ( ! this.checked ) {
148
- $( '#butterbean-control-wpsp_author_location' ).hide();
149
- } else {
150
- $( '#butterbean-control-wpsp_author_location' ).show();
151
- }
152
- });
153
-
154
- // Date location
155
- if ( ! $( '#wpsp-include-date' ).is( ':checked' ) ) {
156
- $( '#butterbean-control-wpsp_date_location' ).hide();
157
- }
158
-
159
- $( '#wpsp-include-date' ).change(function() {
160
- if ( ! this.checked ) {
161
- $( '#butterbean-control-wpsp_date_location' ).hide();
162
- } else {
163
- $( '#butterbean-control-wpsp_date_location' ).show();
164
- }
165
- });
166
-
167
- // Terms location
168
- if ( ! $( '#wpsp-include-terms' ).is( ':checked' ) ) {
169
- $( '#butterbean-control-wpsp_terms_location' ).hide();
170
- }
171
-
172
- $( '#wpsp-include-terms' ).change(function() {
173
- if ( ! this.checked ) {
174
- $( '#butterbean-control-wpsp_terms_location' ).hide();
175
- } else {
176
- $( '#butterbean-control-wpsp_terms_location' ).show();
177
- }
178
- });
179
-
180
- // Dealing with the social options
181
- $( '#wpsp-social-sharing' ).parent().parent().siblings().hide();
182
- if ( $( '#wpsp-social-sharing' ).is( ':checked' ) ) {
183
- $( '#wpsp-social-sharing' ).parent().parent().siblings().show();
184
- }
185
-
186
- $( '#wpsp-social-sharing' ).change(function() {
187
- if ( ! this.checked ) {
188
- $( this ).parent().parent().siblings().hide();
189
- } else {
190
- $( this ).parent().parent().siblings().show();
191
- }
192
- });
193
-
194
- // Pagination
195
- if ( ! $( '#wpsp-pagination' ).is( ':checked' ) ) {
196
- $( '#butterbean-control-wpsp_ajax_pagination' ).hide();
197
- }
198
-
199
- $( '#wpsp-pagination' ).change(function() {
200
- if ( ! this.checked ) {
201
- $( '#butterbean-control-wpsp_ajax_pagination' ).hide();
202
- } else {
203
- $( '#butterbean-control-wpsp_ajax_pagination' ).show();
204
- }
205
- });
 
 
206
  });
1
+ function wpsp_get_taxonomy() {
2
+ type = typeof type !== 'undefined' ? type : 'post';
3
+ var response = jQuery.getJSON({
4
+ type: 'POST',
5
+ url: ajaxurl,
6
+ data: {
7
+ action: 'wpsp_get_taxonomies',
8
+ wpsp_nonce: wpsp_object.nonce,
9
+ post_type: type
10
+ },
11
+ async: false,
12
+ dataType: 'json'
13
+ });
14
+
15
+ return response.responseJSON;
16
+ }
17
+
18
+ function wpsp_get_terms( type ) {
19
+ type = typeof type !== 'undefined' ? type : 'post';
20
+ var response = jQuery.getJSON({
21
+ type: 'POST',
22
+ url: ajaxurl,
23
+ data: {
24
+ action: 'wpsp_get_terms',
25
+ wpsp_nonce: wpsp_object.nonce,
26
+ taxonomy: type
27
+ },
28
+ async: false,
29
+ dataType: 'json'
30
+ });
31
+
32
+ return response.responseJSON;
33
+ }
34
+
35
+ function wpsp_get_option() {
36
+ key = typeof key !== 'undefined' ? key : 'wpsp_taxonomy';
37
+ var response = jQuery.getJSON({
38
+ type: 'POST',
39
+ url: ajaxurl,
40
+ data: {
41
+ action: 'wpsp_get_json_option',
42
+ wpsp_nonce: wpsp_object.nonce,
43
+ key: key,
44
+ id: wpsp_object.post_id
45
+ },
46
+ async: false,
47
+ dataType: 'json',
48
+ }).done( function() {
49
+ jQuery( '#butterbean-control-wpsp_taxonomy' ).css( 'display', 'block' );
50
+ jQuery( '#butterbean-control-wpsp_tax_term' ).css( 'display', 'block' );
51
+ });
52
+
53
+ return response.responseJSON;
54
+ }
55
+
56
+ jQuery( document ).ready( function( $ ) {
57
+ // Populate taxonomy select based on current post type value
58
+ var taxonomies = wpsp_get_taxonomy( $( '#wpsp-post-type' ).val() );
59
+
60
+ $('#wpsp-taxonomy').append( $( '<option></option>' ) );
61
+ $.each(taxonomies, function(key, value) {
62
+ $('#wpsp-taxonomy').append( $( '<option></option>' ).attr( 'value', value ).text( value ) );
63
+ });
64
+
65
+ // Set the selected taxonomy value on load
66
+ $( '#wpsp-taxonomy' ).val( wpsp_get_option( 'wpsp_taxonomy' ) );
67
+
68
+ var terms = wpsp_get_terms( $( '#wpsp-taxonomy' ).val() );
69
+ $('#wpsp-terms').append( $( '<option></option>' ) );
70
+ $.each(terms, function(key, value) {
71
+ $('#wpsp-terms').append( $( '<option></option>' ).attr( 'value', value ).text( value ) );
72
+ });
73
+
74
+ // Set the selected term value on load
75
+ $( '#wpsp-terms' ).val( wpsp_get_option( 'wpsp_tax_term' ) );
76
+
77
+ // Hide the terms of taxonomy is empty on load
78
+ if ( '' == $( '#wpsp-taxonomy' ).val() )
79
+ $( '#butterbean-control-wpsp_tax_term' ).hide();
80
+
81
+ // When changing the post type option
82
+ $( '#wpsp-post-type' ).change(function() {
83
+
84
+ $( '#butterbean-control-wpsp_tax_term' ).hide();
85
+
86
+ $( '#wpsp-taxonomy' ).empty();
87
+
88
+ $( '#wpsp-terms' ).empty();
89
+ $( '#wpsp-terms' ).append( $( '<option></option>' ) );
90
+
91
+ var selectValues = wpsp_get_taxonomy( $(this).val(), false );
92
+
93
+ $('#wpsp-taxonomy').append( $( '<option></option>' ) );
94
+ $.each(selectValues, function(key, value) {
95
+ $('#wpsp-taxonomy').append( $( '<option></option>' ).attr( 'value', value ).text( value ) );
96
+ });
97
+ if ( '' == selectValues ) {
98
+ $( '#butterbean-control-wpsp_taxonomy' ).hide();
99
+ } else {
100
+ $( '#butterbean-control-wpsp_taxonomy' ).show();
101
+ }
102
+ });
103
+
104
+ // When changing the taxonomy option
105
+ $( '#wpsp-taxonomy' ).change(function() {
106
+
107
+ $( '#wpsp-terms' ).empty();
108
+ var selectValues = wpsp_get_terms( $(this).val() );
109
+
110
+ $('#wpsp-terms').append( $( '<option></option>' ) );
111
+ $.each(selectValues, function(key, value) {
112
+ $('#wpsp-terms').append( $( '<option></option>' ).attr( 'value', value ).text( value ) );
113
+ });
114
+
115
+ if ( '' == selectValues || ',' == selectValues )
116
+ $( '#butterbean-control-wpsp_tax_term' ).hide();
117
+ else
118
+ $( '#butterbean-control-wpsp_tax_term' ).show();
119
+ });
120
+
121
+ // Dealing with the image options
122
+ if ( ! $( '#wpsp-image' ).is( ':checked' ) ) {
123
+ $( this ).parent().parent().siblings().hide();
124
+ }
125
+
126
+ $( '#wpsp-image' ).change(function() {
127
+ if ( ! this.checked ) {
128
+ $( this ).parent().parent().siblings().hide();
129
+ } else {
130
+ $( this ).parent().parent().siblings().show();
131
+ }
132
+ });
133
+
134
+ // Excerpt or full content
135
+ $( '#wpsp-content-type' ).change(function() {
136
+ if ( 'excerpt' == $( this ).val() ) {
137
+ $( '#butterbean-control-wpsp_excerpt_length' ).show();
138
+ } else {
139
+ $( '#butterbean-control-wpsp_excerpt_length' ).hide();
140
+ }
141
+ });
142
+
143
+ // Author location
144
+ if ( ! $( '#wpsp-include-author' ).is( ':checked' ) ) {
145
+ $( '#butterbean-control-wpsp_author_location' ).hide();
146
+ }
147
+
148
+ $( '#wpsp-include-author' ).change(function() {
149
+ if ( ! this.checked ) {
150
+ $( '#butterbean-control-wpsp_author_location' ).hide();
151
+ } else {
152
+ $( '#butterbean-control-wpsp_author_location' ).show();
153
+ }
154
+ });
155
+
156
+ // Date location
157
+ if ( ! $( '#wpsp-include-date' ).is( ':checked' ) ) {
158
+ $( '#butterbean-control-wpsp_date_location' ).hide();
159
+ }
160
+
161
+ $( '#wpsp-include-date' ).change(function() {
162
+ if ( ! this.checked ) {
163
+ $( '#butterbean-control-wpsp_date_location' ).hide();
164
+ } else {
165
+ $( '#butterbean-control-wpsp_date_location' ).show();
166
+ }
167
+ });
168
+
169
+ // Terms location
170
+ if ( ! $( '#wpsp-include-terms' ).is( ':checked' ) ) {
171
+ $( '#butterbean-control-wpsp_terms_location' ).hide();
172
+ }
173
+
174
+ $( '#wpsp-include-terms' ).change(function() {
175
+ if ( ! this.checked ) {
176
+ $( '#butterbean-control-wpsp_terms_location' ).hide();
177
+ } else {
178
+ $( '#butterbean-control-wpsp_terms_location' ).show();
179
+ }
180
+ });
181
+
182
+ // Dealing with the social options
183
+ $( '#wpsp-social-sharing' ).parent().parent().siblings().hide();
184
+ if ( $( '#wpsp-social-sharing' ).is( ':checked' ) ) {
185
+ $( '#wpsp-social-sharing' ).parent().parent().siblings().show();
186
+ }
187
+
188
+ $( '#wpsp-social-sharing' ).change(function() {
189
+ if ( ! this.checked ) {
190
+ $( this ).parent().parent().siblings().hide();
191
+ } else {
192
+ $( this ).parent().parent().siblings().show();
193
+ }
194
+ });
195
+
196
+ // Pagination
197
+ if ( ! $( '#wpsp-pagination' ).is( ':checked' ) ) {
198
+ $( '#butterbean-control-wpsp_ajax_pagination' ).hide();
199
+ }
200
+
201
+ $( '#wpsp-pagination' ).change(function() {
202
+ if ( ! this.checked ) {
203
+ $( '#butterbean-control-wpsp_ajax_pagination' ).hide();
204
+ } else {
205
+ $( '#butterbean-control-wpsp_ajax_pagination' ).show();
206
+ }
207
+ });
208
  });
admin/js/button.js CHANGED
@@ -1,42 +1,42 @@
1
- function wpsp_get_post_lists() {
2
- var response = jQuery.getJSON({
3
- type: 'POST',
4
- url: ajaxurl,
5
- data: {
6
- action: 'wpsp_get_post_lists',
7
- wpsp_nonce: wpsp_nonce
8
- },
9
- async: false,
10
- dataType: 'json'
11
- });
12
-
13
- return response.responseJSON;
14
- }
15
-
16
- console.log(wpsp_get_post_lists());
17
-
18
- (function() {
19
- tinymce.PluginManager.add('wpsp_shortcode_button', function( editor, url ) {
20
- editor.addButton( 'wpsp_shortcode_button', {
21
- title: wpsp_add_posts,
22
- icon: 'wpsp-add-icon',
23
- onclick: function() {
24
- editor.windowManager.open( {
25
- width: 300,
26
- height: 75,
27
- title: wpsp_add_posts,
28
- body: [
29
- {
30
- type: 'listbox',
31
- name: 'wpsp_add_posts',
32
- label: false,
33
- 'values': wpsp_get_post_lists(),
34
- }],
35
- onsubmit: function( e ) {
36
- editor.insertContent( '[wp_show_posts id="' + e.data.wpsp_add_posts + '"]');
37
- }
38
- });
39
- }
40
- });
41
- });
42
  })();
1
+ function wpsp_get_post_lists() {
2
+ var response = jQuery.getJSON({
3
+ type: 'POST',
4
+ url: ajaxurl,
5
+ data: {
6
+ action: 'wpsp_get_post_lists',
7
+ wpsp_nonce: wpsp_nonce
8
+ },
9
+ async: false,
10
+ dataType: 'json'
11
+ });
12
+
13
+ return response.responseJSON;
14
+ }
15
+
16
+ console.log(wpsp_get_post_lists());
17
+
18
+ (function() {
19
+ tinymce.PluginManager.add('wpsp_shortcode_button', function( editor, url ) {
20
+ editor.addButton( 'wpsp_shortcode_button', {
21
+ title: wpsp_add_posts,
22
+ icon: 'wpsp-add-icon',
23
+ onclick: function() {
24
+ editor.windowManager.open( {
25
+ width: 300,
26
+ height: 75,
27
+ title: wpsp_add_posts,
28
+ body: [
29
+ {
30
+ type: 'listbox',
31
+ name: 'wpsp_add_posts',
32
+ label: false,
33
+ 'values': wpsp_get_post_lists(),
34
+ }],
35
+ onsubmit: function( e ) {
36
+ editor.insertContent( '[wp_show_posts id="' + e.data.wpsp_add_posts + '"]');
37
+ }
38
+ });
39
+ }
40
+ });
41
+ });
42
  })();
admin/metabox.php CHANGED
@@ -1,902 +1,900 @@
1
- <?php
2
- if ( ! function_exists( 'wpsp_remove_metaboxes' ) ) :
3
- /**
4
- * Remove all metaboxes from our WP Show Posts post type
5
- * @since 0.1
6
- */
7
- add_action('add_meta_boxes', 'wpsp_remove_metaboxes', 99, 2);
8
- function wpsp_remove_metaboxes( $post_type, $post ){
9
-
10
- // If we're not in the wp_show_posts post type, bail.
11
- if( ! in_array( $post_type, array( 'wp_show_posts' ) ) )
12
- return false;
13
-
14
- global $wp_meta_boxes;
15
-
16
- // Don't remove the below
17
- $exceptions = array(
18
- 'submitdiv',
19
- 'butterbean-ui-wp_show_posts',
20
- 'wpsp_shortcode_metabox'
21
- );
22
-
23
- // Loop through all our metaboxes
24
- if( ! empty( $wp_meta_boxes ) ) :
25
- foreach( $wp_meta_boxes as $page => $page_boxes ) :
26
- if ( ! empty( $page_boxes ) ) :
27
- foreach( $page_boxes as $context => $box_context ) :
28
- if( ! empty( $box_context ) ) :
29
- foreach( $box_context as $box_type ) :
30
- if( ! empty( $box_type ) ) :
31
- foreach( $box_type as $id => $box ) :
32
- /** Check to see if the meta box should be removed... */
33
- if( ! in_array( $id, $exceptions ) ) :
34
- remove_meta_box( $id, $page, $context );
35
- endif;
36
- endforeach;
37
- endif;
38
- endforeach;
39
- endif;
40
- endforeach;
41
- endif;
42
- endforeach;
43
- endif;
44
- }
45
- endif;
46
-
47
- if ( ! function_exists( 'wpsp_get_post_types' ) ) :
48
- /**
49
- * List of all our post types exluding our own
50
- * @since 0.1
51
- */
52
- function wpsp_get_post_types()
53
- {
54
- $post_types = get_post_types( array( 'public' => true ) );
55
- $types = array();
56
- foreach ( $post_types as $type ) {
57
- if ( 'wp_show_posts' !== $type && 'attachment' !== $type )
58
- $types[ $type ] = $type;
59
- }
60
-
61
- return $types;
62
- }
63
- endif;
64
-
65
- if ( ! function_exists( 'wpsp_load_butterbean' ) ) :
66
- /**
67
- * Load butterbean inside our post type
68
- * @since 0.1
69
- */
70
- add_action( 'load-post.php', 'wpsp_load_butterbean' );
71
- add_action( 'load-post-new.php', 'wpsp_load_butterbean' );
72
- function wpsp_load_butterbean() {
73
-
74
- // Bail if not our post type.
75
- if ( 'wp_show_posts' !== get_current_screen()->post_type )
76
- return;
77
-
78
- require_once( trailingslashit( dirname( __FILE__ ) ) . '/butterbean/butterbean.php' );
79
- }
80
- endif;
81
-
82
- if ( ! function_exists( 'wpsp_register' ) ) :
83
- /**
84
- * Create all of our metabox options
85
- * @since 0.1
86
- */
87
- add_action( 'butterbean_register', 'wpsp_register', 10, 2 );
88
- function wpsp_register( $butterbean, $post_type ) {
89
-
90
- $defaults = wpsp_get_defaults();
91
-
92
- // Register managers, sections, controls, and settings here.
93
- $butterbean->register_manager(
94
- 'wp_show_posts',
95
- array(
96
- 'label' => esc_html__( 'WP Show Posts', 'wp-show-posts' ),
97
- 'post_type' => 'wp_show_posts',
98
- 'context' => 'normal',
99
- 'priority' => 'high'
100
- )
101
- );
102
-
103
- $manager = $butterbean->get_manager( 'wp_show_posts' );
104
-
105
- $manager->register_section(
106
- 'wpsp_posts',
107
- array(
108
- 'label' => esc_html__( 'Posts', 'wp-show-posts' ),
109
- 'icon' => 'dashicons-admin-post'
110
- )
111
- );
112
-
113
- $manager->register_control(
114
- 'wpsp_post_type', // Same as setting name.
115
- array(
116
- 'type' => 'select',
117
- 'section' => 'wpsp_posts',
118
- 'label' => esc_html__( 'Post Type', 'wp-show-posts' ),
119
- 'choices' => wpsp_get_post_types(),
120
- 'attr' => array( 'id' => 'wpsp-post-type' )
121
- )
122
- );
123
-
124
- $manager->register_setting(
125
- 'wpsp_post_type', // Same as control name.
126
- array(
127
- 'sanitize_callback' => 'sanitize_text_field',
128
- 'default' => $defaults[ 'wpsp_post_type' ] ? $defaults[ 'wpsp_post_type' ] : ''
129
- )
130
- );
131
-
132
- $manager->register_control(
133
- 'wpsp_taxonomy', // Same as setting name.
134
- array(
135
- 'type' => 'select',
136
- 'section' => 'wpsp_posts',
137
- 'label' => esc_html__( 'Taxonomy', 'wp-show-posts' ),
138
- 'choices' => array(),
139
- 'attr' => array( 'id' => 'wpsp-taxonomy' )
140
- )
141
- );
142
-
143
- $manager->register_setting(
144
- 'wpsp_taxonomy', // Same as control name.
145
- array(
146
- 'sanitize_callback' => 'sanitize_text_field',
147
- 'default' => $defaults[ 'wpsp_taxonomy' ] ? $defaults[ 'wpsp_taxonomy' ] : ''
148
- )
149
- );
150
-
151
- $manager->register_control(
152
- 'wpsp_tax_term', // Same as setting name.
153
- array(
154
- 'type' => 'select',
155
- 'section' => 'wpsp_posts',
156
- 'label' => esc_html__( 'Terms', 'wp-show-posts' ),
157
- 'choices' => array(),
158
- 'attr' => array( 'id' => 'wpsp-terms' )
159
- )
160
- );
161
-
162
- $manager->register_setting(
163
- 'wpsp_tax_term', // Same as control name.
164
- array(
165
- 'sanitize_callback' => 'sanitize_text_field',
166
- 'default' => $defaults[ 'wpsp_tax_term' ] ? $defaults[ 'wpsp_tax_term' ] : ''
167
- )
168
- );
169
-
170
- $manager->register_control(
171
- 'wpsp_posts_per_page', // Same as setting name.
172
- array(
173
- 'type' => 'number',
174
- 'section' => 'wpsp_posts',
175
- 'label' => esc_html__( 'Posts per page', 'wp-show-posts' )
176
- )
177
- );
178
-
179
- $manager->register_setting(
180
- 'wpsp_posts_per_page', // Same as control name.
181
- array(
182
- 'sanitize_callback' => 'wpsp_sanitize_intval',
183
- 'default' => $defaults[ 'wpsp_posts_per_page' ] ? $defaults[ 'wpsp_posts_per_page' ] : 10
184
- )
185
- );
186
-
187
- $manager->register_control(
188
- 'wpsp_pagination',
189
- array(
190
- 'type' => 'checkbox',
191
- 'section' => 'wpsp_posts',
192
- 'label' => __( 'Pagination','wp-show-posts-pro' ),
193
- 'description' => __( 'Pagination should only be used if your posts are the only thing in the content area to prevent duplicate content issues.','wp-show-posts' ),
194
- 'attr' => array( 'id' => 'wpsp-pagination' )
195
- )
196
- );
197
-
198
- $manager->register_setting(
199
- 'wpsp_pagination',
200
- array(
201
- 'sanitize_callback' => 'butterbean_validate_boolean',
202
- 'default' => $defaults[ 'wpsp_pagination' ] ? $defaults[ 'wpsp_pagination' ] : false
203
- )
204
- );
205
-
206
- $manager->register_section(
207
- 'wpsp_columns',
208
- array(
209
- 'label' => esc_html__( 'Columns', 'wp-show-posts' ),
210
- 'icon' => 'dashicons-grid-view'
211
- )
212
- );
213
-
214
- $manager->register_control(
215
- 'wpsp_columns', // Same as setting name.
216
- array(
217
- 'type' => 'select',
218
- 'section' => 'wpsp_columns',
219
- 'label' => esc_html__( 'Columns', 'wp-show-posts' ),
220
- 'choices' => array(
221
- 'col-12' => '1',
222
- 'col-6' => '2',
223
- 'col-4' => '3',
224
- 'col-3' => '4',
225
- 'col-20' => '5'
226
- ),
227
- 'attr' => array( 'id' => 'wpsp-columns' )
228
- )
229
- );
230
-
231
- $manager->register_setting(
232
- 'wpsp_columns', // Same as control name.
233
- array(
234
- 'sanitize_callback' => 'sanitize_text_field',
235
- 'default' => $defaults[ 'wpsp_columns' ] ? $defaults[ 'wpsp_columns' ] : '12'
236
- )
237
- );
238
-
239
- $manager->register_control(
240
- 'wpsp_columns_gutter', // Same as setting name.
241
- array(
242
- 'type' => 'text',
243
- 'section' => 'wpsp_columns',
244
- 'label' => esc_html__( 'Columns gutter', 'wp-show-posts' ),
245
- 'attr' => array( 'class' => 'widefat' ),
246
- )
247
- );
248
-
249
- $manager->register_setting(
250
- 'wpsp_columns_gutter', // Same as control name.
251
- array(
252
- 'sanitize_callback' => 'sanitize_text_field',
253
- 'default' => $defaults[ 'wpsp_columns_gutter' ] ? $defaults[ 'wpsp_columns_gutter' ] : ''
254
- )
255
- );
256
-
257
- $manager->register_section(
258
- 'wpsp_images',
259
- array(
260
- 'label' => esc_html__( 'Images', 'wp-show-posts' ),
261
- 'icon' => 'dashicons-format-image'
262
- )
263
- );
264
-
265
- $manager->register_control(
266
- 'wpsp_image',
267
- array(
268
- 'type' => 'checkbox',
269
- 'section' => 'wpsp_images',
270
- 'label' => __( 'Images','wp-show-posts' ),
271
- 'attr' => array( 'id' => 'wpsp-image' )
272
- )
273
- );
274
-
275
- $manager->register_setting(
276
- 'wpsp_image',
277
- array(
278
- 'sanitize_callback' => 'butterbean_validate_boolean',
279
- 'default' => $defaults[ 'wpsp_image' ]
280
- )
281
- );
282
-
283
- $manager->register_control(
284
- 'wpsp_image_width', // Same as setting name.
285
- array(
286
- 'type' => 'number',
287
- 'section' => 'wpsp_images',
288
- 'label' => esc_html__( 'Image width (px)', 'wp-show-posts' ),
289
- 'attr' => array( 'id' => 'wpsp-image-width' )
290
- )
291
- );
292
-
293
- $manager->register_setting(
294
- 'wpsp_image_width', // Same as control name.
295
- array(
296
- 'sanitize_callback' => 'wpsp_sanitize_absint',
297
- 'default' => $defaults[ 'wpsp_image_width' ] ? $defaults[ 'wpsp_image_width' ] : ''
298
- )
299
- );
300
-
301
- $manager->register_control(
302
- 'wpsp_image_height', // Same as setting name.
303
- array(
304
- 'type' => 'number',
305
- 'section' => 'wpsp_images',
306
- 'label' => esc_html__( 'Image height (px)', 'wp-show-posts' ),
307
- 'attr' => array( 'id' => 'wpsp-image-height' )
308
- )
309
- );
310
-
311
- $manager->register_setting(
312
- 'wpsp_image_height', // Same as control name.
313
- array(
314
- 'sanitize_callback' => 'wpsp_sanitize_absint',
315
- 'default' => $defaults[ 'wpsp_image_height' ] ? $defaults[ 'wpsp_image_height' ] : ''
316
- )
317
- );
318
-
319
- $manager->register_control(
320
- 'wpsp_image_alignment', // Same as setting name.
321
- array(
322
- 'type' => 'select',
323
- 'section' => 'wpsp_images',
324
- 'label' => esc_html__( 'Image alignment', 'wp-show-posts' ),
325
- 'choices' => array(
326
- 'left' => __( 'Left','wp-show-posts' ),
327
- 'center' => __( 'Center','wp-show-posts' ),
328
- 'right' => __( 'Right','wp-show-posts' )
329
- ),
330
- 'attr' => array( 'id' => 'wpsp-image-alignment' )
331
- )
332
- );
333
-
334
- $manager->register_setting(
335
- 'wpsp_image_alignment', // Same as control name.
336
- array(
337
- 'sanitize_callback' => 'sanitize_text_field',
338
- 'default' => $defaults[ 'wpsp_image_alignment' ] ? $defaults[ 'wpsp_image_alignment' ] : ''
339
- )
340
- );
341
-
342
- $manager->register_control(
343
- 'wpsp_image_location', // Same as setting name.
344
- array(
345
- 'type' => 'select',
346
- 'section' => 'wpsp_images',
347
- 'label' => esc_html__( 'Image location', 'wp-show-posts' ),
348
- 'choices' => array(
349
- 'below-title' => __( 'Below title','wp-show-posts' ),
350
- 'above-title' => __( 'Above title','wp-show-posts' )
351
- ),
352
- 'attr' => array( 'id' => 'wpsp-image-location' )
353
- )
354
- );
355
-
356
- $manager->register_setting(
357
- 'wpsp_image_location', // Same as control name.
358
- array(
359
- 'sanitize_callback' => 'sanitize_text_field',
360
- 'default' => $defaults[ 'wpsp_image_location' ] ? $defaults[ 'wpsp_image_location' ] : ''
361
- )
362
- );
363
-
364
- $manager->register_section(
365
- 'wpsp_content',
366
- array(
367
- 'label' => esc_html__( 'Content', 'wp-show-posts' ),
368
- 'icon' => 'dashicons-editor-alignleft'
369
- )
370
- );
371
-
372
- $manager->register_control(
373
- 'wpsp_content_type', // Same as setting name.
374
- array(
375
- 'type' => 'select',
376
- 'section' => 'wpsp_content',
377
- 'label' => esc_html__( 'Content type', 'wp-show-posts' ),
378
- 'choices' => array(
379
- 'excerpt' => __( 'Excerpt','wp-show-posts' ),
380
- 'full' => __( 'Full','wp-show-posts' ),
381
- 'none' => __( 'None','wp-show-posts' )
382
- ),
383
- 'attr' => array( 'id' => 'wpsp-content-type' )
384
- )
385
- );
386
-
387
- $manager->register_setting(
388
- 'wpsp_content_type', // Same as control name.
389
- array(
390
- 'sanitize_callback' => 'sanitize_text_field',
391
- 'default' => $defaults[ 'wpsp_content_type' ] ? $defaults[ 'wpsp_content_type' ] : ''
392
- )
393
- );
394
-
395
- $manager->register_control(
396
- 'wpsp_excerpt_length', // Same as setting name.
397
- array(
398
- 'type' => 'number',
399
- 'section' => 'wpsp_content',
400
- 'label' => esc_html__( 'Excerpt length (words)', 'wp-show-posts' ),
401
- 'attr' => array( 'id' => 'wpsp-excerpt-length' )
402
- )
403
- );
404
-
405
- $manager->register_setting(
406
- 'wpsp_excerpt_length', // Same as control name.
407
- array(
408
- 'sanitize_callback' => 'wpsp_sanitize_absint',
409
- 'default' => $defaults[ 'wpsp_excerpt_length' ] ? $defaults[ 'wpsp_excerpt_length' ] : ''
410
- )
411
- );
412
-
413
- $manager->register_control(
414
- 'wpsp_include_title',
415
- array(
416
- 'type' => 'checkbox',
417
- 'section' => 'wpsp_content',
418
- 'label' => __( 'Include title','wp-show-posts-pro' ),
419
- 'attr' => array( 'id' => 'wpsp-include-title' )
420
- )
421
- );
422
-
423
- $manager->register_setting(
424
- 'wpsp_include_title',
425
- array(
426
- 'sanitize_callback' => 'butterbean_validate_boolean',
427
- 'default' => true
428
- )
429
- );
430
-
431
- $manager->register_control(
432
- 'wpsp_read_more_text', // Same as setting name.
433
- array(
434
- 'type' => 'text',
435
- 'section' => 'wpsp_content',
436
- 'label' => esc_html__( 'Read more text', 'wp-show-posts' )
437
- )
438
- );
439
-
440
- $manager->register_setting(
441
- 'wpsp_read_more_text', // Same as control name.
442
- array(
443
- 'sanitize_callback' => 'wp_kses_post',
444
- 'default' => $defaults[ 'wpsp_read_more_text' ] ? $defaults[ 'wpsp_read_more_text' ] : ''
445
- )
446
- );
447
-
448
- $manager->register_section(
449
- 'wpsp_post_meta',
450
- array(
451
- 'label' => esc_html__( 'Meta', 'wp-show-posts' ),
452
- 'icon' => 'dashicons-editor-ul'
453
- )
454
- );
455
-
456
- $manager->register_control(
457
- 'wpsp_include_author',
458
- array(
459
- 'type' => 'checkbox',
460
- 'section' => 'wpsp_post_meta',
461
- 'label' => __( 'Include author','wp-show-posts-pro' ),
462
- 'attr' => array( 'id' => 'wpsp-include-author' )
463
- )
464
- );
465
-
466
- $manager->register_setting(
467
- 'wpsp_include_author',
468
- array(
469
- 'sanitize_callback' => 'butterbean_validate_boolean',
470
- 'default' => $defaults[ 'wpsp_include_author' ] ? $defaults[ 'wpsp_include_author' ] : false
471
- )
472
- );
473
-
474
- $manager->register_control(
475
- 'wpsp_author_location', // Same as setting name.
476
- array(
477
- 'type' => 'select',
478
- 'section' => 'wpsp_post_meta',
479
- 'label' => esc_html__( 'Author location', 'wp-show-posts' ),
480
- 'choices' => array(
481
- 'below-title' => __( 'Below title','wp-show-posts' ),
482
- 'below-post' => __( 'Below post','wp-show-posts' )
483
- ),
484
- 'attr' => array( 'id' => 'wpsp-author-location' )
485
- )
486
- );
487
-
488
- $manager->register_setting(
489
- 'wpsp_author_location', // Same as control name.
490
- array(
491
- 'sanitize_callback' => 'sanitize_text_field',
492
- 'default' => $defaults[ 'wpsp_author_location' ] ? $defaults[ 'wpsp_author_location' ] : ''
493
- )
494
- );
495
-
496
- $manager->register_control(
497
- 'wpsp_include_date',
498
- array(
499
- 'type' => 'checkbox',
500
- 'section' => 'wpsp_post_meta',
501
- 'label' => __( 'Include date','wp-show-posts-pro' ),
502
- 'attr' => array( 'id' => 'wpsp-include-date' )
503
- )
504
- );
505
-
506
- $manager->register_setting(
507
- 'wpsp_include_date',
508
- array(
509
- 'sanitize_callback' => 'butterbean_validate_boolean',
510
- 'default' => $defaults[ 'wpsp_include_date' ] ? $defaults[ 'wpsp_include_date' ] : false
511
- )
512
- );
513
-
514
- $manager->register_control(
515
- 'wpsp_date_location', // Same as setting name.
516
- array(
517
- 'type' => 'select',
518
- 'section' => 'wpsp_post_meta',
519
- 'label' => esc_html__( 'Date location', 'wp-show-posts' ),
520
- 'choices' => array(
521
- 'below-title' => __( 'Below title','wp-show-posts' ),
522
- 'below-post' => __( 'Below post','wp-show-posts' )
523
- ),
524
- 'attr' => array( 'id' => 'wpsp-date-location' )
525
- )
526
- );
527
-
528
- $manager->register_setting(
529
- 'wpsp_date_location', // Same as control name.
530
- array(
531
- 'sanitize_callback' => 'sanitize_text_field',
532
- 'default' => $defaults[ 'wpsp_date_location' ] ? $defaults[ 'wpsp_date_location' ] : ''
533
- )
534
- );
535
-
536
- $manager->register_control(
537
- 'wpsp_include_terms',
538
- array(
539
- 'type' => 'checkbox',
540
- 'section' => 'wpsp_post_meta',
541
- 'label' => __( 'Include terms','wp-show-posts-pro' ),
542
- 'attr' => array( 'id' => 'wpsp-include-terms' )
543
- )
544
- );
545
-
546
- $manager->register_setting(
547
- 'wpsp_include_terms',
548
- array(
549
- 'sanitize_callback' => 'butterbean_validate_boolean',
550
- 'default' => $defaults[ 'wpsp_include_terms' ] ? $defaults[ 'wpsp_include_terms' ] : false
551
- )
552
- );
553
-
554
- $manager->register_control(
555
- 'wpsp_terms_location', // Same as setting name.
556
- array(
557
- 'type' => 'select',
558
- 'section' => 'wpsp_post_meta',
559
- 'label' => esc_html__( 'Terms location', 'wp-show-posts' ),
560
- 'choices' => array(
561
- 'below-title' => __( 'Below title','wp-show-posts' ),
562
- 'below-post' => __( 'Below post','wp-show-posts' )
563
- ),
564
- 'attr' => array( 'id' => 'wpsp-terms-location' )
565
- )
566
- );
567
-
568
- $manager->register_setting(
569
- 'wpsp_terms_location', // Same as control name.
570
- array(
571
- 'sanitize_callback' => 'sanitize_text_field',
572
- 'default' => $defaults[ 'wpsp_terms_location' ] ? $defaults[ 'wpsp_terms_location' ] : ''
573
- )
574
- );
575
-
576
- $manager->register_section(
577
- 'wpsp_query_args',
578
- array(
579
- 'label' => esc_html__( 'More settings', 'wp-show-posts' ),
580
- 'icon' => 'dashicons-admin-generic',
581
- 'priority' => 999
582
- )
583
- );
584
-
585
- $manager->register_control(
586
- 'wpsp_author', // Same as setting name.
587
- array(
588
- 'type' => 'number',
589
- 'section' => 'wpsp_query_args',
590
- 'label' => esc_html__( 'Author ID', 'wp-show-posts' )
591
- )
592
- );
593
-
594
- $manager->register_setting(
595
- 'wpsp_author', // Same as control name.
596
- array(
597
- 'sanitize_callback' => 'wpsp_sanitize_absint',
598
- 'default' => $defaults[ 'wpsp_author' ] ? $defaults[ 'wpsp_author' ] : ''
599
- )
600
- );
601
-
602
- $manager->register_control(
603
- 'wpsp_exclude_current',
604
- array(
605
- 'type' => 'checkbox',
606
- 'section' => 'wpsp_query_args',
607
- 'label' => __( 'Exclude current','wp-show-posts-pro' ),
608
- 'attr' => array( 'id' => 'wpsp-exclude-current' )
609
- )
610
- );
611
-
612
- $manager->register_setting(
613
- 'wpsp_exclude_current',
614
- array(
615
- 'sanitize_callback' => 'butterbean_validate_boolean',
616
- 'default' => $defaults[ 'wpsp_exclude_current' ] ? $defaults[ 'wpsp_exclude_current' ] : false
617
- )
618
- );
619
-
620
- $manager->register_control(
621
- 'wpsp_post_id', // Same as setting name.
622
- array(
623
- 'type' => 'text',
624
- 'section' => 'wpsp_query_args',
625
- 'label' => esc_html__( 'Post IDs', 'wp-show-posts' )
626
- )
627
- );
628
-
629
- $manager->register_setting(
630
- 'wpsp_post_id', // Same as control name.
631
- array(
632
- 'sanitize_callback' => 'sanitize_text_field',
633
- 'default' => $defaults[ 'wpsp_post_id' ] ? $defaults[ 'wpsp_post_id' ] : ''
634
- )
635
- );
636
-
637
- $manager->register_control(
638
- 'wpsp_exclude_post_id', // Same as setting name.
639
- array(
640
- 'type' => 'text',
641
- 'section' => 'wpsp_query_args',
642
- 'label' => esc_html__( 'Exclude Post IDs', 'wp-show-posts' )
643
- )
644
- );
645
-
646
- $manager->register_setting(
647
- 'wpsp_exclude_post_id', // Same as control name.
648
- array(
649
- 'sanitize_callback' => 'sanitize_text_field',
650
- 'default' => $defaults[ 'wpsp_exclude_post_id' ] ? $defaults[ 'wpsp_exclude_post_id' ] : ''
651
- )
652
- );
653
-
654
- $manager->register_control(
655
- 'wpsp_ignore_sticky_posts',
656
- array(
657
- 'type' => 'checkbox',
658
- 'section' => 'wpsp_query_args',
659
- 'label' => __( 'Ignore sticky posts','wp-show-posts-pro' ),
660
- 'attr' => array( 'id' => 'wpsp-ignore-sticky-posts' )
661
- )
662
- );
663
-
664
- $manager->register_setting(
665
- 'wpsp_ignore_sticky_posts',
666
- array(
667
- 'sanitize_callback' => 'butterbean_validate_boolean',
668
- 'default' => $defaults[ 'wpsp_ignore_sticky_posts' ] ? $defaults[ 'wpsp_ignore_sticky_posts' ] : false
669
- )
670
- );
671
-
672
- $manager->register_control(
673
- 'wpsp_offset', // Same as setting name.
674
- array(
675
- 'type' => 'number',
676
- 'section' => 'wpsp_query_args',
677
- 'label' => esc_html__( 'Offset', 'wp-show-posts' )
678
- )
679
- );
680
-
681
- $manager->register_setting(
682
- 'wpsp_offset', // Same as control name.
683
- array(
684
- 'sanitize_callback' => 'wpsp_sanitize_absint',
685
- 'default' => $defaults[ 'wpsp_offset' ] ? $defaults[ 'wpsp_offset' ] : ''
686
- )
687
- );
688
-
689
- $manager->register_control(
690
- 'wpsp_order', // Same as setting name.
691
- array(
692
- 'type' => 'select',
693
- 'section' => 'wpsp_query_args',
694
- 'label' => esc_html__( 'Order', 'wp-show-posts' ),
695
- 'choices' => array(
696
- 'DESC' => __( 'Descending','wp-show-posts' ),
697
- 'ASC' => __( 'Ascending','wp-show-posts' )
698
- ),
699
- 'attr' => array( 'id' => 'wpsp-order' )
700
- )
701
- );
702
-
703
- $manager->register_setting(
704
- 'wpsp_order', // Same as control name.
705
- array(
706
- 'sanitize_callback' => 'sanitize_text_field',
707
- 'default' => $defaults[ 'wpsp_order' ] ? $defaults[ 'wpsp_order' ] : 'DESC'
708
- )
709
- );
710
-
711
- $manager->register_control(
712
- 'wpsp_orderby', // Same as setting name.
713
- array(
714
- 'type' => 'select',
715
- 'section' => 'wpsp_query_args',
716
- 'label' => esc_html__( 'Order by', 'wp-show-posts' ),
717
- 'choices' => array(
718
- 'none' => __( 'No order','wp-show-posts' ),
719
- 'ID' => __( 'ID','wp-show-posts' ),
720
- 'author' => __( 'Author','wp-show-posts' ),
721
- 'title' => __( 'Title','wp-show-posts' ),
722
- 'name' => __( 'Slug','wp-show-posts' ),
723
- 'type' => __( 'Post type','wp-show-posts' ),
724
- 'date' => __( 'Date','wp-show-posts' ),
725
- 'modified' => __( 'Modified','wp-show-posts' ),
726
- 'parent' => __( 'Parent','wp-show-posts' ),
727
- 'rand' => __( 'Random','wp-show-posts' ),
728
- 'comment_count' => __( 'Comment count','wp-show-posts' )
729
- ),
730
- 'attr' => array( 'id' => 'wpsp-orderby' )
731
- )
732
- );
733
-
734
- $manager->register_setting(
735
- 'wpsp_orderby', // Same as control name.
736
- array(
737
- 'sanitize_callback' => 'sanitize_text_field',
738
- 'default' => $defaults[ 'wpsp_orderby' ] ? $defaults[ 'wpsp_orderby' ] : 'date'
739
- )
740
- );
741
-
742
- $manager->register_control(
743
- 'wpsp_post_status', // Same as setting name.
744
- array(
745
- 'type' => 'select',
746
- 'section' => 'wpsp_query_args',
747
- 'label' => esc_html__( 'Status', 'wp-show-posts' ),
748
- 'choices' => array(
749
- 'publish' => __( 'Published','wp-show-posts' ),
750
- 'pending' => __( 'Pending','wp-show-posts' ),
751
- 'draft' => __( 'Draft','wp-show-posts' ),
752
- 'auto-draft' => __( 'Auto draft','wp-show-posts' ),
753
- 'future' => __( 'Future','wp-show-posts' ),
754
- 'private' => __( 'Private','wp-show-posts' ),
755
- 'inherit' => __( 'Inherit','wp-show-posts' ),
756
- 'trash' => __( 'Trash','wp-show-posts' ),
757
- 'any' => __( 'Any','wp-show-posts' )
758
- ),
759
- 'attr' => array( 'id' => 'wpsp-post-status' )
760
- )
761
- );
762
-
763
- $manager->register_setting(
764
- 'wpsp_post_status', // Same as control name.
765
- array(
766
- 'sanitize_callback' => 'sanitize_text_field',
767
- 'default' => $defaults[ 'wpsp_post_status' ] ? $defaults[ 'wpsp_post_status' ] : 'publish'
768
- )
769
- );
770
-
771
- $manager->register_control(
772
- 'wpsp_meta_key', // Same as setting name.
773
- array(
774
- 'type' => 'text',
775
- 'section' => 'wpsp_query_args',
776
- 'label' => esc_html__( 'Meta key', 'wp-show-posts' )
777
- )
778
- );
779
-
780
- $manager->register_setting(
781
- 'wpsp_meta_key', // Same as control name.
782
- array(
783
- 'sanitize_callback' => 'sanitize_text_field',
784
- 'default' => $defaults[ 'wpsp_meta_key' ] ? $defaults[ 'wpsp_meta_key' ] : ''
785
- )
786
- );
787
-
788
- $manager->register_control(
789
- 'wpsp_meta_value', // Same as setting name.
790
- array(
791
- 'type' => 'text',
792
- 'section' => 'wpsp_query_args',
793
- 'label' => esc_html__( 'Meta value', 'wp-show-posts' )
794
- )
795
- );
796
-
797
- $manager->register_setting(
798
- 'wpsp_meta_value', // Same as control name.
799
- array(
800
- 'sanitize_callback' => 'sanitize_text_field',
801
- 'default' => $defaults[ 'wpsp_meta_value' ] ? $defaults[ 'wpsp_meta_value' ] : ''
802
- )
803
- );
804
-
805
- $manager->register_control(
806
- 'wpsp_tax_operator', // Same as setting name.
807
- array(
808
- 'type' => 'select',
809
- 'section' => 'wpsp_query_args',
810
- 'label' => esc_html__( 'Tax operator', 'wp-show-posts' ),
811
- 'choices' => array(
812
- 'IN' => 'IN',
813
- 'NOT IN' => 'NOT IN',
814
- 'AND' => 'AND',
815
- 'EXISTS' => 'EXISTS',
816
- 'NOT EXISTS' => 'NOT EXISTS'
817
- ),
818
- 'attr' => array( 'id' => 'wpsp-tax-operator' )
819
- )
820
- );
821
-
822
- $manager->register_setting(
823
- 'wpsp_tax_operator', // Same as control name.
824
- array(
825
- 'sanitize_callback' => 'sanitize_text_field',
826
- 'default' => $defaults[ 'wpsp_tax_operator' ] ? $defaults[ 'wpsp_tax_operator' ] : 'IN'
827
- )
828
- );
829
-
830
- $manager->register_control(
831
- 'wpsp_no_results', // Same as setting name.
832
- array(
833
- 'type' => 'text',
834
- 'section' => 'wpsp_query_args',
835
- 'label' => esc_html__( 'No results message', 'wp-show-posts' )
836
- )
837
- );
838
-
839
- $manager->register_setting(
840
- 'wpsp_no_results', // Same as control name.
841
- array(
842
- 'sanitize_callback' => 'wp_kses_post',
843
- 'default' => $defaults[ 'wpsp_no_results' ] ? $defaults[ 'wpsp_no_results' ] : ''
844
- )
845
- );
846
- }
847
- endif;
848
-
849
- if ( ! function_exists( 'wpsp_sanitize_intval' ) ) :
850
- /**
851
- * Sanitize our value so it has to be a positive integer
852
- * @since 0.1
853
- */
854
- function wpsp_sanitize_intval( $input ) {
855
- if ( '' == $input )
856
- return $input;
857
-
858
- return intval( $input );
859
- }
860
- endif;
861
-
862
- if ( ! function_exists( 'wpsp_sanitize_absint' ) ) :
863
- /**
864
- * Sanitize our value so it can be a negative or positive integer
865
- * @since 0.1
866
- */
867
- function wpsp_sanitize_absint( $input ) {
868
- if ( '' == $input )
869
- return $input;
870
-
871
- return absint( $input );
872
- }
873
- endif;
874
-
875
- if ( ! function_exists( 'wpsp_add_meta_boxes' ) ) :
876
- /**
877
- * Add our usage metabox
878
- * @since 0.1
879
- */
880
- add_action( 'add_meta_boxes_wp_show_posts', 'wpsp_add_meta_boxes' );
881
- function wpsp_add_meta_boxes( $post ){
882
- add_meta_box( 'wpsp_shortcode', __( 'Usage', 'wp-show-posts' ), 'wpsp_shortcode_metabox', 'wp_show_posts', 'side', 'low' );
883
- }
884
- endif;
885
-
886
- if ( ! function_exists( 'wpsp_shortcode_metabox' ) ) :
887
- /**
888
- * Meta box display callback.
889
- *
890
- * @param WP_Post $post Current post object.
891
- * @since 0.1
892
- */
893
- function wpsp_shortcode_metabox( $post ) {
894
- ?>
895
- <h4 style="margin-bottom:5px;"><?php _e( 'Shortcode','wp-show-posts' ); ?></h4>
896
- <input type="text" class="widefat" value='[wp_show_posts id="<?php echo $post->ID;?>"]' readonly />
897
-
898
- <h4 style="margin-bottom:5px;"><?php _e( 'Function','wp-show-posts' ); ?></h4>
899
- <input type="text" class="widefat" value='<?php echo esc_attr( "<?php if ( function_exists( 'wpsp_display' ) ) wpsp_display( " . $post->ID . " ); ?>" ); ?>' readonly />
900
- <?php
901
- }
902
  endif;
1
+ <?php
2
+ // No direct access, please
3
+ if ( ! defined( 'ABSPATH' ) ) exit;
4
+
5
+ if ( ! function_exists( 'wpsp_remove_metaboxes' ) ) :
6
+ /**
7
+ * Remove all metaboxes from our WP Show Posts post type
8
+ * @since 0.1
9
+ */
10
+ add_action('add_meta_boxes', 'wpsp_remove_metaboxes', 99);
11
+ function wpsp_remove_metaboxes( $post_type ){
12
+
13
+ // If we're not in the wp_show_posts post type, bail.
14
+ if( ! in_array( $post_type, array( 'wp_show_posts' ) ) )
15
+ return false;
16
+
17
+ global $wp_meta_boxes;
18
+
19
+ // Don't remove the below
20
+ $exceptions = array(
21
+ 'submitdiv',
22
+ 'butterbean-ui-wp_show_posts',
23
+ 'wpsp_shortcode_metabox'
24
+ );
25
+
26
+ // Loop through all our metaboxes
27
+ if( ! empty( $wp_meta_boxes ) ) :
28
+ foreach( $wp_meta_boxes as $page => $page_boxes ) :
29
+ if ( ! empty( $page_boxes ) ) :
30
+ foreach( $page_boxes as $context => $box_context ) :
31
+ if( ! empty( $box_context ) ) :
32
+ foreach( $box_context as $box_type ) :
33
+ if( ! empty( $box_type ) ) :
34
+ foreach( $box_type as $id => $box ) :
35
+ /** Check to see if the meta box should be removed... */
36
+ if( ! in_array( $id, $exceptions ) ) :
37
+ remove_meta_box( $id, $page, $context );
38
+ endif;
39
+ endforeach;
40
+ endif;
41
+ endforeach;
42
+ endif;
43
+ endforeach;
44
+ endif;
45
+ endforeach;
46
+ endif;
47
+ }
48
+ endif;
49
+
50
+ if ( ! function_exists( 'wpsp_get_post_types' ) ) :
51
+ /**
52
+ * List of all our post types exluding our own
53
+ * @since 0.1
54
+ */
55
+ function wpsp_get_post_types()
56
+ {
57
+ $post_types = get_post_types( array( 'public' => true ) );
58
+ $types = array();
59
+ foreach ( $post_types as $type ) {
60
+ if ( 'wp_show_posts' !== $type && 'attachment' !== $type )
61
+ $types[ $type ] = $type;
62
+ }
63
+
64
+ return $types;
65
+ }
66
+ endif;
67
+
68
+ if ( ! function_exists( 'wpsp_load_butterbean' ) ) :
69
+ /**
70
+ * Load butterbean inside our post type
71
+ * @since 0.1
72
+ */
73
+ add_action( 'plugins_loaded', 'wpsp_load_butterbean' );
74
+ function wpsp_load_butterbean()
75
+ {
76
+ require_once( trailingslashit( dirname( __FILE__ ) ) . '/butterbean/butterbean.php' );
77
+ }
78
+ endif;
79
+
80
+ if ( ! function_exists( 'wpsp_register' ) ) :
81
+ /**
82
+ * Create all of our metabox options
83
+ * @since 0.1
84
+ */
85
+ add_action( 'butterbean_register', 'wpsp_register', 10, 2 );
86
+ function wpsp_register( $butterbean, $post_type ) {
87
+
88
+ $defaults = wpsp_get_defaults();
89
+
90
+ // Register managers, sections, controls, and settings here.
91
+ $butterbean->register_manager(
92
+ 'wp_show_posts',
93
+ array(
94
+ 'label' => esc_html__( 'WP Show Posts', 'wp-show-posts' ),
95
+ 'post_type' => 'wp_show_posts',
96
+ 'context' => 'normal',
97
+ 'priority' => 'high'
98
+ )
99
+ );
100
+
101
+ $manager = $butterbean->get_manager( 'wp_show_posts' );
102
+
103
+ $manager->register_section(
104
+ 'wpsp_posts',
105
+ array(
106
+ 'label' => esc_html__( 'Posts', 'wp-show-posts' ),
107
+ 'icon' => 'dashicons-admin-post'
108
+ )
109
+ );
110
+
111
+ $manager->register_control(
112
+ 'wpsp_post_type', // Same as setting name.
113
+ array(
114
+ 'type' => 'select',
115
+ 'section' => 'wpsp_posts',
116
+ 'label' => esc_html__( 'Post Type', 'wp-show-posts' ),
117
+ 'choices' => wpsp_get_post_types(),
118
+ 'attr' => array( 'id' => 'wpsp-post-type' )
119
+ )
120
+ );
121
+
122
+ $manager->register_setting(
123
+ 'wpsp_post_type', // Same as control name.
124
+ array(
125
+ 'sanitize_callback' => 'sanitize_text_field',
126
+ 'default' => $defaults[ 'wpsp_post_type' ] ? $defaults[ 'wpsp_post_type' ] : ''
127
+ )
128
+ );
129
+
130
+ $manager->register_control(
131
+ 'wpsp_taxonomy', // Same as setting name.
132
+ array(
133
+ 'type' => 'select',
134
+ 'section' => 'wpsp_posts',
135
+ 'label' => esc_html__( 'Taxonomy', 'wp-show-posts' ),
136
+ 'choices' => array(),
137
+ 'attr' => array( 'id' => 'wpsp-taxonomy' )
138
+ )
139
+ );
140
+
141
+ $manager->register_setting(
142
+ 'wpsp_taxonomy', // Same as control name.
143
+ array(
144
+ 'sanitize_callback' => 'sanitize_text_field',
145
+ 'default' => $defaults[ 'wpsp_taxonomy' ] ? $defaults[ 'wpsp_taxonomy' ] : ''
146
+ )
147
+ );
148
+
149
+ $manager->register_control(
150
+ 'wpsp_tax_term', // Same as setting name.
151
+ array(
152
+ 'type' => 'select',
153
+ 'section' => 'wpsp_posts',
154
+ 'label' => esc_html__( 'Terms', 'wp-show-posts' ),
155
+ 'choices' => array(),
156
+ 'attr' => array( 'id' => 'wpsp-terms' )
157
+ )
158
+ );
159
+
160
+ $manager->register_setting(
161
+ 'wpsp_tax_term', // Same as control name.
162
+ array(
163
+ 'sanitize_callback' => 'sanitize_text_field',
164
+ 'default' => $defaults[ 'wpsp_tax_term' ] ? $defaults[ 'wpsp_tax_term' ] : ''
165
+ )
166
+ );
167
+
168
+ $manager->register_control(
169
+ 'wpsp_posts_per_page', // Same as setting name.
170
+ array(
171
+ 'type' => 'number',
172
+ 'section' => 'wpsp_posts',
173
+ 'label' => esc_html__( 'Posts per page', 'wp-show-posts' )
174
+ )
175
+ );
176
+
177
+ $manager->register_setting(
178
+ 'wpsp_posts_per_page', // Same as control name.
179
+ array(
180
+ 'sanitize_callback' => 'wpsp_sanitize_intval',
181
+ 'default' => $defaults[ 'wpsp_posts_per_page' ] ? $defaults[ 'wpsp_posts_per_page' ] : 10
182
+ )
183
+ );
184
+
185
+ $manager->register_control(
186
+ 'wpsp_pagination',
187
+ array(
188
+ 'type' => 'checkbox',
189
+ 'section' => 'wpsp_posts',
190
+ 'label' => __( 'Pagination','wp-show-posts-pro' ),
191
+ 'description' => __( 'Pagination should only be used if your posts are the only thing in the content area to prevent duplicate content issues.','wp-show-posts' ),
192
+ 'attr' => array( 'id' => 'wpsp-pagination' )
193
+ )
194
+ );
195
+
196
+ $manager->register_setting(
197
+ 'wpsp_pagination',
198
+ array(
199
+ 'sanitize_callback' => 'butterbean_validate_boolean',
200
+ 'default' => $defaults[ 'wpsp_pagination' ] ? $defaults[ 'wpsp_pagination' ] : false
201
+ )
202
+ );
203
+
204
+ $manager->register_section(
205
+ 'wpsp_columns',
206
+ array(
207
+ 'label' => esc_html__( 'Columns', 'wp-show-posts' ),
208
+ 'icon' => 'dashicons-grid-view'
209
+ )
210
+ );
211
+
212
+ $manager->register_control(
213
+ 'wpsp_columns', // Same as setting name.
214
+ array(
215
+ 'type' => 'select',
216
+ 'section' => 'wpsp_columns',
217
+ 'label' => esc_html__( 'Columns', 'wp-show-posts' ),
218
+ 'choices' => array(
219
+ 'col-12' => '1',
220
+ 'col-6' => '2',
221
+ 'col-4' => '3',
222
+ 'col-3' => '4',
223
+ 'col-20' => '5'
224
+ ),
225
+ 'attr' => array( 'id' => 'wpsp-columns' )
226
+ )
227
+ );
228
+
229
+ $manager->register_setting(
230
+ 'wpsp_columns', // Same as control name.
231
+ array(
232
+ 'sanitize_callback' => 'sanitize_text_field',
233
+ 'default' => $defaults[ 'wpsp_columns' ] ? $defaults[ 'wpsp_columns' ] : '12'
234
+ )
235
+ );
236
+
237
+ $manager->register_control(
238
+ 'wpsp_columns_gutter', // Same as setting name.
239
+ array(
240
+ 'type' => 'text',
241
+ 'section' => 'wpsp_columns',
242
+ 'label' => esc_html__( 'Columns gutter', 'wp-show-posts' ),
243
+ 'attr' => array( 'class' => 'widefat' ),
244
+ )
245
+ );
246
+
247
+ $manager->register_setting(
248
+ 'wpsp_columns_gutter', // Same as control name.
249
+ array(
250
+ 'sanitize_callback' => 'sanitize_text_field',
251
+ 'default' => $defaults[ 'wpsp_columns_gutter' ] ? $defaults[ 'wpsp_columns_gutter' ] : ''
252
+ )
253
+ );
254
+
255
+ $manager->register_section(
256
+ 'wpsp_images',
257
+ array(
258
+ 'label' => esc_html__( 'Images', 'wp-show-posts' ),
259
+ 'icon' => 'dashicons-format-image'
260
+ )
261
+ );
262
+
263
+ $manager->register_control(
264
+ 'wpsp_image',
265
+ array(
266
+ 'type' => 'checkbox',
267
+ 'section' => 'wpsp_images',
268
+ 'label' => __( 'Images','wp-show-posts' ),
269
+ 'attr' => array( 'id' => 'wpsp-image' )
270
+ )
271
+ );
272
+
273
+ $manager->register_setting(
274
+ 'wpsp_image',
275
+ array(
276
+ 'sanitize_callback' => 'butterbean_validate_boolean',
277
+ 'default' => $defaults[ 'wpsp_image' ]
278
+ )
279
+ );
280
+
281
+ $manager->register_control(
282
+ 'wpsp_image_width', // Same as setting name.
283
+ array(
284
+ 'type' => 'number',
285
+ 'section' => 'wpsp_images',
286
+ 'label' => esc_html__( 'Image width (px)', 'wp-show-posts' ),
287
+ 'attr' => array( 'id' => 'wpsp-image-width' )
288
+ )
289
+ );
290
+
291
+ $manager->register_setting(
292
+ 'wpsp_image_width', // Same as control name.
293
+ array(
294
+ 'sanitize_callback' => 'wpsp_sanitize_absint',
295
+ 'default' => $defaults[ 'wpsp_image_width' ] ? $defaults[ 'wpsp_image_width' ] : ''
296
+ )
297
+ );
298
+
299
+ $manager->register_control(
300
+ 'wpsp_image_height', // Same as setting name.
301
+ array(
302
+ 'type' => 'number',
303
+ 'section' => 'wpsp_images',
304
+ 'label' => esc_html__( 'Image height (px)', 'wp-show-posts' ),
305
+ 'attr' => array( 'id' => 'wpsp-image-height' )
306
+ )
307
+ );
308
+
309
+ $manager->register_setting(
310
+ 'wpsp_image_height', // Same as control name.
311
+ array(
312
+ 'sanitize_callback' => 'wpsp_sanitize_absint',
313
+ 'default' => $defaults[ 'wpsp_image_height' ] ? $defaults[ 'wpsp_image_height' ] : ''
314
+ )
315
+ );
316
+
317
+ $manager->register_control(
318
+ 'wpsp_image_alignment', // Same as setting name.
319
+ array(
320
+ 'type' => 'select',
321
+ 'section' => 'wpsp_images',
322
+ 'label' => esc_html__( 'Image alignment', 'wp-show-posts' ),
323
+ 'choices' => array(
324
+ 'left' => __( 'Left','wp-show-posts' ),
325
+ 'center' => __( 'Center','wp-show-posts' ),
326
+ 'right' => __( 'Right','wp-show-posts' )
327
+ ),
328
+ 'attr' => array( 'id' => 'wpsp-image-alignment' )
329
+ )
330
+ );
331
+
332
+ $manager->register_setting(
333
+ 'wpsp_image_alignment', // Same as control name.
334
+ array(
335
+ 'sanitize_callback' => 'sanitize_text_field',
336
+ 'default' => $defaults[ 'wpsp_image_alignment' ] ? $defaults[ 'wpsp_image_alignment' ] : ''
337
+ )
338
+ );
339
+
340
+ $manager->register_control(
341
+ 'wpsp_image_location', // Same as setting name.
342
+ array(
343
+ 'type' => 'select',
344
+ 'section' => 'wpsp_images',
345
+ 'label' => esc_html__( 'Image location', 'wp-show-posts' ),
346
+ 'choices' => array(
347
+ 'below-title' => __( 'Below title','wp-show-posts' ),
348
+ 'above-title' => __( 'Above title','wp-show-posts' )
349
+ ),
350
+ 'attr' => array( 'id' => 'wpsp-image-location' )
351
+ )
352
+ );
353
+
354
+ $manager->register_setting(
355
+ 'wpsp_image_location', // Same as control name.
356
+ array(
357
+ 'sanitize_callback' => 'sanitize_text_field',
358
+ 'default' => $defaults[ 'wpsp_image_location' ] ? $defaults[ 'wpsp_image_location' ] : ''
359
+ )
360
+ );
361
+
362
+ $manager->register_section(
363
+ 'wpsp_content',
364
+ array(
365
+ 'label' => esc_html__( 'Content', 'wp-show-posts' ),
366
+ 'icon' => 'dashicons-editor-alignleft'
367
+ )
368
+ );
369
+
370
+ $manager->register_control(
371
+ 'wpsp_content_type', // Same as setting name.
372
+ array(
373
+ 'type' => 'select',
374
+ 'section' => 'wpsp_content',
375
+ 'label' => esc_html__( 'Content type', 'wp-show-posts' ),
376
+ 'choices' => array(
377
+ 'excerpt' => __( 'Excerpt','wp-show-posts' ),
378
+ 'full' => __( 'Full','wp-show-posts' ),
379
+ 'none' => __( 'None','wp-show-posts' )
380
+ ),
381
+ 'attr' => array( 'id' => 'wpsp-content-type' )
382
+ )
383
+ );
384
+
385
+ $manager->register_setting(
386
+ 'wpsp_content_type', // Same as control name.
387
+ array(
388
+ 'sanitize_callback' => 'sanitize_text_field',
389
+ 'default' => $defaults[ 'wpsp_content_type' ] ? $defaults[ 'wpsp_content_type' ] : ''
390
+ )
391
+ );
392
+
393
+ $manager->register_control(
394
+ 'wpsp_excerpt_length', // Same as setting name.
395
+ array(
396
+ 'type' => 'number',
397
+ 'section' => 'wpsp_content',
398
+ 'label' => esc_html__( 'Excerpt length (words)', 'wp-show-posts' ),
399
+ 'attr' => array( 'id' => 'wpsp-excerpt-length' )
400
+ )
401
+ );
402
+
403
+ $manager->register_setting(
404
+ 'wpsp_excerpt_length', // Same as control name.
405
+ array(
406
+ 'sanitize_callback' => 'wpsp_sanitize_absint',
407
+ 'default' => $defaults[ 'wpsp_excerpt_length' ] ? $defaults[ 'wpsp_excerpt_length' ] : ''
408
+ )
409
+ );
410
+
411
+ $manager->register_control(
412
+ 'wpsp_include_title',
413
+ array(
414
+ 'type' => 'checkbox',
415
+ 'section' => 'wpsp_content',
416
+ 'label' => __( 'Include title','wp-show-posts-pro' ),
417
+ 'attr' => array( 'id' => 'wpsp-include-title' )
418
+ )
419
+ );
420
+
421
+ $manager->register_setting(
422
+ 'wpsp_include_title',
423
+ array(
424
+ 'sanitize_callback' => 'butterbean_validate_boolean',
425
+ 'default' => true
426
+ )
427
+ );
428
+
429
+ $manager->register_control(
430
+ 'wpsp_read_more_text', // Same as setting name.
431
+ array(
432
+ 'type' => 'text',
433
+ 'section' => 'wpsp_content',
434
+ 'label' => esc_html__( 'Read more text', 'wp-show-posts' )
435
+ )
436
+ );
437
+
438
+ $manager->register_setting(
439
+ 'wpsp_read_more_text', // Same as control name.
440
+ array(
441
+ 'sanitize_callback' => 'wp_kses_post',
442
+ 'default' => $defaults[ 'wpsp_read_more_text' ] ? $defaults[ 'wpsp_read_more_text' ] : ''
443
+ )
444
+ );
445
+
446
+ $manager->register_section(
447
+ 'wpsp_post_meta',
448
+ array(
449
+ 'label' => esc_html__( 'Meta', 'wp-show-posts' ),
450
+ 'icon' => 'dashicons-editor-ul'
451
+ )
452
+ );
453
+
454
+ $manager->register_control(
455
+ 'wpsp_include_author',
456
+ array(
457
+ 'type' => 'checkbox',
458
+ 'section' => 'wpsp_post_meta',
459
+ 'label' => __( 'Include author','wp-show-posts-pro' ),
460
+ 'attr' => array( 'id' => 'wpsp-include-author' )
461
+ )
462
+ );
463
+
464
+ $manager->register_setting(
465
+ 'wpsp_include_author',
466
+ array(
467
+ 'sanitize_callback' => 'butterbean_validate_boolean',
468
+ 'default' => $defaults[ 'wpsp_include_author' ] ? $defaults[ 'wpsp_include_author' ] : false
469
+ )
470
+ );
471
+
472
+ $manager->register_control(
473
+ 'wpsp_author_location', // Same as setting name.
474
+ array(
475
+ 'type' => 'select',
476
+ 'section' => 'wpsp_post_meta',
477
+ 'label' => esc_html__( 'Author location', 'wp-show-posts' ),
478
+ 'choices' => array(
479
+ 'below-title' => __( 'Below title','wp-show-posts' ),
480
+ 'below-post' => __( 'Below post','wp-show-posts' )
481
+ ),
482
+ 'attr' => array( 'id' => 'wpsp-author-location' )
483
+ )
484
+ );
485
+
486
+ $manager->register_setting(
487
+ 'wpsp_author_location', // Same as control name.
488
+ array(
489
+ 'sanitize_callback' => 'sanitize_text_field',
490
+ 'default' => $defaults[ 'wpsp_author_location' ] ? $defaults[ 'wpsp_author_location' ] : ''
491
+ )
492
+ );
493
+
494
+ $manager->register_control(
495
+ 'wpsp_include_date',
496
+ array(
497
+ 'type' => 'checkbox',
498
+ 'section' => 'wpsp_post_meta',
499
+ 'label' => __( 'Include date','wp-show-posts-pro' ),
500
+ 'attr' => array( 'id' => 'wpsp-include-date' )
501
+ )
502
+ );
503
+
504
+ $manager->register_setting(
505
+ 'wpsp_include_date',
506
+ array(
507
+ 'sanitize_callback' => 'butterbean_validate_boolean',
508
+ 'default' => $defaults[ 'wpsp_include_date' ] ? $defaults[ 'wpsp_include_date' ] : false
509
+ )
510
+ );
511
+
512
+ $manager->register_control(
513
+ 'wpsp_date_location', // Same as setting name.
514
+ array(
515
+ 'type' => 'select',
516
+ 'section' => 'wpsp_post_meta',
517
+ 'label' => esc_html__( 'Date location', 'wp-show-posts' ),
518
+ 'choices' => array(
519
+ 'below-title' => __( 'Below title','wp-show-posts' ),
520
+ 'below-post' => __( 'Below post','wp-show-posts' )
521
+ ),
522
+ 'attr' => array( 'id' => 'wpsp-date-location' )
523
+ )
524
+ );
525
+
526
+ $manager->register_setting(
527
+ 'wpsp_date_location', // Same as control name.
528
+ array(
529
+ 'sanitize_callback' => 'sanitize_text_field',
530
+ 'default' => $defaults[ 'wpsp_date_location' ] ? $defaults[ 'wpsp_date_location' ] : ''
531
+ )
532
+ );
533
+
534
+ $manager->register_control(
535
+ 'wpsp_include_terms',
536
+ array(
537
+ 'type' => 'checkbox',
538
+ 'section' => 'wpsp_post_meta',
539
+ 'label' => __( 'Include terms','wp-show-posts-pro' ),
540
+ 'attr' => array( 'id' => 'wpsp-include-terms' )
541
+ )
542
+ );
543
+
544
+ $manager->register_setting(
545
+ 'wpsp_include_terms',
546
+ array(
547
+ 'sanitize_callback' => 'butterbean_validate_boolean',
548
+ 'default' => $defaults[ 'wpsp_include_terms' ] ? $defaults[ 'wpsp_include_terms' ] : false
549
+ )
550
+ );
551
+
552
+ $manager->register_control(
553
+ 'wpsp_terms_location', // Same as setting name.
554
+ array(
555
+ 'type' => 'select',
556
+ 'section' => 'wpsp_post_meta',
557
+ 'label' => esc_html__( 'Terms location', 'wp-show-posts' ),
558
+ 'choices' => array(
559
+ 'below-title' => __( 'Below title','wp-show-posts' ),
560
+ 'below-post' => __( 'Below post','wp-show-posts' )
561
+ ),
562
+ 'attr' => array( 'id' => 'wpsp-terms-location' )
563
+ )
564
+ );
565
+
566
+ $manager->register_setting(
567
+ 'wpsp_terms_location', // Same as control name.
568
+ array(
569
+ 'sanitize_callback' => 'sanitize_text_field',
570
+ 'default' => $defaults[ 'wpsp_terms_location' ] ? $defaults[ 'wpsp_terms_location' ] : ''
571
+ )
572
+ );
573
+
574
+ $manager->register_section(
575
+ 'wpsp_query_args',
576
+ array(
577
+ 'label' => esc_html__( 'More settings', 'wp-show-posts' ),
578
+ 'icon' => 'dashicons-admin-generic',
579
+ 'priority' => 999
580
+ )
581
+ );
582
+
583
+ $manager->register_control(
584
+ 'wpsp_author', // Same as setting name.
585
+ array(
586
+ 'type' => 'number',
587
+ 'section' => 'wpsp_query_args',
588
+ 'label' => esc_html__( 'Author ID', 'wp-show-posts' )
589
+ )
590
+ );
591
+
592
+ $manager->register_setting(
593
+ 'wpsp_author', // Same as control name.
594
+ array(
595
+ 'sanitize_callback' => 'wpsp_sanitize_absint',
596
+ 'default' => $defaults[ 'wpsp_author' ] ? $defaults[ 'wpsp_author' ] : ''
597
+ )
598
+ );
599
+
600
+ $manager->register_control(
601
+ 'wpsp_exclude_current',
602
+ array(
603
+ 'type' => 'checkbox',
604
+ 'section' => 'wpsp_query_args',
605
+ 'label' => __( 'Exclude current','wp-show-posts-pro' ),
606
+ 'attr' => array( 'id' => 'wpsp-exclude-current' )
607
+ )
608
+ );
609
+
610
+ $manager->register_setting(
611
+ 'wpsp_exclude_current',
612
+ array(
613
+ 'sanitize_callback' => 'butterbean_validate_boolean',
614
+ 'default' => $defaults[ 'wpsp_exclude_current' ] ? $defaults[ 'wpsp_exclude_current' ] : false
615
+ )
616
+ );
617
+
618
+ $manager->register_control(
619
+ 'wpsp_post_id', // Same as setting name.
620
+ array(
621
+ 'type' => 'text',
622
+ 'section' => 'wpsp_query_args',
623
+ 'label' => esc_html__( 'Post IDs', 'wp-show-posts' )
624
+ )
625
+ );
626
+
627
+ $manager->register_setting(
628
+ 'wpsp_post_id', // Same as control name.
629
+ array(
630
+ 'sanitize_callback' => 'sanitize_text_field',
631
+ 'default' => $defaults[ 'wpsp_post_id' ] ? $defaults[ 'wpsp_post_id' ] : ''
632
+ )
633
+ );
634
+
635
+ $manager->register_control(
636
+ 'wpsp_exclude_post_id', // Same as setting name.
637
+ array(
638
+ 'type' => 'text',
639
+ 'section' => 'wpsp_query_args',
640
+ 'label' => esc_html__( 'Exclude Post IDs', 'wp-show-posts' )
641
+ )
642
+ );
643
+
644
+ $manager->register_setting(
645
+ 'wpsp_exclude_post_id', // Same as control name.
646
+ array(
647
+ 'sanitize_callback' => 'sanitize_text_field',
648
+ 'default' => $defaults[ 'wpsp_exclude_post_id' ] ? $defaults[ 'wpsp_exclude_post_id' ] : ''
649
+ )
650
+ );
651
+
652
+ $manager->register_control(
653
+ 'wpsp_ignore_sticky_posts',
654
+ array(
655
+ 'type' => 'checkbox',
656
+ 'section' => 'wpsp_query_args',
657
+ 'label' => __( 'Ignore sticky posts','wp-show-posts-pro' ),
658
+ 'attr' => array( 'id' => 'wpsp-ignore-sticky-posts' )
659
+ )
660
+ );
661
+
662
+ $manager->register_setting(
663
+ 'wpsp_ignore_sticky_posts',
664
+ array(
665
+ 'sanitize_callback' => 'butterbean_validate_boolean',
666
+ 'default' => $defaults[ 'wpsp_ignore_sticky_posts' ] ? $defaults[ 'wpsp_ignore_sticky_posts' ] : false
667
+ )
668
+ );
669
+
670
+ $manager->register_control(
671
+ 'wpsp_offset', // Same as setting name.
672
+ array(
673
+ 'type' => 'number',
674
+ 'section' => 'wpsp_query_args',
675
+ 'label' => esc_html__( 'Offset', 'wp-show-posts' )
676
+ )
677
+ );
678
+
679
+ $manager->register_setting(
680
+ 'wpsp_offset', // Same as control name.
681
+ array(
682
+ 'sanitize_callback' => 'wpsp_sanitize_absint',
683
+ 'default' => $defaults[ 'wpsp_offset' ] ? $defaults[ 'wpsp_offset' ] : ''
684
+ )
685
+ );
686
+
687
+ $manager->register_control(
688
+ 'wpsp_order', // Same as setting name.
689
+ array(
690
+ 'type' => 'select',
691
+ 'section' => 'wpsp_query_args',
692
+ 'label' => esc_html__( 'Order', 'wp-show-posts' ),
693
+ 'choices' => array(
694
+ 'DESC' => __( 'Descending','wp-show-posts' ),
695
+ 'ASC' => __( 'Ascending','wp-show-posts' )
696
+ ),
697
+ 'attr' => array( 'id' => 'wpsp-order' )
698
+ )
699
+ );
700
+
701
+ $manager->register_setting(
702
+ 'wpsp_order', // Same as control name.
703
+ array(
704
+ 'sanitize_callback' => 'sanitize_text_field',
705
+ 'default' => $defaults[ 'wpsp_order' ] ? $defaults[ 'wpsp_order' ] : 'DESC'
706
+ )
707
+ );
708
+
709
+ $manager->register_control(
710
+ 'wpsp_orderby', // Same as setting name.
711
+ array(
712
+ 'type' => 'select',
713
+ 'section' => 'wpsp_query_args',
714
+ 'label' => esc_html__( 'Order by', 'wp-show-posts' ),
715
+ 'choices' => array(
716
+ 'none' => __( 'No order','wp-show-posts' ),
717
+ 'ID' => __( 'ID','wp-show-posts' ),
718
+ 'author' => __( 'Author','wp-show-posts' ),
719
+ 'title' => __( 'Title','wp-show-posts' ),
720
+ 'name' => __( 'Slug','wp-show-posts' ),
721
+ 'type' => __( 'Post type','wp-show-posts' ),
722
+ 'date' => __( 'Date','wp-show-posts' ),
723
+ 'modified' => __( 'Modified','wp-show-posts' ),
724
+ 'parent' => __( 'Parent','wp-show-posts' ),
725
+ 'rand' => __( 'Random','wp-show-posts' ),
726
+ 'comment_count' => __( 'Comment count','wp-show-posts' )
727
+ ),
728
+ 'attr' => array( 'id' => 'wpsp-orderby' )
729
+ )
730
+ );
731
+
732
+ $manager->register_setting(
733
+ 'wpsp_orderby', // Same as control name.
734
+ array(
735
+ 'sanitize_callback' => 'sanitize_text_field',
736
+ 'default' => $defaults[ 'wpsp_orderby' ] ? $defaults[ 'wpsp_orderby' ] : 'date'
737
+ )
738
+ );
739
+
740
+ $manager->register_control(
741
+ 'wpsp_post_status', // Same as setting name.
742
+ array(
743
+ 'type' => 'select',
744
+ 'section' => 'wpsp_query_args',
745
+ 'label' => esc_html__( 'Status', 'wp-show-posts' ),
746
+ 'choices' => array(
747
+ 'publish' => __( 'Published','wp-show-posts' ),
748
+ 'pending' => __( 'Pending','wp-show-posts' ),
749
+ 'draft' => __( 'Draft','wp-show-posts' ),
750
+ 'auto-draft' => __( 'Auto draft','wp-show-posts' ),
751
+ 'future' => __( 'Future','wp-show-posts' ),
752
+ 'private' => __( 'Private','wp-show-posts' ),
753
+ 'inherit' => __( 'Inherit','wp-show-posts' ),
754
+ 'trash' => __( 'Trash','wp-show-posts' ),
755
+ 'any' => __( 'Any','wp-show-posts' )
756
+ ),
757
+ 'attr' => array( 'id' => 'wpsp-post-status' )
758
+ )
759
+ );
760
+
761
+ $manager->register_setting(
762
+ 'wpsp_post_status', // Same as control name.
763
+ array(
764
+ 'sanitize_callback' => 'sanitize_text_field',
765
+ 'default' => $defaults[ 'wpsp_post_status' ] ? $defaults[ 'wpsp_post_status' ] : 'publish'
766
+ )
767
+ );
768
+
769
+ $manager->register_control(
770
+ 'wpsp_meta_key', // Same as setting name.
771
+ array(
772
+ 'type' => 'text',
773
+ 'section' => 'wpsp_query_args',
774
+ 'label' => esc_html__( 'Meta key', 'wp-show-posts' )
775
+ )
776
+ );
777
+
778
+ $manager->register_setting(
779
+ 'wpsp_meta_key', // Same as control name.
780
+ array(
781
+ 'sanitize_callback' => 'sanitize_text_field',
782
+ 'default' => $defaults[ 'wpsp_meta_key' ] ? $defaults[ 'wpsp_meta_key' ] : ''
783
+ )
784
+ );
785
+
786
+ $manager->register_control(
787
+ 'wpsp_meta_value', // Same as setting name.
788
+ array(
789
+ 'type' => 'text',
790
+ 'section' => 'wpsp_query_args',
791
+ 'label' => esc_html__( 'Meta value', 'wp-show-posts' )
792
+ )
793
+ );
794
+
795
+ $manager->register_setting(
796
+ 'wpsp_meta_value', // Same as control name.
797
+ array(
798
+ 'sanitize_callback' => 'sanitize_text_field',
799
+ 'default' => $defaults[ 'wpsp_meta_value' ] ? $defaults[ 'wpsp_meta_value' ] : ''
800
+ )
801
+ );
802
+
803
+ $manager->register_control(
804
+ 'wpsp_tax_operator', // Same as setting name.
805
+ array(
806
+ 'type' => 'select',
807
+ 'section' => 'wpsp_query_args',
808
+ 'label' => esc_html__( 'Tax operator', 'wp-show-posts' ),
809
+ 'choices' => array(
810
+ 'IN' => 'IN',
811
+ 'NOT IN' => 'NOT IN',
812
+ 'AND' => 'AND',
813
+ 'EXISTS' => 'EXISTS',
814
+ 'NOT EXISTS' => 'NOT EXISTS'
815
+ ),
816
+ 'attr' => array( 'id' => 'wpsp-tax-operator' )
817
+ )
818
+ );
819
+
820
+ $manager->register_setting(
821
+ 'wpsp_tax_operator', // Same as control name.
822
+ array(
823
+ 'sanitize_callback' => 'sanitize_text_field',
824
+ 'default' => $defaults[ 'wpsp_tax_operator' ] ? $defaults[ 'wpsp_tax_operator' ] : 'IN'
825
+ )
826
+ );
827
+
828
+ $manager->register_control(
829
+ 'wpsp_no_results', // Same as setting name.
830
+ array(
831
+ 'type' => 'text',
832
+ 'section' => 'wpsp_query_args',
833
+ 'label' => esc_html__( 'No results message', 'wp-show-posts' )
834
+ )
835
+ );
836
+
837
+ $manager->register_setting(
838
+ 'wpsp_no_results', // Same as control name.
839
+ array(
840
+ 'sanitize_callback' => 'wp_kses_post',
841
+ 'default' => $defaults[ 'wpsp_no_results' ] ? $defaults[ 'wpsp_no_results' ] : ''
842
+ )
843
+ );
844
+ }
845
+ endif;
846
+
847
+ if ( ! function_exists( 'wpsp_sanitize_intval' ) ) :
848
+ /**
849
+ * Sanitize our value so it has to be a positive integer
850
+ * @since 0.1
851
+ */
852
+ function wpsp_sanitize_intval( $input ) {
853
+ if ( '' == $input )
854
+ return $input;
855
+
856
+ return intval( $input );
857
+ }
858
+ endif;
859
+
860
+ if ( ! function_exists( 'wpsp_sanitize_absint' ) ) :
861
+ /**
862
+ * Sanitize our value so it can be a negative or positive integer
863
+ * @since 0.1
864
+ */
865
+ function wpsp_sanitize_absint( $input ) {
866
+ if ( '' == $input )
867
+ return $input;
868
+
869
+ return absint( $input );
870
+ }
871
+ endif;
872
+
873
+ if ( ! function_exists( 'wpsp_add_meta_boxes' ) ) :
874
+ /**
875
+ * Add our usage metabox
876
+ * @since 0.1
877
+ */
878
+ add_action( 'add_meta_boxes_wp_show_posts', 'wpsp_add_meta_boxes' );
879
+ function wpsp_add_meta_boxes( $post ){
880
+ add_meta_box( 'wpsp_shortcode', __( 'Usage', 'wp-show-posts' ), 'wpsp_shortcode_metabox', 'wp_show_posts', 'side', 'low' );
881
+ }
882
+ endif;
883
+
884
+ if ( ! function_exists( 'wpsp_shortcode_metabox' ) ) :
885
+ /**
886
+ * Meta box display callback.
887
+ *
888
+ * @param WP_Post $post Current post object.
889
+ * @since 0.1
890
+ */
891
+ function wpsp_shortcode_metabox( $post ) {
892
+ ?>
893
+ <h4 style="margin-bottom:5px;"><?php _e( 'Shortcode','wp-show-posts' ); ?></h4>
894
+ <input type="text" class="widefat" value='[wp_show_posts id="<?php echo $post->ID;?>"]' readonly />
895
+
896
+ <h4 style="margin-bottom:5px;"><?php _e( 'Function','wp-show-posts' ); ?></h4>
897
+ <input type="text" class="widefat" value='<?php echo esc_attr( "<?php if ( function_exists( 'wpsp_display' ) ) wpsp_display( " . $post->ID . " ); ?>" ); ?>' readonly />
898
+ <?php
899
+ }
 
 
900
  endif;
admin/post-type.php CHANGED
@@ -1,57 +1,60 @@
1
- <?php
2
- if ( ! function_exists( 'wp_show_posts_type' ) ) :
3
- /**
4
- * Create our WP Show Posts post type
5
- * @since 0.1
6
- */
7
- add_action( 'init', 'wp_show_posts_type', 0 );
8
- function wp_show_posts_type() {
9
-
10
- $labels = array(
11
- 'name' => _x( 'Post Lists', 'Post Type General Name', 'wp-show-posts' ),
12
- 'singular_name' => _x( 'Post List', 'Post Type Singular Name', 'wp-show-posts' ),
13
- 'menu_name' => __( 'WP Show Posts', 'wp-show-posts' ),
14
- 'name_admin_bar' => __( 'WP Show Posts', 'wp-show-posts' ),
15
- 'archives' => __( 'List Archives', 'wp-show-posts' ),
16
- 'parent_item_colon' => __( 'Parent List:', 'wp-show-posts' ),
17
- 'all_items' => __( 'All Lists', 'wp-show-posts' ),
18
- 'add_new_item' => __( 'Add New List', 'wp-show-posts' ),
19
- 'add_new' => __( 'Add New', 'wp-show-posts' ),
20
- 'new_item' => __( 'New List', 'wp-show-posts' ),
21
- 'edit_item' => __( 'Edit List', 'wp-show-posts' ),
22
- 'update_item' => __( 'Update List', 'wp-show-posts' ),
23
- 'view_item' => __( 'View List', 'wp-show-posts' ),
24
- 'search_items' => __( 'Search List', 'wp-show-posts' ),
25
- 'not_found' => __( 'Not found', 'wp-show-posts' ),
26
- 'not_found_in_trash' => __( 'Not found in Trash', 'wp-show-posts' ),
27
- 'featured_image' => __( 'Featured Image', 'wp-show-posts' ),
28
- 'set_featured_image' => __( 'Set featured image', 'wp-show-posts' ),
29
- 'remove_featured_image' => __( 'Remove featured image', 'wp-show-posts' ),
30
- 'use_featured_image' => __( 'Use as featured image', 'wp-show-posts' ),
31
- 'insert_into_item' => __( 'Insert into list', 'wp-show-posts' ),
32
- 'uploaded_to_this_item' => __( 'Uploaded to this list', 'wp-show-posts' ),
33
- 'items_list' => __( 'Items list', 'wp-show-posts' ),
34
- 'items_list_navigation' => __( 'Items list navigation', 'wp-show-posts' ),
35
- 'filter_items_list' => __( 'Filter items list', 'wp-show-posts' ),
36
- );
37
- $args = array(
38
- 'label' => __( 'Post List', 'wp-show-posts' ),
39
- 'labels' => $labels,
40
- 'supports' => array( 'title' ),
41
- 'hierarchical' => false,
42
- 'public' => false,
43
- 'show_ui' => true,
44
- 'show_in_menu' => true,
45
- 'menu_position' => 5,
46
- 'show_in_admin_bar' => false,
47
- 'show_in_nav_menus' => false,
48
- 'can_export' => true,
49
- 'has_archive' => false,
50
- 'exclude_from_search' => true,
51
- 'publicly_queryable' => false,
52
- 'capability_type' => 'page',
53
- );
54
- register_post_type( 'wp_show_posts', $args );
55
-
56
- }
 
 
 
57
  endif;
1
+ <?php
2
+ // No direct access, please
3
+ if ( ! defined( 'ABSPATH' ) ) exit;
4
+
5
+ if ( ! function_exists( 'wp_show_posts_type' ) ) :
6
+ /**
7
+ * Create our WP Show Posts post type
8
+ * @since 0.1
9
+ */
10
+ add_action( 'init', 'wp_show_posts_type', 0 );
11
+ function wp_show_posts_type() {
12
+
13
+ $labels = array(
14
+ 'name' => _x( 'Post Lists', 'Post Type General Name', 'wp-show-posts' ),
15
+ 'singular_name' => _x( 'Post List', 'Post Type Singular Name', 'wp-show-posts' ),
16
+ 'menu_name' => __( 'WP Show Posts', 'wp-show-posts' ),
17
+ 'name_admin_bar' => __( 'WP Show Posts', 'wp-show-posts' ),
18
+ 'archives' => __( 'List Archives', 'wp-show-posts' ),
19
+ 'parent_item_colon' => __( 'Parent List:', 'wp-show-posts' ),
20
+ 'all_items' => __( 'All Lists', 'wp-show-posts' ),
21
+ 'add_new_item' => __( 'Add New List', 'wp-show-posts' ),
22
+ 'add_new' => __( 'Add New', 'wp-show-posts' ),
23
+ 'new_item' => __( 'New List', 'wp-show-posts' ),
24
+ 'edit_item' => __( 'Edit List', 'wp-show-posts' ),
25
+ 'update_item' => __( 'Update List', 'wp-show-posts' ),
26
+ 'view_item' => __( 'View List', 'wp-show-posts' ),
27
+ 'search_items' => __( 'Search List', 'wp-show-posts' ),
28
+ 'not_found' => __( 'Not found', 'wp-show-posts' ),
29
+ 'not_found_in_trash' => __( 'Not found in Trash', 'wp-show-posts' ),
30
+ 'featured_image' => __( 'Featured Image', 'wp-show-posts' ),
31
+ 'set_featured_image' => __( 'Set featured image', 'wp-show-posts' ),
32
+ 'remove_featured_image' => __( 'Remove featured image', 'wp-show-posts' ),
33
+ 'use_featured_image' => __( 'Use as featured image', 'wp-show-posts' ),
34
+ 'insert_into_item' => __( 'Insert into list', 'wp-show-posts' ),
35
+ 'uploaded_to_this_item' => __( 'Uploaded to this list', 'wp-show-posts' ),
36
+ 'items_list' => __( 'Items list', 'wp-show-posts' ),
37
+ 'items_list_navigation' => __( 'Items list navigation', 'wp-show-posts' ),
38
+ 'filter_items_list' => __( 'Filter items list', 'wp-show-posts' ),
39
+ );
40
+ $args = array(
41
+ 'label' => __( 'Post List', 'wp-show-posts' ),
42
+ 'labels' => $labels,
43
+ 'supports' => array( 'title' ),
44
+ 'hierarchical' => false,
45
+ 'public' => false,
46
+ 'show_ui' => true,
47
+ 'show_in_menu' => true,
48
+ 'menu_position' => 5,
49
+ 'show_in_admin_bar' => false,
50
+ 'show_in_nav_menus' => false,
51
+ 'can_export' => true,
52
+ 'has_archive' => false,
53
+ 'exclude_from_search' => true,
54
+ 'publicly_queryable' => false,
55
+ 'capability_type' => 'page',
56
+ );
57
+ register_post_type( 'wp_show_posts', $args );
58
+
59
+ }
60
  endif;
admin/widget.php CHANGED
@@ -1,100 +1,104 @@
1
- <?php
2
- /**
3
- * Adds WPSP_Widget widget.
4
- */
5
- if ( ! class_exists( 'WPSP_Widget' ) ) :
6
- class WPSP_Widget extends WP_Widget {
7
-
8
- /**
9
- * Register widget with WordPress.
10
- */
11
- function __construct() {
12
- parent::__construct(
13
- 'wpsp_widget', // Base ID
14
- __( 'WP Show Posts', 'wp-show-posts' )
15
- );
16
- }
17
-
18
- /**
19
- * Front-end display of widget.
20
- *
21
- * @see WP_Widget::widget()
22
- *
23
- * @param array $args Widget arguments.
24
- * @param array $instance Saved values from database.
25
- */
26
- public function widget( $args, $instance ) {
27
- echo $args['before_widget'];
28
- if ( ! empty( $instance['title'] ) ) {
29
- echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
30
- }
31
- if ( function_exists( 'wpsp_display' ) ) wpsp_display( absint( $instance['wpsp_id'] ) );
32
- echo $args['after_widget'];
33
- }
34
-
35
- /**
36
- * Back-end widget form.
37
- *
38
- * @see WP_Widget::form()
39
- *
40
- * @param array $instance Previously saved values from database.
41
- */
42
- public function form( $instance ) {
43
- $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
44
- $id = ! empty( $instance['wpsp_id'] ) ? $instance['wpsp_id'] : '';
45
- ?>
46
- <p>
47
- <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( esc_attr( 'Title:' ) ); ?></label>
48
- <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
49
- </p>
50
- <p>
51
- <select name="<?php echo $this->get_field_name( 'wpsp_id' );?>" id="<?php echo $this->get_field_id( 'wpsp_id' );?>">
52
- <?php
53
- $args = array(
54
- 'posts_per_page' => -1,
55
- 'post_type' => 'wp_show_posts',
56
- 'post_status' => 'publish',
57
- 'showposts' => -1
58
- );
59
- $posts = get_posts( $args );
60
-
61
- $count = count( $posts );
62
- $types = array();
63
- if ( $count > 0 ) {
64
- foreach ( $posts as $post ) {
65
- echo '<option value="' . $post->ID . '"' . selected( $id, $post->ID ) . '>' . $post->post_title . '</option>';
66
- }
67
- }
68
- ?>
69
- </select>
70
- </p>
71
- <?php
72
- }
73
-
74
- /**
75
- * Sanitize widget form values as they are saved.
76
- *
77
- * @see WP_Widget::update()
78
- *
79
- * @param array $new_instance Values just sent to be saved.
80
- * @param array $old_instance Previously saved values from database.
81
- *
82
- * @return array Updated safe values to be saved.
83
- */
84
- public function update( $new_instance, $old_instance ) {
85
- $instance = array();
86
- $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
87
- $instance['wpsp_id'] = ( ! empty( $new_instance['wpsp_id'] ) ) ? absint( $new_instance['wpsp_id'] ) : '';
88
-
89
- return $instance;
90
- }
91
-
92
- } // class WPSP_Widget
93
- endif;
94
-
95
- if ( ! function_exists( 'wpsp_register_widget' ) ) :
96
- add_action( 'widgets_init', 'wpsp_register_widget' );
97
- function wpsp_register_widget() {
98
- register_widget( 'WPSP_Widget' );
99
- }
 
 
 
 
100
  endif;
1
+ <?php
2
+ // No direct access, please
3
+ if ( ! defined( 'ABSPATH' ) ) exit;
4
+
5
+ /**
6
+ * Adds WPSP_Widget widget.
7
+ */
8
+ if ( ! class_exists( 'WPSP_Widget' ) ) :
9
+ class WPSP_Widget extends WP_Widget {
10
+
11
+ /**
12
+ * Register widget with WordPress.
13
+ */
14
+ function __construct() {
15
+ parent::__construct(
16
+ 'wpsp_widget', // Base ID
17
+ __( 'WP Show Posts', 'wp-show-posts' )
18
+ );
19
+ }
20
+
21
+ /**
22
+ * Front-end display of widget.
23
+ *
24
+ * @see WP_Widget::widget()
25
+ *
26
+ * @param array $args Widget arguments.
27
+ * @param array $instance Saved values from database.
28
+ */
29
+ public function widget( $args, $instance ) {
30
+ echo $args['before_widget'];
31
+ if ( ! empty( $instance['title'] ) ) {
32
+ echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
33
+ }
34
+ if ( function_exists( 'wpsp_display' ) ) wpsp_display( absint( $instance['wpsp_id'] ) );
35
+ echo $args['after_widget'];
36
+ }
37
+
38
+ /**
39
+ * Back-end widget form.
40
+ *
41
+ * @see WP_Widget::form()
42
+ *
43
+ * @param array $instance Previously saved values from database.
44
+ */
45
+ public function form( $instance ) {
46
+ $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
47
+ $id = ! empty( $instance['wpsp_id'] ) ? $instance['wpsp_id'] : '';
48
+ ?>
49
+ <p>
50
+ <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php _e( esc_attr( 'Title:' ) ); ?></label>
51
+ <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
52
+ </p>
53
+ <p>
54
+ <select name="<?php echo $this->get_field_name( 'wpsp_id' );?>" id="<?php echo $this->get_field_id( 'wpsp_id' );?>">
55
+ <option value=""></option>
56
+ <?php
57
+ $args = array(
58
+ 'posts_per_page' => -1,
59
+ 'post_type' => 'wp_show_posts',
60
+ 'post_status' => 'publish',
61
+ 'showposts' => -1
62
+ );
63
+ $posts = get_posts( $args );
64
+
65
+ $count = count( $posts );
66
+ $types = array();
67
+ if ( $count > 0 ) {
68
+ foreach ( $posts as $post ) {
69
+ echo '<option value="' . $post->ID . '"' . selected( $id, $post->ID ) . '>' . $post->post_title . '</option>';
70
+ }
71
+ }
72
+ ?>
73
+ </select>
74
+ </p>
75
+ <?php
76
+ }
77
+
78
+ /**
79
+ * Sanitize widget form values as they are saved.
80
+ *
81
+ * @see WP_Widget::update()
82
+ *
83
+ * @param array $new_instance Values just sent to be saved.
84
+ * @param array $old_instance Previously saved values from database.
85
+ *
86
+ * @return array Updated safe values to be saved.
87
+ */
88
+ public function update( $new_instance, $old_instance ) {
89
+ $instance = array();
90
+ $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
91
+ $instance['wpsp_id'] = ( ! empty( $new_instance['wpsp_id'] ) ) ? absint( $new_instance['wpsp_id'] ) : '';
92
+
93
+ return $instance;
94
+ }
95
+
96
+ } // class WPSP_Widget
97
+ endif;
98
+
99
+ if ( ! function_exists( 'wpsp_register_widget' ) ) :
100
+ add_action( 'widgets_init', 'wpsp_register_widget' );
101
+ function wpsp_register_widget() {
102
+ register_widget( 'WPSP_Widget' );
103
+ }
104
  endif;
css/wp-show-posts-min.css CHANGED
@@ -1 +1 @@
1
- body .wp-show-posts a{box-shadow:0 0 0 transparent}.wp-show-posts-entry-title a{text-decoration:none}a.wp-show-posts-read-more,a.wp-show-posts-read-more:visited{display:inline-block;padding:8px 15px;border:2px solid #222;border-radius:3px;color:#222;font-size:0.8em;text-decoration:none}.wpsp-read-more{margin:0 0 1em;display:inline-block}a.wp-show-posts-read-more:hover,a.wp-show-posts-read-more:focus{border:2px solid transparent;color:#fff;background:#222;text-decoration:none}.wp-show-posts-image{margin-bottom:1em}.wp-show-posts-image.wpsp-image-left{float:left;margin-right:1.5em}.wp-show-posts-image.wpsp-image-right{float:right;margin-left:1.5em}.wp-show-posts-image.wpsp-image-center{display:block;text-align:center}.wp-show-posts-image img{margin:0 !important;vertical-align:bottom;height:auto}.wp-show-posts-entry-header{margin:0 0 1em;padding:0}.wp-show-posts .wp-show-posts-entry-title{font-size:30px;line-height:35px;margin:0}.wp-show-posts-updated{display:none}.wp-show-posts-entry-summary,.wp-show-posts-entry-content{margin-bottom:1em}.wp-show-posts-entry-meta{font-size:0.8em;color:rgba( 0,0,0,0.5 )}.wp-show-posts-meta a,.wp-show-posts-meta a:visited{color:rgba( 0,0,0,0.5 )}.stack-wp-show-posts-byline,.stack-wp-show-posts-posted-on{display:block}.wp-show-posts-entry-meta-below-post{margin-bottom:1em}.wp-show-posts-columns:not(.wp-show-posts-masonry){display:flex;flex-wrap:wrap}.wp-show-posts-columns .wp-show-posts-single:not(.wp-show-posts-masonry-block){display:flex;flex-direction:row}.wp-show-posts-columns .wp-show-posts-single:not(.wp-show-posts-masonry-block) .wp-show-posts-image img{flex:0 0 auto;object-fit:scale-down}.wpsp-clear{clear:both;display:block;overflow:hidden;visibility:hidden;width:0;height:0}.wp-show-posts:not(.wp-show-posts-columns) .wp-show-posts-single:not(:last-child){margin-bottom:2em}.wp-show-posts-columns .wp-show-posts-entry-title{font-size:25px}.wp-show-posts-columns .wp-show-posts-single.col-md-4 .wp-show-posts-entry-title,.wp-show-posts-columns .wp-show-posts-single.col-md-3 .wp-show-posts-entry-title,.wp-show-posts-columns .wp-show-posts-single.col-md-20 .wp-show-posts-entry-title{font-size:20px}.wp-show-posts-columns .wp-show-posts-inner{flex:1}@media (min-width: 768px){.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-20{float:left}.col-1{width:8.333333%}.col-2{width:16.666667%}.col-3{width:25%}.col-4{width:33.333%}.col-5{width:41.666667%}.col-6{width:50%}.col-7{width:58.333333%}.col-8{width:66.666667%}.col-9{width:75%}.col-10{width:83.333333%}.col-11{width:91.666667%}.col-12{width:100%}.col-20{width:20%}}@media (max-width: 767px){.wp-show-posts-columns,.wp-show-posts-inner{margin-left:0 !important;margin-right:0 !important}}.wp-show-posts-inner *:last-child{margin-bottom:0}.screen-reader-text{clip:rect(1px, 1px, 1px, 1px);position:absolute !important}.screen-reader-text:hover,.screen-reader-text:active,.screen-reader-text:focus{background-color:#f1f1f1;border-radius:3px;box-shadow:0 0 2px 2px rgba(0, 0, 0, 0.6);clip:auto !important;color:#21759b;display:block;font-size:14px;font-weight:bold;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}.wpsp-clearfix:after{content:".";display:block;overflow:hidden;visibility:hidden;font-size:0;line-height:0;width:0;height:0}
1
+ body .wp-show-posts a{box-shadow:0 0 0 transparent}.wp-show-posts-entry-title a{text-decoration:none}a.wp-show-posts-read-more,a.wp-show-posts-read-more:visited{display:inline-block;padding:8px 15px;border:2px solid #222;border-radius:3px;color:#222;font-size:0.8em;text-decoration:none}.wpsp-read-more{margin:0 0 1em;display:inline-block}a.wp-show-posts-read-more:hover,a.wp-show-posts-read-more:focus{border:2px solid transparent;color:#fff;background:#222;text-decoration:none}.wp-show-posts-image{margin-bottom:1em}.wp-show-posts-image.wpsp-image-left{float:left;margin-right:1.5em}.wp-show-posts-image.wpsp-image-right{float:right;margin-left:1.5em}.wp-show-posts-image.wpsp-image-center{display:block;text-align:center}.wp-show-posts-image img{margin:0 !important;vertical-align:bottom;height:auto}.wp-show-posts-entry-header{margin:0 0 1em;padding:0}.wp-show-posts .wp-show-posts-entry-title{font-size:30px;line-height:35px;margin:0}.wp-show-posts-updated{display:none}.wp-show-posts-entry-summary,.wp-show-posts-entry-content{margin-bottom:1em}.wp-show-posts-entry-meta{font-size:0.8em;color:rgba( 0,0,0,0.5 )}.wp-show-posts-meta a,.wp-show-posts-meta a:visited{color:rgba( 0,0,0,0.5 )}.stack-wp-show-posts-byline,.stack-wp-show-posts-posted-on{display:block}.wp-show-posts-entry-meta-below-post{margin-bottom:1em}.wp-show-posts-columns:not(.wp-show-posts-masonry){display:flex;flex-wrap:wrap}.wp-show-posts-columns .wp-show-posts-single:not(.wp-show-posts-masonry-block){display:flex;flex-direction:row}.wp-show-posts-columns .wp-show-posts-single:not(.wp-show-posts-masonry-block) .wp-show-posts-image img{flex:0 0 auto;object-fit:scale-down}.wpsp-clear{clear:both;display:block;overflow:hidden;visibility:hidden;width:0;height:0}.wp-show-posts:not(.wp-show-posts-columns) .wp-show-posts-single:not(:last-child){margin-bottom:2em}.wp-show-posts-columns .wp-show-posts-entry-title{font-size:25px}.wp-show-posts-columns .wp-show-posts-single.col-md-4 .wp-show-posts-entry-title,.wp-show-posts-columns .wp-show-posts-single.col-md-3 .wp-show-posts-entry-title,.wp-show-posts-columns .wp-show-posts-single.col-md-20 .wp-show-posts-entry-title{font-size:20px}.wp-show-posts-columns .wp-show-posts-inner{flex:1}@media (min-width: 768px){.wpsp-col-1,.wpsp-col-2,.wpsp-col-3,.wpsp-col-4,.wpsp-col-5,.wpsp-col-6,.wpsp-col-7,.wpsp-col-8,.wpsp-col-9,.wpsp-col-10,.wpsp-col-11,.wpsp-col-12,.wpsp-col-20{float:left}.wpsp-col-1{width:8.333333%}.wpsp-col-2{width:16.666667%}.wpsp-col-3{width:25%}.wpsp-col-4{width:33.333%}.wpsp-col-5{width:41.666667%}.wpsp-col-6{width:50%}.wpsp-col-7{width:58.333333%}.wpsp-col-8{width:66.666667%}.wpsp-col-9{width:75%}.wpsp-col-10{width:83.333333%}.wpsp-col-11{width:91.666667%}.wpsp-col-12{width:100%}.wpsp-col-20{width:20%}}@media (max-width: 767px){.wp-show-posts-columns,.wp-show-posts-inner{margin-left:0 !important;margin-right:0 !important}.wp-show-posts-columns .wp-show-posts-single{display:block;width:100%}}.wp-show-posts-inner *:last-child{margin-bottom:0}.screen-reader-text{clip:rect(1px, 1px, 1px, 1px);position:absolute !important}.screen-reader-text:hover,.screen-reader-text:active,.screen-reader-text:focus{background-color:#f1f1f1;border-radius:3px;box-shadow:0 0 2px 2px rgba(0, 0, 0, 0.6);clip:auto !important;color:#21759b;display:block;font-size:14px;font-weight:bold;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}.wpsp-clearfix:after{content:".";display:block;overflow:hidden;visibility:hidden;font-size:0;line-height:0;width:0;height:0}
css/wp-show-posts.css CHANGED
@@ -1,235 +1,239 @@
1
- body .wp-show-posts a {
2
- box-shadow: 0 0 0 transparent;
3
- }
4
-
5
- .wp-show-posts-entry-title a {
6
- text-decoration: none;
7
- }
8
-
9
- a.wp-show-posts-read-more,
10
- a.wp-show-posts-read-more:visited {
11
- display: inline-block;
12
- padding: 8px 15px;
13
- border: 2px solid #222;
14
- border-radius: 3px;
15
- color: #222;
16
- font-size: 0.8em;
17
- text-decoration: none;
18
- }
19
-
20
- .wpsp-read-more {
21
- margin: 0 0 1em;
22
- display: inline-block;
23
- }
24
-
25
- a.wp-show-posts-read-more:hover,
26
- a.wp-show-posts-read-more:focus {
27
- border: 2px solid transparent;
28
- color: #fff;
29
- background: #222;
30
- text-decoration: none;
31
- }
32
-
33
- .wp-show-posts-image {
34
- margin-bottom: 1em;
35
- }
36
-
37
- .wp-show-posts-image.wpsp-image-left {
38
- float: left;
39
- margin-right: 1.5em;
40
- }
41
-
42
- .wp-show-posts-image.wpsp-image-right {
43
- float: right;
44
- margin-left: 1.5em;
45
- }
46
-
47
- .wp-show-posts-image.wpsp-image-center {
48
- display: block;
49
- text-align: center;
50
- }
51
-
52
- .wp-show-posts-image img {
53
- margin: 0 !important;
54
- vertical-align: bottom;
55
- height: auto;
56
- }
57
-
58
- .wp-show-posts-entry-header {
59
- margin: 0 0 1em;
60
- padding: 0;
61
- }
62
-
63
- .wp-show-posts .wp-show-posts-entry-title {
64
- font-size: 30px;
65
- line-height: 35px;
66
- margin: 0;
67
- }
68
-
69
- .wp-show-posts-updated {
70
- display: none;
71
- }
72
-
73
- .wp-show-posts-entry-summary,
74
- .wp-show-posts-entry-content {
75
- margin-bottom: 1em;
76
- }
77
-
78
- .wp-show-posts-entry-meta {
79
- font-size: 0.8em;
80
- color: rgba( 0,0,0,0.5 );
81
- }
82
-
83
- .wp-show-posts-meta a,
84
- .wp-show-posts-meta a:visited {
85
- color: rgba( 0,0,0,0.5 );
86
- }
87
-
88
- .stack-wp-show-posts-byline,
89
- .stack-wp-show-posts-posted-on {
90
- display: block;
91
- }
92
-
93
- .wp-show-posts-entry-meta-below-post {
94
- margin-bottom: 1em;
95
- }
96
-
97
- .wp-show-posts-columns:not(.wp-show-posts-masonry) {
98
- display: flex;
99
- flex-wrap: wrap;
100
- }
101
- .wp-show-posts-columns .wp-show-posts-single:not(.wp-show-posts-masonry-block) {
102
- display: flex;
103
- flex-direction: row;
104
- }
105
-
106
- .wp-show-posts-columns .wp-show-posts-single:not(.wp-show-posts-masonry-block) .wp-show-posts-image img {
107
- flex: 0 0 auto;
108
- object-fit: scale-down;
109
- }
110
-
111
- .wpsp-clear {
112
- clear: both;
113
- display: block;
114
- overflow: hidden;
115
- visibility: hidden;
116
- width: 0;
117
- height: 0;
118
- }
119
-
120
- .wp-show-posts:not(.wp-show-posts-columns) .wp-show-posts-single:not(:last-child) {
121
- margin-bottom: 2em;
122
- }
123
-
124
- .wp-show-posts-columns .wp-show-posts-entry-title {
125
- font-size: 25px;
126
- }
127
-
128
- .wp-show-posts-columns .wp-show-posts-single.col-md-4 .wp-show-posts-entry-title,
129
- .wp-show-posts-columns .wp-show-posts-single.col-md-3 .wp-show-posts-entry-title,
130
- .wp-show-posts-columns .wp-show-posts-single.col-md-20 .wp-show-posts-entry-title {
131
- font-size: 20px;
132
- }
133
-
134
- .wp-show-posts-columns .wp-show-posts-inner {
135
- flex: 1;
136
- }
137
-
138
- /* Bootstrap grid system */
139
- @media (min-width: 768px) {
140
- .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col-20 {
141
- float: left;
142
- }
143
- .col-1 {
144
- width: 8.333333%;
145
- }
146
- .col-2 {
147
- width: 16.666667%;
148
- }
149
- .col-3 {
150
- width: 25%;
151
- }
152
- .col-4 {
153
- width: 33.333%;
154
- }
155
- .col-5 {
156
- width: 41.666667%;
157
- }
158
- .col-6 {
159
- width: 50%;
160
- }
161
- .col-7 {
162
- width: 58.333333%;
163
- }
164
- .col-8 {
165
- width: 66.666667%;
166
- }
167
- .col-9 {
168
- width: 75%;
169
- }
170
- .col-10 {
171
- width: 83.333333%;
172
- }
173
- .col-11 {
174
- width: 91.666667%;
175
- }
176
- .col-12 {
177
- width: 100%;
178
- }
179
-
180
- /* 5 columns */
181
- .col-20 {
182
- width: 20%;
183
- }
184
- }
185
-
186
- @media (max-width: 767px) {
187
- .wp-show-posts-columns,
188
- .wp-show-posts-inner {
189
- margin-left: 0 !important;
190
- margin-right: 0 !important;
191
- }
192
- }
193
-
194
- /* Spacing */
195
- .wp-show-posts-inner *:last-child {
196
- margin-bottom: 0;
197
- }
198
-
199
- /* Screen reader text*/
200
- .screen-reader-text {
201
- clip: rect(1px, 1px, 1px, 1px);
202
- position: absolute !important;
203
- }
204
-
205
- .screen-reader-text:hover,
206
- .screen-reader-text:active,
207
- .screen-reader-text:focus {
208
- background-color: #f1f1f1;
209
- border-radius: 3px;
210
- box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6);
211
- clip: auto !important;
212
- color: #21759b;
213
- display: block;
214
- font-size: 14px;
215
- font-weight: bold;
216
- height: auto;
217
- left: 5px;
218
- line-height: normal;
219
- padding: 15px 23px 14px;
220
- text-decoration: none;
221
- top: 5px;
222
- width: auto;
223
- z-index: 100000; /* Above WP toolbar */
224
- }
225
-
226
- .wpsp-clearfix:after {
227
- content: ".";
228
- display: block;
229
- overflow: hidden;
230
- visibility: hidden;
231
- font-size: 0;
232
- line-height: 0;
233
- width: 0;
234
- height: 0;
235
- }
 
 
 
 
1
+ body .wp-show-posts a {
2
+ box-shadow: 0 0 0 transparent;
3
+ }
4
+
5
+ .wp-show-posts-entry-title a {
6
+ text-decoration: none;
7
+ }
8
+
9
+ a.wp-show-posts-read-more,
10
+ a.wp-show-posts-read-more:visited {
11
+ display: inline-block;
12
+ padding: 8px 15px;
13
+ border: 2px solid #222;
14
+ border-radius: 3px;
15
+ color: #222;
16
+ font-size: 0.8em;
17
+ text-decoration: none;
18
+ }
19
+
20
+ .wpsp-read-more {
21
+ margin: 0 0 1em;
22
+ display: inline-block;
23
+ }
24
+
25
+ a.wp-show-posts-read-more:hover,
26
+ a.wp-show-posts-read-more:focus {
27
+ border: 2px solid transparent;
28
+ color: #fff;
29
+ background: #222;
30
+ text-decoration: none;
31
+ }
32
+
33
+ .wp-show-posts-image {
34
+ margin-bottom: 1em;
35
+ }
36
+
37
+ .wp-show-posts-image.wpsp-image-left {
38
+ float: left;
39
+ margin-right: 1.5em;
40
+ }
41
+
42
+ .wp-show-posts-image.wpsp-image-right {
43
+ float: right;
44
+ margin-left: 1.5em;
45
+ }
46
+
47
+ .wp-show-posts-image.wpsp-image-center {
48
+ display: block;
49
+ text-align: center;
50
+ }
51
+
52
+ .wp-show-posts-image img {
53
+ margin: 0 !important;
54
+ vertical-align: bottom;
55
+ height: auto;
56
+ }
57
+
58
+ .wp-show-posts-entry-header {
59
+ margin: 0 0 1em;
60
+ padding: 0;
61
+ }
62
+
63
+ .wp-show-posts .wp-show-posts-entry-title {
64
+ font-size: 30px;
65
+ line-height: 35px;
66
+ margin: 0;
67
+ }
68
+
69
+ .wp-show-posts-updated {
70
+ display: none;
71
+ }
72
+
73
+ .wp-show-posts-entry-summary,
74
+ .wp-show-posts-entry-content {
75
+ margin-bottom: 1em;
76
+ }
77
+
78
+ .wp-show-posts-entry-meta {
79
+ font-size: 0.8em;
80
+ color: rgba( 0,0,0,0.5 );
81
+ }
82
+
83
+ .wp-show-posts-meta a,
84
+ .wp-show-posts-meta a:visited {
85
+ color: rgba( 0,0,0,0.5 );
86
+ }
87
+
88
+ .stack-wp-show-posts-byline,
89
+ .stack-wp-show-posts-posted-on {
90
+ display: block;
91
+ }
92
+
93
+ .wp-show-posts-entry-meta-below-post {
94
+ margin-bottom: 1em;
95
+ }
96
+
97
+ .wp-show-posts-columns:not(.wp-show-posts-masonry) {
98
+ display: flex;
99
+ flex-wrap: wrap;
100
+ }
101
+ .wp-show-posts-columns .wp-show-posts-single:not(.wp-show-posts-masonry-block) {
102
+ display: flex;
103
+ flex-direction: row;
104
+ }
105
+
106
+ .wp-show-posts-columns .wp-show-posts-single:not(.wp-show-posts-masonry-block) .wp-show-posts-image img {
107
+ flex: 0 0 auto;
108
+ object-fit: scale-down;
109
+ }
110
+
111
+ .wpsp-clear {
112
+ clear: both;
113
+ display: block;
114
+ overflow: hidden;
115
+ visibility: hidden;
116
+ width: 0;
117
+ height: 0;
118
+ }
119
+
120
+ .wp-show-posts:not(.wp-show-posts-columns) .wp-show-posts-single:not(:last-child) {
121
+ margin-bottom: 2em;
122
+ }
123
+
124
+ .wp-show-posts-columns .wp-show-posts-entry-title {
125
+ font-size: 25px;
126
+ }
127
+
128
+ .wp-show-posts-columns .wp-show-posts-single.col-md-4 .wp-show-posts-entry-title,
129
+ .wp-show-posts-columns .wp-show-posts-single.col-md-3 .wp-show-posts-entry-title,
130
+ .wp-show-posts-columns .wp-show-posts-single.col-md-20 .wp-show-posts-entry-title {
131
+ font-size: 20px;
132
+ }
133
+
134
+ .wp-show-posts-columns .wp-show-posts-inner {
135
+ flex: 1;
136
+ }
137
+
138
+ /* Bootstrap grid system */
139
+ @media (min-width: 768px) {
140
+ .wpsp-col-1, .wpsp-col-2, .wpsp-col-3, .wpsp-col-4, .wpsp-col-5, .wpsp-col-6, .wpsp-col-7, .wpsp-col-8, .wpsp-col-9, .wpsp-col-10, .wpsp-col-11, .wpsp-col-12, .wpsp-col-20 {
141
+ float: left;
142
+ }
143
+ .wpsp-col-1 {
144
+ width: 8.333333%;
145
+ }
146
+ .wpsp-col-2 {
147
+ width: 16.666667%;
148
+ }
149
+ .wpsp-col-3 {
150
+ width: 25%;
151
+ }
152
+ .wpsp-col-4 {
153
+ width: 33.333%;
154
+ }
155
+ .wpsp-col-5 {
156
+ width: 41.666667%;
157
+ }
158
+ .wpsp-col-6 {
159
+ width: 50%;
160
+ }
161
+ .wpsp-col-7 {
162
+ width: 58.333333%;
163
+ }
164
+ .wpsp-col-8 {
165
+ width: 66.666667%;
166
+ }
167
+ .wpsp-col-9 {
168
+ width: 75%;
169
+ }
170
+ .wpsp-col-10 {
171
+ width: 83.333333%;
172
+ }
173
+ .wpsp-col-11 {
174
+ width: 91.666667%;
175
+ }
176
+ .wpsp-col-12 {
177
+ width: 100%;
178
+ }
179
+
180
+ /* 5 columns */
181
+ .wpsp-col-20 {
182
+ width: 20%;
183
+ }
184
+ }
185
+
186
+ @media (max-width: 767px) {
187
+ .wp-show-posts-columns,
188
+ .wp-show-posts-inner {
189
+ margin-left: 0 !important;
190
+ margin-right: 0 !important;
191
+ }
192
+ .wp-show-posts-columns .wp-show-posts-single {
193
+ display: block;
194
+ width: 100%;
195
+ }
196
+ }
197
+
198
+ /* Spacing */
199
+ .wp-show-posts-inner *:last-child {
200
+ margin-bottom: 0;
201
+ }
202
+
203
+ /* Screen reader text*/
204
+ .screen-reader-text {
205
+ clip: rect(1px, 1px, 1px, 1px);
206
+ position: absolute !important;
207
+ }
208
+
209
+ .screen-reader-text:hover,
210
+ .screen-reader-text:active,
211
+ .screen-reader-text:focus {
212
+ background-color: #f1f1f1;
213
+ border-radius: 3px;
214
+ box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6);
215
+ clip: auto !important;
216
+ color: #21759b;
217
+ display: block;
218
+ font-size: 14px;
219
+ font-weight: bold;
220
+ height: auto;
221
+ left: 5px;
222
+ line-height: normal;
223
+ padding: 15px 23px 14px;
224
+ text-decoration: none;
225
+ top: 5px;
226
+ width: auto;
227
+ z-index: 100000; /* Above WP toolbar */
228
+ }
229
+
230
+ .wpsp-clearfix:after {
231
+ content: ".";
232
+ display: block;
233
+ overflow: hidden;
234
+ visibility: hidden;
235
+ font-size: 0;
236
+ line-height: 0;
237
+ width: 0;
238
+ height: 0;
239
+ }
inc/defaults.php CHANGED
@@ -1,79 +1,82 @@
1
- <?php
2
- if ( ! function_exists( 'wpsp_get_defaults' ) ) :
3
- /**
4
- * Set all of our defaults
5
- * @since 0.1
6
- */
7
- function wpsp_get_defaults()
8
- {
9
- $defaults = array(
10
- 'wpsp_author' => '',
11
- 'wpsp_author_location' => 'below-post',
12
- 'wpsp_columns' => 'col-6',
13
- 'wpsp_columns_gutter' => '2em',
14
- 'wpsp_content_type' => 'excerpt',
15
- 'wpsp_date_location' => 'below-title',
16
- 'wpsp_exclude_current' => false,
17
- 'wpsp_excerpt_length' => 30,
18
- 'wpsp_post_id' => '',
19
- 'wpsp_exclude_post_id' => '',
20
- 'wpsp_ignore_sticky_posts' => false,
21
- 'wpsp_image' => true,
22
- 'wpsp_image_alignment' => 'center',
23
- 'wpsp_image_height' => '',
24
- 'wpsp_image_location' => 'below-title',
25
- 'wpsp_image_lightbox' => false,
26
- 'wpsp_image_gallery' => false,
27
- 'wpsp_image_overlay_color' => '',
28
- 'wpsp_image_overlay_icon' => '',
29
- 'wpsp_image_width' => '',
30
- 'wpsp_include_title' => true,
31
- 'wpsp_include_terms' => false,
32
- 'wpsp_include_author' => false,
33
- 'wpsp_include_date' => true,
34
- 'wpsp_inner_wrapper' => 'article',
35
- 'wpsp_inner_wrapper_class' => '',
36
- 'wpsp_inner_wrapper_style' => '',
37
- 'wpsp_itemtype' => 'CreativeWork',
38
- 'wpsp_meta_key' => '',
39
- 'wpsp_meta_value' => '',
40
- 'wpsp_offset' => 0,
41
- 'wpsp_order' => 'DESC',
42
- 'wpsp_orderby' => 'date',
43
- 'wpsp_pagination' => false,
44
- 'wpsp_post_meta_bottom_style' => 'stack',
45
- 'wpsp_post_meta_top_style' => 'inline',
46
- 'wpsp_post_status' => 'publish',
47
- 'wpsp_post_type' => 'post',
48
- 'wpsp_posts_per_page' => 10,
49
- 'wpsp_read_more_text' => '',
50
- 'wpsp_tax_operator' => 'IN',
51
- 'wpsp_tax_term' => '',
52
- 'wpsp_taxonomy' => 'category',
53
- 'wpsp_terms_location' => 'below-post',
54
- 'wpsp_wrapper' => 'section',
55
- 'wpsp_wrapper_class' => '',
56
- 'wpsp_wrapper_id' => false,
57
- 'wpsp_wrapper_style' => '',
58
- 'wpsp_no_results' => __( 'Sorry, no posts were found.','wp-show-posts' ),
59
- 'wpsp_ajax_pagination' => false,
60
- 'wpsp_masonry' => false,
61
- 'wpsp_social_sharing' => false,
62
- 'wpsp_social_sharing_alignment' => 'right',
63
- 'wpsp_twitter' => false,
64
- 'wpsp_facebook' => false,
65
- 'wpsp_googleplus' => false,
66
- 'wpsp_pinterest' => false,
67
- 'wpsp_love' => false,
68
- 'wpsp_featured_post' => false,
69
- 'wpsp_image_hover_effect' => '',
70
- 'wpsp_read_more_style' => 'hollow',
71
- 'wpsp_read_more_color' => 'black',
72
- 'wpsp_border' => '',
73
- 'wpsp_padding' => '',
74
- 'wpsp_filter' => false
75
- );
76
-
77
- return apply_filters( 'wpsp_defaults', $defaults );
78
- }
 
 
 
79
  endif;
1
+ <?php
2
+ // No direct access, please
3
+ if ( ! defined( 'ABSPATH' ) ) exit;
4
+
5
+ if ( ! function_exists( 'wpsp_get_defaults' ) ) :
6
+ /**
7
+ * Set all of our defaults
8
+ * @since 0.1
9
+ */
10
+ function wpsp_get_defaults()
11
+ {
12
+ $defaults = array(
13
+ 'wpsp_author' => '',
14
+ 'wpsp_author_location' => 'below-post',
15
+ 'wpsp_columns' => 'col-6',
16
+ 'wpsp_columns_gutter' => '2em',
17
+ 'wpsp_content_type' => 'excerpt',
18
+ 'wpsp_date_location' => 'below-title',
19
+ 'wpsp_exclude_current' => false,
20
+ 'wpsp_excerpt_length' => 30,
21
+ 'wpsp_post_id' => '',
22
+ 'wpsp_exclude_post_id' => '',
23
+ 'wpsp_ignore_sticky_posts' => false,
24
+ 'wpsp_image' => true,
25
+ 'wpsp_image_alignment' => 'center',
26
+ 'wpsp_image_height' => '',
27
+ 'wpsp_image_location' => 'below-title',
28
+ 'wpsp_image_lightbox' => false,
29
+ 'wpsp_image_gallery' => false,
30
+ 'wpsp_image_overlay_color' => '',
31
+ 'wpsp_image_overlay_icon' => '',
32
+ 'wpsp_image_width' => '',
33
+ 'wpsp_include_title' => true,
34
+ 'wpsp_include_terms' => false,
35
+ 'wpsp_include_author' => false,
36
+ 'wpsp_include_date' => true,
37
+ 'wpsp_inner_wrapper' => 'article',
38
+ 'wpsp_inner_wrapper_class' => '',
39
+ 'wpsp_inner_wrapper_style' => '',
40
+ 'wpsp_itemtype' => 'CreativeWork',
41
+ 'wpsp_meta_key' => '',
42
+ 'wpsp_meta_value' => '',
43
+ 'wpsp_offset' => 0,
44
+ 'wpsp_order' => 'DESC',
45
+ 'wpsp_orderby' => 'date',
46
+ 'wpsp_pagination' => false,
47
+ 'wpsp_post_meta_bottom_style' => 'stack',
48
+ 'wpsp_post_meta_top_style' => 'inline',
49
+ 'wpsp_post_status' => 'publish',
50
+ 'wpsp_post_type' => 'post',
51
+ 'wpsp_posts_per_page' => 10,
52
+ 'wpsp_read_more_text' => '',
53
+ 'wpsp_tax_operator' => 'IN',
54
+ 'wpsp_tax_term' => '',
55
+ 'wpsp_taxonomy' => 'category',
56
+ 'wpsp_terms_location' => 'below-post',
57
+ 'wpsp_wrapper' => 'section',
58
+ 'wpsp_wrapper_class' => '',
59
+ 'wpsp_wrapper_id' => false,
60
+ 'wpsp_wrapper_style' => '',
61
+ 'wpsp_no_results' => __( 'Sorry, no posts were found.','wp-show-posts' ),
62
+ 'wpsp_ajax_pagination' => false,
63
+ 'wpsp_masonry' => false,
64
+ 'wpsp_social_sharing' => false,
65
+ 'wpsp_social_sharing_alignment' => 'right',
66
+ 'wpsp_twitter' => false,
67
+ 'wpsp_facebook' => false,
68
+ 'wpsp_googleplus' => false,
69
+ 'wpsp_pinterest' => false,
70
+ 'wpsp_love' => false,
71
+ 'wpsp_featured_post' => false,
72
+ 'wpsp_image_hover_effect' => '',
73
+ 'wpsp_read_more_style' => 'hollow',
74
+ 'wpsp_read_more_color' => 'black',
75
+ 'wpsp_border' => '',
76
+ 'wpsp_padding' => '',
77
+ 'wpsp_filter' => false
78
+ );
79
+
80
+ return apply_filters( 'wpsp_defaults', $defaults );
81
+ }
82
  endif;
inc/functions.php CHANGED
@@ -1,420 +1,382 @@
1
- <?php
2
- if ( ! function_exists( 'wpsp_excerpt' ) ) :
3
- /**
4
- * Create our own excerpt function
5
- * @since 0.1
6
- */
7
- function wpsp_excerpt( $text = '', $excerpt_length = 55 ) {
8
- if ( ! $excerpt_length )
9
- return;
10
-
11
- $raw_excerpt = $text;
12
- if ( '' == $text ) {
13
- $text = get_the_content('');
14
-
15
- $text = strip_shortcodes( $text );
16
-
17
- /** This filter is documented in wp-includes/post-template.php */
18
- $text = apply_filters( 'the_content', $text );
19
- $text = str_replace(']]>', ']]&gt;', $text);
20
-
21
- /**
22
- * Filter the string in the "more" link displayed after a trimmed excerpt.
23
- *
24
- * @since 2.9.0
25
- *
26
- * @param string $more_string The string shown within the more link.
27
- */
28
- $excerpt_more = apply_filters( 'wpsp_excerpt_more', '...' );
29
- $text = wp_trim_words( $text, $excerpt_length, $excerpt_more );
30
- }
31
- /**
32
- * Filter the trimmed excerpt string.
33
- *
34
- * @since 2.8.0
35
- *
36
- * @param string $text The trimmed text.
37
- * @param string $raw_excerpt The text prior to trimming.
38
- */
39
- echo apply_filters( 'wp_trim_excerpt', $text, $raw_excerpt );
40
- }
41
- endif;
42
-
43
- if ( ! function_exists( 'wpsp_meta' ) ) :
44
- /**
45
- * Build our post meta
46
- * @since 0.1
47
- */
48
- function wpsp_meta( $location, $post_meta_style )
49
- {
50
- global $wpsp_id;
51
-
52
- if ( ! isset( $wpsp_id ) )
53
- return;
54
-
55
- $author_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_author_location' ) );
56
- $date_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_date_location' ) );
57
- $include_author = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_author' ), FILTER_VALIDATE_BOOLEAN );
58
- $include_terms = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_terms' ), FILTER_VALIDATE_BOOLEAN );
59
- $include_date = filter_var( get_post_meta( $wpsp_id, 'wpsp_include_date', true ), FILTER_VALIDATE_BOOLEAN );
60
- $terms_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_terms_location' ) );
61
- $taxonomy = sanitize_key( wpsp_get_setting( $wpsp_id, 'wpsp_taxonomy' ) );
62
-
63
- $output = array();
64
- if ( ( $include_author && $location == $author_location ) || ( $include_date && $location == $date_location ) || ( $include_terms && $location == $terms_location ) )
65
- echo '<div class="wp-show-posts-entry-meta wp-show-posts-entry-meta-' . $location . ' post-meta-' . $post_meta_style . '">';
66
-
67
- // If our author is enabled, show it
68
- if ( $include_author && $location == $author_location ) :
69
- $output[] = sprintf( '<span class="wp-show-posts-byline wp-show-posts-meta">%1$s</span>',
70
- sprintf( '<span class="wp-show-posts-author vcard" itemtype="http://schema.org/Person" itemscope="itemscope" itemprop="author"><a class="url fn n" href="%1$s" title="%2$s" rel="author" itemprop="url"><span class="author-name" itemprop="name">%3$s</span></a></span>',
71
- esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
72
- esc_attr( sprintf( __( 'View all posts by %s', 'wp-show-posts' ), get_the_author() ) ),
73
- esc_html( get_the_author() )
74
- )
75
- );
76
- endif;
77
-
78
- // Show the date
79
- if ( $include_date && $location == $date_location ) :
80
- $time_string = '<time class="wp-show-posts-entry-date published" datetime="%1$s" itemprop="datePublished">%2$s</time>';
81
- if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) )
82
- $time_string .= '<time class="wp-show-posts-updated" datetime="%3$s" itemprop="dateModified">%4$s</time>';
83
-
84
- $time_string = sprintf( $time_string,
85
- esc_attr( get_the_date( 'c' ) ),
86
- esc_html( get_the_date() ),
87
- esc_attr( get_the_modified_date( 'c' ) ),
88
- esc_html( get_the_modified_date() )
89
- );
90
-
91
- // If our date is enabled, show it
92
- $output[] = sprintf( '<span class="wp-show-posts-posted-on wp-show-posts-meta">%1$s</span>',
93
- sprintf( '<a href="%1$s" title="%2$s" rel="bookmark">%3$s</a>',
94
- esc_url( get_permalink() ),
95
- esc_attr( get_the_time() ),
96
- $time_string
97
- )
98
- );
99
- endif;
100
-
101
- // Show the terms
102
- if ( $include_terms && $location == $terms_location ) :
103
- $output[] = sprintf( '<span class="wp-show-posts-terms wp-show-posts-meta">%1$s</span>',
104
- get_the_term_list( get_the_ID(), $taxonomy, '', ', ' )
105
- );
106
- endif;
107
-
108
- $separator = ( 'inline' == $post_meta_style ) ? ' <span class="wp-show-posts-separator">|</span> ' : '<br />';
109
- echo implode( $separator, $output);
110
-
111
- if ( ( $include_author && $location == $author_location ) || ( $include_date && $location == $date_location ) || ( $include_terms && $location == $terms_location ) )
112
- echo '</div>';
113
- }
114
- endif;
115
-
116
- if ( ! function_exists( 'wpsp_add_post_meta_after_title' ) ) :
117
- add_action( 'wpsp_after_title','wpsp_add_post_meta_after_title' );
118
- function wpsp_add_post_meta_after_title()
119
- {
120
- global $wpsp_id;
121
-
122
- if ( ! isset( $wpsp_id ) )
123
- return;
124
-
125
- $author_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_author_location' ) );
126
- $date_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_date_location' ) );
127
- $terms_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_terms_location' ) );
128
- $include_author = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_author' ), FILTER_VALIDATE_BOOLEAN );
129
- $include_terms = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_terms' ), FILTER_VALIDATE_BOOLEAN );
130
- $include_date = filter_var( get_post_meta( $wpsp_id, 'wpsp_include_date', true ), FILTER_VALIDATE_BOOLEAN );
131
- $post_meta_top_style = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_post_meta_top_style' ) );
132
-
133
- if ( ( $include_author && 'below-title' == $author_location ) || ( $include_date && 'below-title' == $date_location ) || ( $include_terms && 'below-title' == $terms_location ) )
134
- wpsp_meta( 'below-title', $post_meta_top_style );
135
-
136
- }
137
- endif;
138
-
139
- if ( ! function_exists( 'wpsp_add_post_meta_after_content' ) ) :
140
- add_action( 'wpsp_after_content','wpsp_add_post_meta_after_content', 10 );
141
- function wpsp_add_post_meta_after_content()
142
- {
143
- global $wpsp_id;
144
-
145
- if ( ! isset( $wpsp_id ) )
146
- return;
147
-
148
- $author_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_author_location' ) );
149
- $date_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_date_location' ) );
150
- $terms_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_terms_location' ) );
151
- $include_author = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_author' ), FILTER_VALIDATE_BOOLEAN );
152
- $include_terms = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_terms' ), FILTER_VALIDATE_BOOLEAN );
153
- $include_date = filter_var( get_post_meta( $wpsp_id, 'wpsp_include_date', true ), FILTER_VALIDATE_BOOLEAN );
154
- $post_meta_bottom_style = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_post_meta_bottom_style' ) );
155
-
156
- if ( ( $include_author && 'below-post' == $author_location ) || ( $include_date && 'below-post' == $date_location ) || ( $include_terms && 'below-post' == $terms_location ) )
157
- wpsp_meta( 'below-post', $post_meta_bottom_style );
158
- }
159
- endif;
160
-
161
- if ( ! function_exists( 'wpsp_post_image' ) ) :
162
- /**
163
- * Build our post image
164
- * @since 0.1
165
- */
166
- function wpsp_post_image()
167
- {
168
- if ( ! has_post_thumbnail() )
169
- return;
170
-
171
- global $wpsp_id;
172
-
173
- if ( ! isset( $wpsp_id ) )
174
- return;
175
-
176
- $image = sanitize_text_field( get_post_meta( $wpsp_id, 'wpsp_image', true ), FILTER_VALIDATE_BOOLEAN );
177
- if ( ! isset( $image ) || ! $image )
178
- return;
179
-
180
- $image_alignment = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_alignment' ) );
181
- $image_height = absint( wpsp_get_setting( $wpsp_id, 'wpsp_image_height' ) );
182
- $image_width = absint( wpsp_get_setting( $wpsp_id, 'wpsp_image_width' ) );
183
- $image_overlay_color = wpsp_sanitize_hex_color( wpsp_get_setting( $wpsp_id, 'wpsp_image_overlay_color' ) );
184
- $image_overlay_icon = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_overlay_icon' ) );
185
- $image_hover_effect = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_hover_effect' ) );
186
- $columns = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_columns' ) );
187
-
188
- $image_id = get_post_thumbnail_id( get_the_ID(), 'full' );
189
- $image_url = wp_get_attachment_image_src( $image_id, 'full', true );
190
- $image_atts = wpsp_image_attributes( $image_url[1], $image_url[2], $image_width, $image_height );
191
- $hover = ( '' !== $image_hover_effect ) ? $image_hover_effect : '';
192
- ?>
193
- <div class="wp-show-posts-image <?php echo $hover . ' wpsp-image-' . $image_alignment; ?> ">
194
- <?php printf( '<a href="%1$s" %2$s title="%3$s">',
195
- apply_filters( 'wpsp_image_href', esc_url( get_the_permalink() ) ),
196
- apply_filters( 'wpsp_image_data', '' ),
197
- apply_filters( 'wpsp_image_title', esc_attr( get_the_title() ) )
198
- ); ?>
199
- <?php if ( ! empty( $image_atts ) ) : ?>
200
- <img src="<?php echo WPSP_Resize( $image_url[0], $image_atts[ 'width' ], $image_atts[ 'height' ], $image_atts[ 'crop' ], true, $image_atts[ 'upscale' ] ); ?>" alt="<?php esc_attr( the_title() ); ?>" itemprop="image" class="<?php echo $image_alignment; ?>" />
201
- <?php else :
202
- the_post_thumbnail( apply_filters( 'wpsp_default_image_size', 'full' ), array( 'itemprop' => 'image' ) );
203
- endif;
204
-
205
- if ( '' !== $image_overlay_color || '' !== $image_overlay_icon ) :
206
- $color = ( $image_overlay_color ) ? 'style="background-color:' . wpsp_hex2rgba( $image_overlay_color, apply_filters( 'wpsp_overlay_opacity', 0.7 ) ) . '"' : '';
207
- $icon = ( $image_overlay_icon ) ? $image_overlay_icon : 'no-icon';
208
- echo '<span class="wp-show-posts-image-overlay ' . $icon . '" ' . $color . '></span>';
209
- endif;
210
- ?>
211
- </a>
212
- </div>
213
- <?php
214
- }
215
- endif;
216
-
217
- if ( ! function_exists( 'wpsp_add_post_image_before_title' ) ) :
218
- add_action( 'wpsp_before_header','wpsp_add_post_image_before_title' );
219
- function wpsp_add_post_image_before_title()
220
- {
221
- global $wpsp_id;
222
-
223
- if ( ! isset( $wpsp_id ) )
224
- return;
225
-
226
- $image_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_location' ) );
227
-
228
- if ( 'above-title' == $image_location )
229
- wpsp_post_image();
230
- }
231
- endif;
232
-
233
- if ( ! function_exists( 'wpsp_add_post_image_before_content' ) ) :
234
- add_action( 'wpsp_before_content','wpsp_add_post_image_before_content' );
235
- function wpsp_add_post_image_before_content()
236
- {
237
- global $wpsp_id;
238
-
239
- if ( ! isset( $wpsp_id ) )
240
- return;
241
-
242
- $image_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_location' ) );
243
-
244
- if ( 'below-title' == $image_location )
245
- wpsp_post_image();
246
- }
247
- endif;
248
-
249
- if ( ! function_exists( 'wpsp_read_more' ) ) :
250
- add_action( 'wpsp_after_content','wpsp_read_more', 5 );
251
- function wpsp_read_more()
252
- {
253
- global $wpsp_id;
254
-
255
- if ( ! isset( $wpsp_id ) )
256
- return;
257
-
258
- $read_more_text = wp_kses_post( wpsp_get_setting( $wpsp_id, 'wpsp_read_more_text' ) );
259
- $read_more_style = esc_attr( wpsp_get_setting( $wpsp_id, 'wpsp_read_more_style' ) );
260
- $read_more_color = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_read_more_color' ) );
261
-
262
- // The read more button
263
- if ( $read_more_text ) : ?>
264
- <div class="wpsp-read-more">
265
- <a title="<?php echo esc_attr( get_the_title() ); ?>" class="wp-show-posts-read-more <?php echo $read_more_style; ?> <?php echo $read_more_color; ?>" href="<?php esc_url( the_permalink() ); ?>"><?php echo $read_more_text; ?></a>
266
- </div>
267
- <?php endif;
268
- }
269
- endif;
270
-
271
- if ( ! function_exists( 'wpsp_hex2rgba' ) ) :
272
- /**
273
- * Convert hex to RGBA
274
- * @since 0.1
275
- */
276
- function wpsp_hex2rgba($color, $opacity = false) {
277
-
278
- $default = 'rgb(0,0,0)';
279
-
280
- // Return default if no color provided
281
- if(empty($color))
282
- return $default;
283
-
284
- // Sanitize $color if "#" is provided
285
- if ($color[0] == '#' ) {
286
- $color = substr( $color, 1 );
287
- }
288
-
289
- // Check if color has 6 or 3 characters and get values
290
- if (strlen($color) == 6) {
291
- $hex = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
292
- } elseif ( strlen( $color ) == 3 ) {
293
- $hex = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
294
- } else {
295
- return $default;
296
- }
297
-
298
- // Convert hexadec to rgb
299
- $rgb = array_map('hexdec', $hex);
300
-
301
- // Check if opacity is set(rgba or rgb)
302
- if($opacity){
303
- if(abs($opacity) > 1)
304
- $opacity = 1.0;
305
- $output = 'rgba('.implode(",",$rgb).','.$opacity.')';
306
- } else {
307
- $output = 'rgb('.implode(",",$rgb).')';
308
- }
309
-
310
- // Return rgb(a) color string
311
- return $output;
312
- }
313
- endif;
314
-
315
- if ( ! function_exists( 'wpsp_sanitize_hex_color' ) ) :
316
- function wpsp_sanitize_hex_color( $color ) {
317
- if ( '' === $color )
318
- return '';
319
-
320
- // 3 or 6 hex digits, or the empty string.
321
- if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) )
322
- return $color;
323
- }
324
- endif;
325
-
326
- if ( ! function_exists( 'wpsp_image_attributes' ) ) :
327
- /**
328
- * Build our image attributes
329
- * @since 0.1
330
- */
331
- function wpsp_image_attributes( $og_width = '', $og_height = '', $new_width = '', $new_height = '' )
332
- {
333
- $ignore_crop = array( '', '0', '9999' );
334
-
335
- $image_atts = array();
336
-
337
- $image_atts = array(
338
- 'width' => ( in_array( $new_width, $ignore_crop ) ) ? 9999 : intval( $new_width ),
339
- 'height' => ( in_array( $new_height, $ignore_crop ) ) ? 9999 : intval( $new_height ),
340
- 'crop' => ( in_array( $new_width, $ignore_crop ) || in_array( $new_height, $ignore_crop ) ) ? false : true
341
- );
342
-
343
- // If there's no height or width, empty the array
344
- if ( 9999 == $image_atts[ 'width' ] && 9999 == $image_atts[ 'height' ] )
345
- $image_atts = array();
346
-
347
- if ( ! empty( $image_atts ) ) :
348
- // Is our width larger than the OG image and not proportional?
349
- $width_upscale = $image_atts[ 'width' ] > $og_width && $image_atts[ 'width' ] < 9999 ? true : false;
350
-
351
- // Is our height larger than the OG image and not proportional?
352
- $height_upscale = $image_atts[ 'height' ] > $og_height && $image_atts[ 'height' ] < 9999 ? true : false;
353
-
354
- // If both the height and width are larger than the OG image, upscale
355
- $image_atts[ 'upscale' ] = $width_upscale && $height_upscale ? true : false;
356
-
357
- // If the width is larger than the OG image and the height isn't proportional, upscale
358
- $image_atts[ 'upscale' ] = $width_upscale && $image_atts[ 'height' ] < 9999 ? true : $image_atts[ 'upscale' ];
359
-
360
- // If the height is larger than the OG image and width isn't proportional, upscale
361
- $image_atts[ 'upscale' ] = $height_upscale && $image_atts[ 'width' ] < 9999 ? true : $image_atts[ 'upscale' ];
362
-
363
- // If we're upscaling, set crop to true
364
- $image_atts[ 'crop' ] = $image_atts[ 'upscale' ] ? true : $image_atts[ 'crop' ];
365
-
366
- // If one of our sizes is upscaling but the other is proportional, show the full image
367
- if ( $width_upscale && $image_atts[ 'height' ] == 9999 || $height_upscale && $image_atts[ 'width' ] == 9999 )
368
- $image_atts = array();
369
- endif;
370
-
371
- return apply_filters( 'generate_blog_image_attributes', $image_atts );
372
- }
373
- endif;
374
-
375
- if ( ! function_exists( 'wpsp_pagination' ) ) :
376
- /**
377
- * Build our regular pagination
378
- * @since 0.1
379
- */
380
- function wpsp_pagination( $max_num_pages ) {
381
- // Don't print empty markup if there's only one page.
382
- if ( $max_num_pages < 2 ) {
383
- return;
384
- }
385
-
386
- $paged_query = is_front_page() ? 'page' : 'paged';
387
- $paged = get_query_var( $paged_query ) ? intval( get_query_var( $paged_query ) ) : 1;
388
- $pagenum_link = html_entity_decode( get_pagenum_link() );
389
- $query_args = array();
390
- $url_parts = explode( '?', $pagenum_link );
391
-
392
- if ( isset( $url_parts[1] ) ) {
393
- wp_parse_str( $url_parts[1], $query_args );
394
- }
395
-
396
- $pagenum_link = remove_query_arg( array_keys( $query_args ), $pagenum_link );
397
- $pagenum_link = trailingslashit( $pagenum_link ) . '%_%';
398
-
399
- $format = $GLOBALS['wp_rewrite']->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
400
- $format .= $GLOBALS['wp_rewrite']->using_permalinks() ? user_trailingslashit( 'page/%#%', 'paged' ) : '?paged=%#%';
401
-
402
- // Set up paginated links.
403
- $links = paginate_links( array(
404
- 'base' => $pagenum_link,
405
- 'format' => $format,
406
- 'total' => $max_num_pages,
407
- 'current' => $paged,
408
- 'mid_size' => apply_filters( 'wpsp_pagination_mid_size', 1 ),
409
- 'add_args' => array_map( 'urlencode', $query_args ),
410
- 'prev_text' => __( '&larr; Previous', 'wp-show-posts' ),
411
- 'next_text' => __( 'Next &rarr;', 'wp-show-posts' ),
412
- ) );
413
-
414
- if ( $links ) :
415
-
416
- echo $links;
417
-
418
- endif;
419
- }
420
  endif;
1
+ <?php
2
+ // No direct access, please
3
+ if ( ! defined( 'ABSPATH' ) ) exit;
4
+
5
+ if ( ! function_exists( 'wpsp_meta' ) ) :
6
+ /**
7
+ * Build our post meta
8
+ * @since 0.1
9
+ */
10
+ function wpsp_meta( $location, $post_meta_style )
11
+ {
12
+ global $wpsp_id;
13
+
14
+ if ( ! isset( $wpsp_id ) )
15
+ return;
16
+
17
+ $author_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_author_location' ) );
18
+ $date_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_date_location' ) );
19
+ $include_author = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_author' ), FILTER_VALIDATE_BOOLEAN );
20
+ $include_terms = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_terms' ), FILTER_VALIDATE_BOOLEAN );
21
+ $include_date = filter_var( get_post_meta( $wpsp_id, 'wpsp_include_date', true ), FILTER_VALIDATE_BOOLEAN );
22
+ $terms_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_terms_location' ) );
23
+ $taxonomy = sanitize_key( wpsp_get_setting( $wpsp_id, 'wpsp_taxonomy' ) );
24
+
25
+ $output = array();
26
+ if ( ( $include_author && $location == $author_location ) || ( $include_date && $location == $date_location ) || ( $include_terms && $location == $terms_location ) )
27
+ echo '<div class="wp-show-posts-entry-meta wp-show-posts-entry-meta-' . $location . ' post-meta-' . $post_meta_style . '">';
28
+
29
+ // If our author is enabled, show it
30
+ if ( $include_author && $location == $author_location ) :
31
+ $output[] = sprintf( '<span class="wp-show-posts-byline wp-show-posts-meta">%1$s</span>',
32
+ sprintf( '<span class="wp-show-posts-author vcard" itemtype="http://schema.org/Person" itemscope="itemscope" itemprop="author"><a class="url fn n" href="%1$s" title="%2$s" rel="author" itemprop="url"><span class="author-name" itemprop="name">%3$s</span></a></span>',
33
+ esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ),
34
+ esc_attr( sprintf( __( 'View all posts by %s', 'wp-show-posts' ), get_the_author() ) ),
35
+ esc_html( get_the_author() )
36
+ )
37
+ );
38
+ endif;
39
+
40
+ // Show the date
41
+ if ( $include_date && $location == $date_location ) :
42
+ $time_string = '<time class="wp-show-posts-entry-date published" datetime="%1$s" itemprop="datePublished">%2$s</time>';
43
+ if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) )
44
+ $time_string .= '<time class="wp-show-posts-updated" datetime="%3$s" itemprop="dateModified">%4$s</time>';
45
+
46
+ $time_string = sprintf( $time_string,
47
+ esc_attr( get_the_date( 'c' ) ),
48
+ esc_html( get_the_date() ),
49
+ esc_attr( get_the_modified_date( 'c' ) ),
50
+ esc_html( get_the_modified_date() )
51
+ );
52
+
53
+ // If our date is enabled, show it
54
+ $output[] = sprintf( '<span class="wp-show-posts-posted-on wp-show-posts-meta">%1$s</span>',
55
+ sprintf( '<a href="%1$s" title="%2$s" rel="bookmark">%3$s</a>',
56
+ esc_url( get_permalink() ),
57
+ esc_attr( get_the_time() ),
58
+ $time_string
59
+ )
60
+ );
61
+ endif;
62
+
63
+ // Show the terms
64
+ if ( $include_terms && $location == $terms_location ) :
65
+ $output[] = sprintf( '<span class="wp-show-posts-terms wp-show-posts-meta">%1$s</span>',
66
+ get_the_term_list( get_the_ID(), $taxonomy, '', ', ' )
67
+ );
68
+ endif;
69
+
70
+ $separator = ( 'inline' == $post_meta_style ) ? ' <span class="wp-show-posts-separator">|</span> ' : '<br />';
71
+ echo implode( $separator, $output);
72
+
73
+ if ( ( $include_author && $location == $author_location ) || ( $include_date && $location == $date_location ) || ( $include_terms && $location == $terms_location ) )
74
+ echo '</div>';
75
+ }
76
+ endif;
77
+
78
+ if ( ! function_exists( 'wpsp_add_post_meta_after_title' ) ) :
79
+ add_action( 'wpsp_after_title','wpsp_add_post_meta_after_title' );
80
+ function wpsp_add_post_meta_after_title()
81
+ {
82
+ global $wpsp_id;
83
+
84
+ if ( ! isset( $wpsp_id ) )
85
+ return;
86
+
87
+ $author_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_author_location' ) );
88
+ $date_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_date_location' ) );
89
+ $terms_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_terms_location' ) );
90
+ $include_author = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_author' ), FILTER_VALIDATE_BOOLEAN );
91
+ $include_terms = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_terms' ), FILTER_VALIDATE_BOOLEAN );
92
+ $include_date = filter_var( get_post_meta( $wpsp_id, 'wpsp_include_date', true ), FILTER_VALIDATE_BOOLEAN );
93
+ $post_meta_top_style = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_post_meta_top_style' ) );
94
+
95
+ if ( ( $include_author && 'below-title' == $author_location ) || ( $include_date && 'below-title' == $date_location ) || ( $include_terms && 'below-title' == $terms_location ) )
96
+ wpsp_meta( 'below-title', $post_meta_top_style );
97
+
98
+ }
99
+ endif;
100
+
101
+ if ( ! function_exists( 'wpsp_add_post_meta_after_content' ) ) :
102
+ add_action( 'wpsp_after_content','wpsp_add_post_meta_after_content', 10 );
103
+ function wpsp_add_post_meta_after_content()
104
+ {
105
+ global $wpsp_id;
106
+
107
+ if ( ! isset( $wpsp_id ) )
108
+ return;
109
+
110
+ $author_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_author_location' ) );
111
+ $date_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_date_location' ) );
112
+ $terms_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_terms_location' ) );
113
+ $include_author = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_author' ), FILTER_VALIDATE_BOOLEAN );
114
+ $include_terms = filter_var( wpsp_get_setting( $wpsp_id, 'wpsp_include_terms' ), FILTER_VALIDATE_BOOLEAN );
115
+ $include_date = filter_var( get_post_meta( $wpsp_id, 'wpsp_include_date', true ), FILTER_VALIDATE_BOOLEAN );
116
+ $post_meta_bottom_style = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_post_meta_bottom_style' ) );
117
+
118
+ if ( ( $include_author && 'below-post' == $author_location ) || ( $include_date && 'below-post' == $date_location ) || ( $include_terms && 'below-post' == $terms_location ) )
119
+ wpsp_meta( 'below-post', $post_meta_bottom_style );
120
+ }
121
+ endif;
122
+
123
+ if ( ! function_exists( 'wpsp_post_image' ) ) :
124
+ /**
125
+ * Build our post image
126
+ * @since 0.1
127
+ */
128
+ function wpsp_post_image()
129
+ {
130
+ if ( ! has_post_thumbnail() )
131
+ return;
132
+
133
+ global $wpsp_id;
134
+
135
+ if ( ! isset( $wpsp_id ) )
136
+ return;
137
+
138
+ $image = sanitize_text_field( get_post_meta( $wpsp_id, 'wpsp_image', true ), FILTER_VALIDATE_BOOLEAN );
139
+ if ( ! isset( $image ) || ! $image )
140
+ return;
141
+
142
+ $image_alignment = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_alignment' ) );
143
+ $image_height = absint( wpsp_get_setting( $wpsp_id, 'wpsp_image_height' ) );
144
+ $image_width = absint( wpsp_get_setting( $wpsp_id, 'wpsp_image_width' ) );
145
+ $image_overlay_color = wpsp_sanitize_hex_color( wpsp_get_setting( $wpsp_id, 'wpsp_image_overlay_color' ) );
146
+ $image_overlay_icon = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_overlay_icon' ) );
147
+ $image_hover_effect = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_hover_effect' ) );
148
+ $columns = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_columns' ) );
149
+
150
+ $image_id = get_post_thumbnail_id( get_the_ID(), 'full' );
151
+ $image_url = wp_get_attachment_image_src( $image_id, 'full', true );
152
+ $image_atts = wpsp_image_attributes( $image_url[1], $image_url[2], $image_width, $image_height );
153
+ $hover = ( '' !== $image_hover_effect ) ? $image_hover_effect : '';
154
+ ?>
155
+ <div class="wp-show-posts-image <?php echo $hover . ' wpsp-image-' . $image_alignment; ?> ">
156
+ <?php printf( '<a href="%1$s" %2$s title="%3$s">',
157
+ apply_filters( 'wpsp_image_href', esc_url( get_the_permalink() ) ),
158
+ apply_filters( 'wpsp_image_data', '' ),
159
+ apply_filters( 'wpsp_image_title', esc_attr( get_the_title() ) )
160
+ ); ?>
161
+ <?php if ( ! empty( $image_atts ) ) : ?>
162
+ <img src="<?php echo WPSP_Resize( $image_url[0], $image_atts[ 'width' ], $image_atts[ 'height' ], $image_atts[ 'crop' ], true, $image_atts[ 'upscale' ] ); ?>" alt="<?php esc_attr( the_title() ); ?>" itemprop="image" class="<?php echo $image_alignment; ?>" />
163
+ <?php else :
164
+ the_post_thumbnail( apply_filters( 'wpsp_default_image_size', 'full' ), array( 'itemprop' => 'image' ) );
165
+ endif;
166
+
167
+ if ( '' !== $image_overlay_color || '' !== $image_overlay_icon ) :
168
+ $color = ( $image_overlay_color ) ? 'style="background-color:' . wpsp_hex2rgba( $image_overlay_color, apply_filters( 'wpsp_overlay_opacity', 0.7 ) ) . '"' : '';
169
+ $icon = ( $image_overlay_icon ) ? $image_overlay_icon : 'no-icon';
170
+ echo '<span class="wp-show-posts-image-overlay ' . $icon . '" ' . $color . '></span>';
171
+ endif;
172
+ ?>
173
+ </a>
174
+ </div>
175
+ <?php
176
+ }
177
+ endif;
178
+
179
+ if ( ! function_exists( 'wpsp_add_post_image_before_title' ) ) :
180
+ add_action( 'wpsp_before_header','wpsp_add_post_image_before_title' );
181
+ function wpsp_add_post_image_before_title()
182
+ {
183
+ global $wpsp_id;
184
+
185
+ if ( ! isset( $wpsp_id ) )
186
+ return;
187
+
188
+ $image_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_location' ) );
189
+
190
+ if ( 'above-title' == $image_location )
191
+ wpsp_post_image();
192
+ }
193
+ endif;
194
+
195
+ if ( ! function_exists( 'wpsp_add_post_image_before_content' ) ) :
196
+ add_action( 'wpsp_before_content','wpsp_add_post_image_before_content' );
197
+ function wpsp_add_post_image_before_content()
198
+ {
199
+ global $wpsp_id;
200
+
201
+ if ( ! isset( $wpsp_id ) )
202
+ return;
203
+
204
+ $image_location = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_image_location' ) );
205
+
206
+ if ( 'below-title' == $image_location )
207
+ wpsp_post_image();
208
+ }
209
+ endif;
210
+
211
+ if ( ! function_exists( 'wpsp_read_more' ) ) :
212
+ add_action( 'wpsp_after_content','wpsp_read_more', 5 );
213
+ function wpsp_read_more()
214
+ {
215
+ global $wpsp_id;
216
+
217
+ if ( ! isset( $wpsp_id ) )
218
+ return;
219
+
220
+ $read_more_text = wp_kses_post( wpsp_get_setting( $wpsp_id, 'wpsp_read_more_text' ) );
221
+ $read_more_style = esc_attr( wpsp_get_setting( $wpsp_id, 'wpsp_read_more_style' ) );
222
+ $read_more_color = sanitize_text_field( wpsp_get_setting( $wpsp_id, 'wpsp_read_more_color' ) );
223
+
224
+ // The read more button
225
+ if ( $read_more_text ) : ?>
226
+ <div class="wpsp-read-more">
227
+ <a title="<?php echo esc_attr( get_the_title() ); ?>" class="wp-show-posts-read-more <?php echo $read_more_style; ?> <?php echo $read_more_color; ?>" href="<?php esc_url( the_permalink() ); ?>"><?php echo $read_more_text; ?></a>
228
+ </div>
229
+ <?php endif;
230
+ }
231
+ endif;
232
+
233
+ if ( ! function_exists( 'wpsp_hex2rgba' ) ) :
234
+ /**
235
+ * Convert hex to RGBA
236
+ * @since 0.1
237
+ */
238
+ function wpsp_hex2rgba($color, $opacity = false) {
239
+
240
+ $default = 'rgb(0,0,0)';
241
+
242
+ // Return default if no color provided
243
+ if(empty($color))
244
+ return $default;
245
+
246
+ // Sanitize $color if "#" is provided
247
+ if ($color[0] == '#' ) {
248
+ $color = substr( $color, 1 );
249
+ }
250
+
251
+ // Check if color has 6 or 3 characters and get values
252
+ if (strlen($color) == 6) {
253
+ $hex = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
254
+ } elseif ( strlen( $color ) == 3 ) {
255
+ $hex = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
256
+ } else {
257
+ return $default;
258
+ }
259
+
260
+ // Convert hexadec to rgb
261
+ $rgb = array_map('hexdec', $hex);
262
+
263
+ // Check if opacity is set(rgba or rgb)
264
+ if($opacity){
265
+ if(abs($opacity) > 1)
266
+ $opacity = 1.0;
267
+ $output = 'rgba('.implode(",",$rgb).','.$opacity.')';
268
+ } else {
269
+ $output = 'rgb('.implode(",",$rgb).')';
270
+ }
271
+
272
+ // Return rgb(a) color string
273
+ return $output;
274
+ }
275
+ endif;
276
+
277
+ if ( ! function_exists( 'wpsp_sanitize_hex_color' ) ) :
278
+ function wpsp_sanitize_hex_color( $color ) {
279
+ if ( '' === $color )
280
+ return '';
281
+
282
+ // 3 or 6 hex digits, or the empty string.
283
+ if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) )
284
+ return $color;
285
+ }
286
+ endif;
287
+
288
+ if ( ! function_exists( 'wpsp_image_attributes' ) ) :
289
+ /**
290
+ * Build our image attributes
291
+ * @since 0.1
292
+ */
293
+ function wpsp_image_attributes( $og_width = '', $og_height = '', $new_width = '', $new_height = '' )
294
+ {
295
+ $ignore_crop = array( '', '0', '9999' );
296
+
297
+ $image_atts = array();
298
+
299
+ $image_atts = array(
300
+ 'width' => ( in_array( $new_width, $ignore_crop ) ) ? 9999 : intval( $new_width ),
301
+ 'height' => ( in_array( $new_height, $ignore_crop ) ) ? 9999 : intval( $new_height ),
302
+ 'crop' => ( in_array( $new_width, $ignore_crop ) || in_array( $new_height, $ignore_crop ) ) ? false : true
303
+ );
304
+
305
+ // If there's no height or width, empty the array
306
+ if ( 9999 == $image_atts[ 'width' ] && 9999 == $image_atts[ 'height' ] )
307
+ $image_atts = array();
308
+
309
+ if ( ! empty( $image_atts ) ) :
310
+ // Is our width larger than the OG image and not proportional?
311
+ $width_upscale = $image_atts[ 'width' ] > $og_width && $image_atts[ 'width' ] < 9999 ? true : false;
312
+
313
+ // Is our height larger than the OG image and not proportional?
314
+ $height_upscale = $image_atts[ 'height' ] > $og_height && $image_atts[ 'height' ] < 9999 ? true : false;
315
+
316
+ // If both the height and width are larger than the OG image, upscale
317
+ $image_atts[ 'upscale' ] = $width_upscale && $height_upscale ? true : false;
318
+
319
+ // If the width is larger than the OG image and the height isn't proportional, upscale
320
+ $image_atts[ 'upscale' ] = $width_upscale && $image_atts[ 'height' ] < 9999 ? true : $image_atts[ 'upscale' ];
321
+
322
+ // If the height is larger than the OG image and width isn't proportional, upscale
323
+ $image_atts[ 'upscale' ] = $height_upscale && $image_atts[ 'width' ] < 9999 ? true : $image_atts[ 'upscale' ];
324
+
325
+ // If we're upscaling, set crop to true
326
+ $image_atts[ 'crop' ] = $image_atts[ 'upscale' ] ? true : $image_atts[ 'crop' ];
327
+
328
+ // If one of our sizes is upscaling but the other is proportional, show the full image
329
+ if ( $width_upscale && $image_atts[ 'height' ] == 9999 || $height_upscale && $image_atts[ 'width' ] == 9999 )
330
+ $image_atts = array();
331
+ endif;
332
+
333
+ return apply_filters( 'generate_blog_image_attributes', $image_atts );
334
+ }
335
+ endif;
336
+
337
+ if ( ! function_exists( 'wpsp_pagination' ) ) :
338
+ /**
339
+ * Build our regular pagination
340
+ * @since 0.1
341
+ */
342
+ function wpsp_pagination( $max_num_pages ) {
343
+ // Don't print empty markup if there's only one page.
344
+ if ( $max_num_pages < 2 ) {
345
+ return;
346
+ }
347
+
348
+ $paged_query = is_front_page() ? 'page' : 'paged';
349
+ $paged = get_query_var( $paged_query ) ? intval( get_query_var( $paged_query ) ) : 1;
350
+ $pagenum_link = html_entity_decode( get_pagenum_link() );
351
+ $query_args = array();
352
+ $url_parts = explode( '?', $pagenum_link );
353
+
354
+ if ( isset( $url_parts[1] ) ) {
355
+ wp_parse_str( $url_parts[1], $query_args );
356
+ }
357
+
358
+ $pagenum_link = remove_query_arg( array_keys( $query_args ), $pagenum_link );
359
+ $pagenum_link = trailingslashit( $pagenum_link ) . '%_%';
360
+
361
+ $format = $GLOBALS['wp_rewrite']->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
362
+ $format .= $GLOBALS['wp_rewrite']->using_permalinks() ? user_trailingslashit( 'page/%#%', 'paged' ) : '?paged=%#%';
363
+
364
+ // Set up paginated links.
365
+ $links = paginate_links( array(
366
+ 'base' => $pagenum_link,
367
+ 'format' => $format,
368
+ 'total' => $max_num_pages,
369
+ 'current' => $paged,
370
+ 'mid_size' => apply_filters( 'wpsp_pagination_mid_size', 1 ),
371
+ 'add_args' => array_map( 'urlencode', $query_args ),
372
+ 'prev_text' => __( '&larr; Previous', 'wp-show-posts' ),
373
+ 'next_text' => __( 'Next &rarr;', 'wp-show-posts' ),
374
+ ) );
375
+
376
+ if ( $links ) :
377
+
378
+ echo $links;
379
+
380
+ endif;
381
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  endif;
inc/image-resizer.php CHANGED
@@ -1,241 +1,244 @@
1
- <?php
2
- /**
3
- * Title : Aqua Resizer
4
- * Description : Resizes WordPress images on the fly
5
- * Version : 1.2.1
6
- * Author : Syamil MJ
7
- * Author URI : http://aquagraphite.com
8
- * License : WTFPL - http://sam.zoy.org/wtfpl/
9
- * Documentation : https://github.com/sy4mil/Aqua-Resizer/
10
- *
11
- * @param string $url - (required) must be uploaded using wp media uploader
12
- * @param int $width - (required)
13
- * @param int $height - (optional)
14
- * @param bool $crop - (optional) default to soft crop
15
- * @param bool $single - (optional) returns an array if false
16
- * @param bool $upscale - (optional) resizes smaller images
17
- * @uses wp_upload_dir()
18
- * @uses image_resize_dimensions()
19
- * @uses wp_get_image_editor()
20
- *
21
- * @return str|array
22
- */
23
-
24
- if( ! class_exists( 'WPSP_Resize' ) ) {
25
- class WPSP_Exception extends Exception {}
26
-
27
- class WPSP_Resize
28
- {
29
- /**
30
- * The singleton instance
31
- */
32
- static private $instance = null;
33
-
34
- /**
35
- * Should an WPSP_Exception be thrown on error?
36
- * If false (default), then the error will just be logged.
37
- */
38
- public $throwOnError = false;
39
-
40
- /**
41
- * No initialization allowed
42
- */
43
- private function __construct() {}
44
-
45
- /**
46
- * No cloning allowed
47
- */
48
- private function __clone() {}
49
-
50
- /**
51
- * For your custom default usage you may want to initialize an WPSP_Resize object by yourself and then have own defaults
52
- */
53
- static public function getInstance() {
54
- if(self::$instance == null) {
55
- self::$instance = new self;
56
- }
57
-
58
- return self::$instance;
59
- }
60
-
61
- /**
62
- * Run, forest.
63
- */
64
- public function process( $url, $width = null, $height = null, $crop = null, $single = true, $upscale = false ) {
65
- try {
66
- // Validate inputs.
67
- if (!$url)
68
- throw new WPSP_Exception('$url parameter is required');
69
- if (!$width)
70
- throw new WPSP_Exception('$width parameter is required');
71
- if (!$height)
72
- throw new WPSP_Exception('$height parameter is required');
73
-
74
- // Caipt'n, ready to hook.
75
- if ( true === $upscale ) add_filter( 'image_resize_dimensions', array($this, 'WPSP_upscale'), 10, 6 );
76
-
77
- // Define upload path & dir.
78
- $upload_info = wp_upload_dir();
79
- $upload_dir = $upload_info['basedir'];
80
- $upload_url = $upload_info['baseurl'];
81
-
82
- $http_prefix = "http://";
83
- $https_prefix = "https://";
84
- $relative_prefix = "//"; // The protocol-relative URL
85
-
86
- /* if the $url scheme differs from $upload_url scheme, make them match
87
- if the schemes differe, images don't show up. */
88
- if(!strncmp($url,$https_prefix,strlen($https_prefix))){ //if url begins with https:// make $upload_url begin with https:// as well
89
- $upload_url = str_replace($http_prefix,$https_prefix,$upload_url);
90
- }
91
- elseif(!strncmp($url,$http_prefix,strlen($http_prefix))){ //if url begins with http:// make $upload_url begin with http:// as well
92
- $upload_url = str_replace($https_prefix,$http_prefix,$upload_url);
93
- }
94
- elseif(!strncmp($url,$relative_prefix,strlen($relative_prefix))){ //if url begins with // make $upload_url begin with // as well
95
- $upload_url = str_replace(array( 0 => "$http_prefix", 1 => "$https_prefix"),$relative_prefix,$upload_url);
96
- }
97
-
98
-
99
- // Check if $img_url is local.
100
- if ( false === strpos( $url, $upload_url ) )
101
- throw new WPSP_Exception('Image must be local: ' . $url);
102
-
103
- // Define path of image.
104
- $rel_path = str_replace( $upload_url, '', $url );
105
- $img_path = $upload_dir . $rel_path;
106
-
107
- // Check if img path exists, and is an image indeed.
108
- if ( ! file_exists( $img_path ) or ! getimagesize( $img_path ) )
109
- throw new WPSP_Exception('Image file does not exist (or is not an image): ' . $img_path);
110
-
111
- // Get image info.
112
- $info = pathinfo( $img_path );
113
- $ext = $info['extension'];
114
- list( $orig_w, $orig_h ) = getimagesize( $img_path );
115
-
116
- // Get image size after cropping.
117
- $dims = image_resize_dimensions( $orig_w, $orig_h, $width, $height, $crop );
118
- $dst_w = $dims[4];
119
- $dst_h = $dims[5];
120
-
121
- // Return the original image only if it exactly fits the needed measures.
122
- if ( ! $dims && ( ( ( null === $height && $orig_w == $width ) xor ( null === $width && $orig_h == $height ) ) xor ( $height == $orig_h && $width == $orig_w ) ) ) {
123
- $img_url = $url;
124
- $dst_w = $orig_w;
125
- $dst_h = $orig_h;
126
- } else {
127
- // Use this to check if cropped image already exists, so we can return that instead.
128
- $suffix = "{$dst_w}x{$dst_h}";
129
- $dst_rel_path = str_replace( '.' . $ext, '', $rel_path );
130
- $destfilename = "{$upload_dir}{$dst_rel_path}-{$suffix}.{$ext}";
131
-
132
- if ( ! $dims || ( true == $crop && false == $upscale && ( $dst_w < $width || $dst_h < $height ) ) ) {
133
- // Can't resize, so return false saying that the action to do could not be processed as planned.
134
- throw new WPSP_Exception('Unable to resize image because image_resize_dimensions() failed');
135
- }
136
- // Else check if cache exists.
137
- elseif ( file_exists( $destfilename ) && getimagesize( $destfilename ) ) {
138
- $img_url = "{$upload_url}{$dst_rel_path}-{$suffix}.{$ext}";
139
- }
140
- // Else, we resize the image and return the new resized image url.
141
- else {
142
-
143
- $editor = wp_get_image_editor( $img_path );
144
-
145
- if ( is_wp_error( $editor ) || is_wp_error( $editor->resize( $width, $height, $crop ) ) ) {
146
- throw new WPSP_Exception('Unable to get WP_Image_Editor: ' .
147
- $editor->get_error_message() . ' (is GD or ImageMagick installed?)');
148
- }
149
-
150
- $resized_file = $editor->save();
151
-
152
- if ( ! is_wp_error( $resized_file ) ) {
153
- $resized_rel_path = str_replace( $upload_dir, '', $resized_file['path'] );
154
- $img_url = $upload_url . $resized_rel_path;
155
- } else {
156
- throw new WPSP_Exception('Unable to save resized image file: ' . $editor->get_error_message());
157
- }
158
-
159
- }
160
- }
161
-
162
- // Okay, leave the ship.
163
- if ( true === $upscale ) remove_filter( 'image_resize_dimensions', array( $this, 'WPSP_upscale' ) );
164
-
165
- // Return the output.
166
- if ( $single ) {
167
- // str return.
168
- $image = $img_url;
169
- } else {
170
- // array return.
171
- $image = array (
172
- 0 => $img_url,
173
- 1 => $dst_w,
174
- 2 => $dst_h
175
- );
176
- }
177
-
178
- return $image;
179
- }
180
- catch (WPSP_Exception $ex) {
181
- error_log('WPSP_Resize.process() error: ' . $ex->getMessage());
182
-
183
- if ($this->throwOnError) {
184
- // Bubble up exception.
185
- throw $ex;
186
- }
187
- else {
188
- // Return false, so that this patch is backwards-compatible.
189
- return false;
190
- }
191
- }
192
- }
193
-
194
- /**
195
- * Callback to overwrite WP computing of thumbnail measures
196
- */
197
- function WPSP_upscale( $default, $orig_w, $orig_h, $dest_w, $dest_h, $crop ) {
198
- if ( ! $crop ) return null; // Let the wordpress default function handle this.
199
- // Here is the point we allow to use larger image size than the original one.
200
- $aspect_ratio = $orig_w / $orig_h;
201
- $new_w = $dest_w;
202
- $new_h = $dest_h;
203
- if ( ! $new_w ) {
204
- $new_w = intval( $new_h * $aspect_ratio );
205
- }
206
- if ( ! $new_h ) {
207
- $new_h = intval( $new_w / $aspect_ratio );
208
- }
209
- $size_ratio = max( $new_w / $orig_w, $new_h / $orig_h );
210
- $crop_w = round( $new_w / $size_ratio );
211
- $crop_h = round( $new_h / $size_ratio );
212
- $s_x = floor( ( $orig_w - $crop_w ) / 2 );
213
- $s_y = floor( ( $orig_h - $crop_h ) / 2 );
214
- return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );
215
- }
216
- }
217
- }
218
-
219
- if ( ! function_exists( 'WPSP_Resize' ) ) :
220
- /**
221
- * This is just a tiny wrapper function for the class above so that there is no
222
- * need to change any code in your own WP themes. Usage is still the same :)
223
- */
224
- function WPSP_Resize( $url, $width = null, $height = null, $crop = null, $single = true, $upscale = false ) {
225
- /* WPML Fix */
226
- if ( defined( 'ICL_SITEPRESS_VERSION' ) ){
227
- global $sitepress;
228
- $url = $sitepress->convert_url( $url, $sitepress->get_default_language() );
229
- }
230
-
231
- /* Jetpack Photon fix */
232
- if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'photon' ) && function_exists( 'jetpack_photon_url' ) ) {
233
- $type = ( $crop ) ? 'resize' : 'fit';
234
- $args = array( $type => $width . ',' . $height );
235
- return jetpack_photon_url( $url, $args );
236
- }
237
-
238
- $WPSP_Resize = WPSP_Resize::getInstance();
239
- return $WPSP_Resize->process( $url, $width, $height, $crop, $single, $upscale );
240
- }
 
 
 
241
  endif;
1
+ <?php
2
+ /**
3
+ * Title : Aqua Resizer
4
+ * Description : Resizes WordPress images on the fly
5
+ * Version : 1.2.1
6
+ * Author : Syamil MJ
7
+ * Author URI : http://aquagraphite.com
8
+ * License : WTFPL - http://sam.zoy.org/wtfpl/
9
+ * Documentation : https://github.com/sy4mil/Aqua-Resizer/
10
+ *
11
+ * @param string $url - (required) must be uploaded using wp media uploader
12
+ * @param int $width - (required)
13
+ * @param int $height - (optional)
14
+ * @param bool $crop - (optional) default to soft crop
15
+ * @param bool $single - (optional) returns an array if false
16
+ * @param bool $upscale - (optional) resizes smaller images
17
+ * @uses wp_upload_dir()
18
+ * @uses image_resize_dimensions()
19
+ * @uses wp_get_image_editor()
20
+ *
21
+ * @return str|array
22
+ */
23
+
24
+ // No direct access, please
25
+ if ( ! defined( 'ABSPATH' ) ) exit;
26
+
27
+ if( ! class_exists( 'WPSP_Resize' ) ) {
28
+ class WPSP_Exception extends Exception {}
29
+
30
+ class WPSP_Resize
31
+ {
32
+ /**
33
+ * The singleton instance
34
+ */
35
+ static private $instance = null;
36
+
37
+ /**
38
+ * Should an WPSP_Exception be thrown on error?
39
+ * If false (default), then the error will just be logged.
40
+ */
41
+ public $throwOnError = false;
42
+
43
+ /**
44
+ * No initialization allowed
45
+ */
46
+ private function __construct() {}
47
+
48
+ /**
49
+ * No cloning allowed
50
+ */
51
+ private function __clone() {}
52
+
53
+ /**
54
+ * For your custom default usage you may want to initialize an WPSP_Resize object by yourself and then have own defaults
55
+ */
56
+ static public function getInstance() {
57
+ if(self::$instance == null) {
58
+ self::$instance = new self;
59
+ }
60
+
61
+ return self::$instance;
62
+ }
63
+
64
+ /**
65
+ * Run, forest.
66
+ */
67
+ public function process( $url, $width = null, $height = null, $crop = null, $single = true, $upscale = false ) {
68
+ try {
69
+ // Validate inputs.
70
+ if (!$url)
71
+ throw new WPSP_Exception('$url parameter is required');
72
+ if (!$width)
73
+ throw new WPSP_Exception('$width parameter is required');
74
+ if (!$height)
75
+ throw new WPSP_Exception('$height parameter is required');
76
+
77
+ // Caipt'n, ready to hook.
78
+ if ( true === $upscale ) add_filter( 'image_resize_dimensions', array($this, 'WPSP_upscale'), 10, 6 );
79
+
80
+ // Define upload path & dir.
81
+ $upload_info = wp_upload_dir();
82
+ $upload_dir = $upload_info['basedir'];
83
+ $upload_url = $upload_info['baseurl'];
84
+
85
+ $http_prefix = "http://";
86
+ $https_prefix = "https://";
87
+ $relative_prefix = "//"; // The protocol-relative URL
88
+
89
+ /* if the $url scheme differs from $upload_url scheme, make them match
90
+ if the schemes differe, images don't show up. */
91
+ if(!strncmp($url,$https_prefix,strlen($https_prefix))){ //if url begins with https:// make $upload_url begin with https:// as well
92
+ $upload_url = str_replace($http_prefix,$https_prefix,$upload_url);
93
+ }
94
+ elseif(!strncmp($url,$http_prefix,strlen($http_prefix))){ //if url begins with http:// make $upload_url begin with http:// as well
95
+ $upload_url = str_replace($https_prefix,$http_prefix,$upload_url);
96
+ }
97
+ elseif(!strncmp($url,$relative_prefix,strlen($relative_prefix))){ //if url begins with // make $upload_url begin with // as well
98
+ $upload_url = str_replace(array( 0 => "$http_prefix", 1 => "$https_prefix"),$relative_prefix,$upload_url);
99
+ }
100
+
101
+
102
+ // Check if $img_url is local.
103
+ if ( false === strpos( $url, $upload_url ) )
104
+ throw new WPSP_Exception('Image must be local: ' . $url);
105
+
106
+ // Define path of image.
107
+ $rel_path = str_replace( $upload_url, '', $url );
108
+ $img_path = $upload_dir . $rel_path;
109
+
110
+ // Check if img path exists, and is an image indeed.
111
+ if ( ! file_exists( $img_path ) or ! getimagesize( $img_path ) )
112
+ throw new WPSP_Exception('Image file does not exist (or is not an image): ' . $img_path);
113
+
114
+ // Get image info.
115
+ $info = pathinfo( $img_path );
116
+ $ext = $info['extension'];
117
+ list( $orig_w, $orig_h ) = getimagesize( $img_path );
118
+
119
+ // Get image size after cropping.
120
+ $dims = image_resize_dimensions( $orig_w, $orig_h, $width, $height, $crop );
121
+ $dst_w = $dims[4];
122
+ $dst_h = $dims[5];
123
+
124
+ // Return the original image only if it exactly fits the needed measures.
125
+ if ( ! $dims && ( ( ( null === $height && $orig_w == $width ) xor ( null === $width && $orig_h == $height ) ) xor ( $height == $orig_h && $width == $orig_w ) ) ) {
126
+ $img_url = $url;
127
+ $dst_w = $orig_w;
128
+ $dst_h = $orig_h;
129
+ } else {
130
+ // Use this to check if cropped image already exists, so we can return that instead.
131
+ $suffix = "{$dst_w}x{$dst_h}";
132
+ $dst_rel_path = str_replace( '.' . $ext, '', $rel_path );
133
+ $destfilename = "{$upload_dir}{$dst_rel_path}-{$suffix}.{$ext}";
134
+
135
+ if ( ! $dims || ( true == $crop && false == $upscale && ( $dst_w < $width || $dst_h < $height ) ) ) {
136
+ // Can't resize, so return false saying that the action to do could not be processed as planned.
137
+ throw new WPSP_Exception('Unable to resize image because image_resize_dimensions() failed');
138
+ }
139
+ // Else check if cache exists.
140
+ elseif ( file_exists( $destfilename ) && getimagesize( $destfilename ) ) {
141
+ $img_url = "{$upload_url}{$dst_rel_path}-{$suffix}.{$ext}";
142
+ }
143
+ // Else, we resize the image and return the new resized image url.
144
+ else {
145
+
146
+ $editor = wp_get_image_editor( $img_path );
147
+
148
+ if ( is_wp_error( $editor ) || is_wp_error( $editor->resize( $width, $height, $crop ) ) ) {
149
+ throw new WPSP_Exception('Unable to get WP_Image_Editor: ' .
150
+ $editor->get_error_message() . ' (is GD or ImageMagick installed?)');
151
+ }
152
+
153
+ $resized_file = $editor->save();
154
+
155
+ if ( ! is_wp_error( $resized_file ) ) {
156
+ $resized_rel_path = str_replace( $upload_dir, '', $resized_file['path'] );
157
+ $img_url = $upload_url . $resized_rel_path;
158
+ } else {
159
+ throw new WPSP_Exception('Unable to save resized image file: ' . $editor->get_error_message());
160
+ }
161
+
162
+ }
163
+ }
164
+
165
+ // Okay, leave the ship.
166
+ if ( true === $upscale ) remove_filter( 'image_resize_dimensions', array( $this, 'WPSP_upscale' ) );
167
+
168
+ // Return the output.
169
+ if ( $single ) {
170
+ // str return.
171
+ $image = $img_url;
172
+ } else {
173
+ // array return.
174
+ $image = array (
175
+ 0 => $img_url,
176
+ 1 => $dst_w,
177
+ 2 => $dst_h
178
+ );
179
+ }
180
+
181
+ return $image;
182
+ }
183
+ catch (WPSP_Exception $ex) {
184
+ error_log('WPSP_Resize.process() error: ' . $ex->getMessage());
185
+
186
+ if ($this->throwOnError) {
187
+ // Bubble up exception.
188
+ throw $ex;
189
+ }
190
+ else {
191
+ // Return false, so that this patch is backwards-compatible.
192
+ return false;
193
+ }
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Callback to overwrite WP computing of thumbnail measures
199
+ */
200
+ function WPSP_upscale( $default, $orig_w, $orig_h, $dest_w, $dest_h, $crop ) {
201
+ if ( ! $crop ) return null; // Let the wordpress default function handle this.
202
+ // Here is the point we allow to use larger image size than the original one.
203
+ $aspect_ratio = $orig_w / $orig_h;
204
+ $new_w = $dest_w;
205
+ $new_h = $dest_h;
206
+ if ( ! $new_w ) {
207
+ $new_w = intval( $new_h * $aspect_ratio );
208
+ }
209
+ if ( ! $new_h ) {
210
+ $new_h = intval( $new_w / $aspect_ratio );
211
+ }
212
+ $size_ratio = max( $new_w / $orig_w, $new_h / $orig_h );
213
+ $crop_w = round( $new_w / $size_ratio );
214
+ $crop_h = round( $new_h / $size_ratio );
215
+ $s_x = floor( ( $orig_w - $crop_w ) / 2 );
216
+ $s_y = floor( ( $orig_h - $crop_h ) / 2 );
217
+ return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );
218
+ }
219
+ }
220
+ }
221
+
222
+ if ( ! function_exists( 'WPSP_Resize' ) ) :
223
+ /**
224
+ * This is just a tiny wrapper function for the class above so that there is no
225
+ * need to change any code in your own WP themes. Usage is still the same :)
226
+ */
227
+ function WPSP_Resize( $url, $width = null, $height = null, $crop = null, $single = true, $upscale = false ) {
228
+ /* WPML Fix */
229
+ if ( defined( 'ICL_SITEPRESS_VERSION' ) ){
230
+ global $sitepress;
231
+ $url = $sitepress->convert_url( $url, $sitepress->get_default_language() );
232
+ }
233
+
234
+ /* Jetpack Photon fix */
235
+ if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'photon' ) && function_exists( 'jetpack_photon_url' ) ) {
236
+ $type = ( $crop ) ? 'resize' : 'fit';
237
+ $args = array( $type => $width . ',' . $height );
238
+ return jetpack_photon_url( $url, $args );
239
+ }
240
+
241
+ $WPSP_Resize = WPSP_Resize::getInstance();
242
+ return $WPSP_Resize->process( $url, $width, $height, $crop, $single, $upscale );
243
+ }
244
  endif;
js/jquery.matchHeight.js CHANGED
@@ -1,399 +1,399 @@
1
- /**
2
- * jquery-match-height master by @liabru
3
- * http://brm.io/jquery-match-height/
4
- * License: MIT
5
- */
6
-
7
- ;(function(factory) { // eslint-disable-line no-extra-semi
8
- 'use strict';
9
- if (typeof define === 'function' && define.amd) {
10
- // AMD
11
- define(['jquery'], factory);
12
- } else if (typeof module !== 'undefined' && module.exports) {
13
- // CommonJS
14
- module.exports = factory(require('jquery'));
15
- } else {
16
- // Global
17
- factory(jQuery);
18
- }
19
- })(function($) {
20
- /*
21
- * internal
22
- */
23
-
24
- var _previousResizeWidth = -1,
25
- _updateTimeout = -1;
26
-
27
- /*
28
- * _parse
29
- * value parse utility function
30
- */
31
-
32
- var _parse = function(value) {
33
- // parse value and convert NaN to 0
34
- return parseFloat(value) || 0;
35
- };
36
-
37
- /*
38
- * _rows
39
- * utility function returns array of jQuery selections representing each row
40
- * (as displayed after float wrapping applied by browser)
41
- */
42
-
43
- var _rows = function(elements) {
44
- var tolerance = 1,
45
- $elements = $(elements),
46
- lastTop = null,
47
- rows = [];
48
-
49
- // group elements by their top position
50
- $elements.each(function(){
51
- var $that = $(this),
52
- top = $that.offset().top - _parse($that.css('margin-top')),
53
- lastRow = rows.length > 0 ? rows[rows.length - 1] : null;
54
-
55
- if (lastRow === null) {
56
- // first item on the row, so just push it
57
- rows.push($that);
58
- } else {
59
- // if the row top is the same, add to the row group
60
- if (Math.floor(Math.abs(lastTop - top)) <= tolerance) {
61
- rows[rows.length - 1] = lastRow.add($that);
62
- } else {
63
- // otherwise start a new row group
64
- rows.push($that);
65
- }
66
- }
67
-
68
- // keep track of the last row top
69
- lastTop = top;
70
- });
71
-
72
- return rows;
73
- };
74
-
75
- /*
76
- * _parseOptions
77
- * handle plugin options
78
- */
79
-
80
- var _parseOptions = function(options) {
81
- var opts = {
82
- byRow: true,
83
- property: 'height',
84
- target: null,
85
- remove: false
86
- };
87
-
88
- if (typeof options === 'object') {
89
- return $.extend(opts, options);
90
- }
91
-
92
- if (typeof options === 'boolean') {
93
- opts.byRow = options;
94
- } else if (options === 'remove') {
95
- opts.remove = true;
96
- }
97
-
98
- return opts;
99
- };
100
-
101
- /*
102
- * matchHeight
103
- * plugin definition
104
- */
105
-
106
- var matchHeight = $.fn.matchHeight = function(options) {
107
- var opts = _parseOptions(options);
108
-
109
- // handle remove
110
- if (opts.remove) {
111
- var that = this;
112
-
113
- // remove fixed height from all selected elements
114
- this.css(opts.property, '');
115
-
116
- // remove selected elements from all groups
117
- $.each(matchHeight._groups, function(key, group) {
118
- group.elements = group.elements.not(that);
119
- });
120
-
121
- // TODO: cleanup empty groups
122
-
123
- return this;
124
- }
125
-
126
- if (this.length <= 1 && !opts.target) {
127
- return this;
128
- }
129
-
130
- // keep track of this group so we can re-apply later on load and resize events
131
- matchHeight._groups.push({
132
- elements: this,
133
- options: opts
134
- });
135
-
136
- // match each element's height to the tallest element in the selection
137
- matchHeight._apply(this, opts);
138
-
139
- return this;
140
- };
141
-
142
- /*
143
- * plugin global options
144
- */
145
-
146
- matchHeight.version = 'master';
147
- matchHeight._groups = [];
148
- matchHeight._throttle = 80;
149
- matchHeight._maintainScroll = false;
150
- matchHeight._beforeUpdate = null;
151
- matchHeight._afterUpdate = null;
152
- matchHeight._rows = _rows;
153
- matchHeight._parse = _parse;
154
- matchHeight._parseOptions = _parseOptions;
155
-
156
- /*
157
- * matchHeight._apply
158
- * apply matchHeight to given elements
159
- */
160
-
161
- matchHeight._apply = function(elements, options) {
162
- var opts = _parseOptions(options),
163
- $elements = $(elements),
164
- rows = [$elements];
165
-
166
- // take note of scroll position
167
- var scrollTop = $(window).scrollTop(),
168
- htmlHeight = $('html').outerHeight(true);
169
-
170
- // get hidden parents
171
- var $hiddenParents = $elements.parents().filter(':hidden');
172
-
173
- // cache the original inline style
174
- $hiddenParents.each(function() {
175
- var $that = $(this);
176
- $that.data('style-cache', $that.attr('style'));
177
- });
178
-
179
- // temporarily must force hidden parents visible
180
- $hiddenParents.css('display', 'block');
181
-
182
- // get rows if using byRow, otherwise assume one row
183
- if (opts.byRow && !opts.target) {
184
-
185
- // must first force an arbitrary equal height so floating elements break evenly
186
- $elements.each(function() {
187
- var $that = $(this),
188
- display = $that.css('display');
189
-
190
- // temporarily force a usable display value
191
- if (display !== 'inline-block' && display !== 'flex' && display !== 'inline-flex') {
192
- display = 'block';
193
- }
194
-
195
- // cache the original inline style
196
- $that.data('style-cache', $that.attr('style'));
197
-
198
- $that.css({
199
- 'display': display,
200
- 'padding-top': '0',
201
- 'padding-bottom': '0',
202
- 'margin-top': '0',
203
- 'margin-bottom': '0',
204
- 'border-top-width': '0',
205
- 'border-bottom-width': '0',
206
- 'height': '100px',
207
- 'overflow': 'hidden'
208
- });
209
- });
210
-
211
- // get the array of rows (based on element top position)
212
- rows = _rows($elements);
213
-
214
- // revert original inline styles
215
- $elements.each(function() {
216
- var $that = $(this);
217
- $that.attr('style', $that.data('style-cache') || '');
218
- });
219
- }
220
-
221
- $.each(rows, function(key, row) {
222
- var $row = $(row),
223
- targetHeight = 0;
224
-
225
- if (!opts.target) {
226
- // skip apply to rows with only one item
227
- if (opts.byRow && $row.length <= 1) {
228
- $row.css(opts.property, '');
229
- return;
230
- }
231
-
232
- // iterate the row and find the max height
233
- $row.each(function(){
234
- var $that = $(this),
235
- style = $that.attr('style'),
236
- display = $that.css('display');
237
-
238
- // temporarily force a usable display value
239
- if (display !== 'inline-block' && display !== 'flex' && display !== 'inline-flex') {
240
- display = 'block';
241
- }
242
-
243
- // ensure we get the correct actual height (and not a previously set height value)
244
- var css = { 'display': display };
245
- css[opts.property] = '';
246
- $that.css(css);
247
-
248
- // find the max height (including padding, but not margin)
249
- if ($that.outerHeight(false) > targetHeight) {
250
- targetHeight = $that.outerHeight(false);
251
- }
252
-
253
- // revert styles
254
- if (style) {
255
- $that.attr('style', style);
256
- } else {
257
- $that.css('display', '');
258
- }
259
- });
260
- } else {
261
- // if target set, use the height of the target element
262
- targetHeight = opts.target.outerHeight(false);
263
- }
264
-
265
- // iterate the row and apply the height to all elements
266
- $row.each(function(){
267
- var $that = $(this),
268
- verticalPadding = 0;
269
-
270
- // don't apply to a target
271
- if (opts.target && $that.is(opts.target)) {
272
- return;
273
- }
274
-
275
- // handle padding and border correctly (required when not using border-box)
276
- if ($that.css('box-sizing') !== 'border-box') {
277
- verticalPadding += _parse($that.css('border-top-width')) + _parse($that.css('border-bottom-width'));
278
- verticalPadding += _parse($that.css('padding-top')) + _parse($that.css('padding-bottom'));
279
- }
280
-
281
- // set the height (accounting for padding and border)
282
- $that.css(opts.property, (targetHeight - verticalPadding) + 'px');
283
- });
284
- });
285
-
286
- // revert hidden parents
287
- $hiddenParents.each(function() {
288
- var $that = $(this);
289
- $that.attr('style', $that.data('style-cache') || null);
290
- });
291
-
292
- // restore scroll position if enabled
293
- if (matchHeight._maintainScroll) {
294
- $(window).scrollTop((scrollTop / htmlHeight) * $('html').outerHeight(true));
295
- }
296
-
297
- return this;
298
- };
299
-
300
- /*
301
- * matchHeight._applyDataApi
302
- * applies matchHeight to all elements with a data-match-height attribute
303
- */
304
-
305
- matchHeight._applyDataApi = function() {
306
- var groups = {};
307
-
308
- // generate groups by their groupId set by elements using data-match-height
309
- $('[data-match-height], [data-mh]').each(function() {
310
- var $this = $(this),
311
- groupId = $this.attr('data-mh') || $this.attr('data-match-height');
312
-
313
- if (groupId in groups) {
314
- groups[groupId] = groups[groupId].add($this);
315
- } else {
316
- groups[groupId] = $this;
317
- }
318
- });
319
-
320
- // apply matchHeight to each group
321
- $.each(groups, function() {
322
- this.matchHeight(true);
323
- });
324
- };
325
-
326
- /*
327
- * matchHeight._update
328
- * updates matchHeight on all current groups with their correct options
329
- */
330
-
331
- var _update = function(event) {
332
- if (matchHeight._beforeUpdate) {
333
- matchHeight._beforeUpdate(event, matchHeight._groups);
334
- }
335
-
336
- $.each(matchHeight._groups, function() {
337
- matchHeight._apply(this.elements, this.options);
338
- });
339
-
340
- if (matchHeight._afterUpdate) {
341
- matchHeight._afterUpdate(event, matchHeight._groups);
342
- }
343
- };
344
-
345
- matchHeight._update = function(throttle, event) {
346
- // prevent update if fired from a resize event
347
- // where the viewport width hasn't actually changed
348
- // fixes an event looping bug in IE8
349
- if (event && event.type === 'resize') {
350
- var windowWidth = $(window).width();
351
- if (windowWidth === _previousResizeWidth) {
352
- return;
353
- }
354
- _previousResizeWidth = windowWidth;
355
- }
356
-
357
- // throttle updates
358
- if (!throttle) {
359
- _update(event);
360
- } else if (_updateTimeout === -1) {
361
- _updateTimeout = setTimeout(function() {
362
- _update(event);
363
- _updateTimeout = -1;
364
- }, matchHeight._throttle);
365
- }
366
- };
367
-
368
- /*
369
- * bind events
370
- */
371
-
372
- // apply on DOM ready event
373
- $(matchHeight._applyDataApi);
374
-
375
- // update heights on load and resize events
376
- $(window).bind('load', function(event) {
377
- matchHeight._update(false, event);
378
- });
379
-
380
- // throttled update heights on resize events
381
- $(window).bind('resize orientationchange', function(event) {
382
- matchHeight._update(true, event);
383
- });
384
-
385
- });
386
-
387
- jQuery(document).ready( function($) {
388
- var s = document.body || document.documentElement, s = s.style;
389
- if ( s.webkitFlexWrap == '' || s.msFlexWrap == '' || s.flexWrap == '' ) return false;
390
-
391
- jQuery('.wp-show-posts-columns .wp-show-posts-inner').matchHeight();
392
-
393
- var rows = $.fn.matchHeight._rows($('.wp-show-posts-columns .wp-show-posts-inner'));
394
-
395
- $.each(rows, function(i, row) {
396
- row.first().addClass('generate-column-first');
397
- row.last().addClass('generate-column-last');
398
- });
399
  });
1
+ /**
2
+ * jquery-match-height master by @liabru
3
+ * http://brm.io/jquery-match-height/
4
+ * License: MIT
5
+ */
6
+
7
+ ;(function(factory) { // eslint-disable-line no-extra-semi
8
+ 'use strict';
9
+ if (typeof define === 'function' && define.amd) {
10
+ // AMD
11
+ define(['jquery'], factory);
12
+ } else if (typeof module !== 'undefined' && module.exports) {
13
+ // CommonJS
14
+ module.exports = factory(require('jquery'));
15
+ } else {
16
+ // Global
17
+ factory(jQuery);
18
+ }
19
+ })(function($) {
20
+ /*
21
+ * internal
22
+ */
23
+
24
+ var _previousResizeWidth = -1,
25
+ _updateTimeout = -1;
26
+
27
+ /*
28
+ * _parse
29
+ * value parse utility function
30
+ */
31
+
32
+ var _parse = function(value) {
33
+ // parse value and convert NaN to 0
34
+ return parseFloat(value) || 0;
35
+ };
36
+
37
+ /*
38
+ * _rows
39
+ * utility function returns array of jQuery selections representing each row
40
+ * (as displayed after float wrapping applied by browser)
41
+ */
42
+
43
+ var _rows = function(elements) {
44
+ var tolerance = 1,
45
+ $elements = $(elements),
46
+ lastTop = null,
47
+ rows = [];
48
+
49
+ // group elements by their top position
50
+ $elements.each(function(){
51
+ var $that = $(this),
52
+ top = $that.offset().top - _parse($that.css('margin-top')),
53
+ lastRow = rows.length > 0 ? rows[rows.length - 1] : null;
54
+
55
+ if (lastRow === null) {
56
+ // first item on the row, so just push it
57
+ rows.push($that);
58
+ } else {
59
+ // if the row top is the same, add to the row group
60
+ if (Math.floor(Math.abs(lastTop - top)) <= tolerance) {
61
+ rows[rows.length - 1] = lastRow.add($that);
62
+ } else {
63
+ // otherwise start a new row group
64
+ rows.push($that);
65
+ }
66
+ }
67
+
68
+ // keep track of the last row top
69
+ lastTop = top;
70
+ });
71
+
72
+ return rows;
73
+ };
74
+
75
+ /*
76
+ * _parseOptions
77
+ * handle plugin options
78
+ */
79
+
80
+ var _parseOptions = function(options) {
81
+ var opts = {
82
+ byRow: true,
83
+ property: 'height',
84
+ target: null,
85
+ remove: false
86
+ };
87
+
88
+ if (typeof options === 'object') {
89
+ return $.extend(opts, options);
90
+ }
91
+
92
+ if (typeof options === 'boolean') {
93
+ opts.byRow = options;
94
+ } else if (options === 'remove') {
95
+ opts.remove = true;
96
+ }
97
+
98
+ return opts;
99
+ };
100
+
101
+ /*
102
+ * matchHeight
103
+ * plugin definition
104
+ */
105
+
106
+ var matchHeight = $.fn.matchHeight = function(options) {
107
+ var opts = _parseOptions(options);
108
+
109
+ // handle remove
110
+ if (opts.remove) {
111
+ var that = this;
112
+
113
+ // remove fixed height from all selected elements
114
+ this.css(opts.property, '');
115
+
116
+ // remove selected elements from all groups
117
+ $.each(matchHeight._groups, function(key, group) {
118
+ group.elements = group.elements.not(that);
119
+ });
120
+
121
+ // TODO: cleanup empty groups
122
+
123
+ return this;
124
+ }
125
+
126
+ if (this.length <= 1 && !opts.target) {
127
+ return this;
128
+ }
129
+
130
+ // keep track of this group so we can re-apply later on load and resize events
131
+ matchHeight._groups.push({
132
+ elements: this,
133
+ options: opts
134
+ });
135
+
136
+ // match each element's height to the tallest element in the selection
137
+ matchHeight._apply(this, opts);
138
+
139
+ return this;
140
+ };
141
+
142
+ /*
143
+ * plugin global options
144
+ */
145
+
146
+ matchHeight.version = 'master';
147
+ matchHeight._groups = [];
148
+ matchHeight._throttle = 80;
149
+ matchHeight._maintainScroll = false;
150
+ matchHeight._beforeUpdate = null;
151
+ matchHeight._afterUpdate = null;
152
+ matchHeight._rows = _rows;
153
+ matchHeight._parse = _parse;
154
+ matchHeight._parseOptions = _parseOptions;
155
+
156
+ /*
157
+ * matchHeight._apply
158
+ * apply matchHeight to given elements
159
+ */
160
+
161
+ matchHeight._apply = function(elements, options) {
162
+ var opts = _parseOptions(options),
163
+ $elements = $(elements),
164
+ rows = [$elements];
165
+
166
+ // take note of scroll position
167
+ var scrollTop = $(window).scrollTop(),
168
+ htmlHeight = $('html').outerHeight(true);
169
+
170
+ // get hidden parents
171
+ var $hiddenParents = $elements.parents().filter(':hidden');
172
+
173
+ // cache the original inline style
174
+ $hiddenParents.each(function() {
175
+ var $that = $(this);
176
+ $that.data('style-cache', $that.attr('style'));
177
+ });
178
+
179
+ // temporarily must force hidden parents visible
180
+ $hiddenParents.css('display', 'block');
181
+
182
+ // get rows if using byRow, otherwise assume one row
183
+ if (opts.byRow && !opts.target) {
184
+
185
+ // must first force an arbitrary equal height so floating elements break evenly
186
+ $elements.each(function() {
187
+ var $that = $(this),
188
+ display = $that.css('display');
189
+
190
+ // temporarily force a usable display value
191
+ if (display !== 'inline-block' && display !== 'flex' && display !== 'inline-flex') {
192
+ display = 'block';
193
+ }
194
+
195
+ // cache the original inline style
196
+ $that.data('style-cache', $that.attr('style'));
197
+
198
+ $that.css({
199
+ 'display': display,
200
+ 'padding-top': '0',
201
+ 'padding-bottom': '0',
202
+ 'margin-top': '0',
203
+ 'margin-bottom': '0',
204
+ 'border-top-width': '0',
205
+ 'border-bottom-width': '0',
206
+ 'height': '100px',
207
+ 'overflow': 'hidden'
208
+ });
209
+ });
210
+
211
+ // get the array of rows (based on element top position)
212
+ rows = _rows($elements);
213
+
214
+ // revert original inline styles
215
+ $elements.each(function() {
216
+ var $that = $(this);
217
+ $that.attr('style', $that.data('style-cache') || '');
218
+ });
219
+ }
220
+
221
+ $.each(rows, function(key, row) {
222
+ var $row = $(row),
223
+ targetHeight = 0;
224
+
225
+ if (!opts.target) {
226
+ // skip apply to rows with only one item
227
+ if (opts.byRow && $row.length <= 1) {
228
+ $row.css(opts.property, '');
229
+ return;
230
+ }
231
+
232
+ // iterate the row and find the max height
233
+ $row.each(function(){
234
+ var $that = $(this),
235
+ style = $that.attr('style'),
236
+ display = $that.css('display');
237
+
238
+ // temporarily force a usable display value
239
+ if (display !== 'inline-block' && display !== 'flex' && display !== 'inline-flex') {
240
+ display = 'block';
241
+ }
242
+
243
+ // ensure we get the correct actual height (and not a previously set height value)
244
+ var css = { 'display': display };
245
+ css[opts.property] = '';
246
+ $that.css(css);
247
+
248
+ // find the max height (including padding, but not margin)
249
+ if ($that.outerHeight(false) > targetHeight) {
250
+ targetHeight = $that.outerHeight(false);
251
+ }
252
+
253
+ // revert styles
254
+ if (style) {
255
+ $that.attr('style', style);
256
+ } else {
257
+ $that.css('display', '');
258
+ }
259
+ });
260
+ } else {
261
+ // if target set, use the height of the target element
262
+ targetHeight = opts.target.outerHeight(false);
263
+ }
264
+
265
+ // iterate the row and apply the height to all elements
266
+ $row.each(function(){
267
+ var $that = $(this),
268
+ verticalPadding = 0;
269
+
270
+ // don't apply to a target
271
+ if (opts.target && $that.is(opts.target)) {
272
+ return;
273
+ }
274
+
275
+ // handle padding and border correctly (required when not using border-box)
276
+ if ($that.css('box-sizing') !== 'border-box') {
277
+ verticalPadding += _parse($that.css('border-top-width')) + _parse($that.css('border-bottom-width'));
278
+ verticalPadding += _parse($that.css('padding-top')) + _parse($that.css('padding-bottom'));
279
+ }
280
+
281
+ // set the height (accounting for padding and border)
282
+ $that.css(opts.property, (targetHeight - verticalPadding) + 'px');
283
+ });
284
+ });
285
+
286
+ // revert hidden parents
287
+ $hiddenParents.each(function() {
288
+ var $that = $(this);
289
+ $that.attr('style', $that.data('style-cache') || null);
290
+ });
291
+
292
+ // restore scroll position if enabled
293
+ if (matchHeight._maintainScroll) {
294
+ $(window).scrollTop((scrollTop / htmlHeight) * $('html').outerHeight(true));
295
+ }
296
+
297
+ return this;
298
+ };
299
+
300
+ /*
301
+ * matchHeight._applyDataApi
302
+ * applies matchHeight to all elements with a data-match-height attribute
303
+ */
304
+
305
+ matchHeight._applyDataApi = function() {
306
+ var groups = {};
307
+
308
+ // generate groups by their groupId set by elements using data-match-height
309
+ $('[data-match-height], [data-mh]').each(function() {
310
+ var $this = $(this),
311
+ groupId = $this.attr('data-mh') || $this.attr('data-match-height');
312
+
313
+ if (groupId in groups) {
314
+ groups[groupId] = groups[groupId].add($this);
315
+ } else {
316
+ groups[groupId] = $this;
317
+ }
318
+ });
319
+
320
+ // apply matchHeight to each group
321
+ $.each(groups, function() {
322
+ this.matchHeight(true);
323
+ });
324
+ };
325
+
326
+ /*
327
+ * matchHeight._update
328
+ * updates matchHeight on all current groups with their correct options
329
+ */
330
+
331
+ var _update = function(event) {
332
+ if (matchHeight._beforeUpdate) {
333
+ matchHeight._beforeUpdate(event, matchHeight._groups);
334
+ }
335
+
336
+ $.each(matchHeight._groups, function() {
337
+ matchHeight._apply(this.elements, this.options);
338
+ });
339
+
340
+ if (matchHeight._afterUpdate) {
341
+ matchHeight._afterUpdate(event, matchHeight._groups);
342
+ }
343
+ };
344
+
345
+ matchHeight._update = function(throttle, event) {
346
+ // prevent update if fired from a resize event
347
+ // where the viewport width hasn't actually changed
348
+ // fixes an event looping bug in IE8
349
+ if (event && event.type === 'resize') {
350
+ var windowWidth = $(window).width();
351
+ if (windowWidth === _previousResizeWidth) {
352
+ return;
353
+ }
354
+ _previousResizeWidth = windowWidth;
355
+ }
356
+
357
+ // throttle updates
358
+ if (!throttle) {
359
+ _update(event);
360
+ } else if (_updateTimeout === -1) {
361
+ _updateTimeout = setTimeout(function() {
362
+ _update(event);
363
+ _updateTimeout = -1;
364
+ }, matchHeight._throttle);
365
+ }
366
+ };
367
+
368
+ /*
369
+ * bind events
370
+ */
371
+
372
+ // apply on DOM ready event
373
+ $(matchHeight._applyDataApi);
374
+
375
+ // update heights on load and resize events
376
+ $(window).bind('load', function(event) {
377
+ matchHeight._update(false, event);
378
+ });
379
+
380
+ // throttled update heights on resize events
381
+ $(window).bind('resize orientationchange', function(event) {
382
+ matchHeight._update(true, event);
383
+ });
384
+
385
+ });
386
+
387
+ jQuery(document).ready( function($) {
388
+ var s = document.body || document.documentElement, s = s.style;
389
+ if ( s.webkitFlexWrap == '' || s.msFlexWrap == '' || s.flexWrap == '' ) return false;
390
+
391
+ jQuery('.wp-show-posts-columns .wp-show-posts-inner').matchHeight();
392
+
393
+ var rows = $.fn.matchHeight._rows($('.wp-show-posts-columns .wp-show-posts-inner'));
394
+
395
+ $.each(rows, function(i, row) {
396
+ row.first().addClass('generate-column-first');
397
+ row.last().addClass('generate-column-last');
398
+ });
399
  });
license.txt CHANGED
@@ -1,29 +1,29 @@
1
- WP Show Posts is licensed under the GNU General Public License v2 or later
2
- More details here: http://www.gnu.org/licenses/gpl-2.0.html
3
-
4
- == Bundled resources ==
5
-
6
- = Butterbean =
7
-
8
- Licensed under the GNU GPL, version 2 or later.
9
- 2015-2016 � Justin Tadlock.
10
-
11
- = MatchHeight.js =
12
-
13
- jquery.matchHeight.js is licensed under The MIT License (MIT)
14
- Copyright (c) 2014 Liam Brummitt
15
-
16
- = FontAwesome =
17
-
18
- Icons generated with IcoMoon with the following licenses:
19
-
20
- Font License: SIL OFL 1.1 - http://scripts.sil.org/OFL
21
- Code License: MIT License - http://opensource.org/licenses/mit-license.html
22
-
23
- All brand icons are trademarks of their respective owners.
24
-
25
- = Display Posts Shortcode =
26
-
27
- Some of the base code of this plugin was borrowed from the awesome Display Posts Shortcode plugin by Bill Erickson.
28
- https://wordpress.org/plugins/display-posts-shortcode/
29
  http://www.billerickson.net/
1
+ WP Show Posts is licensed under the GNU General Public License v2 or later
2
+ More details here: http://www.gnu.org/licenses/gpl-2.0.html
3
+
4
+ == Bundled resources ==
5
+
6
+ = Butterbean =
7
+
8
+ Licensed under the GNU GPL, version 2 or later.
9
+ 2015-2016 � Justin Tadlock.
10
+
11
+ = MatchHeight.js =
12
+
13
+ jquery.matchHeight.js is licensed under The MIT License (MIT)
14
+ Copyright (c) 2014 Liam Brummitt
15
+
16
+ = FontAwesome =
17
+
18
+ Icons generated with IcoMoon with the following licenses:
19
+
20
+ Font License: SIL OFL 1.1 - http://scripts.sil.org/OFL
21
+ Code License: MIT License - http://opensource.org/licenses/mit-license.html
22
+
23
+ All brand icons are trademarks of their respective owners.
24
+
25
+ = Display Posts Shortcode =
26
+
27
+ Some of the base code of this plugin was borrowed from the awesome Display Posts Shortcode plugin by Bill Erickson.
28
+ https://wordpress.org/plugins/display-posts-shortcode/
29
  http://www.billerickson.net/
readme.txt CHANGED
@@ -1,222 +1,240 @@
1
- === WP Show Posts ===
2
- Contributors: edge22
3
- Donate link: https://wpshowposts.com
4
- Tags: show posts, display posts shortcode, portfolio, gallery, post columns
5
- Requires at least: 4.0
6
- Tested up to: 4.6
7
- Stable tag: 0.6
8
- License: GPLv2 or later
9
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
-
11
- Add posts to your website from any post type using a simple shortcode.
12
-
13
- == Description ==
14
-
15
- https://vimeo.com/175638957
16
-
17
- WP Show Posts allows you to display posts anywhere on your website using an easy to use shortcode.
18
-
19
- You can pull posts from any post type like WooCommerce, Easy Digital Downloads etc..
20
-
21
- This plugin works with any theme.
22
-
23
- Here are the features in the free version:
24
-
25
- = Posts =
26
-
27
- * Post type
28
- * Taxonomy
29
- * Terms
30
- * Posts per page
31
- * Pagination
32
-
33
- = Columns =
34
-
35
- * Columns
36
- * Columns gutter
37
-
38
- = Images =
39
-
40
- * Show images
41
- * Image width
42
- * Image height
43
- * Image alignment
44
- * Image location
45
-
46
- = Content =
47
-
48
- * Content type (excerpt or full post)
49
- * Excerpt length
50
- * Include title
51
- * Read more text
52
-
53
- = Meta =
54
-
55
- * Include author
56
- * Author location
57
- * Include date
58
- * Date location
59
- * Include terms
60
- * Terms location
61
-
62
- = More settings =
63
-
64
- * Author ID
65
- * Exclude current
66
- * Post ID
67
- * Exclude post ID
68
- * Ignore sticky posts
69
- * Offset
70
- * Order
71
- * Order by
72
- * Status
73
- * Meta key
74
- * Meta value
75
- * Tax operator
76
- * No results message
77
-
78
- = Our *Pro* version has these features =
79
-
80
- https://vimeo.com/175660953
81
-
82
- [Check out Pro](https://wpshowposts.com/ "Check out Pro")
83
-
84
- = Posts =
85
-
86
- * AJAX pagination
87
-
88
- = Columns =
89
-
90
- * Masonry
91
- * Featured post
92
-
93
- = Images =
94
-
95
- * Image overlay color
96
- * Image overlay icon
97
- * Image hover effect
98
- * Image lightbox
99
- * Image lightbox gallery
100
-
101
- = Content =
102
-
103
- * Read more style
104
- * Read more color
105
-
106
- = Styling =
107
-
108
- * Border color
109
- * Padding
110
-
111
- = Social =
112
-
113
- * Twitter
114
- * Facebook
115
- * Google+
116
- * Pinterest
117
- * Love it
118
- * Alignment
119
-
120
- Check out GeneratePress, our awesome WordPress theme! (http://wordpress.org/themes/generatepress)
121
-
122
- == Installation ==
123
-
124
- There's two ways to install WP Show Posts.
125
-
126
- 1. Go to "Plugins > Add New" in your Dashboard and search for: WP Show Posts
127
- 2. Download the .zip from WordPress.org, and upload the folder to the `/wp-content/plugins/` directory via FTP.
128
-
129
- In most cases, #1 will work fine and is way easier.
130
-
131
- == Frequently Asked Questions ==
132
-
133
- = How do I create a post list? =
134
-
135
- * Make sure WP Show Posts is activated.
136
- * Navigate to "WP Show Posts > Add New" and configure your list.
137
- * Copy the shortcode provided for you when adding your new list.
138
- * Add your shortcode to your desired page or post.
139
-
140
- == Screenshots ==
141
-
142
- 1. All of your created post lists.
143
- 2. The "Posts" settings tab.
144
- 3. The "Columns" settings tab.
145
- 4. The "Images" settings tab.
146
- 5. The "Content" settings tab.
147
- 6. The "Meta" settings tab.
148
- 7. The "More query ars" settings tab.
149
-
150
- == Changelog ==
151
-
152
- = 0.6 =
153
- * Add height: auto to images to prevent image stretching in Beaver Builder
154
- * Prevent horizontal scrolling when posts are in columns
155
- * Change "More query args" section name to "More settings"
156
- * Allow multiple IDs in "Post ID" option
157
- * Add "Exclude IDs" option
158
- * Add "No results message" option
159
- * Add "WP Show Posts" widget to add posts in widget areas
160
-
161
- = 0.5 =
162
- * Fix conflict with Yoast SEO causing taxonomy and terms fields to be blank
163
- * Add support for translations
164
-
165
- = 0.4 =
166
- * Fix column width issue when content is disabled
167
- * Fix pagination issue when post list is on the front page
168
- * Disable pagination in single posts
169
- * Fix saving of taxonomy and terms fields
170
- * Force no underline on read more buttons
171
-
172
- = 0.3 =
173
- * Remove attachment post type from list for now
174
- * Don't show pagination if there's no posts
175
- * Move wpsp_before_title hook into the <header> element
176
- * New hook: wpsp_before_wrapper
177
- * New hook: wpsp_before_header
178
-
179
- = 0.2 =
180
- * Fix issue with posts showing up in wrong area on page
181
- * Remove read more link if the <!-- more --> tag is used
182
- * Wrap read more button in div: .wpsp-read-more
183
-
184
- = 0.1 =
185
- * Initial release
186
-
187
- == Upgrade Notice ==
188
-
189
- = 0.6 =
190
- * Add height: auto to images to prevent image stretching in Beaver Builder
191
- * Prevent horizontal scrolling when posts are in columns
192
- * Change "More query args" section name to "More settings"
193
- * Allow multiple IDs in "Post ID" option
194
- * Add "Exclude IDs" option
195
- * Add "No results message" option
196
- * Add "WP Show Posts" widget to add posts in widget areas
197
-
198
- = 0.5 =
199
- * Fix conflict with Yoast SEO causing taxonomy and terms fields to be blank
200
- * Add support for translations
201
-
202
- = 0.4 =
203
- * Fix column width issue when content is disabled
204
- * Fix pagination issue when post list is on the front page
205
- * Disable pagination in single posts
206
- * Fix saving of taxonomy and terms fields
207
- * Force no underline on read more buttons
208
-
209
- = 0.3 =
210
- * Remove attachment post type from list for now
211
- * Don't show pagination if there's no posts
212
- * Move wpsp_before_title hook into the <header> element
213
- * New hook: wpsp_before_wrapper
214
- * New hook: wpsp_before_header
215
-
216
- = 0.2 =
217
- * Fix issue with posts showing up in wrong area on page
218
- * Remove read more link if the <!-- more --> tag is used
219
- * Wrap read more button in div: .wpsp-read-more
220
-
221
- = 0.1 =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  * Initial release
1
+ === WP Show Posts ===
2
+ Contributors: edge22
3
+ Donate link: https://wpshowposts.com
4
+ Tags: show posts, display posts shortcode, portfolio, gallery, post columns
5
+ Requires at least: 4.0
6
+ Tested up to: 4.6.1
7
+ Stable tag: 0.7
8
+ License: GPLv2 or later
9
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
+
11
+ Add posts to your website from any post type using a simple shortcode.
12
+
13
+ == Description ==
14
+
15
+ https://vimeo.com/175638957
16
+
17
+ WP Show Posts allows you to display posts anywhere on your website using an easy to use shortcode.
18
+
19
+ You can pull posts from any post type like WooCommerce, Easy Digital Downloads etc..
20
+
21
+ This plugin works with any theme.
22
+
23
+ Here are the features in the free version:
24
+
25
+ = Posts =
26
+
27
+ * Post type
28
+ * Taxonomy
29
+ * Terms
30
+ * Posts per page
31
+ * Pagination
32
+
33
+ = Columns =
34
+
35
+ * Columns
36
+ * Columns gutter
37
+
38
+ = Images =
39
+
40
+ * Show images
41
+ * Image width
42
+ * Image height
43
+ * Image alignment
44
+ * Image location
45
+
46
+ = Content =
47
+
48
+ * Content type (excerpt or full post)
49
+ * Excerpt length
50
+ * Include title
51
+ * Read more text
52
+
53
+ = Meta =
54
+
55
+ * Include author
56
+ * Author location
57
+ * Include date
58
+ * Date location
59
+ * Include terms
60
+ * Terms location
61
+
62
+ = More settings =
63
+
64
+ * Author ID
65
+ * Exclude current
66
+ * Post ID
67
+ * Exclude post ID
68
+ * Ignore sticky posts
69
+ * Offset
70
+ * Order
71
+ * Order by
72
+ * Status
73
+ * Meta key
74
+ * Meta value
75
+ * Tax operator
76
+ * No results message
77
+
78
+ = Our *Pro* version has these features =
79
+
80
+ https://vimeo.com/175660953
81
+
82
+ [Check out Pro](https://wpshowposts.com/ "Check out Pro")
83
+
84
+ = Posts =
85
+
86
+ * AJAX pagination
87
+
88
+ = Columns =
89
+
90
+ * Masonry
91
+ * Featured post
92
+
93
+ = Images =
94
+
95
+ * Image overlay color
96
+ * Image overlay icon
97
+ * Image hover effect
98
+ * Image lightbox
99
+ * Image lightbox gallery
100
+
101
+ = Content =
102
+
103
+ * Read more style
104
+ * Read more color
105
+
106
+ = Styling =
107
+
108
+ * Border color
109
+ * Padding
110
+
111
+ = Social =
112
+
113
+ * Twitter
114
+ * Facebook
115
+ * Google+
116
+ * Pinterest
117
+ * Love it
118
+ * Alignment
119
+
120
+ Check out GeneratePress, our awesome WordPress theme! (http://wordpress.org/themes/generatepress)
121
+
122
+ == Installation ==
123
+
124
+ There's two ways to install WP Show Posts.
125
+
126
+ 1. Go to "Plugins > Add New" in your Dashboard and search for: WP Show Posts
127
+ 2. Download the .zip from WordPress.org, and upload the folder to the `/wp-content/plugins/` directory via FTP.
128
+
129
+ In most cases, #1 will work fine and is way easier.
130
+
131
+ == Frequently Asked Questions ==
132
+
133
+ = How do I create a post list? =
134
+
135
+ * Make sure WP Show Posts is activated.
136
+ * Navigate to "WP Show Posts > Add New" and configure your list.
137
+ * Copy the shortcode provided for you when adding your new list.
138
+ * Add your shortcode to your desired page or post.
139
+
140
+ == Screenshots ==
141
+
142
+ 1. All of your created post lists.
143
+ 2. The "Posts" settings tab.
144
+ 3. The "Columns" settings tab.
145
+ 4. The "Images" settings tab.
146
+ 5. The "Content" settings tab.
147
+ 6. The "Meta" settings tab.
148
+ 7. The "More query ars" settings tab.
149
+
150
+ == Changelog ==
151
+
152
+ = 0.7 =
153
+ * Prevent direct access to files
154
+ * Add prefix to all column classes to avoid conflicts
155
+ * Use wp_trim_words() function for excerpts
156
+ * Fix conflict with Maintenance plugin
157
+ * Make columns full width on mobile
158
+ * Allow more tag usage when excerpt is set
159
+ * Add blank option in widget to fix bug in Customizer/Elementor
160
+
161
+ = 0.6 =
162
+ * Add height: auto to images to prevent image stretching in Beaver Builder
163
+ * Prevent horizontal scrolling when posts are in columns
164
+ * Change "More query args" section name to "More settings"
165
+ * Allow multiple IDs in "Post ID" option
166
+ * Add "Exclude IDs" option
167
+ * Add "No results message" option
168
+ * Add "WP Show Posts" widget to add posts in widget areas
169
+
170
+ = 0.5 =
171
+ * Fix conflict with Yoast SEO causing taxonomy and terms fields to be blank
172
+ * Add support for translations
173
+
174
+ = 0.4 =
175
+ * Fix column width issue when content is disabled
176
+ * Fix pagination issue when post list is on the front page
177
+ * Disable pagination in single posts
178
+ * Fix saving of taxonomy and terms fields
179
+ * Force no underline on read more buttons
180
+
181
+ = 0.3 =
182
+ * Remove attachment post type from list for now
183
+ * Don't show pagination if there's no posts
184
+ * Move wpsp_before_title hook into the <header> element
185
+ * New hook: wpsp_before_wrapper
186
+ * New hook: wpsp_before_header
187
+
188
+ = 0.2 =
189
+ * Fix issue with posts showing up in wrong area on page
190
+ * Remove read more link if the <!-- more --> tag is used
191
+ * Wrap read more button in div: .wpsp-read-more
192
+
193
+ = 0.1 =
194
+ * Initial release
195
+
196
+ == Upgrade Notice ==
197
+
198
+ = 0.7 =
199
+ * Prevent direct access to files
200
+ * Add prefix to all column classes to avoid conflicts
201
+ * Use wp_trim_words() function for excerpts
202
+ * Fix conflict with Maintenance plugin
203
+ * Make columns full width on mobile
204
+ * Allow more tag usage when excerpt is set
205
+ * Add blank option in widget to fix bug in Customizer/Elementor
206
+
207
+ = 0.6 =
208
+ * Add height: auto to images to prevent image stretching in Beaver Builder
209
+ * Prevent horizontal scrolling when posts are in columns
210
+ * Change "More query args" section name to "More settings"
211
+ * Allow multiple IDs in "Post ID" option
212
+ * Add "Exclude IDs" option
213
+ * Add "No results message" option
214
+ * Add "WP Show Posts" widget to add posts in widget areas
215
+
216
+ = 0.5 =
217
+ * Fix conflict with Yoast SEO causing taxonomy and terms fields to be blank
218
+ * Add support for translations
219
+
220
+ = 0.4 =
221
+ * Fix column width issue when content is disabled
222
+ * Fix pagination issue when post list is on the front page
223
+ * Disable pagination in single posts
224
+ * Fix saving of taxonomy and terms fields
225
+ * Force no underline on read more buttons
226
+
227
+ = 0.3 =
228
+ * Remove attachment post type from list for now
229
+ * Don't show pagination if there's no posts
230
+ * Move wpsp_before_title hook into the <header> element
231
+ * New hook: wpsp_before_wrapper
232
+ * New hook: wpsp_before_header
233
+
234
+ = 0.2 =
235
+ * Fix issue with posts showing up in wrong area on page
236
+ * Remove read more link if the <!-- more --> tag is used
237
+ * Wrap read more button in div: .wpsp-read-more
238
+
239
+ = 0.1 =
240
  * Initial release
wp-show-posts.php CHANGED
@@ -1,486 +1,493 @@
1
- <?php
2
- /*
3
- Plugin Name: WP Show Posts
4
- Plugin URI: https://wpshowposts.com
5
- Description: WP Show Posts allows you to list posts (from any post type) anywhere on your site. This includes WooCommerce products or any other post type you might have! Check out the pro version for even more features at https://wpshowposts.com.
6
- Version: 0.6
7
- Author: Tom Usborne
8
- Author URI: https://tomusborne.com
9
- License: GNU General Public License v2 or later
10
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
- Text Domain: wp-show-posts
12
- */
13
-
14
- // Define the current version
15
- define( 'WPSP_VERSION', 0.5 );
16
-
17
- // Add defaults
18
- require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'inc/defaults.php';
19
-
20
- // Add post type
21
- require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/post-type.php';
22
-
23
- // Add admin metabox
24
- require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/metabox.php';
25
-
26
- // Add admin AJAX
27
- require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/ajax.php';
28
-
29
- // Add resizer script
30
- if ( ! class_exists( 'WPSP_Resize' ) ) require_once plugin_dir_path( __FILE__ ) . 'inc/image-resizer.php';
31
-
32
- // Add functions
33
- require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'inc/functions.php';
34
-
35
- // Add admin functions
36
- require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/admin.php';
37
-
38
- // Add widget
39
- require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/widget.php';
40
-
41
- if ( ! function_exists( 'wpsp_load_textdomain' ) ) :
42
- /**
43
- * Load plugin textdomain.
44
- *
45
- * @since 0.5
46
- */
47
- add_action( 'plugins_loaded', 'wpsp_load_textdomain' );
48
- function wpsp_load_textdomain()
49
- {
50
- load_plugin_textdomain( 'wp-show-posts' );
51
- }
52
- endif;
53
-
54
- if ( ! function_exists( 'wpsp_get_min_suffix' ) ) :
55
- /**
56
- * Figure out if we should use minified scripts or not
57
- * @since 0.1
58
- */
59
- function wpsp_get_min_suffix()
60
- {
61
- return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '-min';
62
- }
63
- endif;
64
-
65
- if ( ! function_exists( 'wpsp_enqueue_scripts' ) ) :
66
- /*
67
- * Enqueue our CSS to the front end
68
- * @since 0.1
69
- */
70
- add_action( 'wp_enqueue_scripts', 'wpsp_enqueue_scripts' );
71
- function wpsp_enqueue_scripts()
72
- {
73
- $suffix = wpsp_get_min_suffix();
74
- wp_enqueue_style( 'wp-show-posts', plugins_url( "css/wp-show-posts{$suffix}.css", __FILE__ ), array(), WPSP_VERSION );
75
- }
76
- endif;
77
-
78
- if ( ! function_exists( 'wpsp_get_setting' ) ) :
79
- /*
80
- * Create a helpful wrapper to get our settings and defaults
81
- * @since 0.1
82
- */
83
- function wpsp_get_setting( $id, $key )
84
- {
85
- $defaults = wpsp_get_defaults();
86
- return get_post_meta( $id, $key ) ? get_post_meta( $id, $key, true ) : $defaults[ $key ];
87
- }
88
- endif;
89
-
90
- if ( ! function_exists( 'wpsp_display' ) ) :
91
- /*
92
- * Build the front end of the plugin
93
- * $id parameter needs to match ID of custom post type entry
94
- * @since 0.1
95
- */
96
- function wpsp_display( $id )
97
- {
98
- // Set the global ID of our object
99
- global $wpsp_id;
100
- $wpsp_id = $id;
101
-
102
- // Build our setting variables
103
- $author = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_author' ) );
104
- $columns = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_columns' ) );
105
- $columns_gutter = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_columns_gutter' ) );
106
- $content_type = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_content_type' ) );
107
- $exclude_current = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_exclude_current' ) );
108
- $excerpt_length = absint( wpsp_get_setting( $id, 'wpsp_excerpt_length' ) );
109
- $post_id = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_post_id' ) );
110
- $exclude_post_id = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_exclude_post_id' ) );
111
- $ignore_sticky_posts = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_ignore_sticky_posts' ) );
112
- $image_gallery = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_image_gallery' ) );
113
- $image_lightbox = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_image_lightbox' ) );
114
- $include_title = wp_validate_boolean( get_post_meta( $id, 'wpsp_include_title', true ) );
115
- $author_location = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_author_location' ) );
116
- $date_location = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_date_location' ) );
117
- $terms_location = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_terms_location' ) );
118
- $include_author = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_include_author' ) );
119
- $include_terms = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_include_terms' ) );
120
- $include_date = wp_validate_boolean( get_post_meta( $id, 'wpsp_include_date', true ) );
121
- $inner_wrapper = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_inner_wrapper' ) );
122
- $inner_wrapper_class = array_map( 'sanitize_html_class', ( explode( ' ', wpsp_get_setting( $id, 'wpsp_inner_wrapper_class' ) ) ) );
123
- $inner_wrapper_style = explode( ' ', esc_attr( wpsp_get_setting( $id, 'wpsp_inner_wrapper_style' ) ) );
124
- $itemtype = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_itemtype' ) );
125
- $meta_key = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_meta_key' ) );
126
- $meta_value = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_meta_value' ) );
127
- $offset = absint( wpsp_get_setting( $id, 'wpsp_offset' ) );
128
- $order = sanitize_key( wpsp_get_setting( $id, 'wpsp_order' ) );
129
- $orderby = sanitize_key( wpsp_get_setting( $id, 'wpsp_orderby' ) );
130
- $pagination = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_pagination' ) );
131
- $post_type = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_post_type' ) );
132
- $post_status = wpsp_get_setting( $id, 'wpsp_post_status' ); // Validated later
133
- $posts_per_page = intval( wpsp_get_setting( $id, 'wpsp_posts_per_page' ) );
134
- $tax_operator = wpsp_get_setting( $id, 'wpsp_tax_operator' ); // Validated later
135
- $tax_term = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_tax_term' ) );
136
- $taxonomy = sanitize_key( wpsp_get_setting( $id, 'wpsp_taxonomy' ) );
137
- $wrapper = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_wrapper' ) );
138
- $wrapper_id = sanitize_html_class( wpsp_get_setting( $id, 'wpsp_wrapper_id' ) );
139
- $wrapper_class = array_map( 'sanitize_html_class', ( explode( ' ', wpsp_get_setting( $id, 'wpsp_wrapper_class' ) ) ) );
140
- $wrapper_style = explode( ' ', esc_attr( wpsp_get_setting( $id, 'wpsp_wrapper_style' ) ) );
141
- $no_results = wp_kses_post( wpsp_get_setting( $id, 'wpsp_no_results' ) );
142
- $ajax_pagination = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_ajax_pagination' ) );
143
- $masonry = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_masonry' ) );
144
- $featured_post = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_featured_post' ) );
145
- $border = wpsp_sanitize_hex_color( wpsp_get_setting( $id, 'wpsp_border' ) );
146
- $padding = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_padding' ) );
147
- $filter = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_filter' ) );
148
-
149
- // Grab initiate args for query
150
- $args = array();
151
-
152
- if ( '' !== $order )
153
- $args[ 'order' ] = $order;
154
-
155
- if ( '' !== $orderby )
156
- $args[ 'orderby' ] = $orderby;
157
-
158
- if ( '' !== $post_type )
159
- $args[ 'post_type' ] = $post_type;
160
-
161
- if ( '' !== $posts_per_page )
162
- $args[ 'posts_per_page' ] = $posts_per_page;
163
-
164
- if ( $ignore_sticky_posts )
165
- $args[ 'ignore_sticky_posts' ] = $ignore_sticky_posts;
166
-
167
- if ( '' !== $meta_key )
168
- $args[ 'meta_key' ] = $meta_key;
169
-
170
- if ( '' !== $meta_value )
171
- $args[ 'meta_value' ] = $meta_value;
172
-
173
- if ( $offset > 0 )
174
- $args[ 'offset' ] = $offset;
175
-
176
- if ( '' !== $author )
177
- $args[ 'author' ] = array( $author );
178
-
179
- if ( $pagination && ! is_single() ) :
180
- $paged_query = is_front_page() ? 'page' : 'paged';
181
- $args[ 'paged' ] = get_query_var( $paged_query );
182
- endif;
183
-
184
- // Post Status
185
- $post_status = explode( ', ', $post_status );
186
- $validated = array();
187
- $available = array( 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash', 'any' );
188
-
189
- foreach ( $post_status as $unvalidated )
190
- if ( in_array( $unvalidated, $available ) )
191
- $validated[] = $unvalidated;
192
-
193
- if( !empty( $validated ) )
194
- $args['post_status'] = $validated;
195
-
196
- // If taxonomy attributes, create a taxonomy query
197
- if ( !empty( $taxonomy ) && !empty( $tax_term ) ) {
198
-
199
- if ( 'current' == $tax_term ) {
200
- global $post;
201
- $terms = wp_get_post_terms(get_the_ID(), $taxonomy);
202
- $tax_term = array();
203
- foreach ($terms as $term) {
204
- $tax_term[] = $term->slug;
205
- }
206
- } else {
207
- // Term string to array
208
- $tax_term = explode( ', ', $tax_term );
209
- }
210
-
211
- // Validate operator
212
- if( !in_array( $tax_operator, array( 'IN', 'NOT IN', 'AND' ) ) )
213
- $tax_operator = 'IN';
214
-
215
- $tax_args = array(
216
- 'tax_query' => array(
217
- array(
218
- 'taxonomy' => $taxonomy,
219
- 'field' => 'slug',
220
- 'terms' => $tax_term,
221
- 'operator' => $tax_operator
222
- )
223
- )
224
- );
225
-
226
- $args = array_merge( $args, $tax_args );
227
- }
228
-
229
- // If Post IDs
230
- if( $post_id ) {
231
- $posts_in = array_map( 'intval', explode( ',', $post_id ) );
232
- $args['post__in'] = $posts_in;
233
- }
234
-
235
- // If Exclude Post IDs
236
- if( $exclude_post_id ) {
237
- $posts_not_in = array_map( 'intval', explode( ',', $exclude_post_id ) );
238
- $args['post__not_in'] = $posts_not_in;
239
- }
240
-
241
- // If Exclude Current
242
- if( is_singular() && $exclude_current )
243
- $args['post__not_in'] = array( get_the_ID() );
244
-
245
- // Border
246
- if ( '' !== $border ) {
247
- $wrapper_class[] = 'include-border';
248
- $border = 'border-color: ' . $border . ';';
249
- }
250
-
251
- // Padding
252
- if ( '' !== $padding ) {
253
- $wrapper_class[] = 'include-padding';
254
- $padding = 'padding:' . $padding . ';';
255
- }
256
-
257
- // Columns
258
- if ( $columns !== 'col-12' ) :
259
- wp_enqueue_script( 'wpsp-matchHeight', trailingslashit( plugin_dir_url( __FILE__ ) ) . 'js/jquery.matchHeight.js', array( 'jquery' ), WPSP_VERSION, true );
260
- $wrapper_class[] = 'wp-show-posts-columns';
261
- $wrapper_style[] = 'margin-left:-' . $columns_gutter . ';';
262
- $inner_wrapper_style[] = 'margin: 0 0 ' . $columns_gutter . ' ' . $columns_gutter . ';' . $border . $padding;
263
- endif;
264
-
265
- // Featured post class
266
- $current_post = '';
267
- if ( $columns !== 'col-12' && $featured_post ) :
268
- if ( $columns == 'col-6' )
269
- $current_post = 'col-12';
270
-
271
- if ( $columns == 'col-4' )
272
- $current_post = 'col-8';
273
-
274
- if ( $columns == 'col-3' )
275
- $current_post = 'col-6';
276
-
277
- if ( $columns == 'col-20' )
278
- $current_post = 'col-6';
279
- endif;
280
-
281
- // Masonry
282
- if ( $masonry ) :
283
- $wrapper_class[] = 'wp-show-posts-masonry';
284
- $inner_wrapper_class[] = ' wp-show-posts-masonry-' . $columns;
285
- $inner_wrapper_class[] = ' wp-show-posts-masonry-block';
286
-
287
- wp_enqueue_script( 'wpsp-imagesloaded' );
288
- wp_enqueue_script( 'jquery-masonry' );
289
- wp_add_inline_script( 'jquery-masonry', 'jQuery(function($){var $container = $(".wp-show-posts-masonry");$container.imagesLoaded( function(){$container.fadeIn( 1000 ).masonry({itemSelector : ".wp-show-posts-masonry-block",columnWidth: ".grid-sizer"}).css("opacity","1");});});' );
290
- endif;
291
-
292
- // Filter
293
- // if ( $filter ) :
294
- // wp_enqueue_script( 'wpsp-imagesloaded' );
295
- // wp_enqueue_script( 'wpsp-filterizr' );
296
- // wp_add_inline_script( 'wpsp-filterizr', 'jQuery(function($){ var $filterizd = $( ".wp-show-posts" );$filterizd.imagesLoaded( function(){ $( ".wp-show-posts" ).filterizr("setOptions", {layout: "sameWidth"}); } )});' );
297
- // $inner_wrapper_class[] = 'filtr-item';
298
- // endif;
299
-
300
- // Add the default inner wrapper class
301
- // We don't create the class element up here like below, as we need to add classes inside the loop below as well
302
- $inner_wrapper_class[] = 'wp-show-posts-single';
303
-
304
- if ( 'col-12' == $columns )
305
- $inner_wrapper_class[] = 'wpsp-clearfix';
306
-
307
- // Add the default wrapper class
308
- $wrapper_class[] = 'wp-show-posts';
309
-
310
- // Get the wrapper class
311
- if( !empty( $wrapper_class ) )
312
- $wrapper_class = ' class="' . implode( ' ', $wrapper_class ) . '"';
313
-
314
- // Get the wrapper style
315
- if( !empty( $wrapper_style ) )
316
- $wrapper_style = ' style="' . implode( ' ', $wrapper_style ) . '"';
317
-
318
- // Get the inner wrapper class
319
- if( !empty( $inner_wrapper_style ) )
320
- $inner_wrapper_style = ' style="' . implode( ' ', $inner_wrapper_style ) . '"';
321
-
322
- // Get the wrapper ID
323
- if( !empty( $wrapper_id ) )
324
- $wrapper_id = ' id="' . $wrapper_id . '"';
325
-
326
- $wrapper_atts = apply_filters( 'wpsp_wrapper_atts', '' );
327
-
328
- do_action( 'wpsp_before_wrapper' );
329
-
330
- // if ( $filter ) :
331
- // $post_terms = get_terms( sanitize_text_field( $taxonomy ), 'orderby=count&hide_empty=1' );
332
- // echo '<ul>';
333
- // foreach ( $post_terms as $term ) {
334
- // echo '<li data-filter="' . $term->term_id . '">' . $term->name . '</li>';
335
- // }
336
- // echo '</ul>';
337
- // endif;
338
-
339
- // Start the wrapper
340
- echo '<' . $wrapper . $wrapper_id . $wrapper_class . $wrapper_style . $wrapper_atts . '>';
341
-
342
- if ( $masonry )
343
- echo '<div class="grid-sizer ' . $columns . '"></div>';
344
-
345
- // Start the query
346
- $query = new WP_Query( apply_filters( 'wp_show_posts_shortcode_args', $args ) );
347
-
348
- // Start the loop
349
- if ( $query->have_posts() ) {
350
- while ( $query->have_posts() ) {
351
- $query->the_post();
352
-
353
- // Get page
354
- $paged_query = is_front_page() ? 'page' : 'paged';
355
- $paged = ( get_query_var( $paged_query ) ) ? get_query_var( $paged_query ) : 1;
356
-
357
- $featured = '';
358
- $column_class = '';
359
- // Featured post
360
- if ( $columns !== 'col-12' && $featured_post ) :
361
- if ( $query->current_post == 0 && $paged == 1 ) {
362
- $featured = ' featured-column ' . $current_post;
363
- } else {
364
- $featured = ' ' . $columns;
365
- }
366
- elseif ( $columns !== 'col-12' ) :
367
- $column_class .= ' ' . $columns;
368
- endif;
369
-
370
- $terms_list = '';
371
- // if ( $filter ) :
372
- // $terms_list = wp_get_post_terms( get_the_ID(), $taxonomy );
373
- // $output_terms = array();
374
- // foreach ( $terms_list as $term ) {
375
- // $output_terms[] = $term->term_id;
376
- // }
377
- // $terms_list = 'data-category="' . implode( ', ', $output_terms ) . '"';
378
- // endif;
379
-
380
- // Start inner container
381
- echo '<' . $inner_wrapper . ' class="' . implode( ' ', $inner_wrapper_class ) . $column_class . $featured . '" itemtype="http://schema.org/' . $itemtype . '" itemscope ' . $terms_list . '>';
382
- echo '<div class="wp-show-posts-inner"' . $inner_wrapper_style . '>';
383
-
384
- do_action( 'wpsp_before_header' );
385
-
386
- // The title
387
- if ( $include_title || ( $include_author && 'below-title' == $author_location ) || ( $include_date && 'below-title' == $date_location ) || ( $include_terms && 'below-title' == $terms_location ) ) : ?>
388
- <header class="wp-show-posts-entry-header">
389
- <?php
390
-
391
- do_action( 'wpsp_before_title' );
392
-
393
- if ( $include_title )
394
- the_title( sprintf( '<h2 class="wp-show-posts-entry-title" itemprop="headline"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' );
395
-
396
- do_action( 'wpsp_after_title' );
397
- ?>
398
- </header><!-- .entry-header -->
399
- <?php endif;
400
-
401
- do_action( 'wpsp_before_content' );
402
-
403
- // The excerpt or full content
404
- if ( 'excerpt' == $content_type && $excerpt_length ) : ?>
405
- <div class="wp-show-posts-entry-summary" itemprop="text">
406
- <?php wpsp_excerpt( '', $excerpt_length ); ?>
407
- </div><!-- .entry-summary -->
408
- <?php elseif ( 'full' == $content_type ) : ?>
409
- <div class="wp-show-posts-entry-content" itemprop="text">
410
- <?php the_content( false, false ); ?>
411
- </div><!-- .entry-content -->
412
- <?php endif;
413
-
414
- do_action( 'wpsp_after_content' );
415
-
416
- echo '</div><!-- wp-show-posts-inner -->';
417
- if ( 'col-12' == $columns ) echo '<div class="wpsp-clear"></div>';
418
- // End inner container
419
- echo '</' . $inner_wrapper . '>';
420
- }
421
- } else {
422
- // no posts found
423
- echo ( $columns !== 'col-12' ) ? '<div class="wpsp-no-results" style="margin-left: ' . $columns_gutter . ';">' : '';
424
- echo wpautop( $no_results );
425
- echo ( $columns !== 'col-12' ) ? '</div>' : '';
426
- }
427
- if ( $columns !== 'col-12' ) echo '<div class="wpsp-clear"></div>';
428
- echo '</' . $wrapper . '><!-- .wp-show-posts -->';
429
-
430
- do_action( 'wpsp_after_wrapper' );
431
-
432
- // Pagination
433
- if ( $pagination && $query->have_posts() && ! is_single() ) :
434
- if ( $ajax_pagination && function_exists( 'wpsp_ajax_pagination' ) ) :
435
-
436
- $max_page = $query->max_num_pages;
437
- $nextpage = intval( $paged ) + 1;
438
-
439
- if ( $nextpage <= $max_page )
440
- $next_page_url = next_posts( $max_page, false );
441
-
442
- wpsp_ajax_pagination( $next_page_url, $paged, $max_page );
443
- wp_enqueue_script( 'wpsp-imagesloaded' );
444
- wp_enqueue_script( 'wpsp-ajax-pagination' );
445
- else :
446
- wpsp_pagination( $query->max_num_pages );
447
- endif;
448
- endif;
449
-
450
- // Lightbox and gallery
451
- if ( $image_lightbox ) {
452
- wp_enqueue_script( 'wpsp-featherlight' );
453
- wp_enqueue_style( 'wpsp-featherlight' );
454
-
455
- if ( $image_gallery ) {
456
- wp_enqueue_script( 'wpsp-featherlight-gallery' );
457
- wp_enqueue_style( 'wpsp-featherlight-gallery' );
458
- }
459
- }
460
-
461
- // Restore original Post Data
462
- wp_reset_postdata();
463
- }
464
- endif;
465
-
466
- if ( ! function_exists( 'wpsp_shortcode_function' ) ) :
467
- /*
468
- * Build the shortcode
469
- * @since 0.1
470
- */
471
- add_shortcode( 'wp_show_posts', 'wpsp_shortcode_function' );
472
- function wpsp_shortcode_function( $atts , $content = null ) {
473
- // Attributes
474
- $atts = shortcode_atts(
475
- array(
476
- 'id' => '',
477
- ), $atts, 'wp_show_posts'
478
- );
479
- ob_start();
480
-
481
- if ( $atts[ 'id' ] )
482
- wpsp_display( $atts[ 'id' ] );
483
-
484
- return ob_get_clean();
485
- }
 
 
 
 
 
 
 
486
  endif;
1
+ <?php
2
+ /*
3
+ Plugin Name: WP Show Posts
4
+ Plugin URI: https://wpshowposts.com
5
+ Description: WP Show Posts allows you to list posts (from any post type) anywhere on your site. This includes WooCommerce products or any other post type you might have! Check out the pro version for even more features at https://wpshowposts.com.
6
+ Version: 0.7
7
+ Author: Tom Usborne
8
+ Author URI: https://tomusborne.com
9
+ License: GNU General Public License v2 or later
10
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
+ Text Domain: wp-show-posts
12
+ */
13
+
14
+ // No direct access, please
15
+ if ( ! defined( 'ABSPATH' ) ) exit;
16
+
17
+ // Define the current version
18
+ define( 'WPSP_VERSION', 0.7 );
19
+
20
+ // Add defaults
21
+ require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'inc/defaults.php';
22
+
23
+ // Add post type
24
+ require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/post-type.php';
25
+
26
+ // Add admin metabox
27
+ require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/metabox.php';
28
+
29
+ // Add admin AJAX
30
+ require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/ajax.php';
31
+
32
+ // Add resizer script
33
+ if ( ! class_exists( 'WPSP_Resize' ) ) require_once plugin_dir_path( __FILE__ ) . 'inc/image-resizer.php';
34
+
35
+ // Add functions
36
+ require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'inc/functions.php';
37
+
38
+ // Add admin functions
39
+ require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/admin.php';
40
+
41
+ // Add widget
42
+ require_once trailingslashit( plugin_dir_path( __FILE__ ) ) . 'admin/widget.php';
43
+
44
+ if ( ! function_exists( 'wpsp_load_textdomain' ) ) :
45
+ /**
46
+ * Load plugin textdomain.
47
+ *
48
+ * @since 0.5
49
+ */
50
+ add_action( 'plugins_loaded', 'wpsp_load_textdomain' );
51
+ function wpsp_load_textdomain()
52
+ {
53
+ load_plugin_textdomain( 'wp-show-posts' );
54
+ }
55
+ endif;
56
+
57
+ if ( ! function_exists( 'wpsp_get_min_suffix' ) ) :
58
+ /**
59
+ * Figure out if we should use minified scripts or not
60
+ * @since 0.1
61
+ */
62
+ function wpsp_get_min_suffix()
63
+ {
64
+ return defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '-min';
65
+ }
66
+ endif;
67
+
68
+ if ( ! function_exists( 'wpsp_enqueue_scripts' ) ) :
69
+ /*
70
+ * Enqueue our CSS to the front end
71
+ * @since 0.1
72
+ */
73
+ add_action( 'wp_enqueue_scripts', 'wpsp_enqueue_scripts' );
74
+ function wpsp_enqueue_scripts()
75
+ {
76
+ $suffix = wpsp_get_min_suffix();
77
+ wp_enqueue_style( 'wp-show-posts', plugins_url( "css/wp-show-posts{$suffix}.css", __FILE__ ), array(), WPSP_VERSION );
78
+ }
79
+ endif;
80
+
81
+ if ( ! function_exists( 'wpsp_get_setting' ) ) :
82
+ /*
83
+ * Create a helpful wrapper to get our settings and defaults
84
+ * @since 0.1
85
+ */
86
+ function wpsp_get_setting( $id, $key )
87
+ {
88
+ $defaults = wpsp_get_defaults();
89
+ return get_post_meta( $id, $key ) ? get_post_meta( $id, $key, true ) : $defaults[ $key ];
90
+ }
91
+ endif;
92
+
93
+ if ( ! function_exists( 'wpsp_display' ) ) :
94
+ /*
95
+ * Build the front end of the plugin
96
+ * $id parameter needs to match ID of custom post type entry
97
+ * @since 0.1
98
+ */
99
+ function wpsp_display( $id )
100
+ {
101
+ // Set the global ID of our object
102
+ global $wpsp_id;
103
+ $wpsp_id = $id;
104
+
105
+ // Build our setting variables
106
+ $author = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_author' ) );
107
+ $columns = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_columns' ) );
108
+ $columns_gutter = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_columns_gutter' ) );
109
+ $content_type = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_content_type' ) );
110
+ $exclude_current = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_exclude_current' ) );
111
+ $excerpt_length = absint( wpsp_get_setting( $id, 'wpsp_excerpt_length' ) );
112
+ $post_id = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_post_id' ) );
113
+ $exclude_post_id = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_exclude_post_id' ) );
114
+ $ignore_sticky_posts = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_ignore_sticky_posts' ) );
115
+ $image_gallery = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_image_gallery' ) );
116
+ $image_lightbox = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_image_lightbox' ) );
117
+ $include_title = wp_validate_boolean( get_post_meta( $id, 'wpsp_include_title', true ) );
118
+ $author_location = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_author_location' ) );
119
+ $date_location = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_date_location' ) );
120
+ $terms_location = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_terms_location' ) );
121
+ $include_author = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_include_author' ) );
122
+ $include_terms = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_include_terms' ) );
123
+ $include_date = wp_validate_boolean( get_post_meta( $id, 'wpsp_include_date', true ) );
124
+ $inner_wrapper = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_inner_wrapper' ) );
125
+ $inner_wrapper_class = array_map( 'sanitize_html_class', ( explode( ' ', wpsp_get_setting( $id, 'wpsp_inner_wrapper_class' ) ) ) );
126
+ $inner_wrapper_style = explode( ' ', esc_attr( wpsp_get_setting( $id, 'wpsp_inner_wrapper_style' ) ) );
127
+ $itemtype = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_itemtype' ) );
128
+ $meta_key = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_meta_key' ) );
129
+ $meta_value = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_meta_value' ) );
130
+ $offset = absint( wpsp_get_setting( $id, 'wpsp_offset' ) );
131
+ $order = sanitize_key( wpsp_get_setting( $id, 'wpsp_order' ) );
132
+ $orderby = sanitize_key( wpsp_get_setting( $id, 'wpsp_orderby' ) );
133
+ $pagination = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_pagination' ) );
134
+ $post_type = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_post_type' ) );
135
+ $post_status = wpsp_get_setting( $id, 'wpsp_post_status' ); // Validated later
136
+ $posts_per_page = intval( wpsp_get_setting( $id, 'wpsp_posts_per_page' ) );
137
+ $tax_operator = wpsp_get_setting( $id, 'wpsp_tax_operator' ); // Validated later
138
+ $tax_term = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_tax_term' ) );
139
+ $taxonomy = sanitize_key( wpsp_get_setting( $id, 'wpsp_taxonomy' ) );
140
+ $wrapper = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_wrapper' ) );
141
+ $wrapper_id = sanitize_html_class( wpsp_get_setting( $id, 'wpsp_wrapper_id' ) );
142
+ $wrapper_class = array_map( 'sanitize_html_class', ( explode( ' ', wpsp_get_setting( $id, 'wpsp_wrapper_class' ) ) ) );
143
+ $wrapper_style = explode( ' ', esc_attr( wpsp_get_setting( $id, 'wpsp_wrapper_style' ) ) );
144
+ $no_results = wp_kses_post( wpsp_get_setting( $id, 'wpsp_no_results' ) );
145
+ $ajax_pagination = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_ajax_pagination' ) );
146
+ $masonry = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_masonry' ) );
147
+ $featured_post = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_featured_post' ) );
148
+ $border = wpsp_sanitize_hex_color( wpsp_get_setting( $id, 'wpsp_border' ) );
149
+ $padding = sanitize_text_field( wpsp_get_setting( $id, 'wpsp_padding' ) );
150
+ $filter = wp_validate_boolean( wpsp_get_setting( $id, 'wpsp_filter' ) );
151
+
152
+ // Grab initiate args for query
153
+ $args = array();
154
+
155
+ if ( '' !== $order )
156
+ $args[ 'order' ] = $order;
157
+
158
+ if ( '' !== $orderby )
159
+ $args[ 'orderby' ] = $orderby;
160
+
161
+ if ( '' !== $post_type )
162
+ $args[ 'post_type' ] = $post_type;
163
+
164
+ if ( '' !== $posts_per_page )
165
+ $args[ 'posts_per_page' ] = $posts_per_page;
166
+
167
+ if ( $ignore_sticky_posts )
168
+ $args[ 'ignore_sticky_posts' ] = $ignore_sticky_posts;
169
+
170
+ if ( '' !== $meta_key )
171
+ $args[ 'meta_key' ] = $meta_key;
172
+
173
+ if ( '' !== $meta_value )
174
+ $args[ 'meta_value' ] = $meta_value;
175
+
176
+ if ( $offset > 0 )
177
+ $args[ 'offset' ] = $offset;
178
+
179
+ if ( '' !== $author )
180
+ $args[ 'author' ] = array( $author );
181
+
182
+ if ( $pagination && ! is_single() ) :
183
+ $paged_query = is_front_page() ? 'page' : 'paged';
184
+ $args[ 'paged' ] = get_query_var( $paged_query );
185
+ endif;
186
+
187
+ // Post Status
188
+ $post_status = explode( ', ', $post_status );
189
+ $validated = array();
190
+ $available = array( 'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash', 'any' );
191
+
192
+ foreach ( $post_status as $unvalidated )
193
+ if ( in_array( $unvalidated, $available ) )
194
+ $validated[] = $unvalidated;
195
+
196
+ if( !empty( $validated ) )
197
+ $args['post_status'] = $validated;
198
+
199
+ // If taxonomy attributes, create a taxonomy query
200
+ if ( !empty( $taxonomy ) && !empty( $tax_term ) ) {
201
+
202
+ if ( 'current' == $tax_term ) {
203
+ global $post;
204
+ $terms = wp_get_post_terms(get_the_ID(), $taxonomy);
205
+ $tax_term = array();
206
+ foreach ($terms as $term) {
207
+ $tax_term[] = $term->slug;
208
+ }
209
+ } else {
210
+ // Term string to array
211
+ $tax_term = explode( ', ', $tax_term );
212
+ }
213
+
214
+ // Validate operator
215
+ if( !in_array( $tax_operator, array( 'IN', 'NOT IN', 'AND' ) ) )
216
+ $tax_operator = 'IN';
217
+
218
+ $tax_args = array(
219
+ 'tax_query' => array(
220
+ array(
221
+ 'taxonomy' => $taxonomy,
222
+ 'field' => 'slug',
223
+ 'terms' => $tax_term,
224
+ 'operator' => $tax_operator
225
+ )
226
+ )
227
+ );
228
+
229
+ $args = array_merge( $args, $tax_args );
230
+ }
231
+
232
+ // If Post IDs
233
+ if( $post_id ) {
234
+ $posts_in = array_map( 'intval', explode( ',', $post_id ) );
235
+ $args['post__in'] = $posts_in;
236
+ }
237
+
238
+ // If Exclude Post IDs
239
+ if( $exclude_post_id ) {
240
+ $posts_not_in = array_map( 'intval', explode( ',', $exclude_post_id ) );
241
+ $args['post__not_in'] = $posts_not_in;
242
+ }
243
+
244
+ // If Exclude Current
245
+ if( ( is_singular() && $exclude_current ) || is_single() )
246
+ $args['post__not_in'] = array( get_the_ID() );
247
+
248
+ // Border
249
+ if ( '' !== $border ) {
250
+ $wrapper_class[] = 'include-border';
251
+ $border = 'border-color: ' . $border . ';';
252
+ }
253
+
254
+ // Padding
255
+ if ( '' !== $padding ) {
256
+ $wrapper_class[] = 'include-padding';
257
+ $padding = 'padding:' . $padding . ';';
258
+ }
259
+
260
+ // Columns
261
+ if ( $columns !== 'col-12' ) :
262
+ wp_enqueue_script( 'wpsp-matchHeight', trailingslashit( plugin_dir_url( __FILE__ ) ) . 'js/jquery.matchHeight.js', array( 'jquery' ), WPSP_VERSION, true );
263
+ $wrapper_class[] = 'wp-show-posts-columns';
264
+ $wrapper_style[] = 'margin-left:-' . $columns_gutter . ';';
265
+ $inner_wrapper_style[] = 'margin: 0 0 ' . $columns_gutter . ' ' . $columns_gutter . ';' . $border . $padding;
266
+ endif;
267
+
268
+ // Featured post class
269
+ $current_post = '';
270
+ if ( $columns !== 'col-12' && $featured_post ) :
271
+ if ( $columns == 'col-6' )
272
+ $current_post = 'wpsp-col-12';
273
+
274
+ if ( $columns == 'col-4' )
275
+ $current_post = 'wpsp-col-8';
276
+
277
+ if ( $columns == 'col-3' )
278
+ $current_post = 'wpsp-col-6';
279
+
280
+ if ( $columns == 'col-20' )
281
+ $current_post = 'wpsp-col-6';
282
+ endif;
283
+
284
+ // Masonry
285
+ if ( $masonry ) :
286
+ $wrapper_class[] = 'wp-show-posts-masonry';
287
+ $inner_wrapper_class[] = ' wp-show-posts-masonry-' . $columns;
288
+ $inner_wrapper_class[] = ' wp-show-posts-masonry-block';
289
+
290
+ wp_enqueue_script( 'wpsp-imagesloaded' );
291
+ wp_enqueue_script( 'jquery-masonry' );
292
+ wp_add_inline_script( 'jquery-masonry', 'jQuery(function($){var $container = $(".wp-show-posts-masonry");$container.imagesLoaded( function(){$container.fadeIn( 1000 ).masonry({itemSelector : ".wp-show-posts-masonry-block",columnWidth: ".grid-sizer"}).css("opacity","1");});});' );
293
+ endif;
294
+
295
+ // Filter
296
+ // if ( $filter ) :
297
+ // wp_enqueue_script( 'wpsp-imagesloaded' );
298
+ // wp_enqueue_script( 'wpsp-filterizr' );
299
+ // wp_add_inline_script( 'wpsp-filterizr', 'jQuery(function($){ var $filterizd = $( ".wp-show-posts" );$filterizd.imagesLoaded( function(){ $( ".wp-show-posts" ).filterizr("setOptions", {layout: "sameWidth"}); } )});' );
300
+ // $inner_wrapper_class[] = 'filtr-item';
301
+ // endif;
302
+
303
+ // Add the default inner wrapper class
304
+ // We don't create the class element up here like below, as we need to add classes inside the loop below as well
305
+ $inner_wrapper_class[] = 'wp-show-posts-single';
306
+
307
+ if ( 'col-12' == $columns )
308
+ $inner_wrapper_class[] = 'wpsp-clearfix';
309
+
310
+ // Add the default wrapper class
311
+ $wrapper_class[] = 'wp-show-posts';
312
+
313
+ // Get the wrapper class
314
+ if( !empty( $wrapper_class ) )
315
+ $wrapper_class = ' class="' . implode( ' ', $wrapper_class ) . '"';
316
+
317
+ // Get the wrapper style
318
+ if( !empty( $wrapper_style ) )
319
+ $wrapper_style = ' style="' . implode( ' ', $wrapper_style ) . '"';
320
+
321
+ // Get the inner wrapper class
322
+ if( !empty( $inner_wrapper_style ) )
323
+ $inner_wrapper_style = ' style="' . implode( ' ', $inner_wrapper_style ) . '"';
324
+
325
+ // Get the wrapper ID
326
+ if( !empty( $wrapper_id ) )
327
+ $wrapper_id = ' id="' . $wrapper_id . '"';
328
+
329
+ $wrapper_atts = apply_filters( 'wpsp_wrapper_atts', '' );
330
+
331
+ do_action( 'wpsp_before_wrapper' );
332
+
333
+ // if ( $filter ) :
334
+ // $post_terms = get_terms( sanitize_text_field( $taxonomy ), 'orderby=count&hide_empty=1' );
335
+ // echo '<ul>';
336
+ // foreach ( $post_terms as $term ) {
337
+ // echo '<li data-filter="' . $term->term_id . '">' . $term->name . '</li>';
338
+ // }
339
+ // echo '</ul>';
340
+ // endif;
341
+
342
+ // Start the wrapper
343
+ echo '<' . $wrapper . $wrapper_id . $wrapper_class . $wrapper_style . $wrapper_atts . '>';
344
+
345
+ if ( $masonry )
346
+ echo '<div class="grid-sizer wpsp-' . $columns . '"></div>';
347
+
348
+ // Start the query
349
+ $query = new WP_Query( apply_filters( 'wp_show_posts_shortcode_args', $args ) );
350
+
351
+ // Start the loop
352
+ if ( $query->have_posts() ) {
353
+ while ( $query->have_posts() ) {
354
+ $query->the_post();
355
+
356
+ // Get page
357
+ $paged_query = is_front_page() ? 'page' : 'paged';
358
+ $paged = ( get_query_var( $paged_query ) ) ? get_query_var( $paged_query ) : 1;
359
+
360
+ $featured = '';
361
+ $column_class = '';
362
+ // Featured post
363
+ if ( $columns !== 'col-12' && $featured_post ) :
364
+ if ( $query->current_post == 0 && $paged == 1 ) {
365
+ $featured = ' featured-column ' . $current_post;
366
+ } else {
367
+ $featured = ' wpsp-' . $columns;
368
+ }
369
+ elseif ( $columns !== 'col-12' ) :
370
+ $column_class .= ' wpsp-' . $columns;
371
+ endif;
372
+
373
+ $terms_list = '';
374
+ // if ( $filter ) :
375
+ // $terms_list = wp_get_post_terms( get_the_ID(), $taxonomy );
376
+ // $output_terms = array();
377
+ // foreach ( $terms_list as $term ) {
378
+ // $output_terms[] = $term->term_id;
379
+ // }
380
+ // $terms_list = 'data-category="' . implode( ', ', $output_terms ) . '"';
381
+ // endif;
382
+
383
+ // Start inner container
384
+ echo '<' . $inner_wrapper . ' class="' . implode( ' ', $inner_wrapper_class ) . $column_class . $featured . '" itemtype="http://schema.org/' . $itemtype . '" itemscope ' . $terms_list . '>';
385
+ echo '<div class="wp-show-posts-inner"' . $inner_wrapper_style . '>';
386
+
387
+ do_action( 'wpsp_before_header' );
388
+
389
+ // The title
390
+ if ( $include_title || ( $include_author && 'below-title' == $author_location ) || ( $include_date && 'below-title' == $date_location ) || ( $include_terms && 'below-title' == $terms_location ) ) : ?>
391
+ <header class="wp-show-posts-entry-header">
392
+ <?php
393
+
394
+ do_action( 'wpsp_before_title' );
395
+
396
+ if ( $include_title )
397
+ the_title( sprintf( '<h2 class="wp-show-posts-entry-title" itemprop="headline"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' );
398
+
399
+ do_action( 'wpsp_after_title' );
400
+ ?>
401
+ </header><!-- .entry-header -->
402
+ <?php endif;
403
+
404
+ do_action( 'wpsp_before_content' );
405
+
406
+ // Check to see if we have the more tag
407
+ global $post;
408
+ $more_tag = apply_filters( 'wpsp_more_tag', @strpos( $post->post_content, '<!--more-->' ) );
409
+
410
+ // The excerpt or full content
411
+ if ( 'excerpt' == $content_type && $excerpt_length && ! $more_tag && 'none' !== $content_type ) : ?>
412
+ <div class="wp-show-posts-entry-summary" itemprop="text">
413
+ <?php echo wp_trim_words( get_the_content(), $excerpt_length, '' ); ?>
414
+ </div><!-- .entry-summary -->
415
+ <?php elseif ( ( 'full' == $content_type || $more_tag ) && 'none' !== $content_type ) : ?>
416
+ <div class="wp-show-posts-entry-content" itemprop="text">
417
+ <?php the_content( false, false ); ?>
418
+ </div><!-- .entry-content -->
419
+ <?php endif;
420
+
421
+ do_action( 'wpsp_after_content' );
422
+
423
+ echo '</div><!-- wp-show-posts-inner -->';
424
+ if ( 'col-12' == $columns ) echo '<div class="wpsp-clear"></div>';
425
+ // End inner container
426
+ echo '</' . $inner_wrapper . '>';
427
+ }
428
+ } else {
429
+ // no posts found
430
+ echo ( $columns !== 'col-12' ) ? '<div class="wpsp-no-results" style="margin-left: ' . $columns_gutter . ';">' : '';
431
+ echo wpautop( $no_results );
432
+ echo ( $columns !== 'col-12' ) ? '</div>' : '';
433
+ }
434
+ if ( $columns !== 'col-12' ) echo '<div class="wpsp-clear"></div>';
435
+ echo '</' . $wrapper . '><!-- .wp-show-posts -->';
436
+
437
+ do_action( 'wpsp_after_wrapper' );
438
+
439
+ // Pagination
440
+ if ( $pagination && $query->have_posts() && ! is_single() ) :
441
+ if ( $ajax_pagination && function_exists( 'wpsp_ajax_pagination' ) ) :
442
+
443
+ $max_page = $query->max_num_pages;
444
+ $nextpage = intval( $paged ) + 1;
445
+
446
+ if ( $nextpage <= $max_page )
447
+ $next_page_url = next_posts( $max_page, false );
448
+
449
+ wpsp_ajax_pagination( $next_page_url, $paged, $max_page );
450
+ wp_enqueue_script( 'wpsp-imagesloaded' );
451
+ wp_enqueue_script( 'wpsp-ajax-pagination' );
452
+ else :
453
+ wpsp_pagination( $query->max_num_pages );
454
+ endif;
455
+ endif;
456
+
457
+ // Lightbox and gallery
458
+ if ( $image_lightbox ) {
459
+ wp_enqueue_script( 'wpsp-featherlight' );
460
+ wp_enqueue_style( 'wpsp-featherlight' );
461
+
462
+ if ( $image_gallery ) {
463
+ wp_enqueue_script( 'wpsp-featherlight-gallery' );
464
+ wp_enqueue_style( 'wpsp-featherlight-gallery' );
465
+ }
466
+ }
467
+
468
+ // Restore original Post Data
469
+ wp_reset_postdata();
470
+ }
471
+ endif;
472
+
473
+ if ( ! function_exists( 'wpsp_shortcode_function' ) ) :
474
+ /*
475
+ * Build the shortcode
476
+ * @since 0.1
477
+ */
478
+ add_shortcode( 'wp_show_posts', 'wpsp_shortcode_function' );
479
+ function wpsp_shortcode_function( $atts , $content = null ) {
480
+ // Attributes
481
+ $atts = shortcode_atts(
482
+ array(
483
+ 'id' => '',
484
+ ), $atts, 'wp_show_posts'
485
+ );
486
+ ob_start();
487
+
488
+ if ( $atts[ 'id' ] )
489
+ wpsp_display( $atts[ 'id' ] );
490
+
491
+ return ob_get_clean();
492
+ }
493
  endif;