ZF-12284: Zend_Http_UserAgent_Features_Adapter_WurflApi Sends Persistence Information using WURFL_Configuration_InMemoryConfig to WURFL_WURFLManagerFactory incorrectly

Description

When using the {{INI}} configuration method and using the {{Zend_Application_Resource_UserAgent}} resource loader to initialise {{Zend_Http_UserAgent}} to use {{Zend_Http_UserAgent_Features_Adapter_WurflApi}}; the persistence params are sent through incorrectly.


resources.useragent.wurflapi.wurfl_api_version = "1.1"
resources.useragent.wurflapi.wurfl_lib_dir = APPLICATION_PATH "/../library/Wurfl/"
resources.useragent.wurflapi.wurfl_config_array.wurfl.main-file = APPLICATION_PATH "/../data/wurfl/wurfl.zip"
resources.useragent.wurflapi.wurfl_config_array.wurfl.patches = APPLICATION_PATH "/../data/wurfl/web_browsers_patch.xml"
resources.useragent.wurflapi.wurfl_config_array.persistence.provider = "File"

resources.useragent.wurflapi.wurfl_config_array.persistence.dir  = APPLICATION_PATH "/../data/wurfl/cache/"

resources.useragent.wurflapi.wurfl_config_array.cache.provider = "Null"
resources.useragent.storage.adapter = "Zend_Http_UserAgent_Storage_NonPersistent"

The line of code above that causes the problem is:


resources.useragent.wurflapi.wurfl_config_array.persistence.dir  = APPLICATION_PATH "/../data/wurfl/cache/"
// This is completely ignored:
resources.useragent.wurflapi.wurfl_config_array.persistence.expiration  = 3600

This is sent through to line 85 of {{Zend_Http_UserAgent_Features_Adapter_WurflApi}} as {{$c['persistence']['dir']}} and is a string. When this is passed though to {{WURFL_Configuration_InMemoryConfig::persistence()}} it is of course a string. However {{WURFL_Configuration_InMemoryConfig::persistence()}} expects it to be an array with a key of {"dir"}, e.g. {{array('dir'=>'/temp/my-dir/wurfl/cache/');}} Also, the "expiration" field is not taken into account at all, meaning that we cannot set an "expiration" time for an adaptor/provider.

There is a workaround for this by defining the {{dir}} as follows, and some people have done as follows:


resources.useragent.wurflapi.wurfl_config_array.persistence.dir.dir  = APPLICATION_PATH "/../data/wurfl/cache/"
resources.useragent.wurflapi.wurfl_config_array.persistence.dir.expiration  = 3600

My patch below amends this to be in-keeping with what seems to be Zend Framework Config conventions in using a "params" array. This patch also takes into account those who have used the workaround above and so backward compatible and will not break people's code who have already used the workaround above.

Patch is suggested as follows:

INI File Contents:


resources.useragent.wurflapi.wurfl_config_array.persistence.params.dir  = APPLICATION_PATH "/../data/wurfl/cache/"
resources.useragent.wurflapi.wurfl_config_array.persistence.params.expiration  = 3600

{{Zend_Http_UserAgent_Features_Adapter_WurflApi}} Patch (Line 80)

Existing:


} elseif (!empty($config['wurfl_config_array'])) {
    $c            = $config['wurfl_config_array'];
    $wurflConfig  = new WURFL_Configuration_InMemoryConfig();
    $wurflConfig->wurflFile($c['wurfl']['main-file'])
                ->wurflPatch($c['wurfl']['patches'])
                ->persistence($c['persistence']['provider'], $c['persistence']['dir']);
}

Proposed:


} elseif (!empty($config['wurfl_config_array'])) {
    $c            = $config['wurfl_config_array'];
    $wurflConfig  = new WURFL_Configuration_InMemoryConfig();
    $wurflConfig->wurflFile($c['wurfl']['main-file'])
                ->wurflPatch($c['wurfl']['patches']);
    $persistence = array();
    if (array_key_exists('dir', $c['persistence']) {
        if (is_string($c['persistence']['dir']) {
            $persistence['dir'] = $c['persistence']['dir'];
        } elseif (is_array($c['persistence']['dir'])) {
            $persistence = array_merge($persistence, $c['persistence']['dir']);
        }
    }
    if (array_key_exists('params', $c['persistence']) {
        $persistence = array_merge($persistence, $c['persistence']['params']);
    }
    $wurflConfig->persistence($c['persistence']['provider'], $persistence);
}

This patch allows total backward compatibility, and fix the bug. And so any of the following combinations will work:

"dir" as a string:


resources.useragent.wurflapi.wurfl_config_array.persistence.dir  = APPLICATION_PATH "/../data/wurfl/cache/"
resources.useragent.wurflapi.wurfl_config_array.persistence.params.expiration  = 3600

Old workaround, "dir" array:


resources.useragent.wurflapi.wurfl_config_array.persistence.dir.dir  = APPLICATION_PATH "/../data/wurfl/cache/"
resources.useragent.wurflapi.wurfl_config_array.persistence.dir.expiration  = 3600

New "params" array:


resources.useragent.wurflapi.wurfl_config_array.persistence.params.dir  = APPLICATION_PATH "/../data/wurfl/cache/"
resources.useragent.wurflapi.wurfl_config_array.persistence.params.expiration  = 3600

Comments

I noticed, after I submitted this issue, that there is already a bug in place for this.

http://framework.zend.com/issues/browse/ZF-10795

However, as I mentioned above, the patch above is more comprehensive and is backward compatible for those who may have used the workaround mentioned.

Hi Henry, to accept your patch you must fill out the CLA and add a patch (as file) with unit tests to this issue.

Thanks!

There's not really much point as Wurfl support has been removed from ZF as of version 1.12 - See this thread here:

http://websitefactors.co.uk/php/2012/…

Also, I have written a comprehensive guide to getting the Browscap running using your application ini:

http://websitefactors.co.uk/zend-framework/2012/…

I'll request that this is now closed.