--- /dev/null
+<?php
+/**
+ * Measures the execution time of a block in a template and reports the result
+ * to the log.
+ *
+ * Copyright 2007-2008 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
+ */
+
+/**
+ * Measures the execution time of a block in a template
+ * and reports the result to the log. Example:
+ *
+ * <? $bench = $this->benchmark("Notes section") ?>
+ * <?= $this->expensiveNotesOperation() ?>
+ * <? $bench->end() ?>
+ *
+ * Will add something like "Notes section (0.34523)" to the log.
+ *
+ * You may give an optional logger level as the second argument
+ * ('debug', 'info', 'warn', 'error'). The default is 'info'.
+ * The level may also be given as a Horde_Log::* constant.
+ *
+ * @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_Benchmark extends Horde_View_Helper_Base
+{
+ /**
+ * Start a new benchmark.
+ *
+ * @param string $message Message to log after the benchmark has ended
+ * @param string|integer $level Log level to log after the benchmark has ended
+ * @return Horde_View_Helper_Benchmark_Timer
+ */
+ public function benchmark($message = 'Benchmarking', $level = 'info')
+ {
+ return new Horde_View_Helper_Benchmark_Timer($message, $level, $this->_view->logger);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * An instance of this class is returned by
+ * Horde_View_Helper_Benchmark::benchmark().
+ *
+ * Copyright 2007-2008 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
+ */
+
+/**
+ * An instance of this class is returned by
+ * Horde_View_Helper_Benchmark::benchmark().
+ *
+ * @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_Benchmark_Timer
+{
+ /**
+ * Time that the benchmark was started
+ *
+ * @var float microtime
+ */
+ private $_start;
+
+ /**
+ * Logger instance that will be used to record the
+ * time after the benchmark has ended
+ *
+ * @var null|Horde_Log_Logger
+ */
+ private $_logger;
+
+ /**
+ * Message to log after the benchmark has ended
+ *
+ * @var string
+ */
+ private $_message;
+
+ /**
+ * Log level to log after the benchmark has ended
+ *
+ * @var string|integer
+ */
+ private $_level;
+
+ /**
+ * Start a new benchmark.
+ *
+ * @param string $message Message to log after the benchmark has ended
+ * @param string|integer $level Log level to log after the benchmark has ended
+ * @param null|Horde_Log_Logger $logger Logger instance or NULL if none is available
+ */
+ public function __construct($message, $level = 'info', $logger = null)
+ {
+ $this->_message = $message;
+ $this->_level = $level;
+ $this->_logger = $logger;
+ $this->_start = microtime(true);
+ }
+
+ /**
+ * End the benchmark and log the result.
+ */
+ public function end()
+ {
+ if ($this->_logger) {
+ // compute elapsed time & build message
+ $elapsed = microtime(true) - $this->_start;
+ $message = sprintf("{$this->_message} (%.5f)", $elapsed);
+
+ // log message (level may be specified as integer or string)
+ if (is_integer($this->_level)) {
+ $this->_logger->log($message, $this->_level);
+ } else {
+ $this->_logger->{$this->_level}($message);
+ }
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Copyright 2007-2008 Maintainable Software, LLC
+ * Copyright 2008-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
+ */
+
+/**
+ * Capture lets you extract parts of code which can be used in other points of
+ * the template or even layout file.
+ *
+ * @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_Capture extends Horde_View_Helper_Base
+{
+ /**
+ * Capture allows you to extract a part of the template into an
+ * instance variable. You can use this instance variable anywhere
+ * in your templates and even in your layout. Example:
+ *
+ * <? $capture = $this->capture() ?>
+ * Welcome To my shiny new web page!
+ * <? $this->greeting = $capture->end() ?>
+ *
+ * @return Horde_View_Helper_Capture_Base
+ */
+ public function capture()
+ {
+ return new Horde_View_Helper_Capture_Base();
+ }
+
+ /**
+ * Calling contentFor() stores the block of markup for later use.
+ * Subsequently, you can retrieve it inside an instance variable
+ * that will be named "contentForName" in another template
+ * or in the layout. Example:
+ *
+ * <? $capture = $this->contentFor("header") %>
+ * <script type="text/javascript"> alert('hello world') </script>
+ * <? $capture->end() %>
+ *
+ * You can then use $this->contentForHeader anywhere in your templates:
+ *
+ * <?= $this->contentForHeader ?>
+ *
+ * @param string $name Name of the content that becomes the instance
+ * variable name. "foo" -> "$this->contentForFoo"
+ * @return Horde_View_Helper_Capture_ContentFor
+ */
+ public function contentFor($name)
+ {
+ return new Horde_View_Helper_Capture_ContentFor($name, $this->_view);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Copyright 2007-2008 Maintainable Software, LLC
+ * Copyright 2008-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
+ */
+
+/**
+ * An instance of this class is returned by
+ * Horde_View_Helper_Capture::capture().
+ *
+ * @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_Capture_Base
+{
+ /**
+ * Are we currently buffering?
+ *
+ * @var boolean
+ */
+ protected $_buffering = true;
+
+ /**
+ * Start capturing.
+ */
+ public function __construct()
+ {
+ ob_start();
+ }
+
+ /**
+ * Stop capturing and return what was captured.
+ *
+ * @return string
+ * @throws Horde_View_Exception
+ */
+ public function end()
+ {
+ if ($this->_buffering) {
+ $this->_buffering = false;
+ $output = ob_get_clean();
+ return $output;
+ } else {
+ throw new Horde_View_Exception('Capture already ended');
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Copyright 2007-2008 Maintainable Software, LLC
+ * Copyright 2008-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
+ */
+
+/**
+ * An instance of this class is returned by
+ * Horde_View_Helper_Capture::contentFor().
+ *
+ * @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_Capture_ContentFor extends Horde_View_Helper_Capture_Base
+{
+ /**
+ * Name that will become "$this->contentForName"
+ *
+ * @var string
+ */
+ private $_name;
+
+ /**
+ * Start capturing content that will be stored as
+ * $view->contentForName.
+ *
+ * @param string $name Name of the content that becomes the instance
+ * variable name. "foo" -> "$this->contentForFoo"
+ * @param Horde_View_Base $view
+ */
+ public function __construct($name, $view)
+ {
+ $this->_name = $name;
+ $this->_view = $view;
+ parent::__construct();
+ }
+
+ /**
+ * Stop capturing content and store it in the view.
+ */
+ public function end()
+ {
+ $name = 'contentFor' . ucfirst($this->_name);
+ $this->_view->$name = parent::end();
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Copyright 2007-2008 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
+ */
+
+/**
+ * Dumps a variable for inspection.
+ * Portions borrowed from Paul M. Jones' Solar_Debug
+ *
+ * @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_Debug extends Horde_View_Helper_Base
+{
+ /**
+ * Dumps a variable for inspection.
+ *
+ * @param string $var
+ * @return string
+ */
+ public function debug($var)
+ {
+ return '<pre class="debug_dump">'
+ . htmlspecialchars($this->_fetch($var))
+ . '</pre>';
+ }
+
+ /**
+ * Returns formatted output from var_dump().
+ *
+ * Buffers the var_dump output for a variable and applies some
+ * simple formatting for readability.
+ *
+ * @param mixed $var variable to dump
+ * @return string formatted results of var_dump()
+ */
+ private function _fetch($var)
+ {
+ ob_start();
+ var_dump($var);
+ $output = ob_get_clean();
+ $output = preg_replace("/\]\=\>\n(\s+)/m", "] => ", $output);
+ return $output;
+ }
+
+}
<dir name="View">
<dir name="Helper">
<file name="Base.php" role="php" />
+ <dir name="Benchmark">
+ <file name="Timer.php" role="php" />
+ </dir> <!-- /lib/Horde/View/Helper/Benchmark -->
+ <file name="Benchmark.php" role="php" />
<file name="Block.php" role="php" />
+ <dir name="Capture">
+ <file name="Base.php" role="php" />
+ <file name="ContentFor.php" role="php" />
+ </dir> <!-- /lib/Horde/View/Helper/Capture -->
+ <file name="Capture.php" role="php" />
+ <file name="Debug.php" role="php" />
<file name="Javascript.php" role="php" />
<file name="Tag.php" role="php" />
<file name="Url.php" role="php" />
<phprelease>
<filelist>
<install name="lib/Horde/View/Helper/Base.php" as="Horde/View/Helper/Base.php" />
+ <install name="lib/Horde/View/Helper/Benchmark/Timer.php" as="Horde/View/Helper/Benchmark/Timer.php" />
+ <install name="lib/Horde/View/Helper/Benchmark.php" as="Horde/View/Helper/Benchmark.php" />
<install name="lib/Horde/View/Helper/Block.php" as="Horde/View/Helper/Block.php" />
+ <install name="lib/Horde/View/Helper/Capture/Base.php" as="Horde/View/Helper/Capture/Base.php" />
+ <install name="lib/Horde/View/Helper/Capture/ContentFor.php" as="Horde/View/Helper/Capture/ContentFor.php" />
+ <install name="lib/Horde/View/Helper/Capture.php" as="Horde/View/Helper/Capture.php" />
+ <install name="lib/Horde/View/Helper/Debug.php" as="Horde/View/Helper/Debug.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" />
--- /dev/null
+<?php
+/**
+ * Copyright 2007-2008 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_BenchmarkTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $this->view = new Horde_View();
+ $this->view->addHelper(new Horde_View_Helper_Benchmark($this->view));
+
+ $log = new Horde_Log_Logger($this->mock = new Horde_Log_Handler_Mock());
+ $this->view->logger = $log;
+ }
+
+ public function testWithoutLogger()
+ {
+ $this->view = new Horde_View();
+ $this->view->addHelper(new Horde_View_Helper_Benchmark($this->view));
+
+ $bench = $this->view->benchmark();
+ $bench->end();
+ }
+
+ public function testDefaults()
+ {
+ $bench = $this->view->benchmark();
+ $bench->end();
+ $this->assertEquals(1, count($this->mock->events));
+ $this->assertLastLogged();
+ }
+
+ public function testWithMessage()
+ {
+ $bench = $this->view->benchmark('test_run');
+ $bench->end();
+ $this->assertEquals(1, count($this->mock->events));
+ $this->assertLastLogged('test_run');
+ }
+
+ public function testWithMessageAndLevelAsString()
+ {
+ $bench = $this->view->benchmark('debug_run', 'debug');
+ $bench->end();
+ $this->assertEquals(1, count($this->mock->events));
+ $this->assertLastLogged('debug_run', 'debug');
+ }
+
+ public function testWithMessageAndLevelAsInteger()
+ {
+ $bench = $this->view->benchmark('debug_run', Horde_Log::DEBUG);
+ $bench->end();
+ $this->assertEquals(1, count($this->mock->events));
+ $this->assertLastLogged('debug_run', 'debug');
+ }
+
+ public function assertLastLogged($message = 'Benchmarking', $level = 'info')
+ {
+ $last = end($this->mock->events);
+ $this->assertEquals(strtoupper($level), $last['levelName']);
+ $this->assertRegExp("/^$message \(.*\)$/", $last['message']);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Copyright 2007-2008 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_CaptureTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $this->view = new Horde_View();
+ $this->helper = new Horde_View_Helper_Capture($this->view);
+ }
+
+ public function testCapture()
+ {
+ $capture = $this->helper->capture();
+ echo $expected = '<span>foo</span>';
+
+ $this->assertEquals($expected, $capture->end());
+ }
+
+ public function testCaptureThrowsWhenAlreadyEnded()
+ {
+ $capture = $this->helper->capture();
+ $capture->end();
+
+ try {
+ $capture->end();
+ $this->fail();
+ } catch (Exception $e) {
+ $this->assertType('Horde_View_Exception', $e);
+ $this->assertRegExp('/capture already ended/i', $e->getMessage());
+ }
+ }
+
+ public function testContentFor()
+ {
+ $capture = $this->helper->contentFor('foo');
+ echo $expected = '<span>foo</span>';
+ $capture->end();
+
+ $this->assertEquals($expected, $this->view->contentForFoo);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Copyright 2007-2008 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_DebugTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ $this->helper = new Horde_View_Helper_Debug(new Horde_View());
+ }
+
+ // test truncate
+ public function testDebug()
+ {
+ $expected = '<pre class="debug_dump">string(7) "foo&bar"';
+ $this->assertContains($expected, $this->helper->debug('foo&bar'));
+ }
+
+}