I'm trying to fix a problem with a Wordpress Plugin. I've received the following error:
strpos(): Argument #1 ($haystack) must be of type string, array given
The code i'm getting the error from is as following:
// woocommerce field
if ( $field === '_gallery_images' ) {
// set the image prefix if there is one
$prefix = '';
if ( $tmp_field['prefix'] !== '' ) {
$prefix = $tmp_field['prefix'];
}
// if value is not an array, try to create one
// this may be due to comma separated urls or space separated
if ( ! is_array( $our_value ) ) {
// if we have comma separated URL's, create an array
if ( strpos( $our_value, ',' ) !== false ) {
$array = explode( ',', $our_value );
if ( is_array( $array ) ) {
$our_value = $array;
}
}
// if we have space separated URL's, create an array
// This next line is generating the error
if ( strpos( $our_value, ' ' ) !== false ) {
$array = explode( ' ', $our_value );
if ( is_array( $array ) ) {
$our_value = $array;
}
}
// if we have newline separated URL's, create an array
if ( strpos( $our_value, "\n" ) !== false ) {
$array = explode( "\n", $our_value );
if ( is_array( $array ) ) {
$our_value = $array;
}
}
}
He gets this value from an API and tries to explode the sep urls:
11104_105-b.jpg, 11104_105.jpg, 11104_105-c.jpg, 11104_105-d.jpg
I've updated the post with the full code section, sorry.
The function that cointan an error is the following:
if ( strpos( $our_value, ' ' ) !== false ) {
Here is the full log about the error
PHP Fatal error: Uncaught TypeError: strpos(): Argument #1 ($haystack) must be of type string, array given in /home2/miriamcoelho/public_html/wp-content/plugins/wpgetapi-api-to-posts/includes/class-wpgetapi-api-to-posts-importer.php:1703Stack
trace:#0 /home2/miriamcoelho/public_html/wp-content/plugins/wpgetapi-api-to-posts/includes/class-wpgetapi-api-to-posts-importer.php(1703): strpos(Array, ' ')
#1 /home2/miriamcoelho/public_html/wp-content/plugins/wpgetapi-api-to-posts/includes/class-wpgetapi-api-to-posts-importer.php(808): WPGetAPI_API_To_Posts_Importer->map_fields_and_add_data(Array, Array)
#2 /home2/miriamcoelho/public_html/wp-content/plugins/wpgetapi-api-to-posts/includes/class-wpgetapi-api-to-posts-importer.php(1065): WPGetAPI_API_To_Posts_Importer->create_posts(Array, Array, Array, '1207067011')
#3 /home2/miriamcoelho/public_html/wp-content/plugins/wpgetapi-api-to-posts/includes/class-wpgetapi-api-to-posts-importer.php(956): WPGetAPI_API_To_Posts_Importer->maybe_add_delete_posts_ajax(Array, '1207067011', Array)
#4 /home2/miriamcoelho/public_html/wp-includes/class-wp-hook.php(324): WPGetAPI_API_To_Posts_Importer->run_post_creator_ajax('')
#5 /home2/miriamcoelho/public_html/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters('', Array)
#6 /home2/miriamcoelho/public_html/wp-includes/plugin.php(517): WP_Hook->do_action(Array)
#7 /home2/miriamcoelho/public_html/wp-admin/admin-ajax.php(192): do_action('wp_ajax_wpgetap...')
#8 {main}thrown in /home2/miriamcoelho/public_html/wp-content/plugins/wpgetapi-api-to-posts/includes/class-wpgetapi-api-to-posts-importer.php on line 1703
I don't know how to fix this, and the plugin owner does not seem to be interested in a solution.
You have one big if
that tests for the need to convert a string to array, determining if you enter your 3-stage attempt to convert.
Each stage expects a string in input (strpos
will be uncompromising about it), and, if succeeding, will transform $our_value
to an array, to be passed to the next stage.
But… Wait! Didn't we say that the next stage too wanted a string as input? And that the just-transformed $our_value
is now an array?
You should a minima add your if(!is_array($our_value))
protection before each stage ("convert if not already converted").
But this first solution still has a problem: in the example you gave, 11104_105-b.jpg, 11104_105.jpg, 11104_105-c.jpg, 11104_105-d.jpg
, we have both a comma and a space. How would it behave?
First it will split against commas, letting the spaces in place (thus you'll have [ "11104_105-b.jpg", " 11104_105.jpg", … ]
).
And with our newly introduced protection, those spaces will stay forever.
The ideal solution would be to detect "any serie of one or more space, comma, or newline".
Well, good news: you can use regular expressions to that, replacing explode
by preg_split
.
Replace your whole if ( ! is_array( $our_value ) ) { … }
block by:
if ( ! is_array( $our_value ) ) { // Or if ( is_string( $our_value ) ) {
$our_value = preg_split('[\s,]+', $our_value);
}
And… That's all!
Some explanations:
[\s,]+
means \s
"any whitespace character (space, tabulation, newline…)" or ,
, +
"repeated one or more time".
As we have used []
around whitespace and comma, they are considered the same group, so we can mix them in the repetition (that's why ", "
will rightly be considered a repetition)strpos
before trying to preg_split
preg_split
, which will always return an array:if ( is_array( $array ) )
anymore$array
: we can directly replace $our_value