Reputation: 1279
I am experiencing a problem where the way I am calling a PHP function is causing incorrect output from a a class that otherwise acts properly.
Specifically, I am using the full-name-parser package to split full names in to "first", "middle" and "last" parts. It performs this task accurately.
However, I am trying to do it inside WordPress - specifically during an import via the WPAllImport plugin in which I am importing CSV data as WordPress Users.
WPAllImport supports execution of PHP functions (standard or custom) on import input data, allowing it to be manipulated before saving, eg. [function_name({input_field[1]})]
.
So I have crafted a wrapper function, get_name_part
to allow me to split my input field name_full
in to first, middle and last names for import to those corresponding WordPress fields. My get_name_part
looks like this...
require_once '/home/mysite/public_html/wp-content/plugins/cxt-user-wpai-import/full-name-parser/vendor/autoload.php';
use ADCI\FullNameParser\Parser;
// name eg. Jokubas Phillip Gardner
// part eg. title, first, middle, last, nick, suffix,
// called via eg. [get_name_part({name_full[1]}, "first")]
function get_name_part($name, $part) {
$parser = new Parser(
[
'part' => $part,
// 'fix_case' => FALSE,
'throws' => FALSE
]
);
// Return the parsed name part
$nameObject = $parser->parse($name);
// Give it back to WPAllImport
return $nameObject;
}
That is, it should take the source name name_full
and also a string corresponding to full-name-parser options which describe the name part (either first
, middle
or last
).
In WPAllImport, then, I am calling these three lines, separately, in the WPAllImport fields for first_name, last_name and my custom name_mid...
[get_name_part({name_full[1]}, "first")]
[get_name_part({name_full[1]}, "middle")]
[get_name_part({name_full[1]}, "last")]
In theory, this should allow me to use a single wrapper function to spit back the specified part from the specified full name.
The problem is...
The first operation completes successfully. That is, putting [get_name_part({name_full[1]}, "first")]
in my import settings' first_name field successfully saves a parsed first name (eg. "Jokubas") in the first_name WordPress field.
However, things break down after that. [get_name_part({name_full[1]}, "last")]
places no name at all in the last_name field. It repeatedly fails.
And [get_name_part({name_full[1]}, "middle")]
places an incorrect combination of the actual middle and last (eg. "Phillip Gardner") as middle name.
So the actual output is:
This is not consistent with full-name-parser itself, which correctly parses outside of my function and the import environment, like...
I'm not sure what the reason is, but I feel like it may be something to do with calling the same function three times from the same import step, albeit with different parameters.
I appreciate that I have mentioned a couple of product names above which are not plain PHP. But I feel like there may something I could do in the function code to accommodate the fact that this function is getting called three times, with different parameters, in a single process; that the underlying reason may have something to do with this repetition or contamination.
I have, therefore, considered whether there is a need to destroy all variables at the end of the function. However, executing unset
on $name
, $part
, $parser
or $nameObject
after the return
does not fix anything.
What am I missing?
Thanks.
Edit:
WordPress debug.log shows:
[01-Mar-2018 15:43:06 UTC] WordPress database error Table 'context_wpdb.wpcxt_2_usermeta' doesn't exist for query SHOW COLUMNS FROM wpcxt_2_usermeta made by do_action('admin_init'), WP_Hook->do_action, WP_Hook->apply_filters, call_user_func_array, PMXI_Plugin->adminInit, PMXI_Admin_Manage->edit, PMXI_Admin_Import->template, PMXI_Model->setTable
[01-Mar-2018 15:43:06 UTC] WordPress database error Table 'context_wpdb.wpcxt_2_usermeta' doesn't exist for query SELECT umeta_id, meta_key FROM wpcxt_2_usermeta GROUP BY meta_key ORDER BY umeta_id made by do_action('admin_init'), WP_Hook->do_action, WP_Hook->apply_filters, call_user_func_array, PMXI_Plugin->adminInit, PMXI_Admin_Manage->edit, PMXI_Admin_Import->template, PMXI_Model_List->getBy
The PMXI* prefixes pertain to WPAllImport.
Edit 2:
Here are some valid ways in which full-name-parser operates on its own (ie. slices a supplied full name in to identified components)...
1.
Passing "part" as "all" (or not, since "all" is default) makes $nameObject an object containing all identified portions of the name...
require_once '/home/context/public_html/wp-content/plugins/cxt-user-wpai-import/full-name-parser/vendor/autoload.php';
use ADCI\FullNameParser\Parser;
$parser = new Parser(
[
'part' => 'all',
// 'fix_case' => FALSE,
'throws' => FALSE
]
);
$name = 'Jokubas Phillip Gardner';
$nameObject = $parser->parse($name);
print_r($nameObject);
... so the above outputs all available portions of the name...
FullNameParser\Name Object ( [leadingInitial:ADCI\FullNameParser\Name:private] => [firstName:ADCI\FullNameParser\Name:private] => Jokūbas [nicknames:ADCI\FullNameParser\Name:private] => [middleName:ADCI\FullNameParser\Name:private] => Phillip [lastName:ADCI\FullNameParser\Name:private] => Gardner [academicTitle:ADCI\FullNameParser\Name:private] => [suffix:ADCI\FullNameParser\Name:private] => [errors:ADCI\FullNameParser\Name:private] => Array ( ) )
That is correct behaviour.
2.
But passing only one portion of the name, eg. 'part' as 'last', like follows, makes $nameObject a string, containing only the one stated portion. So...
require_once '/home/context/public_html/wp-content/plugins/cxt-user-wpai-import/full-name-parser/vendor/autoload.php';
use ADCI\FullNameParser\Parser;
$parser = new Parser(
[
'part' => 'last',
// 'fix_case' => FALSE,
'throws' => FALSE
]
);
$name = 'Jokubas Phillip Gardner';
$nameObject = $parser->parse($name);
echo 'Here is my nameObject: ' . $nameObject . '<br />';
The above outputs the following only...
Gardner
That is also correct behaviour.
3.
Full-name-parser has named get*
functions dedicated to obtaining individual portions, eg. getFirstName()
, but they do not appear to be essential. I was attempting to use the part
parameter instead.
Upvotes: 2
Views: 1136
Reputation: 1607
Ok, the first attempt was wrong, but I think I found the problem.
This behavior happens if there is a space at the end of the name. Actually the parser can not find the last name in this case, and throws an exception, but you have turned exceptions off.
If you try
$parser = new ADCI\FullNameParser\Parser(['throws' => FALSE]);
var_dump($parser->parse('Jokubas Phillip Gardner '));
You will see:
class ADCI\FullNameParser\Name#2 (8) {
private $leadingInitial =>
NULL
private $firstName =>
string(7) "Jokubas"
private $nicknames =>
NULL
private $middleName =>
string(15) "Phillip Gardner"
private $lastName =>
NULL
private $academicTitle =>
NULL
private $suffix =>
NULL
private $errors =>
array(1) {
[0] =>
string(26) "Couldn't find a last name."
}
}
So the solution is to trim
your input.
function get_name_part($name, $part) {
$parser = new Parser(
[
'part' => $part,
// 'fix_case' => FALSE,
// 'throws' => FALSE
]
);
// Return the parsed name part
return $parser->parse(trim($name));
}
Upvotes: 1
Reputation: 5589
'context_wpdb.wpcxt_2_usermeta' doesn't exist.
The obviuos in the error message is that there is a table missing or it is in the wrong schema.
How this impacts and if has to do with your issue it is difficult to know.
To help you troubble shoot the issue here there is a plugin that I took from some page some time ago.
This plugin will let you add log statemets to your code that will come out in the wp-content/debug.log
file.
In this way you can inspect the different values for the functions you are calling and see what can be wrong.
For the plugin to work you have to set the following in wp_config.php:
define('WP_DEBUG', true);
define('WP_DEBUG_DISPLAY', false);
define('WP_DEBUG_LOG', true);
Once the plugin is installed, just add write_log($variable);
in your code for it to come out in the debug.log
file.
/* Plugin */
if(!defined('ABSPATH')) exit;
if ( ! function_exists('write_log')) {
function write_log ( $log ) {
if (defined('WP_DEBUG_LOG') && true === WP_DEBUG_LOG){
if ( is_array( $log ) || is_object( $log ) ) {
error_log( print_r( $log, true ) );
} else {
error_log( $log );
}
}
}
}
The plugin is meant to be put standalone in the wp-content/plugins
folder.
When you are finished, remove the write_log()
statements from your code, remove the plugin, and turn off the debug settings in wp_config.php
Upvotes: 0