revamp helpers to use horde_view_helper_base base class, add tag and javascript helpe...
authorChuck Hagenbuch <chuck@horde.org>
Tue, 17 Feb 2009 05:14:47 +0000 (00:14 -0500)
committerChuck Hagenbuch <chuck@horde.org>
Tue, 17 Feb 2009 05:14:47 +0000 (00:14 -0500)
framework/View/lib/Horde/View/Helper.php [deleted file]
framework/View/lib/Horde/View/Helper/Base.php [new file with mode: 0644]
framework/View/lib/Horde/View/Helper/Block.php
framework/View/lib/Horde/View/Helper/Javascript.php [new file with mode: 0644]
framework/View/lib/Horde/View/Helper/Tag.php [new file with mode: 0644]
framework/View/lib/Horde/View/Helper/Url.php
framework/View/package.xml
framework/View/test/Horde/View/AllTests.php
framework/View/test/Horde/View/Helper/JavascriptTest.php [new file with mode: 0644]
framework/View/test/Horde/View/Helper/TagTest.php [new file with mode: 0644]
framework/View/test/Horde/View/InterfaceTest.php

diff --git a/framework/View/lib/Horde/View/Helper.php b/framework/View/lib/Horde/View/Helper.php
deleted file mode 100644 (file)
index d4a9577..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/**
- * @category Horde
- * @package Horde_View
- */
-
-/**
- * Abstract class for Horde_View_Helper objects.
- *
- * @category Horde
- * @package Horde_View
- */
-abstract class Horde_View_Helper
-{
-    /**
-     * The parent view invoking the helper
-     *
-     * @var Horde_View
-     */
-    protected $_view;
-
-    /**
-     * Create a helper for $view
-     *
-     * @param Horde_View $view The view to help.
-     */
-    public function __construct($view)
-    {
-        $this->_view = $view;
-        $view->addHelper($this);
-    }
-
-    /**
-     * Call chaining so other helpers can be called transparently.
-     *
-     * @param string $method The helper method.
-     * @param array $args The parameters for the helper.
-     *
-     * @return string The result of the helper method.
-     */
-    public function __call($method, $args)
-    {
-        return call_user_func_array(array($this->_view, $method), $args);
-    }
-
-}
diff --git a/framework/View/lib/Horde/View/Helper/Base.php b/framework/View/lib/Horde/View/Helper/Base.php
new file mode 100644 (file)
index 0000000..aeb2aed
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/**
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
+ */
+
+/**
+ * Abstract class for Horde_View_Helper objects.
+ *
+ * All helpers hold a link back to the instance of the view.  The undefined
+ * property handlers (__get()/__call() methods) are used to mix helpers
+ * together, effectively placing them on the same pane of glass (the view) and
+ * allowing any helper to call any other.
+ *
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
+ */
+abstract class Horde_View_Helper_Base
+{
+    /**
+     * The parent view invoking the helper
+     *
+     * @var Horde_View
+     */
+    protected $_view;
+
+    /**
+     * Create a helper for $view
+     *
+     * @param Horde_View $view The view to help.
+     */
+    public function __construct($view)
+    {
+        $this->_view = $view;
+        $view->addHelper($this);
+    }
+
+    /**
+     * Proxy on undefined property access (get)
+     */
+    public function __get($name)
+    {
+        return $this->_view->$name;
+    }
+
+    /**
+     * Proxy on undefined property access (set)
+     */
+    public function __set($name, $value)
+    {
+        return $this->_view->$name = $value;
+    }
+
+    /**
+     * Call chaining so other helpers can be called transparently.
+     *
+     * @param string $method The helper method.
+     * @param array $args The parameters for the helper.
+     *
+     * @return string The result of the helper method.
+     */
+    public function __call($method, $args)
+    {
+        return $this->_view->__call($method, $args);
+    }
+
+}
index f087843..1292faf 100644 (file)
@@ -1,18 +1,20 @@
 <?php
 /**
- * $Horde: framework/View/lib/Horde/View/Helper/Block.php,v 1.2 2008/10/09 02:43:53 chuck Exp $
+ * Copyright 2006-2009 The Horde Project (http://www.horde.org/)
  *
- * @category Horde
- * @package Horde_View
- * @subpackage Helpers
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
  */
 
 /**
  * View helper for displaying Horde_Block objects
  *
- * @category Horde
- * @package Horde_View
- * @subpackage Helpers
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
  */
 class Horde_View_Helper_Block extends Horde_View_Helper
 {
diff --git a/framework/View/lib/Horde/View/Helper/Javascript.php b/framework/View/lib/Horde/View/Helper/Javascript.php
new file mode 100644 (file)
index 0000000..8aaa499
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright 2007 Maintainable Software, LLC
+ * Copyright 2006-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
+ */
+
+/**
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
+ */
+class Horde_View_Helper_Javascript extends Horde_View_Helper_Base
+{
+    public function escapeJavascript($javascript)
+    {
+        return str_replace(array('\\',   "\r\n", "\r",  "\n",  '"',  "'"),
+                           array('\0\0', "\\n",  "\\n", "\\n", '\"', "\'"),
+                           $javascript);
+    }
+
+    public function javascriptTag($content, $htmlOptions = array())
+    {
+        return $this->contentTag('script',
+                                 $this->javascriptCdataSection($content),
+                                 array_merge($htmlOptions, array('type' => 'text/javascript')));
+    }
+
+    // @todo nodoc
+    public function javascriptCdataSection($content)
+    {
+        return "\n//" . $this->cdataSection("\n$content\n//") . "\n";
+    }
+
+}
diff --git a/framework/View/lib/Horde/View/Helper/Tag.php b/framework/View/lib/Horde/View/Helper/Tag.php
new file mode 100644 (file)
index 0000000..705e488
--- /dev/null
@@ -0,0 +1,159 @@
+<?php
+/**
+ * Copyright 2007 Maintainable Software, LLC
+ * Copyright 2006-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
+ */
+
+/**
+ * Use these methods to generate HTML tags programmatically.
+ * By default, they output XHTML compliant tags.
+ *
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
+ */
+class Horde_View_Helper_Tag extends Horde_View_Helper_Base
+{
+    /**
+     * HTML attributes that get converted from boolean to the attribute name:
+     * array('disabled' => true) becomes array('disabled' => 'disabled')
+     *
+     * @var array
+     */
+    private $_booleanAttributes = array('disabled', 'readonly', 'multiple');
+
+    /**
+     * Returns an empty HTML tag of type $name which by default is XHTML
+     * compliant. Setting $open to true will create an open tag compatible
+     * with HTML 4.0 and below. Add HTML attributes by passing an attributes
+     * hash to $options. For attributes with no value (like disabled and
+     * readonly), give it a value of TRUE in the $options array.
+     *
+     *   $this->tag("br")
+     *      # => <br />
+     *   $this->tag("br", null, true)
+     *     # => <br>
+     *   $this->tag("input", array('type' => 'text', 'disabled' => true))
+     *      # => <input type="text" disabled="disabled" />
+     *
+     * @param string   $name     Tag name
+     * @param string   $options  Tag attributes
+     * @param boolean  $open     Leave tag open for HTML 4.0 and below?
+     * @param string             Generated HTML tag
+     */
+    public function tag($name, $options = null, $open = false)
+    {
+        return "<$name"
+             . ($options ? $this->tagOptions($options) : '')
+             . ($open ? '>' : ' />');
+    }
+
+    /**
+     * Returns an HTML block tag of type $name surrounding the $content. Add
+     * HTML attributes by passing an attributes hash to $options. For attributes
+     * with no value (like disabled and readonly), give it a value of TRUE in
+     * the $options array.
+     *
+     *   $this->contentTag("p", "Hello world!")
+     *     # => <p>Hello world!</p>
+     *   $this->contentTag("div", $this->contentTag("p", "Hello world!"), array("class" => "strong"))
+     *     # => <div class="strong"><p>Hello world!</p></div>
+     *   $this->contentTag("select", $options, array("multiple" => true))
+     *     # => <select multiple="multiple">...options...</select>
+     *
+     * @param  string  $name      Tag name
+     * @param  string  $content   Content to place between the tags
+     * @param  array   $options   Tag attributes
+     * @return string             Genereated HTML tags with content between
+     */
+    public function contentTag($name, $content, $options = null)
+    {
+        $tagOptions = ($options ? $this->tagOptions($options) : '');
+        return "<$name$tagOptions>$content</$name>";
+    }
+
+    /**
+     * Returns a CDATA section with the given $content.  CDATA sections
+     * are used to escape blocks of text containing characters which would
+     * otherwise be recognized as markup. CDATA sections begin with the string
+     * <tt><![CDATA[</tt> and end with (and may not contain) the string <tt>]]></tt>.
+     *
+     *   $this->cdataSection("<hello world>")
+     *     # => <![CDATA[<hello world>]]>
+     *
+     * @param   string $content  Content for inside CDATA section
+     * @return  string           CDATA section with content
+     */
+    public function cdataSection($content)
+    {
+        return "<![CDATA[$content]]>";
+    }
+
+    /**
+     * Returns the escaped $html without affecting existing escaped entities.
+     *
+     *   $this->escapeOnce("1 > 2 &amp; 3")
+     *     # => "1 &lt; 2 &amp; 3"
+     *
+     * @param  string  $html    HTML to be escaped
+     * @return string           Escaped HTML without affecting existing escaped entities
+     */
+    public function escapeOnce($html)
+    {
+        return $this->_fixDoubleEscape(htmlspecialchars($html));
+    }
+
+    /**
+     * Converts an associative array of $options into
+     * a string of HTML attributes
+     *
+     * @param  array  $options  key/value pairs
+     * @param  string           key1="value1" key2="value2"
+     */
+    public function tagOptions($options)
+    {
+        foreach ($options as $k => &$v) {
+            if ($v === null || $v === false) {
+                unset($options[$k]);
+            } else {
+                if (in_array($k, $this->_booleanAttributes)) {
+                    $v = $k;
+                }
+            }
+        }
+
+        if (! empty($options)) {
+            foreach ($options as $k => &$v) {
+                $v = $k . '="' . $this->escapeOnce($v) . '"';
+            }
+            sort($options);
+            return ' ' . implode(' ', $options);
+        } else {
+            return '';
+        }
+    }
+
+    /**
+     * Fix double-escaped entities, such as &amp;amp;, &amp;#123;, etc.
+     *
+     * @param  string  $escaped  Double-escaped entities
+     * @return string            Entities fixed
+     */
+    private function _fixDoubleEscape($escaped)
+    {
+        return preg_replace('/&amp;([a-z]+|(#\d+));/i', '&\\1;', $escaped);
+    }
+
+}
index 27e449e..2fe1480 100644 (file)
@@ -1,18 +1,27 @@
 <?php
 /**
- * $Horde: framework/View/lib/Horde/View/Helper/Url.php,v 1.2 2008/10/09 02:43:53 chuck Exp $
+ * Copyright 2007 Maintainable Software, LLC
+ * Copyright 2006-2009 The Horde Project (http://www.horde.org/)
  *
- * @category Horde
- * @package Horde_View
- * @subpackage Helpers
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
  */
 
 /**
- * View helper for URLs
+ * View helpers for URLs
  *
- * @category Horde
- * @package Horde_View
- * @subpackage Helpers
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage Helper
  */
 class Horde_View_Helper_Url extends Horde_View_Helper
 {
@@ -66,9 +75,44 @@ class Horde_View_Helper_Url extends Horde_View_Helper
     }
 
     /**
-     * Creates a link tag of the given $name using $url unless the current
-     * request URI is the same as the links, in which case only the name is
-     * returned.
+     * Creates a link tag of the given +name+ using a URL created by the set of
+     * +options+ unless the current request URI is the same as the links, in
+     * which case only the name is returned (or the given block is yielded, if
+     * one exists).  You can give link_to_unless_current a block which will
+     * specialize the default behavior (e.g., show a "Start Here" link rather
+     * than the link's text).
+     *
+     * ==== Examples
+     * Let's say you have a navigation menu...
+     *
+     *   <ul id="navbar">
+     *     <li><%= link_to_unless_current("Home", { :action => "index" }) %></li>
+     *     <li><%= link_to_unless_current("About Us", { :action => "about" }) %></li>
+     *   </ul>
+     *
+     * If in the "about" action, it will render...
+     *
+     *   <ul id="navbar">
+     *     <li><a href="/controller/index">Home</a></li>
+     *     <li>About Us</li>
+     *   </ul>
+     *
+     * ...but if in the "home" action, it will render:
+     *
+     *   <ul id="navbar">
+     *     <li><a href="/controller/index">Home</a></li>
+     *     <li><a href="/controller/about">About Us</a></li>
+     *   </ul>
+     *
+     * The implicit block given to link_to_unless_current is evaluated if the current
+     * action is the action given.  So, if we had a comments page and wanted to render a
+     * "Go Back" link instead of a link to the comments page, we could do something like this...
+     *
+     *    <%=
+     *        link_to_unless_current("Comment", { :controller => 'comments', :action => 'new}) do
+     *           link_to("Go back", { :controller => 'posts', :action => 'index' })
+     *        end
+     *     %>
      */
     public function linkToUnlessCurrent($name, $url, $htmlOptions = array())
     {
@@ -79,9 +123,24 @@ class Horde_View_Helper_Url extends Horde_View_Helper
     /**
      * Creates a link tag of the given +name+ using a URL created by the set of
      * +options+ unless +condition+ is true, in which case only the name is
-     * returned. To specialize the default behavior (i.e., show a login link rather
-     * than just the plaintext link text), you can pass a block that
+     * returned. To specialize the default behavior (i.e., show a login link
+     * rather than just the plaintext link text), you can pass a block that
      * accepts the name or the full argument list for link_to_unless.
+     *
+     * ==== Examples
+     *   <%= link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) %>
+     *   # If the user is logged in...
+     *   # => <a href="/controller/reply/">Reply</a>
+     *
+     *   <%=
+     *      link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) do |name|
+     *        link_to(name, { :controller => "accounts", :action => "signup" })
+     *      end
+     *   %>
+     *   # If the user is logged in...
+     *   # => <a href="/controller/reply/">Reply</a>
+     *   # If not...
+     *   # => <a href="/accounts/signup">Reply</a>
      */
     public function linkToUnless($condition, $name, $url, $htmlOptions = array())
     {
@@ -94,6 +153,21 @@ class Horde_View_Helper_Url extends Horde_View_Helper
      * returned. To specialize the default behavior, you can pass a block that
      * accepts the name or the full argument list for link_to_unless (see the examples
      * in link_to_unless).
+     *
+     * ==== Examples
+     *   <%= link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) %>
+     *   # If the user isn't logged in...
+     *   # => <a href="/sessions/new/">Login</a>
+     *
+     *   <%=
+     *      link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) do
+     *        link_to(@current_user.login, { :controller => "accounts", :action => "show", :id => @current_user })
+     *      end
+     *   %>
+     *   # If the user isn't logged in...
+     *   # => <a href="/sessions/new/">Login</a>
+     *   # If they are logged in...
+     *   # => <a href="/accounts/show/3">my_username</a>
      */
     public function linkToIf($condition, $name, $url, $htmlOptions = array())
     {
@@ -110,70 +184,4 @@ class Horde_View_Helper_Url extends Horde_View_Helper
         return $url == $_SERVER['REQUEST_URI'];
     }
 
-    // @TODO Move these methods to a generic HTML/Tag helper
-
-    /**
-     * HTML attributes that get converted from boolean to the attribute name:
-     * array('disabled' => true) becomes array('disabled' => 'disabled')
-     *
-     * @var array
-     */
-    private $_booleanAttributes = array('disabled', 'readonly', 'multiple', 'selected', 'checked');
-
-    /**
-     * Converts an associative array of $options into
-     * a string of HTML attributes
-     *
-     * @param  array  $options  key/value pairs
-     * @param  string           key1="value1" key2="value2"
-     */
-    public function tagOptions($options)
-    {
-        foreach ($options as $k => &$v) {
-            if ($v === null || $v === false) {
-                unset($options[$k]);
-            } else {
-                if (in_array($k, $this->_booleanAttributes)) {
-                    $v = $k;
-                }
-            }
-        }
-
-        if (!empty($options)) {
-            foreach ($options as $k => &$v) {
-                $v = $k . '="' . $this->escapeOnce($v) . '"';
-            }
-            sort($options);
-            return ' ' . implode(' ', $options);
-        } else {
-            return '';
-        }
-    }
-
-    /**
-     * Returns the escaped $html without affecting existing escaped entities.
-     *
-     *   $this->escapeOnce("1 > 2 &amp; 3")
-     *     => "1 &lt; 2 &amp; 3"
-     *
-     * @param  string  $html    HTML to be escaped
-     *
-     * @return string           Escaped HTML without affecting existing escaped entities
-     */
-    public function escapeOnce($html)
-    {
-        return $this->_fixDoubleEscape(htmlspecialchars($html, ENT_QUOTES, $this->getEncoding()));
-    }
-
-    /**
-     * Fix double-escaped entities, such as &amp;amp;
-     *
-     * @param  string  $escaped  Double-escaped entities
-     * @return string            Entities fixed
-     */
-    private function _fixDoubleEscape($escaped)
-    {
-        return preg_replace('/&amp;([a-z]+|(#\d+));/i', '&\\1;', $escaped);
-    }
-
 }
