<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.http.user-agent-device">
    <title>The UserAgent Device Interface</title>

    <sect2 id="zend.http.user-agent-device.intro">
        <title>Overview</title>

        <para>
            Once the User-Agent has been parsed and capabilities retrieved from the <link
                linkend="zend.http.user-agent-features">Features adapter</link>, you will be
            returned an object that represents the discovered brower device. This interface
            describes the various capabilities you may now introspect.
        </para>

        <para>
            Additionally, the various device classes define algorithms for matching the devices they
            describe. By implementing this interface, you may provide additional logic around these
            capabilities.
        </para>
    </sect2>

    <sect2 id="zend.http.user-agent-device.quick-start">
        <title>Quick Start</title>

        <para>
            The <interfacename>Zend_Http_UserAgent_Device</interfacename> interface defines the
            following methods.
        </para>

        <programlisting language="php"><![CDATA[
interface Zend_Http_UserAgent_Device extends Serializable
{
    public function __construct($userAgent = null, array $server = array(), array $config = array());
    public static function match($userAgent, $server);
    public function getAllFeatures();
    public function getAllGroups();
    public function getBrowser();
    public function getBrowserVersion();
    public function getGroup($group);
    public function getImageFormatSupport();
    public function getImages();
    public function getMaxImageHeight();
    public function getMaxImageWidth();
    public function getPhysicalScreenHeight();
    public function getPhysicalScreenWidth();
    public function getPreferredMarkup();
    public function getUserAgent();
    public function getXhtmlSupportLevel();
    public function hasFlashSupport();
    public function hasPdfSupport();
    public function hasPhoneNumber();
    public function httpsSupport();
}
]]></programlisting>

        <para>
            The static function <methodname>match()</methodname> should be used to determine whether
            the provided User-Agent and environment (represented by the <varname>$server</varname>
            variable) match this device. If they do, the <classname>Zend_Http_UserAgent</classname>
            class will then create an instance of the class, passing it the User-Agent,
            <varname>$server</varname> array, and any configuration available; at this time, it is
            expected that the Device class will consult with a features adapter, if present, and
            populate itself with discovered capabilities.
        </para>

        <para>
            In practice, you will likely extend
            <classname>Zend_Http_UserAgent_AbstractDevice</classname>, which provides functionality
            around discovering capabilities from the User-Agent string itself, as well as
            discovering and querying a <link linkend="zend.http.user-agent-features">Features
                adapter</link>.
        </para>
    </sect2>

    <sect2 id="zend.http.user-agent-device.options">
        <title>Configuration Options</title>

        <para>
            Configuration options are defined on a per-device basis. The following options are
            defined in <classname>Zend_Http_UserAgent_AbstractDevice</classname>. Like all options,
            the "." character represents an additional level of depth to the configuration array.
        </para>

        <variablelist>
            <title>Device Options</title>

            <varlistentry>
                <term>features.classname</term>

                <listitem>
                    <para>
                        The name of a <link linkend="zend.http.user-agent-features">Features
                            adapter</link> class that has either been previously loaded or which is
                        discoverable via autoloading, or used in conjunction with the
                        <varname>features.path</varname> option. This class must implement the
                        <interfacename>Zend_Http_UserAgent_Features_Adapter</interfacename>
                        interface.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry>
                <term>features.path</term>

                <listitem>
                    <para>
                        If provided, the filesystem path to the features adapter class being used.
                        The path must either be an absolute path or discoverable via the
                        <varname>include_path</varname>.
                    </para>
                </listitem>
            </varlistentry>

        </variablelist>
    </sect2>

    <sect2 id="zend.http.user-agent-device.methods">
        <title>Available Methods</title>

        <variablelist>
            <varlistentry id="zend.http.user-agent-device.methods.constructor">
                <term>
                    <methodsynopsis>
                        <methodname>__construct</methodname>
                        <methodparam>
                            <funcparams>$userAgent = null, array $server = array(), array $config =
                                array()</funcparams>
                        </methodparam>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Expects a User-Agent string, an array representing the HTTP environment, and an
                        array of configuration values. The values are all optional, as they may be
                        populated during deserialization.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.match">
                <term>
                    <methodsynopsis>
                        <methodname>match</methodname>
                        <methodparam>
                            <funcparams>$userAgent, $server</funcparams>
                        </methodparam>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        This method is static.
                    </para>

                    <para>
                        Provided the <varname>$userAgent</varname> string and an array representing the
                        HTTP headers provided in the request, determine if they match the capabilities
                        of this device. This method should return a boolean.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-all-features">
                <term>
                    <methodsynopsis>
                        <methodname>getAllFeatures</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Returns an array of key/value pairs representing the features supported by
                        this device instance.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-all-groups">
                <term>
                    <methodsynopsis>
                        <methodname>getAllGroups</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Similar to <methodname>getAllFeatures()</methodname>, this retrieves all
                        features, but grouped by type.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.has-feature">
                <term>
                    <methodsynopsis>
                        <methodname>hasFeature</methodname>
                        <methodparam>
                            <funcparams>$feature</funcparams>
                        </methodparam>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Query the device to determine if it contains information on a specific
                        feature.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-feature">
                <term>
                    <methodsynopsis>
                        <methodname>getFeature</methodname>
                        <methodparam>
                            <funcparams>$feature</funcparams>
                        </methodparam>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the value of a specific device feature, if present. Typically, this
                        will return a boolean <constant>false</constant> or a
                        <constant>null</constant> value if the feature is not defined.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-browser">
                <term>
                    <methodsynopsis>
                        <methodname>getBrowser</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Returns the browser string as discoverd from the User-Agent string.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-browser-version">
                <term>
                    <methodsynopsis>
                        <methodname>getBrowserVersion</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the browser version as discovered from the User-Agent string.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-group">
                <term>
                    <methodsynopsis>
                        <methodname>getGroup</methodname>
                        <methodparam>
                            <funcparams>$group</funcparams>
                        </methodparam>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Get all features from a given feature group.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-image-format-support">
                <term>
                    <methodsynopsis>
                        <methodname>getImageFormatSupport</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve a list of supported image types.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-images">
                <term>
                    <methodsynopsis>
                        <methodname>getImages</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Alias for <methodname>getImageFormatSupport()</methodname>.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-max-image-height">
                <term>
                    <methodsynopsis>
                        <methodname>getMaxImageHeight</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the maximum supported image height for the current device instance.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-max-image-width">
                <term>
                    <methodsynopsis>
                        <methodname>getMaxImageWidth</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the maximum supported image width for the current device instance.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-physical-screen-height">
                <term>
                    <methodsynopsis>
                        <methodname>getPhysicalScreenHeight</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the physical screen height for the current device instance.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-physical-screen-width">
                <term>
                    <methodsynopsis>
                        <methodname>getPhysicalScreenWidth</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the physical screen width for the current device instance.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-preferred-markup">
                <term>
                    <methodsynopsis>
                        <methodname>getPreferredMarkup</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the preferred markup format for the current device instance.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-user-agent">
                <term>
                    <methodsynopsis>
                        <methodname>getUserAgent</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the User-Agent string for the current device instance.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.get-xhtml-support-level">
                <term>
                    <methodsynopsis>
                        <methodname>getXhtmlSupportLevel</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Retrieve the supported X/HTML version for the current device instance.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.has-flash-support">
                <term>
                    <methodsynopsis>
                        <methodname>hasFlashSupport</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Determine if the current device instance supports Flash.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.has-pdf-support">
                <term>
                    <methodsynopsis>
                        <methodname>hasPdfSupport</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Determine if the current device instance supports PDF.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.has-phone-number">
                <term>
                    <methodsynopsis>
                        <methodname>hasPhoneNumber</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Determine if the device has an associated phone number. Note: does not
                        retrieve the phone number. This can be useful for determining if the device
                        is a mobile phone versus another wireless capable device.
                    </para>
                </listitem>
            </varlistentry>

            <varlistentry id="zend.http.user-agent-device.methods.https-support">
                <term>
                    <methodsynopsis>
                        <methodname>httpsSupport</methodname>
                    </methodsynopsis>
                </term>

                <listitem>
                    <para>
                        Determine if the current device instance supports HTTPS.
                    </para>
                </listitem>
            </varlistentry>
        </variablelist>
    </sect2>

    <sect2 id="zend.http.user-agent-device.examples">
        <title>Examples</title>

        <example id="zend.http.user-agent-device.examples.support">
            <title>Determining Supported Features</title>

            <para>
                You may wish to direct the user to specific areas of your site based on features
                supported by the device they are using. For instance, if a particular app works only
                in Flash, you might direct a non-Flash-capable device to a page indicating the
                application will not work on their device; or for a device not capable of HTTPS, you
                may indicate certain actions, such as purchases, are not available.
            </para>

            <programlisting language="php"><![CDATA[
$userAgent = new Zend_Http_UserAgent();
$device    = $userAgent->getDevice();

// Redirect to a Flash version of the app:
if ($device->hasFlashSupport()) {
    header('Location: /flash/app');
    exit;
}

// Determine whether to show a "purchase" link:
if ($device->httpsSupport()) {
    echo '<a href="https://store-site.com/purchase">Purchase!</a>';
} else {
    echo 'Purchasing is unavailable on this device.';
}
]]></programlisting>
        </example>

        <example id="zend.http.user-agent-device.examples.images">
            <title>Dynamically Scaling Images</title>

            <para>
                You may wish to alter the image sizes present in order to achieve a specific design
                within mobile devices. You may use a variety of methods in the device object to make
                this happen.
            </para>

            <programlisting language="php"><![CDATA[
$userAgent = new Zend_Http_UserAgent();
$device    = $userAgent->getDevice();

// Get the maximum image width and height
$maxWidth  = $device->getMaxImageWidth();
$maxHeight = $device->getMaxImageHeight();

// Create an <img> tag with appropriate sizes
echo '<img src="/images/foo.png"';
if ((null !== $maxWidth) && ($maxWidth < 328)) {
    echo ' width="' . $maxWidth . '"';
}
if ((null !== $maxHeight) && ($maxHeight < 400)) {
    echo ' height="' . $maxHeight . '"';
}
echo '/>';
]]></programlisting>
        </example>

        <note>
            <title>Markup- based scaling is not ideal</title>

            <para>
                Markup-based scaling such as in the example above is not the best approach, as
                it means that the full-sized image is still delivered to the device. A better
                approach is to pre-scale your images to a variety of sizes representing the
                devices you wish to support, and then using the device capabilities to determine
                which image to use.
            </para>
        </note>
    </sect2>
</sect1>
