Browse Source

[ZF-7490] Zend_Validate_EmailAddress:

- added a way to set hostname messages from within the email validator

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@17468 44c647ce-9c0f-0410-b52a-842ac1e357ba
thomas 16 years ago
parent
commit
77d79655b3

+ 128 - 98
documentation/manual/en/module_specs/Zend_Validate-EmailAddress.xml

@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- Reviewed: no -->
 <sect2 id="zend.validate.set.email_address">
-
     <title>EmailAddress</title>
 
     <para>
@@ -10,12 +9,12 @@
         these against known specifications for email addresses and hostnames.
     </para>
 
-    <para>
-        <emphasis>Basic usage</emphasis>
-    </para>
+    <sect3 id="zend.validate.set.email_address.basic">
+        <title>Basic usage</title>
 
-    <para>
-        A basic example of usage is below:
+        <para>
+            A basic example of usage is below:
+        </para>
 
         <programlisting language="php"><![CDATA[
 $validator = new Zend_Validate_EmailAddress();
@@ -29,43 +28,45 @@ if ($validator->isValid($email)) {
 }
 ]]></programlisting>
 
-        This will match the email address <varname>$email</varname> and on failure populate
-        <code>$validator->getMessages()</code> with useful error messages.
-    </para>
-
-    <para>
-        <emphasis>Complex local parts</emphasis>
-    </para>
-
-    <para>
-        <classname>Zend_Validate_EmailAddress</classname> will match any valid email address
-        according to RFC2822. For example, valid emails include <code>bob@domain.com</code>,
-        <code>bob+jones@domain.us</code>, <code>"bob@jones"@domain.com</code> and
-        <code>"bob jones"@domain.com</code>
-    </para>
-
-    <para>
-        Some obsolete email formats will not currently validate (e.g. carriage returns or a
-        "\" character in an email address).
-    </para>
-
-    <para>
-        <emphasis>Validating different types of hostnames</emphasis>
-    </para>
-
-    <para>
-        The hostname part of an email address is validated against <link
-            linkend="zend.validate.set.hostname">
-            <classname>Zend_Validate_Hostname</classname></link>. By default
-        only DNS hostnames of the form <code>domain.com</code> are accepted, though if you wish you
-        can accept IP addresses and Local hostnames too.
-    </para>
-
-    <para>
-        To do this you need to instantiate <classname>Zend_Validate_EmailAddress</classname> passing
-        a parameter to indicate the type of hostnames you want to accept. More details are included
-        in <classname>Zend_Validate_Hostname</classname>, though an example of how to accept both
-        DNS and Local hostnames appears below:
+        <para>
+            This will match the email address <varname>$email</varname> and on failure populate
+            <code>$validator->getMessages()</code> with useful error messages.
+        </para>
+    </sect3>
+
+    <sect3 id="zend.validate.set.email_address.complexlocal">
+        <title>Complex local parts</title>
+
+        <para>
+            <classname>Zend_Validate_EmailAddress</classname> will match any valid email address
+            according to RFC2822. For example, valid emails include <code>bob@domain.com</code>,
+            <code>bob+jones@domain.us</code>, <code>"bob@jones"@domain.com</code> and
+            <code>"bob jones"@domain.com</code>
+        </para>
+
+        <para>
+            Some obsolete email formats will not currently validate (e.g. carriage returns or a
+            "\" character in an email address).
+        </para>
+    </sect3>
+
+    <sect3 id="zend.validate.set.email_address.hostnametype">
+        <title>Validating different types of hostnames</title>
+
+        <para>
+            The hostname part of an email address is validated against <link
+                linkend="zend.validate.set.hostname">
+                <classname>Zend_Validate_Hostname</classname></link>. By default
+            only DNS hostnames of the form <code>domain.com</code> are accepted, though if you wish
+            you can accept IP addresses and Local hostnames too.
+        </para>
+
+        <para>
+            To do this you need to instantiate <classname>Zend_Validate_EmailAddress</classname>
+            passing a parameter to indicate the type of hostnames you want to accept. More details
+            are included in <classname>Zend_Validate_Hostname</classname>, though an example of how
+            to accept both DNS and Local hostnames appears below:
+        </para>
 
         <programlisting language="php"><![CDATA[
 $validator = new Zend_Validate_EmailAddress(
@@ -80,85 +81,114 @@ if ($validator->isValid($email)) {
     }
 }
 ]]></programlisting>
-    </para>
+    </sect3>
 
-    <para>
-        <emphasis>Checking if the hostname actually accepts email</emphasis>
-    </para>
+    <sect3 id="zend.validate.set.email_address.checkacceptance">
+        <title>Checking if the hostname actually accepts email</title>
 
-    <para>
-        Just because an email address is in the correct format, it doesn't necessarily mean that
-        email address actually exists. To help solve this problem, you can use MX validation to
-        check whether an MX (email) entry exists in the DNS record for the email's hostname.
-        This tells you that the hostname accepts email, but doesn't tell you the exact email
-        address itself is valid.
-    </para>
+        <para>
+            Just because an email address is in the correct format, it doesn't necessarily mean
+            that email address actually exists. To help solve this problem, you can use MX
+            validation to check whether an MX (email) entry exists in the DNS record for the
+            email's hostname. This tells you that the hostname accepts email, but doesn't tell you
+            the exact email address itself is valid.
+        </para>
 
-    <para>
-        MX checking is not enabled by default and at this time is only supported by UNIX platforms.
-        To enable MX checking you can pass a second parameter to the
-        <classname>Zend_Validate_EmailAddress</classname> constructor.
+        <para>
+            MX checking is not enabled by default and at this time is only supported by UNIX
+            platforms. To enable MX checking you can pass a second parameter to the
+            <classname>Zend_Validate_EmailAddress</classname> constructor.
+        </para>
 
         <programlisting language="php"><![CDATA[
 $validator = new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_DNS,
                                             true);
 ]]></programlisting>
 
-        Alternatively you can either pass <constant>TRUE</constant> or <constant>FALSE</constant> to
-        <code>$validator->setValidateMx()</code> to enable or disable MX validation.
-    </para>
-
-    <para>
-        By enabling this setting network functions will be used to check for the presence of an
-        MX record on the hostname of the email address you wish to validate. Please be aware
-        this will likely slow your script down.
-    </para>
-
-    <para>
-        <emphasis>Validating International Domains Names</emphasis>
-    </para>
-
-    <para>
-        <classname>Zend_Validate_EmailAddress</classname> will also match international characters
-        that exist in some domains. This is known as International Domain Name (IDN) support. This
-        is enabled by default, though you can disable this by changing the setting via the internal
-        <classname>Zend_Validate_Hostname</classname> object that exists within
-        <classname>Zend_Validate_EmailAddress</classname>.
+        <para>
+            Alternatively you can either pass <constant>TRUE</constant> or
+            <constant>FALSE</constant> to <code>$validator->setValidateMx()</code> to enable or
+            disable MX validation.
+        </para>
+
+        <para>
+            By enabling this setting network functions will be used to check for the presence of an
+            MX record on the hostname of the email address you wish to validate. Please be aware
+            this will likely slow your script down.
+        </para>
+    </sect3>
+
+    <sect3 id="zend.validate.set.email_address.validateidn">
+        <title>Validating International Domains Names</title>
+
+        <para>
+            <classname>Zend_Validate_EmailAddress</classname> will also match international
+            characters that exist in some domains. This is known as International Domain Name (IDN)
+            support. This is enabled by default, though you can disable this by changing the
+            setting via the internal <classname>Zend_Validate_Hostname</classname> object that
+            exists within <classname>Zend_Validate_EmailAddress</classname>.
+        </para>
 
         <programlisting language="php"><![CDATA[
 $validator->hostnameValidator->setValidateIdn(false);
 ]]></programlisting>
 
-        More information on the usage of <methodname>setValidateIdn()</methodname> appears in the
-        <classname>Zend_Validate_Hostname</classname> documentation.
-    </para>
+        <para>
+            More information on the usage of <methodname>setValidateIdn()</methodname> appears in
+            the <classname>Zend_Validate_Hostname</classname> documentation.
+        </para>
 
-    <para>
-        Please note IDNs are only validated if you allow DNS hostnames to be validated.
-    </para>
+        <para>
+            Please note IDNs are only validated if you allow DNS hostnames to be validated.
+        </para>
+    </sect3>
 
-    <para>
-        <emphasis>Validating Top Level Domains</emphasis>
-    </para>
+    <sect3 id="zend.validate.set.email_address.validatetld">
+        <title>Validating Top Level Domains</title>
 
-    <para>
-        By default a hostname will be checked against a list of known TLDs. This is enabled by
-        default, though you can disable this by changing the setting via the internal
-        <classname>Zend_Validate_Hostname</classname> object that exists within
-        <classname>Zend_Validate_EmailAddress</classname>.
+        <para>
+            By default a hostname will be checked against a list of known TLDs. This is enabled by
+            default, though you can disable this by changing the setting via the internal
+            <classname>Zend_Validate_Hostname</classname> object that exists within
+            <classname>Zend_Validate_EmailAddress</classname>.
+        </para>
 
         <programlisting language="php"><![CDATA[
 $validator->hostnameValidator->setValidateTld(false);
 ]]></programlisting>
 
-        More information on the usage of <methodname>setValidateTld()</methodname> appears in the
-        <classname>Zend_Validate_Hostname</classname> documentation.
-    </para>
+        <para>
+            More information on the usage of <methodname>setValidateTld()</methodname> appears in
+            the <classname>Zend_Validate_Hostname</classname> documentation.
+        </para>
 
-    <para>
-        Please note TLDs are only validated if you allow DNS hostnames to be validated.
-    </para>
+        <para>
+            Please note TLDs are only validated if you allow DNS hostnames to be validated.
+        </para>
+    </sect3>
+
+    <sect3 id="zend.validate.set.email_address.setmessage">
+        <title>Setting messages</title>
+
+        <para>
+            <classname>Zend_Validate_EmailAddress</classname> makes also use of
+            <classname>Zend_Validate_Hostname</classname> to check the hostname part of a given
+            email address. As with Zend Framework 1.10 you can simply set messages for
+            <classname>Zend_Validate_Hostname</classname> from within
+            <classname>Zend_Validate_EmailAddress</classname>.
+        </para>
+
+        <programlisting language="php"><![CDATA[
+$validator = new Zend_Validate_EmailAddress();
+$validator->setMessages(array(Zend_Validate_Hostname::UNKNOWN_TLD => 'I don't know the TLD you gave'));
+]]></programlisting>
 
+        <para>
+            Before Zend Framework 1.10 you had to attach the messages to your own
+            <classname>Zend_Validate_Hostname</classname>, and then set this validator within
+            <classname>Zend_Validate_EmailAddress</classname> to get your own messages returned.
+        </para>
+    </sect3>
 </sect2>
 <!--
 vim:se ts=4 sw=4 et:

+ 27 - 1
library/Zend/Validate/EmailAddress.php

@@ -112,6 +112,31 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
     }
 
     /**
+     * Sets the validation failure message template for a particular key
+     * Adds the ability to set messages to the attached hostname validator
+     *
+     * @param  string $messageString
+     * @param  string $messageKey     OPTIONAL
+     * @return Zend_Validate_Abstract Provides a fluent interface
+     * @throws Zend_Validate_Exception
+     */
+    public function setMessage($messageString, $messageKey = null)
+    {
+        $messageKeys = $messageKey;
+        if ($messageKey === null) {
+            $keys = array_keys($this->_messageTemplates);
+            $messageKeys = current($keys);
+        }
+
+        if (!isset($this->_messageTemplates[$messageKeys])) {
+            $this->hostnameValidator->setMessage($messageString, $messageKey);
+        }
+
+        $this->_messageTemplates[$messageKeys] = $messageString;
+        return $this;
+    }
+
+    /**
      * Returns the set hostname validator
      *
      * @return Zend_Validate_Hostname
@@ -212,7 +237,8 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
         } else if ($this->_validateMx) {
             // MX check on hostname via dns_get_record()
             if ($this->validateMxSupported()) {
-                $result = dns_get_mx($this->_hostname, $mxHosts);
+                $mxHosts = array();
+                dns_get_mx($this->_hostname, $mxHosts);
                 if (count($mxHosts) < 1) {
                     $hostnameResult = false;
                     $this->_error(self::INVALID_MX_RECORD);

+ 32 - 1
tests/Zend/Validate/EmailAddressTest.php

@@ -433,12 +433,43 @@ class Zend_Validate_EmailAddressTest extends PHPUnit_Framework_TestCase
     }
 
     /**
-     * @ZF-4352
+     * @see ZF-4352
      */
     public function testNonStringValidation()
     {
         $this->assertFalse($this->_validator->isValid(array(1 => 1)));
     }
+
+    /**
+     * @see ZF-7490
+     */
+    public function testSettingHostnameMessagesThroughEmailValidator()
+    {
+        $translations = array(
+            'hostnameIpAddressNotAllowed' => 'hostnameIpAddressNotAllowed translation',
+            'hostnameUnknownTld' => 'hostnameUnknownTld translation',
+            'hostnameDashCharacter' => 'hostnameDashCharacter translation',
+            'hostnameInvalidHostnameSchema' => 'hostnameInvalidHostnameSchema translation',
+            'hostnameUndecipherableTld' => 'hostnameUndecipherableTld translation',
+            'hostnameInvalidHostname' => 'hostnameInvalidHostname translation',
+            'hostnameInvalidLocalName' => 'hostnameInvalidLocalName translation',
+            'hostnameLocalNameNotAllowed' => 'hostnameLocalNameNotAllowed translation',
+        );
+
+        $this->_validator->setMessages($translations);
+        $this->_validator->isValid('_XX.!!3xx@0.239,512.777');
+        $messages = $this->_validator->getMessages();
+        $found = false;
+        foreach ($messages as $code => $message) {
+            if (array_key_exists($code, $translations)) {
+                $this->assertEquals($translations[$code], $message);
+                $found = true;
+                break;
+            }
+        }
+
+        $this->assertTrue($found);
+    }
 }
 
 if (PHPUnit_MAIN_METHOD == 'Zend_Validate_EmailAddressTest::main') {