Version Description
- Feature: Import WP Tasty Recipes
- Improvement: Better handling of shortcodes in JSON-LD metadata
- Fix: Problem with double recipes in categories
- Fix: Jetpack Contact Form compatibility problem on manage page
Download this release
Release Info
Developer | BrechtVds |
Plugin | WP Recipe Maker |
Version | 1.23.0 |
Comparing to | |
See all releases |
Code changes from version 1.22.0 to 1.23.0
- assets/js/admin/manage.js +7 -0
- includes/admin/class-wprm-migrations.php +3 -0
- includes/admin/class-wprm-recipe-saver.php +4 -2
- includes/admin/import/class-wprm-import-tasty.php +437 -0
- includes/admin/migrations/wprm-1-23-0-categories.php +43 -0
- includes/class-wp-recipe-maker.php +1 -1
- includes/public/class-wprm-metadata.php +1 -1
- includes/public/class-wprm-rating.php +12 -0
- includes/public/class-wprm-shortcode.php +24 -0
- includes/public/class-wprm-taxonomies.php +0 -3
- readme.txt +11 -0
- templates/admin/menu/faq/whats_new.php +8 -0
- templates/admin/modal/tabs/recipe-details.php +2 -4
- wp-recipe-maker.php +1 -1
assets/js/admin/manage.js
CHANGED
@@ -378,3 +378,10 @@ jQuery(document).ready(function($) {
|
|
378 |
}
|
379 |
});
|
380 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
378 |
}
|
379 |
});
|
380 |
});
|
381 |
+
|
382 |
+
// Prevent Jetpack compatibility problem.
|
383 |
+
var grunionEditorView = grunionEditorView || {
|
384 |
+
labels : {
|
385 |
+
tinymce_label: ''
|
386 |
+
}
|
387 |
+
};
|
includes/admin/class-wprm-migrations.php
CHANGED
@@ -55,6 +55,9 @@ class WPRM_Migrations {
|
|
55 |
if ( version_compare( $migrated_to_version, '1.19.0' ) < 0 ) {
|
56 |
require_once( WPRM_DIR . 'includes/admin/migrations/wprm-1-19-0-nutrition-label.php' );
|
57 |
}
|
|
|
|
|
|
|
58 |
|
59 |
if ( '0.0.0' === $migrated_to_version ) {
|
60 |
self::$notices = array();
|
55 |
if ( version_compare( $migrated_to_version, '1.19.0' ) < 0 ) {
|
56 |
require_once( WPRM_DIR . 'includes/admin/migrations/wprm-1-19-0-nutrition-label.php' );
|
57 |
}
|
58 |
+
if ( version_compare( $migrated_to_version, '1.23.0' ) < 0 ) {
|
59 |
+
require_once( WPRM_DIR . 'includes/admin/migrations/wprm-1-23-0-categories.php' );
|
60 |
+
}
|
61 |
|
62 |
if ( '0.0.0' === $migrated_to_version ) {
|
63 |
self::$notices = array();
|
includes/admin/class-wprm-recipe-saver.php
CHANGED
@@ -223,8 +223,10 @@ class WPRM_Recipe_Saver {
|
|
223 |
|
224 |
update_post_meta( $recipe_id, 'wprm_parent_post_id', $post_id );
|
225 |
|
226 |
-
//
|
227 |
-
|
|
|
|
|
228 |
}
|
229 |
}
|
230 |
|
223 |
|
224 |
update_post_meta( $recipe_id, 'wprm_parent_post_id', $post_id );
|
225 |
|
226 |
+
// Optionally associate categories with recipes.
|
227 |
+
if ( is_object_in_taxonomy( WPRM_POST_TYPE, 'category' ) ) {
|
228 |
+
wp_set_post_categories( $recipe_id, $cat_ids );
|
229 |
+
}
|
230 |
}
|
231 |
}
|
232 |
|
includes/admin/import/class-wprm-import-tasty.php
ADDED
@@ -0,0 +1,437 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Responsible for importing Tasty recipes.
|
4 |
+
*
|
5 |
+
* @link http://bootstrapped.ventures
|
6 |
+
* @since 1.23.0
|
7 |
+
*
|
8 |
+
* @package WP_Recipe_Maker
|
9 |
+
* @subpackage WP_Recipe_Maker/includes/admin/import
|
10 |
+
*/
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Responsible for importing Tasty recipes.
|
14 |
+
*
|
15 |
+
* @since 1.23.0
|
16 |
+
* @package WP_Recipe_Maker
|
17 |
+
* @subpackage WP_Recipe_Maker/includes/admin/import
|
18 |
+
* @author Brecht Vandersmissen <brecht@bootstrapped.ventures>
|
19 |
+
*/
|
20 |
+
class WPRM_Import_Tasty extends WPRM_Import {
|
21 |
+
/**
|
22 |
+
* Get the UID of this import source.
|
23 |
+
*
|
24 |
+
* @since 1.23.0
|
25 |
+
*/
|
26 |
+
public function get_uid() {
|
27 |
+
return 'tasty';
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Wether or not this importer requires a manual search for recipes.
|
32 |
+
*
|
33 |
+
* @since 1.23.0
|
34 |
+
*/
|
35 |
+
public function requires_search() {
|
36 |
+
return false;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Get the name of this import source.
|
41 |
+
*
|
42 |
+
* @since 1.23.0
|
43 |
+
*/
|
44 |
+
public function get_name() {
|
45 |
+
return 'Tasty Recipes';
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Get HTML for the import settings.
|
50 |
+
*
|
51 |
+
* @since 1.23.0
|
52 |
+
*/
|
53 |
+
public function get_settings_html() {
|
54 |
+
return '';
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Get the total number of recipes to import.
|
59 |
+
*
|
60 |
+
* @since 1.23.0
|
61 |
+
*/
|
62 |
+
public function get_recipe_count() {
|
63 |
+
$args = array(
|
64 |
+
'post_type' => 'tasty_recipe',
|
65 |
+
'post_status' => 'any',
|
66 |
+
'posts_per_page' => 1,
|
67 |
+
);
|
68 |
+
|
69 |
+
$query = new WP_Query( $args );
|
70 |
+
return $query->found_posts;
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Get a list of recipes that are available to import.
|
75 |
+
*
|
76 |
+
* @since 1.23.0
|
77 |
+
* @param int $page Page of recipes to get.
|
78 |
+
*/
|
79 |
+
public function get_recipes( $page = 0 ) {
|
80 |
+
$recipes = array();
|
81 |
+
|
82 |
+
$limit = 100;
|
83 |
+
$offset = $limit * $page;
|
84 |
+
|
85 |
+
$args = array(
|
86 |
+
'post_type' => 'tasty_recipe',
|
87 |
+
'post_status' => 'any',
|
88 |
+
'orderby' => 'date',
|
89 |
+
'order' => 'DESC',
|
90 |
+
'posts_per_page' => $limit,
|
91 |
+
'offset' => $offset,
|
92 |
+
);
|
93 |
+
|
94 |
+
$query = new WP_Query( $args );
|
95 |
+
|
96 |
+
if ( $query->have_posts() ) {
|
97 |
+
$posts = $query->posts;
|
98 |
+
|
99 |
+
foreach ( $posts as $post ) {
|
100 |
+
$recipes[ $post->ID ] = array(
|
101 |
+
'name' => $post->post_title,
|
102 |
+
'url' => get_edit_post_link( $post->ID ),
|
103 |
+
);
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
return $recipes;
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Get recipe with the specified ID in the import format.
|
112 |
+
*
|
113 |
+
* @since 1.23.0
|
114 |
+
* @param mixed $id ID of the recipe we want to import.
|
115 |
+
* @param array $post_data POST data passed along when submitting the form.
|
116 |
+
*/
|
117 |
+
public function get_recipe( $id, $post_data ) {
|
118 |
+
$recipe = array(
|
119 |
+
'import_id' => $id,
|
120 |
+
'import_backup' => array(),
|
121 |
+
);
|
122 |
+
|
123 |
+
$post = get_post( $id );
|
124 |
+
|
125 |
+
// Featured Image.
|
126 |
+
$recipe['image_id'] = get_post_thumbnail_id( $id );
|
127 |
+
|
128 |
+
// Simple Matching.
|
129 |
+
$recipe['name'] = $post->post_title;
|
130 |
+
$recipe['summary'] = get_post_meta( $id, 'description', true );
|
131 |
+
$recipe['notes'] = get_post_meta( $id, 'notes', true );
|
132 |
+
$recipe['author_name'] = get_post_meta( $id, 'author_name', true );
|
133 |
+
|
134 |
+
if ( $recipe['author_name'] ) {
|
135 |
+
$recipe['author_display'] = 'custom';
|
136 |
+
}
|
137 |
+
|
138 |
+
// Servings.
|
139 |
+
$tasty_yield = get_post_meta( $id, 'yield', true );
|
140 |
+
$match = preg_match( '/^\s*\d+/', $tasty_yield, $servings_array );
|
141 |
+
if ( 1 === $match ) {
|
142 |
+
$servings = str_replace( ' ','', $servings_array[0] );
|
143 |
+
} else {
|
144 |
+
$servings = '';
|
145 |
+
}
|
146 |
+
|
147 |
+
$servings_unit = preg_replace( '/^\s*\d+\s*/', '', $tasty_yield );
|
148 |
+
|
149 |
+
$recipe['servings'] = $servings;
|
150 |
+
$recipe['servings_unit'] = $servings_unit;
|
151 |
+
|
152 |
+
// Recipe times.
|
153 |
+
$recipe['prep_time'] = $this->get_minutes_for_time( get_post_meta( $id, 'prep_time', true ) );
|
154 |
+
$recipe['cook_time'] = $this->get_minutes_for_time( get_post_meta( $id, 'cook_time', true ) );
|
155 |
+
|
156 |
+
// Recipe tags.
|
157 |
+
$recipe['tags'] = array();
|
158 |
+
$recipe['tags']['course'] = array_map( 'trim', explode( ',', get_post_meta( $id, 'category', true ) ) );
|
159 |
+
$recipe['tags']['cuisine'] = array_map( 'trim', explode( ',', get_post_meta( $id, 'cuisine', true ) ) );
|
160 |
+
|
161 |
+
// Ingredients.
|
162 |
+
$tasty_ingredients = $this->parse_recipe_component_list( get_post_meta( $id, 'ingredients', true ) );
|
163 |
+
|
164 |
+
$ingredients = array();
|
165 |
+
|
166 |
+
foreach ( $tasty_ingredients as $tasty_group ) {
|
167 |
+
$group = array(
|
168 |
+
'name' => $tasty_group['name'],
|
169 |
+
'ingredients' => array(),
|
170 |
+
);
|
171 |
+
|
172 |
+
foreach ( $tasty_group['items'] as $tasty_item ) {
|
173 |
+
$text = trim( strip_tags( $tasty_item ) );
|
174 |
+
|
175 |
+
if ( ! empty( $text ) ) {
|
176 |
+
$group['ingredients'][] = array(
|
177 |
+
'raw' => $text,
|
178 |
+
);
|
179 |
+
}
|
180 |
+
}
|
181 |
+
|
182 |
+
$ingredients[] = $group;
|
183 |
+
}
|
184 |
+
$recipe['ingredients'] = $ingredients;
|
185 |
+
|
186 |
+
// Instructions.
|
187 |
+
$tasty_instructions = $this->parse_recipe_component_list( get_post_meta( $id, 'instructions', true ) );
|
188 |
+
|
189 |
+
$instructions = array();
|
190 |
+
|
191 |
+
foreach ( $tasty_instructions as $tasty_group ) {
|
192 |
+
$group = array(
|
193 |
+
'name' => $tasty_group['name'],
|
194 |
+
'instructions' => array(),
|
195 |
+
);
|
196 |
+
|
197 |
+
foreach ( $tasty_group['items'] as $tasty_item ) {
|
198 |
+
$text = trim( strip_tags( $tasty_item ) );
|
199 |
+
|
200 |
+
// Find any images.
|
201 |
+
preg_match_all( '/<img[^>]+>/i', $tasty_item, $img_tags );
|
202 |
+
|
203 |
+
foreach ( $img_tags as $img_tag ) {
|
204 |
+
preg_match_all( '/src="([^"]*)"/i', $img_tag[0], $img );
|
205 |
+
|
206 |
+
if ( $img[1] ) {
|
207 |
+
$img_src = $img[1][0];
|
208 |
+
$image_id = $this->get_or_upload_attachment( $id, $img_src );
|
209 |
+
|
210 |
+
if ( $image_id ) {
|
211 |
+
$group['instructions'][] = array(
|
212 |
+
'text' => $text,
|
213 |
+
'image' => $image_id,
|
214 |
+
);
|
215 |
+
$text = ''; // Only add same text once.
|
216 |
+
}
|
217 |
+
}
|
218 |
+
}
|
219 |
+
|
220 |
+
if ( ! empty( $text ) ) {
|
221 |
+
$group['instructions'][] = array(
|
222 |
+
'text' => $text,
|
223 |
+
);
|
224 |
+
}
|
225 |
+
}
|
226 |
+
|
227 |
+
$instructions[] = $group;
|
228 |
+
}
|
229 |
+
$recipe['instructions'] = $instructions;
|
230 |
+
|
231 |
+
// Nutrition Facts.
|
232 |
+
$recipe['nutrition'] = array();
|
233 |
+
|
234 |
+
// Serving size.
|
235 |
+
$tasty_serving_size = get_post_meta( $id, 'serving_size', true );
|
236 |
+
$match = preg_match( '/^\s*\d+/', $tasty_serving_size, $servings_array );
|
237 |
+
if ( 1 === $match ) {
|
238 |
+
$servings = str_replace( ' ','', $servings_array[0] );
|
239 |
+
} else {
|
240 |
+
$servings = '';
|
241 |
+
}
|
242 |
+
|
243 |
+
$servings_unit = preg_replace( '/^\s*\d+\s*/', '', $tasty_serving_size );
|
244 |
+
|
245 |
+
$recipe['nutrition']['serving_size'] = $servings;
|
246 |
+
$recipe['nutrition']['serving_unit'] = $servings_unit;
|
247 |
+
|
248 |
+
$recipe['nutrition']['calories'] = get_post_meta( $id, 'calories', true );
|
249 |
+
$recipe['nutrition']['sugar'] = get_post_meta( $id, 'sugar', true );
|
250 |
+
$recipe['nutrition']['sodium'] = get_post_meta( $id, 'sodium', true );
|
251 |
+
$recipe['nutrition']['fat'] = get_post_meta( $id, 'fat', true );
|
252 |
+
$recipe['nutrition']['saturated_fat'] = get_post_meta( $id, 'saturated_fat', true );
|
253 |
+
$recipe['nutrition']['polyunsaturated_fat'] = get_post_meta( $id, 'unsaturated_fat', true );
|
254 |
+
$recipe['nutrition']['trans_fat'] = get_post_meta( $id, 'trans_fat', true );
|
255 |
+
$recipe['nutrition']['carbohydrates'] = get_post_meta( $id, 'carbohydrates', true );
|
256 |
+
$recipe['nutrition']['fiber'] = get_post_meta( $id, 'fiber', true );
|
257 |
+
$recipe['nutrition']['protein'] = get_post_meta( $id, 'protein', true );
|
258 |
+
$recipe['nutrition']['cholesterol'] = get_post_meta( $id, 'cholesterol', true );
|
259 |
+
|
260 |
+
return $recipe;
|
261 |
+
}
|
262 |
+
|
263 |
+
/**
|
264 |
+
* Replace the original recipe with the newly imported WPRM one.
|
265 |
+
*
|
266 |
+
* @since 1.23.0
|
267 |
+
* @param mixed $id ID of the recipe we want replace.
|
268 |
+
* @param mixed $wprm_id ID of the WPRM recipe to replace with.
|
269 |
+
* @param array $post_data POST data passed along when submitting the form.
|
270 |
+
*/
|
271 |
+
public function replace_recipe( $id, $wprm_id, $post_data ) {
|
272 |
+
// We don't know which posts use this recipe so we rely on the fallback shortcode.
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Custom strtotime function for Tasty format.
|
277 |
+
*
|
278 |
+
* @since 1.23.0
|
279 |
+
* @param mixed $time Time to get in minutes.
|
280 |
+
* @param mixed $now Time now.
|
281 |
+
*/
|
282 |
+
public static function strtotime( $time, $now = null ) {
|
283 |
+
if ( null === $now ) {
|
284 |
+
$now = time();
|
285 |
+
}
|
286 |
+
// Parse string to remove any info in parentheses.
|
287 |
+
$time = preg_replace( '/\([^\)]+\)/' , '' , $time );
|
288 |
+
return strtotime( $time, $now );
|
289 |
+
}
|
290 |
+
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Get the time in minutes.
|
294 |
+
*
|
295 |
+
* @since 1.23.0
|
296 |
+
* @param mixed $time Time to get in minutes.
|
297 |
+
*/
|
298 |
+
private function get_minutes_for_time( $time ) {
|
299 |
+
// Assume a number is minutes.
|
300 |
+
if ( is_numeric( $time ) ) {
|
301 |
+
$time = "{$time} minutes";
|
302 |
+
}
|
303 |
+
$now = time();
|
304 |
+
$time = $this->strtotime( $time, $now );
|
305 |
+
|
306 |
+
return ( $time - $now ) / 60;
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* Blob to array.
|
311 |
+
*
|
312 |
+
* @since 1.23.0
|
313 |
+
* @param mixed $component Component to parse.
|
314 |
+
*/
|
315 |
+
private function parse_recipe_component_list( $component ) {
|
316 |
+
$component_list = array();
|
317 |
+
$component_group = array(
|
318 |
+
'name' => '',
|
319 |
+
'items' => array(),
|
320 |
+
);
|
321 |
+
|
322 |
+
$bits = explode( PHP_EOL, $component );
|
323 |
+
foreach ( $bits as $bit ) {
|
324 |
+
|
325 |
+
$test_bit = trim( $bit );
|
326 |
+
if ( empty( $test_bit ) ) {
|
327 |
+
continue;
|
328 |
+
}
|
329 |
+
if ( $this->is_heading( $bit ) ) {
|
330 |
+
$component_list[] = $component_group;
|
331 |
+
|
332 |
+
$component_group = array(
|
333 |
+
'name' => strip_tags( trim( $bit ) ),
|
334 |
+
'items' => array(),
|
335 |
+
);
|
336 |
+
} else {
|
337 |
+
$component_group['items'][] = trim( $bit );
|
338 |
+
}
|
339 |
+
}
|
340 |
+
|
341 |
+
$component_list[] = $component_group;
|
342 |
+
|
343 |
+
return $component_list;
|
344 |
+
}
|
345 |
+
|
346 |
+
/**
|
347 |
+
* Check if line is heading.
|
348 |
+
*
|
349 |
+
* @since 1.23.0
|
350 |
+
* @param mixed $string String to parse.
|
351 |
+
*/
|
352 |
+
private function is_heading( $string ) {
|
353 |
+
$string = trim( $string );
|
354 |
+
// For The Red Beans:.
|
355 |
+
if ( ':' === substr( $string, -1, 1 ) ) {
|
356 |
+
return true;
|
357 |
+
}
|
358 |
+
// <strong>For The Red Beans</strong>.
|
359 |
+
if ( '<strong>' === substr( $string, 0, 8 ) && '</strong>' === substr( $string, -9, 9 ) ) {
|
360 |
+
return true;
|
361 |
+
}
|
362 |
+
// <h3>For The Red Beans</h3>.
|
363 |
+
if ( preg_match( '#^<h[1-6]>.+<\/h[1-6]>$#', $string ) ) {
|
364 |
+
return true;
|
365 |
+
}
|
366 |
+
return false;
|
367 |
+
}
|
368 |
+
|
369 |
+
/**
|
370 |
+
* Get image attachment ID from a given URL or sideload the image if not on the website.
|
371 |
+
*
|
372 |
+
* @since 1.23.0
|
373 |
+
* @param int $post_id Post to associate the image with.
|
374 |
+
* @param mixed $url Image URL.
|
375 |
+
*/
|
376 |
+
private function get_or_upload_attachment( $post_id, $url ) {
|
377 |
+
$url = str_replace( array( "\n", "\t", "\r" ), '', $url );
|
378 |
+
$image_id = $this->get_attachment_id_from_url( $url );
|
379 |
+
|
380 |
+
if ( $image_id ) {
|
381 |
+
return $image_id;
|
382 |
+
} else {
|
383 |
+
$media = media_sideload_image( $url, $post_id );
|
384 |
+
|
385 |
+
$attachments = get_posts( array(
|
386 |
+
'numberposts' => '1',
|
387 |
+
'post_parent' => $post_id,
|
388 |
+
'post_type' => 'attachment',
|
389 |
+
'post_mime_type' => 'image',
|
390 |
+
'orderby' => 'post_date',
|
391 |
+
'order' => 'DESC',
|
392 |
+
)
|
393 |
+
);
|
394 |
+
|
395 |
+
if ( count( $attachments ) > 0 ) {
|
396 |
+
return $attachments[0]->ID;
|
397 |
+
}
|
398 |
+
}
|
399 |
+
|
400 |
+
return false;
|
401 |
+
}
|
402 |
+
|
403 |
+
/**
|
404 |
+
* Get image attachment ID from a given URL.
|
405 |
+
* Source: https://philipnewcomer.net/2012/11/get-the-attachment-id-from-an-image-url-in-wordpress/
|
406 |
+
*
|
407 |
+
* @since 1.23.0
|
408 |
+
* @param mixed $attachment_url Image URL.
|
409 |
+
*/
|
410 |
+
private function get_attachment_id_from_url( $attachment_url = '' ) {
|
411 |
+
global $wpdb;
|
412 |
+
$attachment_id = false;
|
413 |
+
|
414 |
+
// If there is no url, return.
|
415 |
+
if ( '' === $attachment_url ) {
|
416 |
+
return;
|
417 |
+
}
|
418 |
+
|
419 |
+
// Get the upload directory paths.
|
420 |
+
$upload_dir_paths = wp_upload_dir();
|
421 |
+
|
422 |
+
// Make sure the upload path base directory exists in the attachment URL, to verify that we're working with a media library image.
|
423 |
+
if ( false !== strpos( $attachment_url, $upload_dir_paths['baseurl'] ) ) {
|
424 |
+
|
425 |
+
// If this is the URL of an auto-generated thumbnail, get the URL of the original image.
|
426 |
+
$attachment_url = preg_replace( '/-\d+x\d+(?=\.(jpg|jpeg|png|gif)$)/i', '', $attachment_url );
|
427 |
+
|
428 |
+
// Remove the upload path base directory from the attachment URL.
|
429 |
+
$attachment_url = str_replace( $upload_dir_paths['baseurl'] . '/', '', $attachment_url );
|
430 |
+
|
431 |
+
// Finally, run a custom database query to get the attachment ID from the modified attachment URL.
|
432 |
+
$attachment_id = $wpdb->get_var( $wpdb->prepare( "SELECT wposts.ID FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta WHERE wposts.ID = wpostmeta.post_id AND wpostmeta.meta_key = '_wp_attached_file' AND wpostmeta.meta_value = '%s' AND wposts.post_type = 'attachment'", $attachment_url ) ); // @codingStandardsIgnoreLine
|
433 |
+
}
|
434 |
+
|
435 |
+
return $attachment_id;
|
436 |
+
}
|
437 |
+
}
|
includes/admin/migrations/wprm-1-23-0-categories.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Migration for removing the categories associated with recipes again.
|
4 |
+
*
|
5 |
+
* @link http://bootstrapped.ventures
|
6 |
+
* @since 1.23.0
|
7 |
+
*
|
8 |
+
* @package WP_Recipe_Maker
|
9 |
+
* @subpackage WP_Recipe_Maker/includes/admin/migrations
|
10 |
+
*/
|
11 |
+
|
12 |
+
// Associate categories with recipes during migration.
|
13 |
+
register_taxonomy_for_object_type( 'category', WPRM_POST_TYPE );
|
14 |
+
|
15 |
+
// Loop through all recipes.
|
16 |
+
$limit = 100;
|
17 |
+
$offset = 0;
|
18 |
+
|
19 |
+
while ( true ) {
|
20 |
+
$args = array(
|
21 |
+
'post_type' => WPRM_POST_TYPE,
|
22 |
+
'post_status' => 'any',
|
23 |
+
'orderby' => 'date',
|
24 |
+
'order' => 'DESC',
|
25 |
+
'fields' => 'ids',
|
26 |
+
'posts_per_page' => $limit,
|
27 |
+
'offset' => $offset,
|
28 |
+
);
|
29 |
+
|
30 |
+
$query = new WP_Query( $args );
|
31 |
+
|
32 |
+
if ( ! $query->have_posts() ) {
|
33 |
+
break;
|
34 |
+
}
|
35 |
+
|
36 |
+
$posts = $query->posts;
|
37 |
+
|
38 |
+
foreach ( $posts as $post ) {
|
39 |
+
wp_delete_object_term_relationships( $post, 'category' );
|
40 |
+
}
|
41 |
+
|
42 |
+
$offset += $limit;
|
43 |
+
}
|
includes/class-wp-recipe-maker.php
CHANGED
@@ -31,7 +31,7 @@ class WP_Recipe_Maker {
|
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
private function define_constants() {
|
34 |
-
define( 'WPRM_VERSION', '1.
|
35 |
define( 'WPRM_PREMIUM_VERSION_REQUIRED', '1.6.0' );
|
36 |
define( 'WPRM_POST_TYPE', 'wprm_recipe' );
|
37 |
define( 'WPRM_DIR', plugin_dir_path( dirname( __FILE__ ) ) );
|
31 |
* @since 1.0.0
|
32 |
*/
|
33 |
private function define_constants() {
|
34 |
+
define( 'WPRM_VERSION', '1.23.0' );
|
35 |
define( 'WPRM_PREMIUM_VERSION_REQUIRED', '1.6.0' );
|
36 |
define( 'WPRM_POST_TYPE', 'wprm_recipe' );
|
37 |
define( 'WPRM_DIR', plugin_dir_path( dirname( __FILE__ ) ) );
|
includes/public/class-wprm-metadata.php
CHANGED
@@ -51,7 +51,7 @@ class WPRM_Metadata {
|
|
51 |
$sanitized[ $key ] = self::sanitize_metadata( $value );
|
52 |
}
|
53 |
} else {
|
54 |
-
$sanitized = strip_shortcodes( wp_strip_all_tags( $metadata ) );
|
55 |
}
|
56 |
return $sanitized;
|
57 |
}
|
51 |
$sanitized[ $key ] = self::sanitize_metadata( $value );
|
52 |
}
|
53 |
} else {
|
54 |
+
$sanitized = strip_shortcodes( wp_strip_all_tags( do_shortcode( $metadata ) ) );
|
55 |
}
|
56 |
return $sanitized;
|
57 |
}
|
includes/public/class-wprm-rating.php
CHANGED
@@ -85,9 +85,21 @@ class WPRM_Rating {
|
|
85 |
|
86 |
foreach ( $comments as $comment ) {
|
87 |
$comment_rating = intval( get_comment_meta( $comment->comment_ID, 'wprm-comment-rating', true ) );
|
|
|
88 |
if ( $comment_rating ) {
|
89 |
$rating['count']++;
|
90 |
$rating['total'] += $comment_rating;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
}
|
92 |
}
|
93 |
|
85 |
|
86 |
foreach ( $comments as $comment ) {
|
87 |
$comment_rating = intval( get_comment_meta( $comment->comment_ID, 'wprm-comment-rating', true ) );
|
88 |
+
|
89 |
if ( $comment_rating ) {
|
90 |
$rating['count']++;
|
91 |
$rating['total'] += $comment_rating;
|
92 |
+
} else {
|
93 |
+
// Check for EasyRecipe or WP Tasty rating.
|
94 |
+
$comment_rating = intval( get_comment_meta( $comment->comment_ID, 'ERRating', true ) );
|
95 |
+
|
96 |
+
if ( $comment_rating ) {
|
97 |
+
$rating['count']++;
|
98 |
+
$rating['total'] += $comment_rating;
|
99 |
+
|
100 |
+
// This should be migrated.
|
101 |
+
update_comment_meta( $comment->comment_ID, 'wprm-comment-rating', $comment_rating );
|
102 |
+
}
|
103 |
}
|
104 |
}
|
105 |
|
includes/public/class-wprm-shortcode.php
CHANGED
@@ -34,6 +34,9 @@ class WPRM_Shortcode {
|
|
34 |
|
35 |
add_filter( 'content_edit_pre', array( __CLASS__, 'replace_wpultimaterecipe_shortcode' ) );
|
36 |
add_filter( 'content_edit_pre', array( __CLASS__, 'replace_bigoven_shortcode' ) );
|
|
|
|
|
|
|
37 |
|
38 |
add_action( 'init', array( __CLASS__, 'fallback_shortcodes' ), 11 );
|
39 |
}
|
@@ -48,6 +51,10 @@ class WPRM_Shortcode {
|
|
48 |
add_shortcode( 'seo_recipe', array( __CLASS__, 'recipe_shortcode' ) );
|
49 |
}
|
50 |
|
|
|
|
|
|
|
|
|
51 |
if ( ! shortcode_exists( 'ultimate-recipe' ) ) {
|
52 |
add_shortcode( 'ultimate-recipe', array( __CLASS__, 'recipe_shortcode' ) );
|
53 |
}
|
@@ -79,6 +86,23 @@ class WPRM_Shortcode {
|
|
79 |
return $content;
|
80 |
}
|
81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
/**
|
83 |
* Replace BigOven shortcode with ours.
|
84 |
*
|
34 |
|
35 |
add_filter( 'content_edit_pre', array( __CLASS__, 'replace_wpultimaterecipe_shortcode' ) );
|
36 |
add_filter( 'content_edit_pre', array( __CLASS__, 'replace_bigoven_shortcode' ) );
|
37 |
+
add_filter( 'content_edit_pre', array( __CLASS__, 'replace_tasty_shortcode' ) );
|
38 |
+
|
39 |
+
add_filter( 'the_content', array( __CLASS__, 'replace_tasty_shortcode' ) );
|
40 |
|
41 |
add_action( 'init', array( __CLASS__, 'fallback_shortcodes' ), 11 );
|
42 |
}
|
51 |
add_shortcode( 'seo_recipe', array( __CLASS__, 'recipe_shortcode' ) );
|
52 |
}
|
53 |
|
54 |
+
if ( ! shortcode_exists( 'tasty-recipe' ) ) {
|
55 |
+
add_shortcode( 'tasty-recipe', array( __CLASS__, 'recipe_shortcode' ) );
|
56 |
+
}
|
57 |
+
|
58 |
if ( ! shortcode_exists( 'ultimate-recipe' ) ) {
|
59 |
add_shortcode( 'ultimate-recipe', array( __CLASS__, 'recipe_shortcode' ) );
|
60 |
}
|
86 |
return $content;
|
87 |
}
|
88 |
|
89 |
+
/**
|
90 |
+
* Replace BigOven shortcode with ours.
|
91 |
+
*
|
92 |
+
* @since 1.23.0
|
93 |
+
* @param mixed $content Content we want to filter before it gets passed along.
|
94 |
+
*/
|
95 |
+
public static function replace_tasty_shortcode( $content ) {
|
96 |
+
preg_match_all( "/\[tasty-recipe\s.*?id='?\"?(\d+).*?]/im", $content, $matches );
|
97 |
+
foreach ( $matches[0] as $key => $match ) {
|
98 |
+
if ( WPRM_POST_TYPE === get_post_type( $matches[1][ $key ] ) ) {
|
99 |
+
$content = str_replace( $match, '[wprm-recipe id="' . $matches[1][ $key ] . '"]', $content );
|
100 |
+
}
|
101 |
+
}
|
102 |
+
|
103 |
+
return $content;
|
104 |
+
}
|
105 |
+
|
106 |
/**
|
107 |
* Replace BigOven shortcode with ours.
|
108 |
*
|
includes/public/class-wprm-taxonomies.php
CHANGED
@@ -50,9 +50,6 @@ class WPRM_Taxonomies {
|
|
50 |
register_taxonomy( $taxonomy, WPRM_POST_TYPE, $args );
|
51 |
register_taxonomy_for_object_type( $taxonomy, WPRM_POST_TYPE );
|
52 |
}
|
53 |
-
|
54 |
-
// Associate categories with recipes as well.
|
55 |
-
register_taxonomy_for_object_type( 'category', WPRM_POST_TYPE );
|
56 |
}
|
57 |
|
58 |
/**
|
50 |
register_taxonomy( $taxonomy, WPRM_POST_TYPE, $args );
|
51 |
register_taxonomy_for_object_type( $taxonomy, WPRM_POST_TYPE );
|
52 |
}
|
|
|
|
|
|
|
53 |
}
|
54 |
|
55 |
/**
|
readme.txt
CHANGED
@@ -34,6 +34,7 @@ An overview of WP Recipe Maker features:
|
|
34 |
* **Full text search** for your recipes
|
35 |
* Access your recipes through the WordPress **REST API**
|
36 |
* Built-in **SEO check** for your recipe metadata
|
|
|
37 |
* **Import your recipes** from other plugins (see below)
|
38 |
|
39 |
= WP Recipe Maker Premium =
|
@@ -65,6 +66,7 @@ Currently using another recipe plugin? No problem! You can easily migrate all yo
|
|
65 |
* ZipList and Zip Recipes
|
66 |
* Yummly
|
67 |
* Yumprint Recipe Card
|
|
|
68 |
* (More coming soon!)
|
69 |
|
70 |
This plugin is in active development. Feel free to contact us with any feature requests or ideas.
|
@@ -101,6 +103,12 @@ Yes! We pride ourselves on offering awesome support and almost always answer sup
|
|
101 |
|
102 |
== Changelog ==
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
= 1.22.0 =
|
105 |
* Feature: RTL support for recipe templates and print
|
106 |
* Improvement: Print and unit conversion functionality when using the print templates
|
@@ -337,6 +345,9 @@ Yes! We pride ourselves on offering awesome support and almost always answer sup
|
|
337 |
|
338 |
== Upgrade notice ==
|
339 |
|
|
|
|
|
|
|
340 |
= 1.22.0 =
|
341 |
Update required if you want to use the latest version of WP Recipe Maker Premium
|
342 |
|
34 |
* **Full text search** for your recipes
|
35 |
* Access your recipes through the WordPress **REST API**
|
36 |
* Built-in **SEO check** for your recipe metadata
|
37 |
+
* Compatible with **RTL** languages
|
38 |
* **Import your recipes** from other plugins (see below)
|
39 |
|
40 |
= WP Recipe Maker Premium =
|
66 |
* ZipList and Zip Recipes
|
67 |
* Yummly
|
68 |
* Yumprint Recipe Card
|
69 |
+
* Tasty Recipes
|
70 |
* (More coming soon!)
|
71 |
|
72 |
This plugin is in active development. Feel free to contact us with any feature requests or ideas.
|
103 |
|
104 |
== Changelog ==
|
105 |
|
106 |
+
= 1.23.0 =
|
107 |
+
* Feature: Import WP Tasty Recipes
|
108 |
+
* Improvement: Better handling of shortcodes in JSON-LD metadata
|
109 |
+
* Fix: Problem with double recipes in categories
|
110 |
+
* Fix: Jetpack Contact Form compatibility problem on manage page
|
111 |
+
|
112 |
= 1.22.0 =
|
113 |
* Feature: RTL support for recipe templates and print
|
114 |
* Improvement: Print and unit conversion functionality when using the print templates
|
345 |
|
346 |
== Upgrade notice ==
|
347 |
|
348 |
+
= 1.23.0 =
|
349 |
+
Update to prevent a Jetpack compatibility problem
|
350 |
+
|
351 |
= 1.22.0 =
|
352 |
Update required if you want to use the latest version of WP Recipe Maker Premium
|
353 |
|
templates/admin/menu/faq/whats_new.php
CHANGED
@@ -11,6 +11,14 @@
|
|
11 |
|
12 |
?>
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
<h3>2017-08-24 | WP Recipe Maker Premium 1.6.0</h3>
|
15 |
<ul>
|
16 |
<li>Feature: User Ratings</li>
|
11 |
|
12 |
?>
|
13 |
|
14 |
+
<h3>2017-09-01 | WP Recipe Maker 1.23.0</h3>
|
15 |
+
<ul>
|
16 |
+
<li>Feature: Import WP Tasty Recipes</li>
|
17 |
+
<li>Improvement: Better handling of shortcodes in JSON-LD metadata</li>
|
18 |
+
<li>Fix: Problem with double recipes in categories</li>
|
19 |
+
<li>Fix: Jetpack Contact Form compatibility problem on manage page</li>
|
20 |
+
</ul>
|
21 |
+
|
22 |
<h3>2017-08-24 | WP Recipe Maker Premium 1.6.0</h3>
|
23 |
<ul>
|
24 |
<li>Feature: User Ratings</li>
|
templates/admin/modal/tabs/recipe-details.php
CHANGED
@@ -15,10 +15,8 @@
|
|
15 |
<?php do_action( 'wprm_modal_notice' ); ?>
|
16 |
<div class="wprm-easyrecipe-warning" style="display: none;">
|
17 |
<strong>Warning!</strong>
|
18 |
-
<p>
|
19 |
-
<p>
|
20 |
-
<p>We also have an <a href="http://bootstrapped.ventures/wp-recipe-maker/import-from-easyrecipe/" target="_blank">EasyRecipe import feature</a> if you'd like to migrate those recipes!</p>
|
21 |
-
<p>This problem does not occur for new posts or posts without recipes. If you're getting this warning in those cases, please <a href="http://bootstrapped.ventures/wp-recipe-maker/support/" target="_blank">contact us</a>!</p>
|
22 |
</div>
|
23 |
<div class="wprm-recipe-form-container wprm-recipe-image-container">
|
24 |
<label for="wprm-recipe-image-id"><?php esc_html_e( 'Image', 'wp-recipe-maker' ); ?></label>
|
15 |
<?php do_action( 'wprm_modal_notice' ); ?>
|
16 |
<div class="wprm-easyrecipe-warning" style="display: none;">
|
17 |
<strong>Warning!</strong>
|
18 |
+
<p>We're detecting a compatibility problem, potentially breaking some of our functionality. You could try disabling all other plugins for a second to see if you can find the conflict.</p>
|
19 |
+
<p>Please <a href="http://bootstrapped.ventures/wp-recipe-maker/support/" target="_blank">contact us</a> for more help!</p>
|
|
|
|
|
20 |
</div>
|
21 |
<div class="wprm-recipe-form-container wprm-recipe-image-container">
|
22 |
<label for="wprm-recipe-image-id"><?php esc_html_e( 'Image', 'wp-recipe-maker' ); ?></label>
|
wp-recipe-maker.php
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
* Plugin Name: WP Recipe Maker
|
16 |
* Plugin URI: http://bootstrapped.ventures/wp-recipe-maker/
|
17 |
* Description: The easy and user-friendly recipe plugin for everyone. Automatic JSON-LD metadata for better SEO will get you more visitors!
|
18 |
-
* Version: 1.
|
19 |
* Author: Bootstrapped Ventures
|
20 |
* Author URI: http://bootstrapped.ventures/
|
21 |
* License: GPL-2.0+
|
15 |
* Plugin Name: WP Recipe Maker
|
16 |
* Plugin URI: http://bootstrapped.ventures/wp-recipe-maker/
|
17 |
* Description: The easy and user-friendly recipe plugin for everyone. Automatic JSON-LD metadata for better SEO will get you more visitors!
|
18 |
+
* Version: 1.23.0
|
19 |
* Author: Bootstrapped Ventures
|
20 |
* Author URI: http://bootstrapped.ventures/
|
21 |
* License: GPL-2.0+
|