index a64f090..282d6c2 100644 (file)
@@ -14,6 +14,12 @@ http://pear.php.net/dtd/package-2.0.xsd">
   <email>chuck@horde.org</email>
   <active>yes</active>
  </lead>
+ <lead>
+  <name>Mike Naberezny</name>
+  <user>mnaberez</user>
+  <email>mike@maintainable.com</email>
+  <active>yes</active>
+ </lead>
  <date>2008-02-12</date>
  <time>17:00:00</time>
  <version>
@@ -33,12 +39,14 @@ http://pear.php.net/dtd/package-2.0.xsd">
     <dir name="Horde">
      <dir name="View">
       <dir name="Helper">
+       <file name="Base.php" role="php" />
        <file name="Block.php" role="php" />
+       <file name="Javascript.php" role="php" />
+       <file name="Tag.php" role="php" />
        <file name="Url.php" role="php" />
       </dir> <!-- /lib/Horde/View/Helper -->
       <file name="Base.php" role="php" />
       <file name="Exception.php" role="php" />
-      <file name="Helper.php" role="php" />
       <file name="Interface.php" role="php" />
      </dir> <!-- /lib/Horde/View -->
      <file name="View.php" role="php" />
@@ -58,11 +66,13 @@ http://pear.php.net/dtd/package-2.0.xsd">
  </dependencies>
  <phprelease>
   <filelist>
