npr / nprapi-wordpress

Access the NPR API from within WordPress. This repository is no longer being maintained. See the README for more information.
GNU General Public License v2.0
13 stars 30 forks source link

Wordpress Multisite Install: Fatal Error with PHP 7 #66

Open mack-linebaugh opened 5 years ago

mack-linebaugh commented 5 years ago

I had this plugin up and working on a single install of Wordpress 5.1 and PHP 7.2. I decided to switch it a multisite install. Afterward, I couldn't activate the plugin. I deleted it, reinstalled it, and kept getting the same error:

Fatal error: Uncaught ArgumentCountError: Too few arguments to function wpdb::prepare(), 1 passed in /npr-story-api/ds-npr-api.php on line 74 and exactly 2 expected in /wp-includes/wp-db.php:1295 Stack trace: #0 /npr-story-api/ds-npr-api.php(74): wpdb->prepare('SELECT blog_id ...') #1 [internal function]: nprstory_activation('') #2 /wp-includes/class-wp-hook.php(286): call_user_func_array('nprstory_activa...', Array) #3 /wp-includes/class-wp-hook.php(310): WP_Hook->apply_filters('', Array) #4 /wp-includes/plugin.php(465): WP_Hook->do_action(Array) #5 /nas/content/live/nashpubraddev/wp-admin/plugins.php(177): do_action('activate_npr-st...') #6 {main} thrown in /wp-includes/wp-db.php on line 1295

So the error originates in this function (line 74, referenced in the error message, is in bold):

function nprstory_activation() { global $wpdb; if ( function_exists( 'is_multisite' ) && is_multisite() ) { // check if it is a network activation - if so, run the activation function for each blog id $old_blog = $wpdb->blogid; // Get all blog ids $blogids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM $wpdb->blogs" ) ); foreach ( $blogids as $blog_id ) { switch_to_blog( $blog_id ); nprstory_activate(); } switch_to_blog( $old_blog ); } else { nprstory_activate(); } }

From Wordpress documentation:

With the upcoming PHP 7.1, former warnings when passing too few arguments to a function got raised to an ArgumentCountError exception with the following format: Fatal error: Uncaught ArgumentCountError: Too few arguments to function foobar()

Anyone know of a fix for this? One that doesn't involve editing wp-db.php, class-wp-hook.php, and plugin.php?

jwcounts commented 5 years ago

It looks like the main issue is with the usage of $wpdb->prepare, since it expects 2 arguments and only one is provided.

https://developer.wordpress.org/reference/classes/wpdb/prepare/

It's preforming a sprintf() find-and-replace on the query, and it's expecting something like this:

$blogids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM %s", $wpdb->blogs ) );
mack-linebaugh commented 5 years ago

I'm pasting this solution I generously received from @jwcounts on Slack, which solved the issue for me:

The $wpdb->prepare() function in Wordpress, which is referenced in the nprstory_activation() function, needs 2 arguments to work correctly: a query with placeholders, and the data to replace those placeholders.

Example: $wpdb->prepare( 'SELECT blog_id from %s', $wpdb->blog ); The %s is a placeholder for a string, and the $wpdb->blog is the string that will replace it. The prepare() function performs this replacement in order to help organize and sanitize the query

So, line 74 in the ds-npr-api.php should look like this: $blogids = $wpdb->get_col( $wpdb->prepare( "SELECT blog_id FROM %s", $wpdb->blogs ) );