I just inherited a custom plugin that takes Formstack submissions and creates WordPress posts from them. The posts are created fine, however the form contents are stored as serialized data in post_content.
I am tasked with enabling these posts to be edited within the WP Dashboard. Currently when you click on a post title, you are presented with a page that just shows the data; no capability to edit the data.
Enabling the editor controls within "supports" in the functions.php file gives me the editor with the serialized data just dumped in the editor.
I have never had to setup a custom edit page for a specific post type in WP. Is there someone out there who can direct me so a site that explains this? I'm running in circles.
You can filter the content before it is presented in the admin editing screen.
function my_filter_function_name( $content, $post_id ) {
if(get_post_type($post_id) == 'the_post_type_in_question'){
$serialized_content = $content;
$content_array = unserialize($serialized_content);
// do something with this array to put it in the format you want
// .....
$content = $new_formatted_content;
}
return $content;
}
add_filter( 'content_edit_pre', 'my_filter_function_name', 10, 2 );
But, that doesn't seem like it's going to be of much use to you.
In your situation, I suggest you take the time to write a script to convert all those posts so that everything is stored as post meta. (create the custom fields, first).
If your theme isn't built on any framework, then I think the quickest way to create a custom field is to use the Advanced Custom Fields plugin.
Then, once you know the meta_keys, you can write that script. E.g.
$posts = get_posts('post_type'=>'the_post_type','posts_per_page'=> -1);
foreach($posts as $post){
$content_array = unserialize($post->post_content);
// how you do the next bit will depend on whether or not this is an associative array. I'm going to assume it is (because it's a little easier :) )
foreach($content_array as $meta_key=>$meta_value){
update_post_meta($post->ID, $meta_key, $meta_value);
}
// just put what you actually want as the post content back into the post content:
wp_update_post(array('ID'=>$post->ID,'post_content'=>$content_array['post_content'])); // assuming the key of the element you want to be the post content is 'post_content'
}
To run this script, you could simply create a temporary new page and then create a template file specifically for that page and put the above code into that file (then visit the page).
You need to modify the plugin so that the data is unserialized before modifying, then serialized before saving to DB...
Alternatively, try using WP's CORE functionality:
https://codex.wordpress.org/Function_Reference/maybe_serialize
https://codex.wordpress.org/Function_Reference/maybe_unserialize
https://codex.wordpress.org/Function_Reference/is_serialized
https://codex.wordpress.org/Function_Reference/is_serialized_string
Related
I'm using PHP automation to create new Wordpress posts (with wp_insert_post). I'm also using 'Simple Fields' to add additional meta fields for displaying on the front end.
My code creates the Wordpress post, keeps the post ID in a variable and then goes on to add the required meta data immediately afterwards.
Trimming all the other clutter, this is my process:
// Insert the post into the database and return the post ID
$post_id = wp_insert_post( $my_post );
// Add '$price' to relevant meta field
update_post_meta($post_id, '_simple_fields_fieldGroupID_1_fieldID_4_numInSet_0', $price);
This works fine, when I check the database, the 'price' meta field has the correct information inserted.
The problems starts when I try to extract it using:
echo simple_fields_value("price", $post->ID);
The code works - But the only way I can get it to pull the data is to log into the Wordpress admin, open the post for editing and then hit 'Update'.
Providing I open every post and hit 'Update', there's not a problem with my code... it does everything as expected.
My question is, what is the 'Update' button doing that I'm not? I've tried using 'wp_update_post' to re-open the post and save after the meta data is added to see if that helped, but it doesn't.
// Open and update post to ensure meta data saves correctly
$update_post = array(
'ID' => $post_id,
'post_title' => $title
);
// Update the post into the database
wp_update_post($update_post);
Your help on this would be much appreciated,
It looks like you are using the Simple Fields Plugin. I have never personally used this plugin, however I had a quick look and it looks like the plugin runs a few extra things on the save of the post. Here is one of the queries it uses for some sort of cacheing :
// Save info about the fact that this post have been saved. This info is used to determine if a post should get default values or not.
update_post_meta($post_id, "_simple_fields_been_saved", "1");
Since you are inserting this meta value manually, I would recommend you use the native wordpress get_post_meta function to call the value, your query should look something like this:
get_post_meta($post->ID, "_simple_fields_fieldGroupID_1_fieldID_4_numInSet_0");
I have a WordPress site that has a standard Page called Places with URL
example.com/places/
And I have several child Pages called by cities
example.com/places/city-1
example.com/places/city-2
Now, I have a custom post type Place that should indicate a single place and should have permalink like
example.com/places/place-1
But then if I go to one of the previous links with city-1, city-2 I get 404 obviously because there is no place with that permalink.
Is there a way for WordPress to drop to previous permalink. So if there is no place with that name, look for a page with it.
You could probably use the the REFERER-value from the PHP server variable $_SERVER, but it´s not very reliable and can be altered.
I am using the plugin "Permalink Finder" in one of the pages I am maintaining and that works quite well for finding changed URL. You could give it a try and see if it works for you, too.
In case somebody ever having a similar problem, it can be done by using verbose page rules. This is an example I found at WordPress Stack Exchange
https://wordpress.stackexchange.com/questions/22438/how-to-make-pages-slug-have-priority-over-any-other-taxonomies-like-custom-post
add_action( 'init', 'wpse16902_init' );
function wpse16902_init() {
$GLOBALS['wp_rewrite']->use_verbose_page_rules = true;
}
add_filter( 'page_rewrite_rules', 'wpse16902_collect_page_rewrite_rules' );
function wpse16902_collect_page_rewrite_rules( $page_rewrite_rules )
{
$GLOBALS['wpse16902_page_rewrite_rules'] = $page_rewrite_rules;
return array();
}
add_filter( 'rewrite_rules_array', 'wspe16902_prepend_page_rewrite_rules' );
function wspe16902_prepend_page_rewrite_rules( $rewrite_rules )
{
return $GLOBALS['wpse16902_page_rewrite_rules'] + $rewrite_rules;
}
I have created two plugins. Plugin A gets the latest posts, all of them. It has an option that can remove posts by entering their ID, this is accessible via the shortcode or directly in functions.php. This works.
Plugin B gets the most popular posts using an internal analytics systems. I have a variable called $most_popular_ids which contains all of the post ID's of the highest viewed posts for that particular category. So $most_popular_ids changes depending on which page it is on. This works.
These are displayed side by side on the main pages of the website. So ideally I would like them to not show duplicate posts.
What I finally need to do is pass $most_popular_ids from plugin B to plugin A or to functions.php. This will allow me to exclude all of the most popular posts from the latest posts.
Obviously making the variable global only works in the scope of the file so that won't work. I tried creating a $_SESSION but you can't do that in Wordpress as far as I know. Most of the stuff in the plugins can't be redeclared so my include attempts didn't work either :\
Can anyone help me?
You can use sessions in WordPress, but it would probably be easier to use the wp_cache_set() and wp_cache_get() functions
For example, in Plugin B you would do something like:
wp_cache_set('mykey_most_popular_ids', $most_popular_ids);
Then in Plugin A or your functions file you can do:
$most_popular_ids = wp_cache_get('mykey_most_popular_ids);
Obviously you'd need to make sure the function in Plugin B sets the cache entry before trying to get it in Plugin A of the functions file
Here's an approach using filters. In plugin A, implement a filter that allows to set the post__not_in param of the query:
$query_args = array();
$post__not_in = apply_filters( 'check_for_most_popular_ids', false );
if( $post__not_in && is_array( $post__not_in ) )
$query_args['post__not_in'] = $post__not_in;
$query = new WP_Query( $query_args );
In plugin B, hook into the filter and pass the most popular IDs:
add_filter( 'check_for_most_popular_ids', 'send_most_popular_ids', 10, 1 );
function send_most_popular_ids( $post__not_in = false )
{
$most_popular_ids = get_most_popular_ids(); // returns array of IDs OR false
if( $most_popular_ids )
return $most_popular_ids;
return $post__not_in;
}
I've recently started developing a portfolio website which I would like to link to my wordpress blog using simplepie. It's been quite a smooth process so far - loading names and descriptions of posts, and linking them to the full post was quite easy. However, I would like the option to render the posts in my own website as well. Getting the full content of a given post is simple, but what I would like to do is provide a list of recent posts which link to a php page on my portfolio website that takes a GET variable of some sort to identify the post, so that I can render the full content there.
That's where I've run into problems - there doesn't seem to be any way to look up a post according to a specific id or name or similar. Is there any way I can pull some unique identifier from a post object on one page, then pass the identifier to another page and look up the specific post there? If that's impossible, is there any way for me to simply pass the entire post object, or temporarily store it somewhere so it can be used by the other page?
Thank you for your time.
I stumbled across your question looking for something else about simplepie. But I do work with an identifier while using simplepie. So this seems to be the answer to your question:
My getFeedPosts-function in PHP looks like this:
public function getFeedPosts($numberPosts = null) {
$feed = new SimplePie(); // default options
$feed->set_feed_url('http://yourname.blogspot.com'); // Set the feed
$feed->enable_cache(true); /* Enable caching */
$feed->set_cache_duration(1800); /* seconds to cache the feed */
$feed->init(); // Run SimplePie.
$feed->handle_content_type();
$allFeeds = array();
$number = $numberPosts>0 ? $numberPosts : 0;
foreach ($feed->get_items(0, $number) as $item) {
$singleFeed = array(
'author'=>$item->get_author(),
'categories'=>$item->get_categories(),
'copyright'=>$item->get_copyright(),
'content'=>$item->get_content(),
'date'=>$item->get_date("d.m.Y H:i"),
'description'=>$item->get_description(),
'id'=>$item->get_id(),
'latitude'=>$item->get_latitude(),
'longitude'=>$item->get_longitude(),
'permalink'=>$item->get_permalink(),
'title'=>$item->get_title()
);
array_push($allFeeds, $singleFeed);
}
$feed = null;
return json_encode($allFeeds);
}
As you can see, I build a associative array and return it as JSON what makes it really easy using jQuery and ajax (in my case) on the client side.
The 'id' is a unique identifier of every post in my blog. So this is the key to identify the same post also in another function/on another page. You just have to iterate the posts and compare this id. As far as I can see, there is no get_item($ID)-function. There is an get_item($key)-function but it is also just taking out a specific post from the list of all posts by the array-position (which is nearly the same way I suggest).
Going a bit mad here... :)
I'm just trying to add CCK fields from a Content Profile content type into page-user.tpl.php (I'm creating a highly-themed user profile page).
There seem to be two methods, both of which have a unique disadvantage that I can't seem to overcome:
'$content profile' method.
$var = $content_profile->get_variables('profile');
print $var['field_last_name'][0]['safe'];
This is great, except I can't seem to pass the currently viewed user into $content_profile, and it therefore always shows the logged in user.
'$content profile load' method.
$account_id = arg(1);
$account = user_load($account_id);
$user_id = $account->uid;
$var = content_profile_load('profile', $user_id);
print $var->field_first_name[0]['value'];
Fine, but now I can't access the full rendered fields, only the plain values (i.e. if the field has paragraphs they won't show up).
How can I have both things at once? In other words how can I show fields relating to the currently viewed user that are also rendered (the 'safe' format in 1)?
I've Googled and Googled and I just end up going round in circles. :(
Cheers,
James
Your content profile load method seems to be the closest to what you want.
In your example:
$account_id = arg(1);
$account = user_load($account_id);
$user_id = $account->uid;
$var = content_profile_load('profile', $user_id);
print $var->field_first_name[0]['value'];
The $var is just a node object. You can get the "full rendered fields" in a number of ways (assuming you mean your field with a filter applied).
The most important thing to check is that you're field is actually configured properly.
Go to:
admin/content/node-type/[node-type]/fields/field_[field-name] to configure your field and make sure that under text processing that you've got "Filtered text" selected.
If that doesn't fix it,try applying this:
content_view_field(content_fields("field_last_name"), $var, FALSE, FALSE)
(more info on this here: http://www.trevorsimonton.com/blog/cck-field-render-node-formatter-format-output-print-echo )
in place of this:
print $var->field_first_name[0]['value'];
if none of that helps... try out some of the things i've got on my blog about this very problem:
http://www.trevorsimonton.com/blog/print-filtered-text-body-input-format-text-processing-node-template-field-php-drupal
When you're creating a user profile page there is a built in mechanism for it. just create a user template file, user_profile.tpl.php.
When you use the built in mechanism you automatically get access to the $account object of the user you are browsing, including all user profile cck fields. You have the fields you are looking for without having to programmatically load the user.
I have a field called profile_bio and am able to spit out any mark up that is in without ever having to ask for the $account.
<?php if ($account->content[Profile][profile_bio]['#value']) print "<h3>Bio</h3>".$account->content[Profile][profile_bio]['#value']; ?>
I've tried themeing content profiles by displaying profile node fields through the userpage before and it always seems a little "hacky" to me. What I've grown quite fond of is simply going to the content profile settings page for that node type and setting the display to "Display the full content". This is fine and dandy except for the stupid markup like the node type name that content profile injects.
a solution for that is to add a preprocess function for the content profile template. one that will unset the $title and remove the node-type name that appears on the profile normally.
function mymodule_preprocess_content_profile_display_view(&$variables) {
if ($variables['type'] == 'nodetypename') {
unset($variables['title']);
}
}
A function similar to this should do the trick. Now to theme user profiles you can simply theme your profile nodes as normal.