├── assets
├── css
│ ├── admin.css
│ ├── admin.less
│ ├── layout.css
│ └── layout.less
└── images
│ ├── features-icon.png
│ └── features-icon@x2.png
├── classes
├── class-woothemes-features-taxonomy.php
├── class-woothemes-features.php
└── class-woothemes-widget-features.php
├── lang
├── woothemes-features-en_GB.po
└── woothemes-features-xx_XX.pot
├── readme.txt
├── woothemes-features-template.php
└── woothemes-features.php
/assets/css/admin.css:
--------------------------------------------------------------------------------
1 | #adminmenu .menu-icon-feature div.wp-menu-image:before {
2 | content: '\f155';
3 | }
--------------------------------------------------------------------------------
/assets/css/admin.less:
--------------------------------------------------------------------------------
1 | // Features icon
2 | #adminmenu .menu-icon-feature div.wp-menu-image:before {
3 | content: '\f155';
4 | }
--------------------------------------------------------------------------------
/assets/css/layout.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Front-end layout styles.
3 | */
4 | .clearfix {
5 | zoom: 1;
6 | }
7 | .clearfix:before,
8 | .clearfix:after {
9 | content: "";
10 | display: table;
11 | }
12 | .clearfix:after {
13 | clear: both;
14 | }
15 | .widget_woothemes_features {
16 | margin: 0;
17 | zoom: 1;
18 | }
19 | .widget_woothemes_features:before,
20 | .widget_woothemes_features:after {
21 | content: "";
22 | display: table;
23 | }
24 | .widget_woothemes_features:after {
25 | clear: both;
26 | }
27 | .widget_woothemes_features > h3 {
28 | margin: 0 0 .8em;
29 | }
30 | .widget_woothemes_features .feature {
31 | display: block;
32 | text-align: center;
33 | margin-bottom: 2em;
34 | }
35 | .widget_woothemes_features .feature h3 a {
36 | color: inherit;
37 | }
38 | .widget_woothemes_features .feature img {
39 | float: none;
40 | margin: 0 auto 1em auto;
41 | border: none;
42 | }
43 | .widget_woothemes_features .feature .feature-title {
44 | margin: 0 0 .8em;
45 | padding: 0;
46 | font-size: 1.2em;
47 | border: none;
48 | }
49 | @media only screen and (min-width: 980px) {
50 | #main .widget_woothemes_features .columns-1 .feature {
51 | width: 100%;
52 | text-align: left;
53 | }
54 | #main .widget_woothemes_features .columns-1 .feature img {
55 | float: left;
56 | margin: 0 2em 0 1em;
57 | }
58 | #main .widget_woothemes_features .columns-2 .feature {
59 | width: 47%;
60 | text-align: left;
61 | }
62 | #main .widget_woothemes_features .columns-2 .feature img {
63 | float: left;
64 | margin: 0 2em 0 1em;
65 | }
66 | #main .widget_woothemes_features .columns-3 .feature {
67 | width: 30%;
68 | text-align: center;
69 | }
70 | #main .widget_woothemes_features .columns-3 .feature img {
71 | float: none;
72 | }
73 | #main .widget_woothemes_features .columns-4 .feature {
74 | width: 21%;
75 | text-align: center;
76 | }
77 | #main .widget_woothemes_features .columns-4 .feature img {
78 | float: none;
79 | }
80 | #main .widget_woothemes_features .columns-5 .feature {
81 | width: 16%;
82 | text-align: center;
83 | }
84 | #main .widget_woothemes_features .columns-5 .feature img {
85 | float: none;
86 | }
87 | #main .widget_woothemes_features .columns-6 .feature {
88 | width: 12.4%;
89 | text-align: center;
90 | }
91 | #main .widget_woothemes_features .columns-6 .feature img {
92 | float: none;
93 | }
94 | #main .widget_woothemes_features .feature {
95 | float: left;
96 | margin-right: 5%;
97 | }
98 | #main .widget_woothemes_features .feature.last {
99 | margin-right: 0;
100 | }
101 | #main .widget_woothemes_features .feature .feature-content {
102 | overflow: hidden;
103 | }
104 | #sidebar .widget_woothemes_features .columns-2 .feature,
105 | #sidebar .widget_woothemes_features .columns-3 .feature,
106 | #sidebar .widget_woothemes_features .columns-4 .feature,
107 | #sidebar .widget_woothemes_features .columns-5 .feature,
108 | #sidebar .widget_woothemes_features .columns-6 .feature {
109 | width: 100%;
110 | float: none;
111 | margin-right: 0;
112 | clear: both;
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/assets/css/layout.less:
--------------------------------------------------------------------------------
1 | /**
2 | * Front-end layout styles.
3 | */
4 |
5 | .clearfix {
6 | zoom: 1; // For IE 6/7 (trigger hasLayout)
7 |
8 | &:before, &:after {
9 | content: "";
10 | display: table;
11 | }
12 |
13 | &:after {
14 | clear:both;
15 | }
16 | }
17 |
18 | .widget_woothemes_features {
19 | margin: 0;
20 | .clearfix;
21 |
22 | > h3 {
23 | margin: 0 0 .8em;
24 | }
25 |
26 | .feature {
27 | display:block;
28 | text-align: center;
29 | margin-bottom: 2em;
30 |
31 | h3 a {
32 | color: inherit;
33 | }
34 |
35 | img {
36 | float: none;
37 | margin: 0 auto 1em auto;
38 | border: none;
39 | }
40 |
41 | .feature-title {
42 | margin: 0 0 .8em;
43 | padding: 0;
44 | font-size: 1.2em;
45 | border: none;
46 | }
47 | }
48 | }
49 |
50 | // Layout
51 | @media only screen and ( min-width: 980px ) {
52 |
53 | #main {
54 | .widget_woothemes_features {
55 | .columns-1 {
56 | .feature {
57 | width: 100%;
58 | text-align: left;
59 |
60 | img {
61 | float: left;
62 | margin: 0 2em 0 1em;
63 | }
64 | }
65 | }
66 |
67 | .columns-2 {
68 | .feature {
69 | width: 47%;
70 | text-align:left;
71 |
72 | img {
73 | float:left;
74 | margin: 0 2em 0 1em;
75 | }
76 | }
77 | }
78 |
79 | .columns-3 {
80 | .feature {
81 | width: 30%;
82 | text-align:center;
83 |
84 | img {
85 | float:none;
86 | }
87 | }
88 | }
89 | .columns-4 {
90 | .feature {
91 | width: 21%;
92 | text-align:center;
93 |
94 | img {
95 | float:none;
96 | }
97 | }
98 | }
99 | .columns-5 {
100 | .feature {
101 | width: 16%;
102 | text-align:center;
103 | img {
104 | float:none;
105 | }
106 | }
107 | }
108 |
109 | .columns-6 {
110 | .feature {
111 | width: 12.4%;
112 | text-align:center;
113 |
114 | img {
115 | float:none;
116 | }
117 | }
118 | }
119 |
120 | .feature {
121 | float: left;
122 | margin-right: 5%;
123 |
124 | &.last {
125 | margin-right: 0;
126 | }
127 |
128 | .feature-content{
129 | overflow: hidden;
130 | }
131 | }
132 | }
133 | }
134 |
135 | #sidebar {
136 | .widget_woothemes_features {
137 | .columns-2,
138 | .columns-3,
139 | .columns-4,
140 | .columns-5,
141 | .columns-6 {
142 | .feature {
143 | width: 100%;
144 | float: none;
145 | margin-right: 0;
146 | clear: both;
147 | }
148 | }
149 | }
150 | }
151 | }
--------------------------------------------------------------------------------
/assets/images/features-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/woocommerce/features/1f3c59cc608b3b19254b98411d21f38a4cf82522/assets/images/features-icon.png
--------------------------------------------------------------------------------
/assets/images/features-icon@x2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/woocommerce/features/1f3c59cc608b3b19254b98411d21f38a4cf82522/assets/images/features-icon@x2.png
--------------------------------------------------------------------------------
/classes/class-woothemes-features-taxonomy.php:
--------------------------------------------------------------------------------
1 | post_type = 'feature';
67 | $this->token = esc_attr( $token );
68 | $this->singular = esc_html( $singular );
69 | $this->plural = esc_html( $plural );
70 |
71 | if ( '' == $this->singular ) $this->singular = __( 'Category', 'woothemes-features' );
72 | if ( '' == $this->plural ) $this->plural = __( 'Categories', 'woothemes-features' );
73 |
74 | $this->args = wp_parse_args( $args, $this->_get_default_args() );
75 | } // End __construct()
76 |
77 | /**
78 | * Return an array of default arguments.
79 | * @access private
80 | * @since 1.3.0
81 | * @return array Default arguments.
82 | */
83 | private function _get_default_args () {
84 | return array( 'labels' => $this->_get_default_labels(), 'public' => true, 'hierarchical' => true, 'show_ui' => true, 'show_admin_column' => true, 'query_var' => true, 'show_in_nav_menus' => false, 'show_tagcloud' => false );
85 | } // End _get_default_args()
86 |
87 | /**
88 | * Return an array of default labels.
89 | * @access private
90 | * @since 1.3.0
91 | * @return array Default labels.
92 | */
93 | private function _get_default_labels () {
94 | return array(
95 | 'name' => sprintf( _x( '%s', 'taxonomy general name', 'woothemes-features' ), $this->plural ),
96 | 'singular_name' => sprintf( _x( '%s', 'taxonomy singular name', 'woothemes-features' ), $this->singular ),
97 | 'search_items' => sprintf( __( 'Search %s', 'woothemes-features' ), $this->plural ),
98 | 'all_items' => sprintf( __( 'All %s', 'woothemes-features' ), $this->plural ),
99 | 'parent_item' => sprintf( __( 'Parent %s', 'woothemes-features' ), $this->singular ),
100 | 'parent_item_colon' => sprintf( __( 'Parent %s:', 'woothemes-features' ), $this->singular ),
101 | 'edit_item' => sprintf( __( 'Edit %s', 'woothemes-features' ), $this->singular ),
102 | 'update_item' => sprintf( __( 'Update %s', 'woothemes-features' ), $this->singular ),
103 | 'add_new_item' => sprintf( __( 'Add New %s', 'woothemes-features' ), $this->singular ),
104 | 'new_item_name' => sprintf( __( 'New %s Name', 'woothemes-features' ), $this->singular ),
105 | 'menu_name' => sprintf( __( '%s', 'woothemes-features' ), $this->plural )
106 | );
107 | } // End _get_default_labels()
108 |
109 | /**
110 | * Register the taxonomy.
111 | * @access public
112 | * @since 1.3.0
113 | * @return void
114 | */
115 | public function register () {
116 | register_taxonomy( esc_attr( $this->token ), esc_attr( $this->post_type ), (array)$this->args );
117 | } // End register()
118 | } // End Class
119 | ?>
--------------------------------------------------------------------------------
/classes/class-woothemes-features.php:
--------------------------------------------------------------------------------
1 | dir = dirname( $file );
33 | $this->file = $file;
34 | $this->assets_dir = trailingslashit( $this->dir ) . 'assets';
35 | $this->assets_url = esc_url( trailingslashit( plugins_url( '/assets/', $file ) ) );
36 | $this->token = 'feature';
37 |
38 | $this->load_plugin_textdomain();
39 | add_action( 'init', array( $this, 'load_localisation' ), 0 );
40 |
41 | // Run this on activation.
42 | register_activation_hook( $this->file, array( $this, 'activation' ) );
43 |
44 | add_action( 'init', array( $this, 'register_post_type' ) );
45 | add_action( 'init', array( $this, 'register_taxonomy' ) );
46 |
47 | if ( is_admin() ) {
48 | global $pagenow;
49 |
50 | add_action( 'admin_menu', array( $this, 'meta_box_setup' ), 20 );
51 | add_action( 'save_post', array( $this, 'meta_box_save' ) );
52 | add_filter( 'enter_title_here', array( $this, 'enter_title_here' ) );
53 | add_action( 'admin_print_styles', array( $this, 'enqueue_admin_styles' ), 10 );
54 | add_filter( 'post_updated_messages', array( $this, 'updated_messages' ) );
55 |
56 | if ( $pagenow == 'edit.php' && isset( $_GET['post_type'] ) && esc_attr( $_GET['post_type'] ) == $this->token ) {
57 | add_filter( 'manage_edit-' . $this->token . '_columns', array( $this, 'register_custom_column_headings' ), 10, 1 );
58 | add_action( 'manage_posts_custom_column', array( $this, 'register_custom_columns' ), 10, 2 );
59 | }
60 | }
61 |
62 | add_action( 'after_setup_theme', array( $this, 'ensure_post_thumbnails_support' ) );
63 | add_action( 'after_setup_theme', array( $this, 'load_frontend_layout_css' ), 20 );
64 | add_action( 'after_setup_theme', array( $this, 'register_image_sizes' ) );
65 | } // End __construct()
66 |
67 | /**
68 | * Register the post type.
69 | *
70 | * @access public
71 | * @param string $token
72 | * @param string 'Features'
73 | * @param string 'Features'
74 | * @param array $supports
75 | * @return void
76 | */
77 | public function register_post_type () {
78 | $labels = array(
79 | 'name' => _x( 'Features', 'post type general name', 'woothemes-features' ),
80 | 'singular_name' => _x( 'Feature', 'post type singular name', 'woothemes-features' ),
81 | 'add_new' => _x( 'Add New', 'feature', 'woothemes-features' ),
82 | 'add_new_item' => sprintf( __( 'Add New %s', 'woothemes-features' ), __( 'Feature', 'woothemes-features' ) ),
83 | 'edit_item' => sprintf( __( 'Edit %s', 'woothemes-features' ), __( 'Feature', 'woothemes-features' ) ),
84 | 'new_item' => sprintf( __( 'New %s', 'woothemes-features' ), __( 'Feature', 'woothemes-features' ) ),
85 | 'all_items' => sprintf( __( 'All %s', 'woothemes-features' ), __( 'Features', 'woothemes-features' ) ),
86 | 'view_item' => sprintf( __( 'View %s', 'woothemes-features' ), __( 'Feature', 'woothemes-features' ) ),
87 | 'search_items' => sprintf( __( 'Search %a', 'woothemes-features' ), __( 'Features', 'woothemes-features' ) ),
88 | 'not_found' => sprintf( __( 'No %s Found', 'woothemes-features' ), __( 'Features', 'woothemes-features' ) ),
89 | 'not_found_in_trash' => sprintf( __( 'No %s Found In Trash', 'woothemes-features' ), __( 'Features', 'woothemes-features' ) ),
90 | 'parent_item_colon' => '',
91 | 'menu_name' => __( 'Features', 'woothemes-features' )
92 |
93 | );
94 |
95 | $single_slug = apply_filters( 'woothemes_features_single_slug', _x( 'feature', 'single post url slug', 'woothemes-features' ) );
96 | $archive_slug = apply_filters( 'woothemes_features_archive_slug', _x( 'features', 'post archive url slug', 'woothemes-features' ) );
97 |
98 | $args = array(
99 | 'labels' => $labels,
100 | 'public' => true,
101 | 'publicly_queryable' => true,
102 | 'show_ui' => true,
103 | 'show_in_menu' => true,
104 | 'query_var' => true,
105 | 'rewrite' => array( 'slug' => $single_slug ),
106 | 'capability_type' => 'post',
107 | 'has_archive' => $archive_slug,
108 | 'hierarchical' => false,
109 | 'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'page-attributes' ),
110 | 'menu_position' => 5,
111 | 'menu_icon' => ''
112 | );
113 | register_post_type( $this->token, apply_filters( 'woothemes_features_post_type_args', $args ) );
114 | } // End register_post_type()
115 |
116 | /**
117 | * Register the "feature-category" taxonomy.
118 | * @access public
119 | * @since 1.3.0
120 | * @return void
121 | */
122 | public function register_taxonomy () {
123 | $this->taxonomy_category = new Woothemes_Features_Taxonomy(); // Leave arguments empty, to use the default arguments.
124 | $this->taxonomy_category->register();
125 | } // End register_taxonomy()
126 |
127 | /**
128 | * Add custom columns for the "manage" screen of this post type.
129 | *
130 | * @access public
131 | * @param string $column_name
132 | * @param int $id
133 | * @since 1.0.0
134 | * @return void
135 | */
136 | public function register_custom_columns ( $column_name, $id ) {
137 | global $wpdb, $post;
138 |
139 | $meta = get_post_custom( $id );
140 |
141 | switch ( $column_name ) {
142 |
143 | case 'image':
144 | $value = '';
145 |
146 | $value = $this->get_image( $id, 40 );
147 |
148 | echo $value;
149 | break;
150 |
151 | default:
152 | break;
153 |
154 | }
155 | } // End register_custom_columns()
156 |
157 | /**
158 | * Add custom column headings for the "manage" screen of this post type.
159 | *
160 | * @access public
161 | * @param array $defaults
162 | * @since 1.0.0
163 | * @return void
164 | */
165 | public function register_custom_column_headings ( $defaults ) {
166 | $new_columns = array( 'image' => __( 'Image', 'woothemes-features' ) );
167 |
168 | $last_item = '';
169 |
170 | if ( isset( $defaults['date'] ) ) { unset( $defaults['date'] ); }
171 |
172 | if ( count( $defaults ) > 2 ) {
173 | $last_item = array_slice( $defaults, -1 );
174 |
175 | array_pop( $defaults );
176 | }
177 | $defaults = array_merge( $defaults, $new_columns );
178 |
179 | if ( $last_item != '' ) {
180 | foreach ( $last_item as $k => $v ) {
181 | $defaults[$k] = $v;
182 | break;
183 | }
184 | }
185 |
186 | return $defaults;
187 | } // End register_custom_column_headings()
188 |
189 | /**
190 | * Update messages for the post type admin.
191 | * @since 1.0.0
192 | * @param array $messages Array of messages for all post types.
193 | * @return array Modified array.
194 | */
195 | public function updated_messages ( $messages ) {
196 | global $post, $post_ID;
197 |
198 | $messages[$this->token] = array(
199 | 0 => '', // Unused. Messages start at index 1.
200 | 1 => sprintf( __( 'Feature updated. %sView feature%s', 'woothemes-features' ), '', '' ),
201 | 2 => __( 'Custom field updated.', 'woothemes-features' ),
202 | 3 => __( 'Custom field deleted.', 'woothemes-features' ),
203 | 4 => __( 'Feature updated.', 'woothemes-features' ),
204 | /* translators: %s: date and time of the revision */
205 | 5 => isset($_GET['revision']) ? sprintf( __( 'Feature restored to revision from %s', 'woothemes-features' ), wp_post_revision_title( (int) $_GET['revision'], false ) ) : false,
206 | 6 => sprintf( __( 'Feature published. %sView feature%s', 'woothemes-features' ), '', '' ),
207 | 7 => __('Feature saved.'),
208 | 8 => sprintf( __( 'Feature submitted. %sPreview feature%s', 'woothemes-features' ), '', '' ),
209 | 9 => sprintf( __( 'Feature scheduled for: %1$s. %2$sPreview feature%3$s', 'woothemes-features' ),
210 | // translators: Publish box date format, see http://php.net/date
211 | '' . date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ) . '', '', '' ),
212 | 10 => sprintf( __( 'Feature draft updated. %sPreview feature%s', 'woothemes-features' ), '', '' ),
213 | );
214 |
215 | return $messages;
216 | } // End updated_messages()
217 |
218 | /**
219 | * Setup the meta box.
220 | *
221 | * @access public
222 | * @since 1.1.0
223 | * @return void
224 | */
225 | public function meta_box_setup () {
226 | add_meta_box( 'feature-data', __( 'Feature Details', 'woothemes-features' ), array( $this, 'meta_box_content' ), $this->token, 'normal', 'high' );
227 | } // End meta_box_setup()
228 |
229 | /**
230 | * The contents of our meta box.
231 | *
232 | * @access public
233 | * @since 1.1.0
234 | * @return void
235 | */
236 | public function meta_box_content () {
237 | global $post_id;
238 | $fields = get_post_custom( $post_id );
239 | $field_data = $this->get_custom_fields_settings();
240 |
241 | $html = '';
242 |
243 | $html .= '';
244 |
245 | if ( 0 < count( $field_data ) ) {
246 | $html .= '
' . "\n";
262 | }
263 |
264 | echo $html;
265 | } // End meta_box_content()
266 |
267 | /**
268 | * Save meta box fields.
269 | *
270 | * @access public
271 | * @since 1.1.0
272 | * @param int $post_id
273 | * @return void
274 | */
275 | public function meta_box_save ( $post_id ) {
276 | global $post, $messages;
277 |
278 | // Verify
279 | if ( ( get_post_type() != $this->token ) || ! wp_verify_nonce( $_POST['woo_' . $this->token . '_noonce'], plugin_basename( $this->dir ) ) ) {
280 | return $post_id;
281 | }
282 |
283 | if ( 'page' == $_POST['post_type'] ) {
284 | if ( ! current_user_can( 'edit_page', $post_id ) ) {
285 | return $post_id;
286 | }
287 | } else {
288 | if ( ! current_user_can( 'edit_post', $post_id ) ) {
289 | return $post_id;
290 | }
291 | }
292 |
293 | $field_data = $this->get_custom_fields_settings();
294 | $fields = array_keys( $field_data );
295 |
296 | foreach ( $fields as $f ) {
297 |
298 | ${$f} = strip_tags(trim($_POST[$f]));
299 |
300 | // Escape the URLs.
301 | if ( 'url' == $field_data[$f]['type'] ) {
302 | ${$f} = esc_url( ${$f} );
303 | }
304 |
305 | if ( get_post_meta( $post_id, '_' . $f ) == '' ) {
306 | add_post_meta( $post_id, '_' . $f, ${$f}, true );
307 | } elseif( ${$f} != get_post_meta( $post_id, '_' . $f, true ) ) {
308 | update_post_meta( $post_id, '_' . $f, ${$f} );
309 | } elseif ( ${$f} == '' ) {
310 | delete_post_meta( $post_id, '_' . $f, get_post_meta( $post_id, '_' . $f, true ) );
311 | }
312 | }
313 | } // End meta_box_save()
314 |
315 | /**
316 | * Customise the "Enter title here" text.
317 | *
318 | * @access public
319 | * @since 1.0.0
320 | * @param string $title
321 | * @return void
322 | */
323 | public function enter_title_here ( $title ) {
324 | if ( get_post_type() == $this->token ) {
325 | $title = __( 'Enter the feature title here', 'woothemes-features' );
326 | }
327 | return $title;
328 | } // End enter_title_here()
329 |
330 | /**
331 | * Enqueue post type admin CSS.
332 | *
333 | * @access public
334 | * @since 1.0.0
335 | * @return void
336 | */
337 | public function enqueue_admin_styles () {
338 | wp_register_style( 'woothemes-features-admin', esc_url( $this->assets_url . 'css/admin.css' ), array(), '1.0.2' );
339 | wp_enqueue_style( 'woothemes-features-admin' );
340 | } // End enqueue_admin_styles()
341 |
342 | /**
343 | * Enqueue post type layout CSS.
344 | *
345 | * @access public
346 | * @since 1.5.0
347 | * @return void
348 | */
349 | public function enqueue_layout_styles () {
350 | wp_register_style( 'woothemes-features-layout', esc_url( $this->assets_url . 'css/layout.css' ), array(), '1.0.0' );
351 | wp_enqueue_style( 'woothemes-features-layout' );
352 | } // End enqueue_layout_styles()
353 |
354 | /**
355 | * Get the settings for the custom fields.
356 | * @since 1.1.0
357 | * @return array
358 | */
359 | public function get_custom_fields_settings () {
360 | $fields = array();
361 |
362 | $fields['url'] = array(
363 | 'name' => __( 'URL', 'woothemes-features' ),
364 | 'description' => __( 'Enter a URL that applies to this feature (for example: http://woothemes.com/).', 'woothemes-features' ),
365 | 'type' => 'url',
366 | 'default' => '',
367 | 'section' => 'info'
368 | );
369 |
370 | return apply_filters( 'woothemes_features_custom_fields_settings', $fields );
371 | } // End get_custom_fields_settings()
372 |
373 | /**
374 | * Get the image for the given ID.
375 | * @param int $id Post ID.
376 | * @param string/array/int $size Image dimension. (default: "feature-thumbnail")
377 | * @since 1.0.0
378 | * @return string
tag.
379 | */
380 | protected function get_image ( $id, $size = 'feature-thumbnail' ) {
381 | $response = '';
382 |
383 | if ( has_post_thumbnail( $id ) ) {
384 | // If not a string or an array, and not an integer, default to 150x9999.
385 | if ( ( is_int( $size ) || ( 0 < intval( $size ) ) ) && ! is_array( $size ) ) {
386 | $size = array( intval( $size ), intval( $size ) );
387 | } elseif ( ! is_string( $size ) && ! is_array( $size ) ) {
388 | $size = array( 150, 9999 );
389 | }
390 | $response = get_the_post_thumbnail( intval( $id ), $size );
391 | }
392 |
393 | return $response;
394 | } // End get_image()
395 |
396 | /**
397 | * Register image sizes.
398 | * @since 1.0.0
399 | * @return void
400 | */
401 | public function register_image_sizes () {
402 | if ( function_exists( 'add_image_size' ) ) {
403 | add_image_size( 'feature-thumbnail', 150, 9999 ); // 150 pixels wide (and unlimited height)
404 | }
405 | } // End register_image_sizes()
406 |
407 | /**
408 | * Get features.
409 | * @param string/array $args Arguments to be passed to the query.
410 | * @since 1.0.0
411 | * @return array/boolean Array if true, boolean if false.
412 | */
413 | public function get_features ( $args = '' ) {
414 | $defaults = array(
415 | 'limit' => 5,
416 | 'orderby' => 'menu_order',
417 | 'order' => 'DESC',
418 | 'id' => 0,
419 | 'category' => 0,
420 | 'custom_links_only' => false
421 | );
422 |
423 | $args = wp_parse_args( $args, $defaults );
424 |
425 | // Allow child themes/plugins to filter here.
426 | $args = apply_filters( 'woothemes_get_features_args', $args );
427 |
428 | // The Query Arguments.
429 | $query_args = array();
430 | $query_args['post_type'] = 'feature';
431 | $query_args['numberposts'] = $args['limit'];
432 | $query_args['orderby'] = $args['orderby'];
433 | $query_args['order'] = $args['order'];
434 | $query_args['suppress_filters'] = false;
435 |
436 | if ( is_numeric( $args['id'] ) && ( intval( $args['id'] ) > 0 ) ) {
437 | $query_args['p'] = intval( $args['id'] );
438 | }
439 |
440 | // Whitelist checks.
441 | if ( ! in_array( $query_args['orderby'], array( 'none', 'ID', 'author', 'title', 'date', 'modified', 'parent', 'rand', 'comment_count', 'menu_order', 'meta_value', 'meta_value_num' ) ) ) {
442 | $query_args['orderby'] = 'date';
443 | }
444 |
445 | if ( ! in_array( $query_args['order'], array( 'ASC', 'DESC' ) ) ) {
446 | $query_args['order'] = 'DESC';
447 | }
448 |
449 | if ( ! in_array( $query_args['post_type'], get_post_types() ) ) {
450 | $query_args['post_type'] = 'feature';
451 | }
452 |
453 | $tax_field_type = '';
454 |
455 | // If the category ID is specified.
456 | if ( is_numeric( $args['category'] ) && 0 < intval( $args['category'] ) ) {
457 | $tax_field_type = 'id';
458 | }
459 |
460 | // If the category slug is specified.
461 | if ( ! is_numeric( $args['category'] ) && is_string( $args['category'] ) ) {
462 | $tax_field_type = 'slug';
463 | }
464 |
465 | // Setup the taxonomy query.
466 | if ( '' != $tax_field_type ) {
467 | $term = $args['category'];
468 | if ( is_string( $term ) ) { $term = esc_html( $term ); } else { $term = intval( $term ); }
469 | $query_args['tax_query'] = array( array( 'taxonomy' => 'feature-category', 'field' => $tax_field_type, 'terms' => array( $term ) ) );
470 | }
471 |
472 | // The Query.
473 | $query = get_posts( $query_args );
474 |
475 | // The Display.
476 | if ( ! is_wp_error( $query ) && is_array( $query ) && count( $query ) > 0 ) {
477 | foreach ( $query as $k => $v ) {
478 | $meta = get_post_custom( $v->ID );
479 |
480 | // Get the image.
481 | $query[$k]->image = $this->get_image( $v->ID, $args['size'] );
482 |
483 | // Get the URL.
484 | if ( isset( $meta['_url'][0] ) && '' != $meta['_url'][0] ) {
485 | $query[$k]->url = esc_url( $meta['_url'][0] );
486 | } else {
487 | if ( true == $args['custom_links_only'] ) {
488 | $query[$k]->url = '';
489 | } else {
490 | $query[$k]->url = get_permalink( $v->ID );
491 | }
492 | }
493 | }
494 | } else {
495 | $query = false;
496 | }
497 |
498 | return $query;
499 | } // End get_features()
500 |
501 | /**
502 | * Load the plugin's localisation file.
503 | * @access public
504 | * @since 1.0.0
505 | * @return void
506 | */
507 | public function load_localisation () {
508 | load_plugin_textdomain( 'woothemes-features', false, dirname( plugin_basename( $this->file ) ) . '/lang/' );
509 | } // End load_localisation()
510 |
511 | /**
512 | * Load the plugin textdomain from the main WordPress "languages" folder.
513 | * @since 1.0.0
514 | * @return void
515 | */
516 | public function load_plugin_textdomain () {
517 | $domain = 'woothemes-features';
518 | // The "plugin_locale" filter is also used in load_plugin_textdomain()
519 | $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
520 |
521 | load_textdomain( $domain, WP_LANG_DIR . '/' . $domain . '/' . $domain . '-' . $locale . '.mo' );
522 | load_plugin_textdomain( $domain, FALSE, dirname( plugin_basename( $this->file ) ) . '/lang/' );
523 | } // End load_plugin_textdomain()
524 |
525 | /**
526 | * Run on activation.
527 | * @access public
528 | * @since 1.0.0
529 | * @return void
530 | */
531 | public function activation () {
532 | $this->register_plugin_version();
533 | $this->flush_rewrite_rules();
534 | } // End activation()
535 |
536 | /**
537 | * Register the plugin's version.
538 | * @access public
539 | * @since 1.0.0
540 | * @return void
541 | */
542 | private function register_plugin_version () {
543 | if ( $this->version != '' ) {
544 | update_option( 'woothemes-features' . '-version', $this->version );
545 | }
546 | } // End register_plugin_version()
547 |
548 | /**
549 | * Flush the rewrite rules
550 | * @access public
551 | * @since 1.3.1
552 | * @return void
553 | */
554 | private function flush_rewrite_rules () {
555 | $this->register_post_type();
556 | flush_rewrite_rules();
557 | } // End flush_rewrite_rules()
558 |
559 | /**
560 | * Ensure that "post-thumbnails" support is available for those themes that don't register it.
561 | * @since 1.0.1
562 | * @return void
563 | */
564 | public function ensure_post_thumbnails_support () {
565 | if ( ! current_theme_supports( 'post-thumbnails' ) ) { add_theme_support( 'post-thumbnails' ); }
566 | } // End ensure_post_thumbnails_support()
567 |
568 | /**
569 | * Load the front-end layout styles for themes that don't include a built-in support for Features.
570 | * @since 1.5.0
571 | * @return void
572 | */
573 | public function load_frontend_layout_css () {
574 | if ( ! current_theme_supports( 'features-by-woothemes' ) || apply_filters( 'woothemes_features_layout_css', false ) ) {
575 | add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_layout_styles' ), 10 );
576 | }
577 | } // End load_frontend_layout_css()
578 |
579 | } // End Class
--------------------------------------------------------------------------------
/classes/class-woothemes-widget-features.php:
--------------------------------------------------------------------------------
1 | woothemes_widget_cssclass = 'widget_woothemes_features';
42 | $this->woothemes_widget_description = __( 'Recent features listed on your site.', 'woothemes-features' );
43 | $this->woothemes_widget_idbase = 'woothemes_features';
44 | $this->woothemes_widget_title = __( 'Features', 'woothemes-features' );
45 |
46 | /* Widget settings. */
47 | $widget_ops = array(
48 | 'classname' => $this->woothemes_widget_cssclass,
49 | 'description' => $this->woothemes_widget_description
50 | );
51 |
52 | /* Widget control settings. */
53 | $control_ops = array(
54 | 'width' => 250,
55 | 'height' => 350,
56 | 'id_base' => $this->woothemes_widget_idbase
57 | );
58 |
59 | /* Create the widget. */
60 | parent::__construct( $this->woothemes_widget_idbase, $this->woothemes_widget_title, $widget_ops, $control_ops );
61 |
62 | } // End __construct()
63 |
64 | /**
65 | * Display the widget on the frontend.
66 | * @since 1.0.0
67 | * @param array $args Widget arguments.
68 | * @param array $instance Widget settings for this instance.
69 | * @return void
70 | */
71 | public function widget( $args, $instance ) {
72 | extract( $args, EXTR_SKIP );
73 |
74 | /* Our variables from the widget settings. */
75 | $title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
76 |
77 | /* Before widget (defined by themes). */
78 | $args = array();
79 |
80 | $args['before'] = $before_widget;
81 |
82 | /* After widget (defined by themes). */
83 | $args['after'] = $after_widget;
84 |
85 | /* Display the widget title if one was input (before and after defined by themes). */
86 | if ( $title ) {
87 | $args['title'] = $title;
88 | $args['before_title'] = $before_title;
89 | $args['after_title'] = $after_title;
90 | }
91 |
92 | /* Widget content. */
93 | // Add actions for plugins/themes to hook onto.
94 | do_action( $this->woothemes_widget_cssclass . '_top' );
95 |
96 | // Integer values.
97 | if ( isset( $instance['limit'] ) && ( 0 < count( $instance['limit'] ) ) ) {
98 | $args['limit'] = intval( $instance['limit'] );
99 | }
100 |
101 | if ( isset( $instance['specific_id'] ) && ( 0 < count( $instance['specific_id'] ) ) ) {
102 | $args['id'] = intval( $instance['specific_id'] );
103 | }
104 |
105 | if ( isset( $instance['size'] ) ){
106 | if( is_numeric( $instance['size'] ) && ( 0 < count( $instance['size'] ) ) ) {
107 | $args['size'] = intval( $instance['size'] );
108 | } else {
109 | $args['size'] = $instance['size'];
110 | }
111 | }
112 |
113 | if ( isset( $instance['per_row'] ) && ( 0 < count( $instance['per_row'] ) ) ) {
114 | $args['per_row'] = intval( $instance['per_row'] );
115 | }
116 |
117 | if ( isset( $instance['category'] ) && is_numeric( $instance['category'] ) ) {
118 | $args['category'] = intval( $instance['category'] );
119 | }
120 |
121 | // Boolean values.
122 | if ( isset( $instance['link_title'] ) && $instance['link_title'] == true && $instance['custom_links_only'] == false ) {
123 | $args['link_title'] = true;
124 | $args['custom_links_only'] = false;
125 | } elseif ( isset( $instance['link_title'] ) && $instance['link_title'] == true && isset( $instance['custom_links_only'] ) && $instance['custom_links_only'] == true ) {
126 | $args['link_title'] = true;
127 | $args['custom_links_only'] = true;
128 | } elseif ( isset( $instance['link_title'] ) && $instance['link_title'] == false && isset( $instance['custom_links_only'] ) && $instance['custom_links_only'] == false ) {
129 | $args['link_title'] = false;
130 | $args['custom_links_only'] = false;
131 | }
132 |
133 | // Select boxes.
134 | if ( isset( $instance['orderby'] ) && in_array( $instance['orderby'], array_keys( $this->get_orderby_options() ) ) ) {
135 | $args['orderby'] = $instance['orderby'];
136 | }
137 |
138 | if ( isset( $instance['order'] ) && in_array( $instance['order'], array_keys( $this->get_order_options() ) ) ) {
139 | $args['order'] = $instance['order'];
140 | }
141 |
142 | // Display the features.
143 | woothemes_features( $args );
144 |
145 | // Add actions for plugins/themes to hook onto.
146 | do_action( $this->woothemes_widget_cssclass . '_bottom' );
147 | } // End widget()
148 |
149 | /**
150 | * Method to update the settings from the form() method.
151 | * @since 1.0.0
152 | * @param array $new_instance New settings.
153 | * @param array $old_instance Previous settings.
154 | * @return array Updated settings.
155 | */
156 | public function update ( $new_instance, $old_instance ) {
157 | $instance = $old_instance;
158 |
159 | /* Strip tags for title and name to remove HTML (important for text inputs). */
160 | $instance['title'] = strip_tags( $new_instance['title'] );
161 |
162 | /* Make sure the integer values are definitely integers. */
163 | $instance['limit'] = intval( $new_instance['limit'] );
164 | $instance['specific_id'] = intval( $new_instance['specific_id'] );
165 |
166 | if( is_numeric( $new_instance['size'] ) ){
167 | $instance['size'] = intval( $new_instance['size'] );
168 | } else {
169 | $size = sanitize_title_with_dashes( $new_instance['size'] );
170 | $instance['size'] = in_array( $size, get_intermediate_image_sizes() ) ? $size : 'thumbnail';
171 | }
172 |
173 | $instance['per_row'] = intval( $new_instance['per_row'] );
174 | $instance['category'] = intval( $new_instance['category'] );
175 |
176 | /* The checkbox is returning a Boolean (true/false), so we check for that. */
177 | $instance['link_title'] = (bool) esc_attr( $new_instance['link_title'] );
178 | $instance['custom_links_only'] = (bool) esc_attr( $new_instance['custom_links_only'] );
179 |
180 | /* The select box is returning a text value, so we escape it. */
181 | $instance['orderby'] = esc_attr( $new_instance['orderby'] );
182 | $instance['order'] = esc_attr( $new_instance['order'] );
183 |
184 | return $instance;
185 | } // End update()
186 |
187 | /**
188 | * The form on the widget control in the widget administration area.
189 | * Make use of the get_field_id() and get_field_name() function when creating your form elements. This handles the confusing stuff.
190 | * @since 1.0.0
191 | * @param array $instance The settings for this instance.
192 | * @return void
193 | */
194 | public function form( $instance ) {
195 |
196 | /* Set up some default widget settings. */
197 | /* Make sure all keys are added here, even with empty string values. */
198 | $defaults = array(
199 | 'title' => '',
200 | 'limit' => 5,
201 | 'orderby' => 'menu_order',
202 | 'order' => 'DESC',
203 | 'specific_id' => '',
204 | 'size' => 50,
205 | 'per_row' => 3,
206 | 'category' => 0,
207 | 'link_title' => true,
208 | 'custom_links_only' => false
209 | );
210 |
211 | $instance = wp_parse_args( (array) $instance, $defaults );
212 | ?>
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
241 |
242 |
243 |
244 |
245 |
250 |
251 |
252 |
253 |
254 | 'feature-category', 'class' => 'widefat', 'show_option_all' => __( 'All', 'woothemes-features' ), 'id' => $this->get_field_id( 'category' ), 'name' => $this->get_field_name( 'category' ), 'selected' => $instance['category'] );
256 | wp_dropdown_categories( $dropdown_args );
257 | ?>
258 |
259 |
260 |
261 | />
262 |
263 |
264 |
265 |
266 | />
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 | __( 'No Order', 'woothemes-features' ),
286 | 'ID' => __( 'Entry ID', 'woothemes-features' ),
287 | 'title' => __( 'Title', 'woothemes-features' ),
288 | 'date' => __( 'Date Added', 'woothemes-features' ),
289 | 'menu_order' => __( 'Specified Order Setting', 'woothemes-features' ),
290 | 'rand' => __( 'Random Order', 'woothemes-features' )
291 | );
292 | } // End get_orderby_options()
293 |
294 | /**
295 | * Get an array of the available order options.
296 | * @since 1.0.0
297 | * @return array
298 | */
299 | protected function get_order_options () {
300 | return array(
301 | 'ASC' => __( 'Ascending', 'woothemes-features' ),
302 | 'DESC' => __( 'Descending', 'woothemes-features' )
303 | );
304 | } // End get_order_options()
305 | } // End Class
306 |
307 | /* Register the widget. */
308 | add_action( 'widgets_init', create_function( '', 'return register_widget("WooThemes_Widget_Features");' ), 1 );
--------------------------------------------------------------------------------
/lang/woothemes-features-en_GB.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Project-Id-Version: Features v1.3.1\n"
4 | "Report-Msgid-Bugs-To: \n"
5 | "POT-Creation-Date: \n"
6 | "PO-Revision-Date: 2013-07-31 12:39:51+0000\n"
7 | "Last-Translator: Matt \n"
8 | "Language-Team: \n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "Plural-Forms: nplurals=2; plural=n != 1;\n"
13 | "X-Generator: CSL v1.x\n"
14 | "X-Poedit-Language: English\n"
15 | "X-Poedit-Country: UNITED KINGDOM\n"
16 | "X-Poedit-SourceCharset: utf-8\n"
17 | "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
18 | "X-Poedit-Basepath: ../\n"
19 | "X-Poedit-Bookmarks: \n"
20 | "X-Poedit-SearchPath-0: .\n"
21 | "X-Textdomain-Support: yes"
22 |
23 | #: classes/class-woothemes-features.php:78
24 | #@ woothemes-features
25 | msgctxt "post type general name"
26 | msgid "Features"
27 | msgstr ""
28 |
29 | #: classes/class-woothemes-features.php:79
30 | #@ woothemes-features
31 | msgctxt "post type singular name"
32 | msgid "Feature"
33 | msgstr ""
34 |
35 | #: classes/class-woothemes-features.php:80
36 | #@ woothemes-features
37 | msgctxt "feature"
38 | msgid "Add New"
39 | msgstr ""
40 |
41 | #: classes/class-woothemes-features-taxonomy.php:103
42 | #: classes/class-woothemes-features.php:81
43 | #, php-format
44 | #@ woothemes-features
45 | msgid "Add New %s"
46 | msgstr ""
47 |
48 | #: classes/class-woothemes-features.php:81
49 | #: classes/class-woothemes-features.php:82
50 | #: classes/class-woothemes-features.php:83
51 | #: classes/class-woothemes-features.php:85
52 | #@ woothemes-features
53 | msgid "Feature"
54 | msgstr ""
55 |
56 | #: classes/class-woothemes-features-taxonomy.php:101
57 | #: classes/class-woothemes-features.php:82
58 | #, php-format
59 | #@ woothemes-features
60 | msgid "Edit %s"
61 | msgstr ""
62 |
63 | #: classes/class-woothemes-features.php:83
64 | #, php-format
65 | #@ woothemes-features
66 | msgid "New %s"
67 | msgstr ""
68 |
69 | #: classes/class-woothemes-features-taxonomy.php:98
70 | #: classes/class-woothemes-features.php:84
71 | #, php-format
72 | #@ woothemes-features
73 | msgid "All %s"
74 | msgstr ""
75 |
76 | #: classes/class-woothemes-features.php:84
77 | #: classes/class-woothemes-features.php:86
78 | #: classes/class-woothemes-features.php:87
79 | #: classes/class-woothemes-features.php:88
80 | #: classes/class-woothemes-features.php:90
81 | #: classes/class-woothemes-widget-features.php:44
82 | #@ woothemes-features
83 | msgid "Features"
84 | msgstr ""
85 |
86 | #: classes/class-woothemes-features.php:85
87 | #, php-format
88 | #@ woothemes-features
89 | msgid "View %s"
90 | msgstr ""
91 |
92 | #: classes/class-woothemes-features.php:86
93 | #, php-format
94 | #@ woothemes-features
95 | msgid "Search %a"
96 | msgstr ""
97 |
98 | #: classes/class-woothemes-features.php:87
99 | #, php-format
100 | #@ woothemes-features
101 | msgid "No %s Found"
102 | msgstr ""
103 |
104 | #: classes/class-woothemes-features.php:88
105 | #, php-format
106 | #@ woothemes-features
107 | msgid "No %s Found In Trash"
108 | msgstr ""
109 |
110 | #: classes/class-woothemes-features.php:165
111 | #@ woothemes-features
112 | msgid "Image"
113 | msgstr ""
114 |
115 | #: classes/class-woothemes-features.php:199
116 | #, php-format
117 | #@ woothemes-features
118 | msgid "Feature updated. %sView feature%s"
119 | msgstr ""
120 |
121 | #: classes/class-woothemes-features.php:200
122 | #@ woothemes-features
123 | msgid "Custom field updated."
124 | msgstr ""
125 |
126 | #: classes/class-woothemes-features.php:201
127 | #@ woothemes-features
128 | msgid "Custom field deleted."
129 | msgstr ""
130 |
131 | #: classes/class-woothemes-features.php:202
132 | #@ woothemes-features
133 | msgid "Feature updated."
134 | msgstr ""
135 |
136 | #. translators: %s: date and time of the revision
137 | #: classes/class-woothemes-features.php:204
138 | #, php-format
139 | #@ woothemes-features
140 | msgid "Feature restored to revision from %s"
141 | msgstr ""
142 |
143 | #: classes/class-woothemes-features.php:205
144 | #, php-format
145 | #@ woothemes-features
146 | msgid "Feature published. %sView feature%s"
147 | msgstr ""
148 |
149 | #: classes/class-woothemes-features.php:206
150 | #@ default
151 | msgid "Feature saved."
152 | msgstr ""
153 |
154 | #: classes/class-woothemes-features.php:207
155 | #, php-format
156 | #@ woothemes-features
157 | msgid "Feature submitted. %sPreview feature%s"
158 | msgstr ""
159 |
160 | #: classes/class-woothemes-features.php:208
161 | #, php-format
162 | #@ woothemes-features
163 | msgid "Feature scheduled for: %1$s. %2$sPreview feature%3$s"
164 | msgstr ""
165 |
166 | #: classes/class-woothemes-features.php:210
167 | #@ default
168 | msgid "M j, Y @ G:i"
169 | msgstr ""
170 |
171 | #: classes/class-woothemes-features.php:211
172 | #, php-format
173 | #@ woothemes-features
174 | msgid "Feature draft updated. %sPreview feature%s"
175 | msgstr ""
176 |
177 | #: classes/class-woothemes-features.php:324
178 | #@ woothemes-features
179 | msgid "Enter the feature title here"
180 | msgstr ""
181 |
182 | #: classes/class-woothemes-widget-features.php:42
183 | #@ woothemes-features
184 | msgid "Recent features listed on your site."
185 | msgstr ""
186 |
187 | #: classes/class-woothemes-widget-features.php:159
188 | #@ woothemes-features
189 | msgid "Title (optional):"
190 | msgstr ""
191 |
192 | #: classes/class-woothemes-widget-features.php:164
193 | #@ woothemes-features
194 | msgid "Limit:"
195 | msgstr ""
196 |
197 | #: classes/class-woothemes-widget-features.php:169
198 | #@ woothemes-features
199 | msgid "Image Size (in pixels):"
200 | msgstr ""
201 |
202 | #: classes/class-woothemes-widget-features.php:179
203 | #@ woothemes-features
204 | msgid "Order By:"
205 | msgstr ""
206 |
207 | #: classes/class-woothemes-widget-features.php:188
208 | #@ woothemes-features
209 | msgid "Order Direction:"
210 | msgstr ""
211 |
212 | #: classes/class-woothemes-widget-features.php:205
213 | #@ woothemes-features
214 | msgid "Specific ID (optional):"
215 | msgstr ""
216 |
217 | #: classes/class-woothemes-widget-features.php:219
218 | #@ woothemes-features
219 | msgid "No Order"
220 | msgstr ""
221 |
222 | #: classes/class-woothemes-widget-features.php:220
223 | #@ woothemes-features
224 | msgid "Entry ID"
225 | msgstr ""
226 |
227 | #: classes/class-woothemes-widget-features.php:221
228 | #@ woothemes-features
229 | msgid "Title"
230 | msgstr ""
231 |
232 | #: classes/class-woothemes-widget-features.php:222
233 | #@ woothemes-features
234 | msgid "Date Added"
235 | msgstr ""
236 |
237 | #: classes/class-woothemes-widget-features.php:223
238 | #@ woothemes-features
239 | msgid "Specified Order Setting"
240 | msgstr ""
241 |
242 | #: classes/class-woothemes-widget-features.php:235
243 | #@ woothemes-features
244 | msgid "Ascending"
245 | msgstr ""
246 |
247 | #: classes/class-woothemes-widget-features.php:236
248 | #@ woothemes-features
249 | msgid "Descending"
250 | msgstr ""
251 |
252 | #: classes/class-woothemes-features.php:225
253 | #@ woothemes-features
254 | msgid "Feature Details"
255 | msgstr ""
256 |
257 | #: classes/class-woothemes-features.php:350
258 | #@ woothemes-features
259 | msgid "URL"
260 | msgstr ""
261 |
262 | #: classes/class-woothemes-features.php:351
263 | #@ woothemes-features
264 | msgid "Enter a URL that applies to this feature (for example: http://woothemes.com/)."
265 | msgstr ""
266 |
267 | #: classes/class-woothemes-widget-features.php:174
268 | #@ woothemes-features
269 | msgid "Items Per Row:"
270 | msgstr ""
271 |
272 | #: classes/class-woothemes-widget-features.php:208
273 | #@ woothemes-features
274 | msgid "Display a specific feature, rather than a list."
275 | msgstr ""
276 |
277 | #: classes/class-woothemes-widget-features.php:224
278 | #@ woothemes-features
279 | msgid "Random Order"
280 | msgstr ""
281 |
282 | #: classes/class-woothemes-features-taxonomy.php:71
283 | #@ woothemes-features
284 | msgid "Category"
285 | msgstr ""
286 |
287 | #: classes/class-woothemes-features-taxonomy.php:72
288 | #@ woothemes-features
289 | msgid "Categories"
290 | msgstr ""
291 |
292 | #: classes/class-woothemes-features-taxonomy.php:95
293 | #, php-format
294 | #@ woothemes-features
295 | msgctxt "taxonomy general name"
296 | msgid "%s"
297 | msgstr ""
298 |
299 | #: classes/class-woothemes-features-taxonomy.php:96
300 | #, php-format
301 | #@ woothemes-features
302 | msgctxt "taxonomy singular name"
303 | msgid "%s"
304 | msgstr ""
305 |
306 | #: classes/class-woothemes-features-taxonomy.php:97
307 | #, php-format
308 | #@ woothemes-features
309 | msgid "Search %s"
310 | msgstr ""
311 |
312 | #: classes/class-woothemes-features-taxonomy.php:99
313 | #, php-format
314 | #@ woothemes-features
315 | msgid "Parent %s"
316 | msgstr ""
317 |
318 | #: classes/class-woothemes-features-taxonomy.php:100
319 | #, php-format
320 | #@ woothemes-features
321 | msgid "Parent %s:"
322 | msgstr ""
323 |
324 | #: classes/class-woothemes-features-taxonomy.php:102
325 | #, php-format
326 | #@ woothemes-features
327 | msgid "Update %s"
328 | msgstr ""
329 |
330 | #: classes/class-woothemes-features-taxonomy.php:104
331 | #, php-format
332 | #@ woothemes-features
333 | msgid "New %s Name"
334 | msgstr ""
335 |
336 | #: classes/class-woothemes-features-taxonomy.php:105
337 | #, php-format
338 | #@ woothemes-features
339 | msgid "%s"
340 | msgstr ""
341 |
342 | #: classes/class-woothemes-widget-features.php:197
343 | #@ woothemes-features
344 | msgid "Category:"
345 | msgstr ""
346 |
347 | #: classes/class-woothemes-widget-features.php:199
348 | #@ woothemes-features
349 | msgid "All"
350 | msgstr ""
351 |
352 | #: classes/class-woothemes-features.php:94
353 | #@ woothemes-features
354 | msgctxt "single post url slug"
355 | msgid "feature"
356 | msgstr ""
357 |
358 | #: classes/class-woothemes-features.php:95
359 | #@ woothemes-features
360 | msgctxt "post archive url slug"
361 | msgid "features"
362 | msgstr ""
363 |
364 |
--------------------------------------------------------------------------------
/lang/woothemes-features-xx_XX.pot:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Project-Id-Version: PlaceHolder\n"
4 | "Report-Msgid-Bugs-To: \n"
5 | "POT-Creation-Date: \n"
6 | "PO-Revision-Date: 2012-10-17 12:43:24+0000\n"
7 | "Last-Translator: none\n"
8 | "Language-Team: \n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "Plural-Forms: nplurals=2; plural=n != 1;\n"
13 | "X-Poedit-Language: English\n"
14 | "X-Poedit-Country: UNITED STATES\n"
15 | "X-Poedit-SourceCharset: utf-8\n"
16 | "X-Poedit-KeywordsList: __;_e;__ngettext:1,2;_n:1,2;__ngettext_noop:1,2;_n_noop:1,2;_c,_nc:4c,1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;_nx_noop:4c,1,2;\n"
17 | "X-Poedit-Basepath: ../\n"
18 | "X-Poedit-Bookmarks: \n"
19 | "X-Poedit-SearchPath-0: .\n"
20 | "X-Textdomain-Support: yes"
21 |
22 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | === Features by WooThemes ===
2 | Contributors: woothemes, mattyza, jameskoster, hlashbrooke, jeffikus, danieldudzic
3 | Donate link: http://woothemes.com/
4 | Tags: features, widget, shortcode, template-tag, services
5 | Requires at least: 3.4.2
6 | Tested up to: 4.3.1
7 | Stable tag: 1.5.0
8 | License: GPLv2 or later
9 | License URI: http://www.gnu.org/licenses/gpl-2.0.html
10 |
11 | Show off what features your company, product or service offers, using our shortcode, widget or template tag.
12 |
13 | == Description ==
14 |
15 | "Features by WooThemes" is a clean and easy-to-use features showcase management system for WordPress. Load in the features your product, company or services offers, and display them via a shortcode, widget or template tag on your website.
16 |
17 | Looking for a helping hand? [View plugin documentation](http://wordpress.org/extend/plugins/features-by-woothemes/other_notes/).
18 |
19 | Looking to contribute code to this plugin? [Fork the repository over at GitHub](http://github.com/woothemes/features/).
20 | (submit pull requests to the "develop" branch)
21 |
22 | == Usage ==
23 |
24 | To display your features via a theme or a custom plugin, please use the following code:
25 |
26 | ``
27 |
28 | To add arguments to this, please use any of the following arguments, using the syntax provided below:
29 |
30 | * 'limit' => 5 (the maximum number of items to display)
31 | * 'orderby' => 'menu_order' (how to order the items - accepts all default WordPress ordering options)
32 | * 'order' => 'DESC' (the order direction)
33 | * 'id' => 0 (display a specific item)
34 | * 'echo' => true (whether to display or return the data - useful with the template tag)
35 | * 'size' => 50 (the pixel dimensions of the image)
36 | * 'per_row' => 3 (when creating rows, how many items display in a single row?)
37 | * 'link_title' => true (link the feature's title to it's permalink)
38 | * 'custom_links_only' => true (link the feature's title only if a custom URL is set)
39 | * 'title' => '' (an optional title)
40 | * 'before' => '<div class="widget widget_woothemes_features">' (the starting HTML, wrapping the features)
41 | * 'after' => '</div>' (the ending HTML, wrapping the features)
42 | * 'before_title' => '<h2>' (the starting HTML, wrapping the title)
43 | * 'after_title' => '</h2>' (the ending HTML, wrapping the title)
44 | * 'category' => 0 (the ID/slug of the category to filter by)
45 |
46 | The various options for the "orderby" parameter are:
47 |
48 | * 'none'
49 | * 'ID'
50 | * 'author'
51 | * 'title'
52 | * 'date'
53 | * 'modified'
54 | * 'parent'
55 | * 'rand'
56 | * 'comment_count'
57 | * 'menu_order'
58 | * 'meta_value'
59 | * 'meta_value_num'
60 |
61 | ` 10, 'link_title' => false ) ); ?>`
62 |
63 | The same arguments apply to the shortcode which is `[woothemes_features]` and the template tag, which is ``.
64 |
65 | == Usage Examples ==
66 |
67 | Adjusting the limit and image dimension, using the arguments in the three possible methods:
68 |
69 | do_action() call:
70 |
71 | ` 10, 'size' => 100 ) ); ?>`
72 |
73 | woothemes_features() template tag:
74 |
75 | ` 10, 'size' => 100 ) ); ?>`
76 |
77 | [woothemes_features] shortcode:
78 |
79 | `[woothemes_features limit="10" size="100"]`
80 |
81 | == Installation ==
82 |
83 | Installing "Features by WooThemes" can be done either by searching for "Features by WooThemes" via the "Plugins > Add New" screen in your WordPress dashboard, or by using the following steps:
84 |
85 | 1. Download the plugin via WordPress.org.
86 | 1. Upload the ZIP file through the "Plugins > Add New > Upload" screen in your WordPress dashboard.
87 | 1. Activate the plugin through the 'Plugins' menu in WordPress
88 | 1. Place `` in your templates, or use the provided widget or shortcode.
89 |
90 | == Frequently Asked Questions ==
91 |
92 | = The plugin looks unstyled when I activate it. Why is this? =
93 |
94 | "Features by WooThemes" is a lean plugin that aims to keep it's purpose as clean and clear as possible. Thus, we don't load any preset CSS styling, to allow full control over the styling within your theme or child theme.
95 |
96 | = How do I contribute? =
97 |
98 | We encourage everyone to contribute their ideas, thoughts and code snippets. This can be done by forking the [repository over at GitHub](http://github.com/woothemes/features/).
99 |
100 | = Can I make feature links open in a new window / tab? =
101 |
102 | You sure can, just use the following snippet:
103 |
104 | `add_filter( 'woothemes_features_disable_external_links', '__return_false' );`
105 |
106 | == Screenshots ==
107 |
108 | 1. The features management screen within the WordPress admin.
109 |
110 | == Upgrade Notice ==
111 |
112 | = 1.5.0 =
113 | * Add argument to features widget to accept image pixel size or thumbnail name.
114 | * Adds basic front-end layout styling.
115 |
116 | = 1.4.4 =
117 | * Removes deprecated constructor call for WP_Widget, action hook fix.
118 |
119 | = 1.4.0 =
120 | * WordPress 3.8 support (3.8 is now the minimum required version).
121 | * Adds the ability to link only features with a custom URL set.
122 |
123 | = 1.3.1 =
124 | * Adds filters for the single features and features archives URL slugs
125 | * Adds a flush_rewrite_rules() call on plugin activation
126 |
127 | = 1.3.0 =
128 | * Adds "woothemes_features_content" filter and shortcode support. Adds "feature-category" taxonomy.
129 |
130 | = 1.2.2 =
131 | * Minor bugfixes to the "order" directions options and additions to the "woothemes_features_html" filter.
132 |
133 | = 1.2.1 =
134 | * Minor bugfix to the output of the "Features" widget.
135 |
136 | = 1.2.0 =
137 | * Adds basic WPML support.
138 | * Enhancements to the widget output.
139 | * Adds new arguments for controlling the HTML wrapping the features, as well as wrapping the title.
140 | * Ads support for the excerpt.
141 |
142 | = 1.1.0 =
143 | * Adds "URL" custom field.
144 | * Adds "link_title" option to the shortcode.
145 | * Routine plugin maintenance.
146 |
147 | = 1.0.0 =
148 | * Initial release. Woo!
149 |
150 | == Changelog ==
151 |
152 | = 1.5.0 =
153 | * 2015.11.20
154 | * Update - add argument to features widget for pixel size or image thumbnail name.
155 | * New - Adds basic front-end layout styling.
156 |
157 | = 1.4.4 =
158 | * 2015.07.06
159 | * Fix - Action hook typo (props helgatheviking).
160 | * Removes deprecated constructor call for WP_Widget
161 |
162 | = 1.4.3 =
163 | * 2014.08.18
164 | * Tweak - Made post type args filterable (props lkraav).
165 |
166 | = 1.4.2 =
167 | * 2014-02-03
168 | * Fix - Link title options in the widget.
169 |
170 | = 1.4.1 =
171 | * 2014-01-30
172 | * New - Filter to set feature links to open in a new window.
173 | * Fix - Widget image size option.
174 | * Tweak - Better WPML integration.
175 |
176 | = 1.4.0 =
177 | * 2014-01-17
178 | * UI tweaks for WordPress 3.8.
179 | * Default args are now filterable via woothemes_features_default_args.
180 | * Adds the ability to link only features with a custom URL set.
181 | * Adds a new %%PERMALINK%% tag to the templating engine.
182 | * Adjusts the 'id' parameter to cater for multipe ID values.
183 |
184 | = 1.3.1 =
185 | * 2013-08-01.
186 | * Adds "woothemes_features_single_slug" as a filter for the single feature URL slug
187 | * Adds "woothemes_features_archive_slug" as a filter for the features archive URL slug
188 | * Adds a flush_rewrite_rules() call on plugin activation
189 |
190 | = 1.3.0 =
191 | * 2013-04-30.
192 | * Adds "woothemes_features_content" filter for modifying the content of features when outputting the features list.
193 | * Adds default filters to the "woothemes_features_content" hook, enabling shortcodes in the content or excerpt fields.
194 | * Adds "feature-category" taxonomy and necessary logic for displaying features from a specified category.
195 | * Adds "columns-X" class to the ".features" DIV tag, for easier styling, using the "per_row" attribute.
196 |
197 | = 1.2.2 =
198 | * 2013-01-03
199 | * Fix the "order" direction options to be in capitals.
200 | * Enhance the "woothemes_features_html" filter.
201 | * Make sure to use the_content() if there is no custom excerpt.
202 | * Add support for ordering by "rand" to the widget.
203 | * Allow the "size" parameter to receive an array of dimensions.
204 |
205 | = 1.2.1 =
206 | * 2012-11-29
207 | * Makes sure the ending wrapping markup for the widget is declared in the appropriate location, before calling the woothemes_features() function.
208 |
209 | = 1.2.0 =
210 | * 2012-11-27
211 | * Adds basic WPML support to the get_features() method.
212 | * Moves the "title" outside of the ".features" DIV tag.
213 | * Adds "before" and "after" arguments for filtering the HTML for the container. Integrate the $before_widget and $after widget variables to use these parameters with the widget.
214 | * If the "link title" option is enabled, link the image as well.
215 | * Adds "before_title" and "after_title" arguments, for filtering the title's wrapping HTML. Integrate the $before_title and $after_title widget variables to use these parameters with the widget.
216 | * Adds support for the excerpt.
217 |
218 | = 1.1.0 =
219 | * 2012-11-08
220 | * Adds "link_title" option to the shortcode.
221 | * Adds "URL" custom field, to use in place of linking to the permalink, if it is specified.
222 |
223 | = 1.0.1 =
224 | * 2012-11-06
225 | * Tweak - first / last classes applied regardless
226 |
227 | = 1.0.0 =
228 | * 2012-10-23
229 | * Initial release. Woo!
--------------------------------------------------------------------------------
/woothemes-features-template.php:
--------------------------------------------------------------------------------
1 | get_features( $args );
14 | } // End woothemes_get_features()
15 | }
16 |
17 | /**
18 | * Enable the usage of do_action( 'woothemes_features' ) to display features within a theme/plugin.
19 | *
20 | * @since 1.0.0
21 | */
22 | add_action( 'woothemes_features', 'woothemes_features' );
23 |
24 | if ( ! function_exists( 'woothemes_features' ) ) {
25 | /**
26 | * Display or return HTML-formatted testimonials.
27 | * @param string/array $args Arguments.
28 | * @since 1.0.0
29 | * @return string
30 | */
31 | function woothemes_features ( $args = '' ) {
32 | global $post;
33 |
34 | $defaults = apply_filters( 'woothemes_features_default_args', array(
35 | 'limit' => 5,
36 | 'orderby' => 'menu_order',
37 | 'order' => 'DESC',
38 | 'id' => 0,
39 | 'echo' => true,
40 | 'size' => 150,
41 | 'per_row' => 3,
42 | 'link_title' => true,
43 | 'custom_links_only' => true,
44 | 'title' => '',
45 | 'before' => '',
46 | 'after' => '
',
47 | 'before_title' => '',
48 | 'after_title' => '
',
49 | 'category' => 0
50 | ) );
51 |
52 | $args = wp_parse_args( $args, $defaults );
53 |
54 | // Allow child themes/plugins to filter here.
55 | $args = apply_filters( 'woothemes_features_args', $args );
56 | $html = '';
57 |
58 | do_action( 'woothemes_features_before', $args );
59 |
60 | // The Query.
61 | $query = woothemes_get_features( $args );
62 |
63 | // The Display.
64 | if ( ! is_wp_error( $query ) && is_array( $query ) && count( $query ) > 0 ) {
65 | $html .= $args['before'] . "\n";
66 |
67 | if ( '' != $args['title'] ) {
68 | $html .= $args['before_title'] . esc_html( $args['title'] ) . $args['after_title'] . "\n";
69 | }
70 |
71 | $html .= '' . "\n";
72 |
73 | // Begin templating logic.
74 | $tpl = '
%%IMAGE%%
%%TITLE%%
%%CONTENT%%
';
75 | $tpl = apply_filters( 'woothemes_features_item_template', $tpl, $args );
76 |
77 | $i = 0;
78 | foreach ( $query as $post ) {
79 | $template = $tpl;
80 | $i++;
81 |
82 | setup_postdata( $post );
83 |
84 | $class = 'feature';
85 |
86 | if( ( 0 == $i % $args['per_row'] ) ) {
87 | $class .= ' last';
88 | } elseif ( 0 == ( $i - 1 ) % ( $args['per_row'] ) ) {
89 | $class .= ' first';
90 | }
91 |
92 | if( is_numeric( $args['size'] ) ){
93 | $image_size = array( $args['size'], $args['size'] );
94 | } else {
95 | $image_size = $args['size'];
96 | }
97 |
98 | $image_size = apply_filters( 'woothemes_features_image_size', $image_size, $post );
99 |
100 | $image = get_the_post_thumbnail( $post->ID, $image_size );
101 |
102 | $title = get_the_title();
103 |
104 | if ( apply_filters( 'woothemes_features_disable_external_links', true ) ) {
105 | $external = '';
106 | } else {
107 | $external = 'target="_blank"';
108 | }
109 |
110 | if ( true == $args['link_title'] && '' != $post->url ) {
111 | $image = '
' . $image . '';
112 | $title = '
' . $title . '';
113 | }
114 |
115 | // Optionally display the image, if it is available.
116 | if ( has_post_thumbnail() ) {
117 | $template = str_replace( '%%IMAGE%%', $image, $template );
118 | } else {
119 | $template = str_replace( '%%IMAGE%%', '', $template );
120 | }
121 |
122 | $template = str_replace( '%%CLASS%%', $class, $template );
123 | $template = str_replace( '%%TITLE%%', $title, $template );
124 |
125 | $template = str_replace( '%%PERMALINK%%', esc_url( get_permalink( get_the_ID() ) ), $template );
126 |
127 | if ( '' != $post->post_excerpt ) {
128 | $content = get_the_excerpt();
129 | } else {
130 | $content = get_the_content();
131 | }
132 | $content = apply_filters( 'woothemes_features_content', $content, $post );
133 | $template = str_replace( '%%CONTENT%%', $content, $template );
134 |
135 | $template = apply_filters( 'woothemes_features_template', $template, $post );
136 |
137 | $html .= $template;
138 |
139 | if( ( 0 == $i % $args['per_row'] ) ) {
140 | $html .= '
' . "\n";
141 | }
142 | }
143 |
144 | $html .= '
' . "\n";
145 | $html .= $args['after'] . "\n";
146 |
147 | wp_reset_postdata();
148 | }
149 |
150 | // Allow child themes/plugins to filter here.
151 | $html = apply_filters( 'woothemes_features_html', $html, $query, $args );
152 |
153 | if ( $args['echo'] != true ) { return $html; }
154 |
155 | // Should only run is "echo" is set to true.
156 | echo $html;
157 |
158 | do_action( 'woothemes_features_after', $args ); // Only if "echo" is set to true.
159 | } // End woothemes_features()
160 | }
161 |
162 | if ( ! function_exists( 'woothemes_features_shortcode' ) ) {
163 | /**
164 | * The shortcode function.
165 | * @since 1.0.0
166 | * @param array $atts Shortcode attributes.
167 | * @param string $content If the shortcode is a wrapper, this is the content being wrapped.
168 | * @return string Output using the template tag.
169 | */
170 | function woothemes_features_shortcode ( $atts, $content = null ) {
171 | $args = (array)$atts;
172 |
173 | $defaults = array(
174 | 'limit' => 5,
175 | 'orderby' => 'menu_order',
176 | 'order' => 'DESC',
177 | 'id' => 0,
178 | 'echo' => true,
179 | 'size' => 150,
180 | 'per_row' => 3,
181 | 'link_title' => true,
182 | 'custom_links_only' => false,
183 | 'category' => 0
184 | );
185 |
186 | $args = shortcode_atts( $defaults, $atts );
187 |
188 | // Make sure we return and don't echo.
189 | $args['echo'] = false;
190 |
191 | // Fix integers.
192 | if ( isset( $args['limit'] ) ) $args['limit'] = intval( $args['limit'] );
193 | if ( isset( $args['id'] ) ) $args['id'] = intval( $args['id'] );
194 |
195 | if ( isset( $args['size'] ) ){
196 | if( is_numeric( $args['size'] ) ){
197 | $args['size'] = intval( $args['size'] );
198 | } else {
199 | $size = sanitize_title_with_dashes( $args['size'] );
200 | $args['size'] = in_array( $size, get_intermediate_image_sizes() ) ? $size : 'thumbnail';
201 | }
202 | }
203 |
204 | if ( isset( $args['per_row'] ) && ( 0 < intval( $args['per_row'] ) ) ) $args['per_row'] = intval( $args['per_row'] );
205 | if ( isset( $args['category'] ) && is_numeric( $args['category'] ) ) $args['category'] = intval( $args['category'] );
206 |
207 | // Fix booleans.
208 | foreach ( array( 'link_title', 'custom_links_only' ) as $k => $v ) {
209 | if ( isset( $args[$v] ) && ( 'true' == $args[$v] ) ) {
210 | $args[$v] = true;
211 | } else {
212 | $args[$v] = false;
213 | }
214 | }
215 |
216 | return woothemes_features( $args );
217 | } // End woothemes_features_shortcode()
218 | }
219 |
220 | add_shortcode( 'woothemes_features', 'woothemes_features_shortcode' );
221 |
222 | if ( ! function_exists( 'woothemes_features_content_default_filters' ) ) {
223 | /**
224 | * Adds default filters to the "woothemes_features_content" filter point.
225 | * @since 1.3.0
226 | * @return void
227 | */
228 | function woothemes_features_content_default_filters () {
229 | add_filter( 'woothemes_features_content', 'do_shortcode' );
230 | } // End woothemes_features_content_default_filters()
231 |
232 | add_action( 'woothemes_features_before', 'woothemes_features_content_default_filters' );
233 | }
234 | ?>
--------------------------------------------------------------------------------
/woothemes-features.php:
--------------------------------------------------------------------------------
1 | version = '1.5.0';
--------------------------------------------------------------------------------