When saving a user entity with user_save and with a phone field defined, phone_field_presave() tries to call phone_libphonenumber_clean() which is defined in phone.libphonenumber.inc and not yet loaded.

Comments

sylvain lecoy’s picture

Status: Active » Needs review
StatusFileSize
new516 bytes

This patch fix it.

sylvain lecoy’s picture

Sorry you have to add:

module_load_include('inc', 'phone', 'includes/phone.libphonenumber');

instead of

module_load_include('inc', 'phone', 'phone.libphonenumber');

cdale’s picture

Status: Needs review » Postponed (maintainer needs more info)

This is incorrect.

the phone_libphonenumber() call should take care of loading up the required include files via the libraries module.

If this file is not loaded, then something else has gone wrong somewhere, and I'd much rather try and track that issue down.

Do you have steps to replicate this from a clean D7 install with just phone and libraries enabled?

sylvain lecoy’s picture

Yes, put this in a unit test:

<?php
  function testSave() {
    $user = $this->drupalCreateUser();
    $user->phone[LANGUAGE_NONE][0]['number'] = '123456789';
    $user->phone[LANGUAGE_NONE][0]['countrycode'] = '33';
    user_save($user);

    $user = user_load($user->uid, TRUE);
    $this->assertEqual('123456789', $user->phone[LANGUAGE_NONE][0]['number'], 'Phone field number saved.', 'Phone');
    $this->assertEqual('33', $user->phone[LANGUAGE_NONE][0]['countrycode'], 'Phone field countrycode saved.', 'Phone');
  }
?>

Of course you might also create a field type phone called 'phone' on the 'user' entity.

And you are right because I get another problem which is: can't load libphonenumber/PhoneNumberUtil.

sylvain lecoy’s picture

Status: Postponed (maintainer needs more info) » Needs work
cdale’s picture

Status: Needs work » Postponed (maintainer needs more info)

I've tried to replicate this, but cannot. I've added a phone field to the user entity, created a new user, saved/updated an existing user, I even deleted an account, all worked fine and as expected.

Have you tried with the latest 7.x-2.x branch and the latest libphonenumber code?

sylvain lecoy’s picture

Status: Postponed (maintainer needs more info) » Needs work

Are you reproducing the code via the Drupal UI ? Because with the drupal UI and user form editing it works.

Reproduce the step using the user_save() function. I gave you a sample of a Unit Test function, do you want a full class to execute ?

Yes I use the -dev version.

sylvain lecoy’s picture

It is not loading the library because:

In a testing context, the module is installed and then executed in the same thread.

The function phone_libphonenumber() caches a boolean value called $success which remains true once checkings are done at module installation (e.g. with libraries_detect() function).

Thus, when calling again the phone_libphonenumber() function in the phone_field_presave function on user_save(), $success is already set to TRUE and the loading of php files never happen.

To resolve the problem I had to write these lines of code in save() method of the user controller:

<?php
    module_load_include('inc', 'phone', 'includes/phone.libphonenumber');
    libraries_load('libphonenumber-for-php');
?>

This work-around fixed my test case.

To reproduce the steps, I guess you just call phone_libphonenumber(TRUE) once somewhere in your code, then calling phone_libphonenumber() wont load the library.

This is easily fixable by changing the way this function works, and cache another static variable which indicates whether or not the library has been loaded.

cweagans’s picture

Status: Needs work » Needs review
StatusFileSize
new942 bytes

Something like this?

cdale’s picture

Title: Fatal error: Call to undefined function phone_libphonenumber_clean() in phone.module on line 467. » phone_libphonenumber() caches $detect_only; breaks unit tests
StatusFileSize
new1.54 KB

Ahh, I didn't click that is was not through the UI, and that is was being run by unit tests.

The patch in #9 won't work, as it will trigger a hook_requirements error I think as $library['loaded'] is only true after libraries_load I believe.

A better approach is not to statically cache the success call for detect only.

Something like the following?

sylvain lecoy’s picture

Status: Needs review » Reviewed & tested by the community

It not only break unit test, but possibly a client request which first checks if the library exists (with detect) before loading it.

The patch in #10 is working for me.

cweagans’s picture

Status: Reviewed & tested by the community » Fixed

Looks good to me too. Committed and pushed to 7.x-2.x.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.