A client of ours has heavily used contact forms using cf7 and flamingo.
The admin page "Address Book" was VERY slow (many seconds!)
It seemed to spend a lot of time in Flamingo_Contacts_List_Table->column_history()
There is a LOOP which does a FIND for matching messages.
I have speeded it up by doing get_objects_in_term()
and using post__in
instead of searching by slug, specifying just ids
for fields, and using none
for orderby
as we are just after the count.
I hope this may be useful?
// Contact channels
$terms = get_terms( Flamingo_Inbound_Message::channel_taxonomy );
if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
foreach ( (array) $terms as $term ) {
// !!! get ALL posts in using the TERM, these are the messages we want
$objects = get_objects_in_term($term->term_id, Flamingo_Inbound_Message::channel_taxonomy );
Flamingo_Inbound_Message::find( array(
//'channel' => $term->slug, // !!!
's' => $item->email,
'fields'=> 'ids', // !!! want just ids so we can count
'post__in' => $objects, // !!!
'orderby' => 'none', // !!! don't bother trying to order, we just want count!
) );
$count = (int) Flamingo_Inbound_Message::count();
if ( ! $count ) {
continue;
}
Also, the contact forms were VERY SLOW to SUBMIT (over a minute!)
Flamingo_Inbound_Message->save()
relies on WordPress to ensure unique post SLUGS, which works by checking for the specified slug and if found, appending a suffix and try again, if that is found then try the next suffux up, and so on.
When there are tens of thousands of submissions of the same form, this means tens of thousands of queries, which takes a while!
We can speed this up by using ONE QUERY to find the LARGEST suffix in use, and using the next one up, or if none then suffix "2" (the WordPress code seems to start with suffix 2)
If we specify the POST_NAME as an argument for wp_insert_post()
then WordPress won't do the check.
if ( $this->timestamp
and $datetime = date_create( '@' . $this->timestamp ) ) {
$datetime->setTimezone( wp_timezone() );
$postarr['post_date'] = $datetime->format( 'Y-m-d H:i:s' );
}
/* !!! if there are tens of thousands of posts with the SAME TITLE
* and we DON'T SPECIFY a post_name (slug) here
* we will have to loop through the posts with that name ONE AT A TIME
* until we get to a name which doesn't exist yet
*/
// Post slugs must be unique across all posts.
global $wpdb;
$slug = sanitize_title($postarr['post_title']);
$post_type = $postarr['post_type'];
$post_id = $postarr['ID'];
$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID ) );
if($post_name_check) {
// we have a post with that name already
$suffix = 2;
$alt_post_name = $slug.'-';
// find the BIGGEST suffix from the DB
$check_sql = "SELECT CAST(SUBSTRING(post_name,LENGTH(%s)+1) AS INTEGER) FROM $wpdb->posts WHERE post_name LIKE %s AND post_type=%s AND ID != %3d ORDER BY 1 DESC LIMIT 1";
$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $alt_post_name.'%', $post_type, $post_ID ) );
if($post_name_check) {
$suffix = absint($post_name_check)+1; // number from DB plus one
}
$slug .= '-'.$suffix; // either next suffix from DB or 2
$postarr['post_name'] = $slug;
} else {
// we DONT have a post with that name already, and can save a db query later by specifying the name here
$postarr['post_name'] = $slug;
}
$post_id = wp_insert_post( $postarr );