Added:
trunk/Tipos/Widget.php (contents, props changed)
Log:
Base class for widgets.
Added: trunk/Tipos/Widget.php
==============================================================================
--- (empty file)
+++ trunk/Tipos/Widget.php Sat Oct 11 10:48:19 2008
@@ -0,0 +1,208 @@
+<?php
+/**
+ *
+ * Base class for widgets used inside apps. Widgets (or "components") are
very
+ * basic applications that can be shared by page controllers. For example,
+ * some controllers can use a shared "calendar" assigning the result of a
+ * widget as a variable for their views, as in the example:
+ *
+ * {{code: php
+ *
+ * $widget = Solar::factory('Tipos_Widget_Calendar');
+ * $this->calendar = $widget->fetch('month-calendar');
+ *
+ * }}}
+ *
+ * This allows the possibility to set page content pieces dynamically,
based
+ * on the app configuration or in a definitions stored in XML, models, etc.
+ *
+ * Code was almost entirely extracted from Solar_Controller_Page.
+ *
+ * @category Tipos
+ *
+ * @package Tipos_Controller
+ *
+ * @author Rodrigo Moraes <rodrigo...@gmail.com>
+ *
+ * @license http://opensource.org/licenses/bsd-license.php BSD
+ *
+ * @version $Id$
+ *
+ */
+abstract class Tipos_Widget extends Solar_Base
+{
+ /**
+ *
+ * The name of the view to be rendered.
+ *
+ * @var string
+ *
+ */
+ protected $_view = null;
+
+ /**
+ *
+ * The object used to render the widget.
+ *
+ * @var Solar_View
+ *
+ */
+ protected $_view_object;
+
+ /**
+ *
+ * Widget output.
+ *
+ * @var string
+ *
+ */
+ protected $_content;
+
+ /**
+ *
+ * Executes the requested action and returns its output.
+ *
+ * @param string $action The action to be executed in dashes format,
e.g,
+ * 'foo-bar' will execute actionFooBar() using the
template 'fooBar.php'.
+ *
+ * @param array $params Parameters to be passed to the action.
+ *
+ * @return string The action output.
+ *
+ */
+ public function fetch($action, $params = array())
+ {
+ // reset content, in case it was set for a previous widget
+ $this->_content = null;
+
+ // convert action name to camel case
+ $camel = ucwords(str_replace('-', ' ', $action));
+ $camel = str_replace(' ', '', $camel);
+
+ // build the method name
+ $method = 'action' . $camel;
+
+ if (! method_exists($this, $method)) {
+ throw $this->_exception('ERR_ACTION_NOT_FOUND', array(
+ 'action' => $action,
+ 'params' => $params,
+ ));
+ }
+
+ // set the view to the requested action
+ $camel[0] = strtolower($camel[0]);
+ $this->_view = $camel;
+
+ // run the action method
+ $this->$method($params);
+
+ // render the view?
+ if ($this->_view) {
+ $this->_renderView();
+ }
+
+ // done, return the content
+ return $this->_content;
+ }
+
+ /**
+ *
+ * Setup a view object and the response body based on the view.
+ *
+ * @return void
+ *
+ */
+ protected function _renderView()
+ {
+ if (! $this->_view_object) {
+ // only set the view once, and not every time an action is
called
+ $this->_setViewObject();
+ }
+ $this->_view_object->assign($this);
+
+ // set the template name
+ $tpl = $this->_view . '.php';
+
+ // fetch the view
+ try {
+ $this->_content = $this->_view_object->fetch($tpl);
+ } catch (Solar_View_Exception_TemplateNotFound $e) {
+ throw $this->_exception('ERR_VIEW_NOT_FOUND', array(
+ 'path' => $e->getInfo('path'),
+ 'name' => $e->getInfo('name'),
+ ));
+ }
+ }
+
+ /**
+ *
+ * Set up a view object, its template paths, and its helper stacks.
+ *
+ * @return void
+ *
+ */
+ protected function _setViewObject()
+ {
+ $this->_view_object = Solar::factory('Solar_View');
+
+ // who is the vendor of this controller?
+ $class = get_class($this);
+ $pos = strpos($class, '_');
+ $vendor = substr($class, 0, $pos);
+
+ // if vendor is not Solar, add {Vendor}_View_Helper
+ if ($vendor != 'Solar') {
+ $this->_view_object->addHelperClass("{$vendor}_View_Helper");
+ }
+
+ // get the parents of the current class, including self
+ $stack = array_reverse(Solar_Class::parents($this, true));
+
+ // remove Solar_Base and Tipos_Widget
+ array_pop($stack);
+ array_pop($stack);
+
+ // set view and helper stacks
+ $helper_stack = array();
+ foreach ($stack as $key => $val) {
+ $stack[$key] = str_replace('_', '/', $val) . '/View';
+ $helper_stack[$key] = $val . '_Helper';
+ }
+
+ // done: add the stacks
+ $this->_view_object->addTemplatePath($stack);
+ $this->_view_object->addHelperClass($helper_stack);
+ }
+
+ /**
+ *
+ * Try to force users to define what their view variables are.
+ *
+ * @param string $key The property name.
+ *
+ * @param mixed $val The property value.
+ *
+ */
+ public function __set($key, $val)
+ {
+ throw $this->_exception(
+ 'ERR_PROPERTY_NOT_DEFINED',
+ array('property' => "\$$key")
+ );
+ }
+
+ /**
+ *
+ * Try to force users to define what their view variables are.
+ *
+ * @param string $key The property name.
+ *
+ */
+ public function __get($key)
+ {
+ throw $this->_exception(
+ 'ERR_PROPERTY_NOT_DEFINED',
+ array('property' => "\$$key")
+ );
+ }
+}