+   <install name="lib/Horde/View/Helper/Base.php" as="Horde/View/Helper/Base.php" />
    <install name="lib/Horde/View/Helper/Block.php" as="Horde/View/Helper/Block.php" />
+   <install name="lib/Horde/View/Helper/Javascript.php" as="Horde/View/Helper/Javascript.php" />
+   <install name="lib/Horde/View/Helper/Tag.php" as="Horde/View/Helper/Tag.php" />
    <install name="lib/Horde/View/Helper/Url.php" as="Horde/View/Helper/Url.php" />
    <install name="lib/Horde/View/Base.php" as="Horde/View/Base.php" />
    <install name="lib/Horde/View/Exception.php" as="Horde/View/Exception.php" />
-   <install name="lib/Horde/View/Helper.php" as="Horde/View/Helper.php" />
    <install name="lib/Horde/View/Interface.php" as="Horde/View/Interface.php" />
    <install name="lib/Horde/View.php" as="Horde/View.php" />
   </filelist>
index dbebda2..ead96dc 100644 (file)
@@ -1,5 +1,9 @@
 <?php
 /**
+ * Copyright 2006-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @category   Horde
  * @package    Horde_View
  * @subpackage UnitTests
  */
@@ -20,6 +24,19 @@ class Horde_View_AllTests {
 
     public static function suite()
     {
+        // Catch strict standards
+        error_reporting(E_ALL | E_STRICT);
+
+        // Ensure a default timezone is set.
+        date_default_timezone_set('America/New_York');
+
+        // Set up autoload
+        set_include_path(dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR . 'lib' . PATH_SEPARATOR . get_include_path());
+        if (!spl_autoload_functions()) {
+            spl_autoload_register(create_function('$class', '$filename = str_replace(array(\'::\', \'_\'), \'/\', $class); @include_once "$filename.php";'));
+        }
+
+        // Build the suite
         $suite = new PHPUnit_Framework_TestSuite('Horde Framework - Horde_View');
 
         $basedir = dirname(__FILE__);
diff --git a/framework/View/test/Horde/View/Helper/JavascriptTest.php b/framework/View/test/Horde/View/Helper/JavascriptTest.php
new file mode 100644 (file)
index 0000000..546cca7
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright 2007 Maintainable Software, LLC
+ * Copyright 2006-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage UnitTests
+ */
+
+/**
+ * @group      view
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage UnitTests
+ */
+class Horde_View_Helper_JavascriptTest extends PHPUnit_Framework_TestCase
+{
+    public function setUp()
+    {
+        $this->view = new Horde_View();
+        $this->view->addHelper(new Horde_View_Helper_Tag($this->view));
+        $this->view->addHelper(new Horde_View_Helper_Javascript($this->view));
+    }
+
+    public function testJavascriptTag()
+    {
+        $this->assertEquals("<script type=\"text/javascript\">\n//<![CDATA[\nfoo = 1;\n//]]>\n</script>",
+                            $this->view->javascriptTag('foo = 1;'));
+    }
+
+}
diff --git a/framework/View/test/Horde/View/Helper/TagTest.php b/framework/View/test/Horde/View/Helper/TagTest.php
new file mode 100644 (file)
index 0000000..49ebe9c
--- /dev/null
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Copyright 2007 Maintainable Software, LLC
+ * Copyright 2006-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage UnitTests
+ */
+
+/**
+ * @group      view
+ * @author     Mike Naberezny <mike@maintainable.com>
+ * @author     Derek DeVries <derek@maintainable.com>
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @license    http://opensource.org/licenses/bsd-license.php
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage UnitTests
+ */
+class Horde_View_Helper_TagTest extends PHPUnit_Framework_TestCase
+{
+    public function setUp()
+    {
+        $this->helper = new Horde_View_Helper_Tag(new Horde_View());
+    }
+
+    public function testTag()
+    {
+        $this->assertEquals('<br />', $this->helper->tag('br'));
+        $this->assertEquals('<br clear="left" />',
+                            $this->helper->tag('br', array('clear' => 'left')));
+        $this->assertEquals('<br>',
+                            $this->helper->tag('br', null, true));
+    }
+
+    public function testTagOptions()
+    {
+        $this->assertRegExp('/\A<p class="(show|elsewhere)" \/>\z/',
+                            $this->helper->tag('p', array('class' => 'show',
+                                                          'class' => 'elsewhere')));
+    }
+
+    public function testTagOptionsRejectsNullOption()
+    {
+        $this->assertEquals('<p />',
+                            $this->helper->tag('p', array('ignored' => null)));
+    }
+
+    public function testTagOptionsAcceptsBlankOption()
+    {
+        $this->assertEquals('<p included="" />',
+                            $this->helper->tag('p', array('included' => '')));
+    }
+
+    public function testTagOptionsConvertsBooleanOption()
+    {
+        $this->assertEquals('<p disabled="disabled" multiple="multiple" readonly="readonly" />',
+                            $this->helper->tag('p', array('disabled' => true,
+                                                          'multiple' => true,
+                                                          'readonly' => true)));
+    }
+
+    public function testContentTag()
+    {
+        $this->assertEquals('<a href="create">Create</a>',
+                            $this->helper->contentTag('a', 'Create', array('href' => 'create')));
+    }
+
+    public function testCdataSection()
+    {
+        $this->assertEquals('<![CDATA[<hello world>]]>', $this->helper->cdataSection('<hello world>'));
+    }
+
+    public function testEscapeOnce()
+    {
+        $this->assertEquals('1 &lt; 2 &amp; 3', $this->helper->escapeOnce('1 < 2 &amp; 3'));
+    }
+
+    public function testDoubleEscapingAttributes()
+    {
+        $attributes = array('1&amp;2', '1 &lt; 2', '&#8220;test&#8220;');
+        foreach ($attributes as $escaped) {
+            $this->assertEquals("<a href=\"$escaped\" />",
+                                $this->helper->tag('a', array('href' => $escaped)));
+        }
+    }
+
+    public function testSkipInvalidEscapedAttributes()
+    {
+        $attributes = array('&1;', '&#1dfa3;', '& #123;');
+        foreach ($attributes as $escaped) {
+            $this->assertEquals('<a href="' . str_replace('&', '&amp;', $escaped) . '" />',
+                                $this->helper->tag('a', array('href' => $escaped)));
+        }
+    }
+}
index bcbc158..44536af 100644 (file)
@@ -1,14 +1,20 @@
 <?php
 /**
- * @category Horde
- * @package Horde_View
+ * Copyright 2006-2009 The Horde Project (http://www.horde.org/)
+ *
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @category   Horde
+ * @package    Horde_View
  * @subpackage UnitTests
  */
 
-require_once dirname(__FILE__) . '/../../../lib/Horde/View/Interface.php';
-require_once dirname(__FILE__) . '/../../../lib/Horde/View/Base.php';
-require_once dirname(__FILE__) . '/../../../lib/Horde/View.php';
-
+/**
+ * @group      view
+ * @author     Chuck Hagenbuch <chuck@horde.org>
+ * @category   Horde
+ * @package    Horde_View
+ * @subpackage UnitTests
+ */
 class Horde_View_InterfaceTest extends PHPUnit_Framework_TestCase {
 
     public function testViewInterface()