From af01a5b640051968f1b7fb3c1ea7512856a8e59b Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Sat, 10 Jul 2010 02:16:49 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20Piwik=20=E5=88=B0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=BA=93=E4=B8=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +YUCHENG HU+ git-svn-id: https://svn.code.sf.net/p/hawebs/svn@446 a2543c7e-f6e9-4f8a-8bff-1ffc34733512 --- oss/piwik/trunk/libs/Event/Dispatcher.php | 485 ++++ oss/piwik/trunk/libs/Event/Notification.php | 193 ++ oss/piwik/trunk/libs/HTML/Common.php | 465 ++++ oss/piwik/trunk/libs/HTML/QuickForm.php | 2065 +++++++++++++++++ .../trunk/libs/HTML/QuickForm/Renderer.php | 158 ++ .../libs/HTML/QuickForm/Renderer/Array.php | 340 +++ .../HTML/QuickForm/Renderer/ArraySmarty.php | 403 ++++ .../libs/HTML/QuickForm/Renderer/Default.php | 485 ++++ .../HTML/QuickForm/Renderer/ITDynamic.php | 300 +++ .../libs/HTML/QuickForm/Renderer/ITStatic.php | 504 ++++ .../libs/HTML/QuickForm/Renderer/Object.php | 477 ++++ .../HTML/QuickForm/Renderer/ObjectFlexy.php | 294 +++ .../HTML/QuickForm/Renderer/QuickHtml.php | 213 ++ oss/piwik/trunk/libs/HTML/QuickForm/Rule.php | 82 + .../libs/HTML/QuickForm/Rule/Callback.php | 124 + .../libs/HTML/QuickForm/Rule/Compare.php | 105 + .../trunk/libs/HTML/QuickForm/Rule/Email.php | 73 + .../trunk/libs/HTML/QuickForm/Rule/Range.php | 75 + .../trunk/libs/HTML/QuickForm/Rule/Regex.php | 107 + .../libs/HTML/QuickForm/Rule/Required.php | 63 + .../libs/HTML/QuickForm/RuleRegistry.php | 349 +++ .../trunk/libs/HTML/QuickForm/advcheckbox.php | 286 +++ .../libs/HTML/QuickForm/autocomplete.php | 258 ++ .../trunk/libs/HTML/QuickForm/button.php | 80 + .../trunk/libs/HTML/QuickForm/checkbox.php | 277 +++ oss/piwik/trunk/libs/HTML/QuickForm/date.php | 528 +++++ .../trunk/libs/HTML/QuickForm/element.php | 494 ++++ oss/piwik/trunk/libs/HTML/QuickForm/file.php | 358 +++ oss/piwik/trunk/libs/HTML/QuickForm/group.php | 588 +++++ .../trunk/libs/HTML/QuickForm/header.php | 74 + .../trunk/libs/HTML/QuickForm/hidden.php | 94 + .../libs/HTML/QuickForm/hiddenselect.php | 118 + .../trunk/libs/HTML/QuickForm/hierselect.php | 596 +++++ oss/piwik/trunk/libs/HTML/QuickForm/html.php | 77 + oss/piwik/trunk/libs/HTML/QuickForm/image.php | 127 + oss/piwik/trunk/libs/HTML/QuickForm/input.php | 209 ++ oss/piwik/trunk/libs/HTML/QuickForm/link.php | 200 ++ .../trunk/libs/HTML/QuickForm/password.php | 115 + oss/piwik/trunk/libs/HTML/QuickForm/radio.php | 251 ++ oss/piwik/trunk/libs/HTML/QuickForm/reset.php | 79 + .../trunk/libs/HTML/QuickForm/select.php | 719 ++++++ .../trunk/libs/HTML/QuickForm/static.php | 201 ++ .../trunk/libs/HTML/QuickForm/submit.php | 89 + oss/piwik/trunk/libs/HTML/QuickForm/text.php | 98 + .../trunk/libs/HTML/QuickForm/textarea.php | 229 ++ .../trunk/libs/HTML/QuickForm/xbutton.php | 153 ++ .../trunk/libs/Zend/Loader/Autoloader.php | 584 +++++ .../libs/Zend/Loader/Autoloader/Interface.php | 34 + .../libs/Zend/Loader/Autoloader/Resource.php | 460 ++++ .../trunk/libs/Zend/Loader/Exception.php | 35 + .../trunk/libs/Zend/Loader/PluginLoader.php | 484 ++++ .../Zend/Loader/PluginLoader/Exception.php | 39 + .../Zend/Loader/PluginLoader/Interface.php | 75 + oss/piwik/trunk/libs/Zend/Log/Exception.php | 33 + .../trunk/libs/Zend/Log/FactoryInterface.php | 38 + .../trunk/libs/Zend/Log/Filter/Abstract.php | 60 + .../trunk/libs/Zend/Log/Filter/Interface.php | 40 + .../trunk/libs/Zend/Log/Filter/Message.php | 85 + .../trunk/libs/Zend/Log/Filter/Priority.php | 101 + .../trunk/libs/Zend/Log/Filter/Suppress.php | 77 + .../trunk/libs/Zend/Log/Formatter/Firebug.php | 50 + .../libs/Zend/Log/Formatter/Interface.php | 41 + .../trunk/libs/Zend/Log/Formatter/Simple.php | 85 + .../trunk/libs/Zend/Log/Formatter/Xml.php | 121 + .../trunk/libs/Zend/Log/Writer/Abstract.php | 129 + oss/piwik/trunk/libs/Zend/Log/Writer/Db.php | 139 ++ .../trunk/libs/Zend/Log/Writer/Firebug.php | 200 ++ oss/piwik/trunk/libs/Zend/Log/Writer/Mail.php | 307 +++ oss/piwik/trunk/libs/Zend/Log/Writer/Mock.php | 78 + oss/piwik/trunk/libs/Zend/Log/Writer/Null.php | 57 + .../trunk/libs/Zend/Log/Writer/Stream.php | 135 ++ .../trunk/libs/Zend/Log/Writer/Syslog.php | 187 ++ .../libs/Zend/Log/Writer/ZendMonitor.php | 111 + 73 files changed, 17443 insertions(+) create mode 100644 oss/piwik/trunk/libs/Event/Dispatcher.php create mode 100644 oss/piwik/trunk/libs/Event/Notification.php create mode 100644 oss/piwik/trunk/libs/HTML/Common.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer/Array.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer/ArraySmarty.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer/Default.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer/ITDynamic.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer/ITStatic.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer/Object.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer/ObjectFlexy.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Renderer/QuickHtml.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Rule.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Rule/Callback.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Rule/Compare.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Rule/Email.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Rule/Range.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Rule/Regex.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/Rule/Required.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/RuleRegistry.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/advcheckbox.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/autocomplete.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/button.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/checkbox.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/date.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/element.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/file.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/group.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/header.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/hidden.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/hiddenselect.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/hierselect.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/html.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/image.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/input.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/link.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/password.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/radio.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/reset.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/select.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/static.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/submit.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/text.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/textarea.php create mode 100644 oss/piwik/trunk/libs/HTML/QuickForm/xbutton.php create mode 100644 oss/piwik/trunk/libs/Zend/Loader/Autoloader.php create mode 100644 oss/piwik/trunk/libs/Zend/Loader/Autoloader/Interface.php create mode 100644 oss/piwik/trunk/libs/Zend/Loader/Autoloader/Resource.php create mode 100644 oss/piwik/trunk/libs/Zend/Loader/Exception.php create mode 100644 oss/piwik/trunk/libs/Zend/Loader/PluginLoader.php create mode 100644 oss/piwik/trunk/libs/Zend/Loader/PluginLoader/Exception.php create mode 100644 oss/piwik/trunk/libs/Zend/Loader/PluginLoader/Interface.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Exception.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/FactoryInterface.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Filter/Abstract.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Filter/Interface.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Filter/Message.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Filter/Priority.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Filter/Suppress.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Formatter/Firebug.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Formatter/Interface.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Formatter/Simple.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Formatter/Xml.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/Abstract.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/Db.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/Firebug.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/Mail.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/Mock.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/Null.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/Stream.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/Syslog.php create mode 100644 oss/piwik/trunk/libs/Zend/Log/Writer/ZendMonitor.php diff --git a/oss/piwik/trunk/libs/Event/Dispatcher.php b/oss/piwik/trunk/libs/Event/Dispatcher.php new file mode 100644 index 00000000..d98dc294 --- /dev/null +++ b/oss/piwik/trunk/libs/Event/Dispatcher.php @@ -0,0 +1,485 @@ + | +// | Stephan Schmidt | +// +-----------------------------------------------------------------------+ +// +// $Id: Dispatcher.php 1296 2009-07-08 04:19:14Z vipsoft $ + +/** + * Pseudo 'static property' for Notification object + * @global array $GLOBALS["_Event_Dispatcher"] + */ +$GLOBALS['_Event_Dispatcher'] = array( + 'NotificationClass' => 'Event_Notification' + ); + +/** + * Registers a global observer + */ +define('EVENT_DISPATCHER_GLOBAL', ''); + +/** + * Dispatch notifications using PHP callbacks + * + * The Event_Dispatcher acts acts as a notification dispatch table. + * It is used to notify other objects of interesting things, if + * they meet certain criteria. This information is encapsulated + * in {@link Event_Notification} objects. Client objects register + * themselves with the Event_Dispatcher as observers of specific + * notifications posted by other objects. When an event occurs, + * an object posts an appropriate notification to the Event_Dispatcher. + * The Event_Dispatcher dispatches a message to each + * registered observer, passing the notification as the sole argument. + * + * The Event_Dispatcher is actually a combination of three design + * patterns: the Singleton, {@link http://c2.com/cgi/wiki?MediatorPattern Mediator}, + * and Observer patterns. The idea behind Event_Dispatcher is borrowed from + * {@link http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/index.html Apple's Cocoa framework}. + * + * @category Event + * @package Event_Dispatcher + * @author Bertrand Mansion + * @author Stephan Schmidt + * @copyright 1997-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/Event_Dispatcher + */ +class Event_Dispatcher +{ + /** + * Registered observer callbacks + * @var array + * @access private + */ + var $_ro = array(); + + /** + * Pending notifications + * @var array + * @access private + */ + var $_pending = array(); + + /** + * Nested observers + * @var array + * @access private + */ + var $_nestedDispatchers = array(); + + /** + * Name of the dispatcher + * @var string + * @access private + */ + var $_name = null; + + /** + * Class used for notifications + * @var string + * @access private + */ + var $_notificationClass = null; + + /** + * PHP4 constructor + * + * Please use {@link getInstance()} instead. + * + * @access private + * @param string Name of the notification dispatcher. + */ +// function Event_Dispatcher($name) +// { +// Event_Dispatcher::__construct($name); +// } + + /** + * PHP5 constructor + * + * Please use {@link getInstance()} instead. + * + * @access private + * @param string Name of the notification dispatcher. + */ + function __construct($name) + { + $this->_name = $name; + $this->_notificationClass = $GLOBALS['_Event_Dispatcher']['NotificationClass']; + } + + /** + * Returns a notification dispatcher singleton + * + * There is usually no need to have more than one notification + * center for an application so this is the recommended way + * to get a Event_Dispatcher object. + * + * @param string Name of the notification dispatcher. + * The default notification dispatcher is named __default. + * + * @return object Event_Dispatcher + */ + static function getInstance($name = '__default') + { + static $dispatchers = array(); + + if (!isset($dispatchers[$name])) { + $dispatchers[$name] = new Event_Dispatcher($name); + } + + return $dispatchers[$name]; + } + + /** + * Registers an observer callback + * + * This method registers a {@link http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback callback} + * which is called when the notification corresponding to the + * criteria given at registration time is posted. + * The criteria are the notification name and eventually the + * class of the object posted with the notification. + * + * If there are any pending notifications corresponding to the criteria + * given here, the callback will be called straight away. + * + * If the notification name is empty, the observer will receive all the + * posted notifications. Same goes for the class name. + * + * @access public + * @param mixed A PHP callback + * @param string Expected notification name, serves as a filter + * @param string Expected contained object class, serves as a filter + * @return void + */ + function addObserver($callback, $nName = EVENT_DISPATCHER_GLOBAL, $class = null) + { + if (is_array($callback)) { + if (is_object($callback[0])) { + // Note : PHP4 does not allow correct object comparison so + // only the class name is used for registration checks. + $reg = get_class($callback[0]).'::'.$callback[1]; + } else { + $reg = $callback[0].'::'.$callback[1]; + } + } else { + $reg = $callback; + } + + $this->_ro[$nName][$reg] = array( + 'callback' => $callback, + 'class' => $class + ); + + // Post eventual pending notifications for this observer + if (isset($this->_pending[$nName])) { + foreach (array_keys($this->_pending[$nName]) as $k) { + $notification =& $this->_pending[$nName][$k]; + if (!$notification->isNotificationCancelled()) { + $object = $notification->getNotificationObject(); + $objClass = is_object($object) ? get_class($object) : null; + if (empty($class) || strcasecmp($class, $objClass) == 0) { + call_user_func_array($callback, array(&$notification)); + //-- Piwik Hack --// + $notification->increaseNotificationCount($callback); + //-- End Piwik Hack --// + } + } + } + } + } + + /** + * Creates and posts a notification object + * + * The purpose of the optional associated object is generally to pass + * the object posting the notification to the observers, so that the + * observers can query the posting object for more information about + * the event. + * + * Notifications are by default added to a pending notification list. + * This way, if an observer is not registered by the time they are + * posted, it will still be notified when it is added as an observer. + * This behaviour can be turned off in order to make sure that only + * the registered observers will be notified. + * + * The info array serves as a container for any kind of useful + * information. It is added to the notification object and posted along. + * + * @access public + * @param object Notification associated object + * @param string Notification name + * @param array Optional user information + * @param bool Whether the notification is pending + * @param bool Whether you want the notification to bubble up + * @return object The notification object + */ + function &post(&$object, $nName, $info = array(), $pending = true, $bubble = true) + { + $notification = new $this->_notificationClass($object, $nName, $info); + return $this->postNotification($notification, $pending, $bubble); + } + + /** + * Posts the {@link Event_Notification} object + * + * @access public + * @param object The Notification object + * @param bool Whether to post the notification immediately + * @param bool Whether you want the notification to bubble up + * @see Event_Dispatcher::post() + * @return object The notification object + */ + function &postNotification(&$notification, $pending = true, $bubble = true) + { + $nName = $notification->getNotificationName(); + if ($pending === true) { + $this->_pending[$nName][] =& $notification; + } + + $object = $notification->getNotificationObject(); + $objClass = is_object($object) ? get_class($object) : null; + + // Find the registered observers + if (isset($this->_ro[$nName])) { + foreach (array_keys($this->_ro[$nName]) as $k) { + $rObserver =& $this->_ro[$nName][$k]; + if ($notification->isNotificationCancelled()) { + return $notification; + } + if (empty($rObserver['class']) || + strcasecmp($rObserver['class'], $objClass) == 0) { + $callback = $rObserver['callback']; + call_user_func_array($callback, array(&$notification)); + //-- Piwik Hack --// + $notification->increaseNotificationCount($callback); + //-- End Piwik Hack --// + } + } + } + + // Notify globally registered observers + if (isset($this->_ro[EVENT_DISPATCHER_GLOBAL])) { + foreach (array_keys($this->_ro[EVENT_DISPATCHER_GLOBAL]) as $k) { + $rObserver =& $this->_ro[EVENT_DISPATCHER_GLOBAL][$k]; + if ($notification->isNotificationCancelled()) { + return $notification; + } + if (empty($rObserver['class']) || + strcasecmp($rObserver['class'], $objClass) == 0) { + call_user_func_array($rObserver['callback'], array(&$notification)); + //-- Piwik Hack --// + $notification->increaseNotificationCount(get_class($rObserver['callback'][0]), $rObserver['callback'][1]); + //-- End Piwik Hack --// + } + } + } + + if ($bubble === false) { + return $notification; + } + + // Notify in nested dispatchers + foreach (array_keys($this->_nestedDispatchers) as $nested) { + $notification =& $this->_nestedDispatchers[$nested]->postNotification($notification, $pending); + } + + return $notification; + } + + /** + * Removes a registered observer that correspond to the given criteria + * + * @access public + * @param mixed A PHP callback + * @param string Notification name + * @param string Contained object class + * @return bool True if an observer was removed, false otherwise + */ + function removeObserver($callback, $nName = EVENT_DISPATCHER_GLOBAL, $class = null) + { + if (is_array($callback)) { + if (is_object($callback[0])) { + $reg = get_class($callback[0]).'::'.$callback[1]; + } else { + $reg = $callback[0].'::'.$callback[1]; + } + } else { + $reg = $callback; + } + + $removed = false; + if (isset($this->_ro[$nName][$reg])) { + if (!empty($class)) { + if (strcasecmp($this->_ro[$nName][$reg]['class'], $class) == 0) { + unset($this->_ro[$nName][$reg]); + $removed = true; + } + } else { + unset($this->_ro[$nName][$reg]); + $removed = true; + } + } + + if (isset($this->_ro[$nName]) && count($this->_ro[$nName]) == 0) { + unset($this->_ro[$nName]); + } + return $removed; + } + + /** + * Check, whether the specified observer has been registered with the + * dispatcher + * + * @access public + * @param mixed A PHP callback + * @param string Notification name + * @param string Contained object class + * @return bool True if the observer has been registered, false otherwise + */ + function observerRegistered($callback, $nName = EVENT_DISPATCHER_GLOBAL, $class = null) + { + if (is_array($callback)) { + if (is_object($callback[0])) { + $reg = get_class($callback[0]).'::'.$callback[1]; + } else { + $reg = $callback[0].'::'.$callback[1]; + } + } else { + $reg = $callback; + } + + if (!isset($this->_ro[$nName][$reg])) { + return false; + } + if (empty($class)) { + return true; + } + if (strcasecmp($this->_ro[$nName][$reg]['class'], $class) == 0) { + return true; + } + return false; + } + + /** + * Get all observers, that have been registered for a notification + * + * @access public + * @param string Notification name + * @param string Contained object class + * @return array List of all observers + */ + function getObservers($nName = EVENT_DISPATCHER_GLOBAL, $class = null) + { + $observers = array(); + if (!isset($this->_ro[$nName])) { + return $observers; + } + foreach ($this->_ro[$nName] as $reg => $observer) { + if ($class == null || $observer['class'] == null || strcasecmp($observer['class'], $class) == 0) { + $observers[] = $reg; + } + } + return $observers; + } + + /** + * Get the name of the dispatcher. + * + * The name is the unique identifier of a dispatcher. + * + * @access public + * @return string name of the dispatcher + */ + function getName() + { + return $this->_name; + } + + /** + * add a new nested dispatcher + * + * Notifications will be broadcasted to this dispatcher as well, which + * allows you to create event bubbling. + * + * @access public + * @param Event_Dispatcher The nested dispatcher + */ + function addNestedDispatcher(&$dispatcher) + { + $name = $dispatcher->getName(); + $this->_nestedDispatchers[$name] =& $dispatcher; + } + + /** + * remove a nested dispatcher + * + * @access public + * @param Event_Dispatcher Dispatcher to remove + * @return boolean + */ + function removeNestedDispatcher($dispatcher) + { + if (is_object($dispatcher)) { + $dispatcher = $dispatcher->getName(); + } + if (!isset($this->_nestedDispatchers[$dispatcher])) { + return false; + } + unset($this->_nestedDispatchers[$dispatcher]); + return true; + } + + /** + * Changes the class used for notifications + * + * You may call this method on an object to change it for a single + * dispatcher or statically, to set the default for all dispatchers + * that will be created. + * + * @access public + * @param string name of the notification class + * @return boolean + */ + function setNotificationClass($class) + { + if (isset($this) && is_a($this, 'Event_Dispatcher')) { + $this->_notificationClass = $class; + return true; + } + $GLOBALS['_Event_Dispatcher']['NotificationClass'] = $class; + return true; + } + +} diff --git a/oss/piwik/trunk/libs/Event/Notification.php b/oss/piwik/trunk/libs/Event/Notification.php new file mode 100644 index 00000000..75ba3bd7 --- /dev/null +++ b/oss/piwik/trunk/libs/Event/Notification.php @@ -0,0 +1,193 @@ + | +// | Stephan Schmidt | +// +-----------------------------------------------------------------------+ +// +// $Id: Notification.php 1230 2009-06-16 04:42:53Z vipsoft $ + +/** + * Default state of the notification + */ +define('EVENT_NOTIFICATION_STATE_DEFAULT', 0); + +/** + * Notification has been cancelled + */ +define('EVENT_NOTIFICATION_STATE_CANCELLED', 1); + +/** + * A Notification object + * + * The Notification object can be easily subclassed and serves as a container + * for the information about the notification. It holds an object which is + * usually a reference to the object that posted the notification, + * a notification name used to identify the notification and some user + * information which can be anything you need. + * + * @category Event + * @package Event_Dispatcher + * @author Bertrand Mansion + * @author Stephan Schmidt + * @copyright 1997-2005 The PHP Group + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @version Release: @package_version@ + * @link http://pear.php.net/package/Event_Dispatcher + */ +class Event_Notification +{ + /** + * name of the notofication + * @var string + * @access private + */ + var $_notificationName; + + /** + * object of interesed (the sender of the notification, in most cases) + * @var object + * @access private + */ + var $_notificationObject; + + /** + * additional information about the notification + * @var mixed + * @access private + */ + var $_notificationInfo = array(); + + /** + * state of the notification + * + * This may be: + * - EVENT_NOTIFICATION_STATE_DEFAULT + * - EVENT_NOTIFICATION_STATE_CANCELLED + * + * @var integer + * @access private + */ + var $_notificationState = EVENT_NOTIFICATION_STATE_DEFAULT; + + /** + * amount of observers that received this notification + * @var mixed + * @access private + */ + var $_notificationCount = 0; + + /** + * Constructor + * + * @access public + * @param object The object of interest for the notification, + * usually is the posting object + * @param string Notification name + * @param array Free information array + */ + function Event_Notification(&$object, $name, $info = array()) + { + $this->_notificationObject =& $object; + $this->_notificationName = $name; + $this->_notificationInfo = $info; + } + + /** + * Returns the notification name + * @return string Notification name + */ + function getNotificationName() + { + return $this->_notificationName; + } + + /** + * Returns the contained object + * @return object Contained object + */ + function &getNotificationObject() + { + return $this->_notificationObject; + } + + /** + * Returns the user info array + * @return array user info + */ + function getNotificationInfo() + { + return $this->_notificationInfo; + } + + /** + * Increase the internal count + * + * @access public + */ + function increaseNotificationCount() + { + ++$this->_notificationCount; + } + + /** + * Get the number of posted notifications + * + * @access public + * @return int + */ + function getNotificationCount() + { + return $this->_notificationCount; + } + + /** + * Cancel the notification + * + * @access public + * @return void + */ + function cancelNotification() + { + $this->_notificationState = EVENT_NOTIFICATION_STATE_CANCELLED; + } + + /** + * Checks whether the notification has been cancelled + * + * @access public + * @return boolean + */ + function isNotificationCancelled() + { + return ($this->_notificationState === EVENT_NOTIFICATION_STATE_CANCELLED); + } +} diff --git a/oss/piwik/trunk/libs/HTML/Common.php b/oss/piwik/trunk/libs/HTML/Common.php new file mode 100644 index 00000000..6415392d --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/Common.php @@ -0,0 +1,465 @@ + + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: Common.php 1297 2009-07-08 04:58:45Z vipsoft $ + * @link http://pear.php.net/package/HTML_Common/ + */ + +/** + * Base class for all HTML classes + * + * @category HTML + * @package HTML_Common + * @author Adam Daniel + * @version Release: 1.2.5 + * @abstract + */ +class HTML_Common +{ + /** + * Associative array of attributes + * @var array + * @access private + */ + var $_attributes = array(); + + /** + * Tab offset of the tag + * @var int + * @access private + */ + var $_tabOffset = 0; + + /** + * Tab string + * @var string + * @since 1.7 + * @access private + */ + var $_tab = "\11"; + + /** + * Contains the line end string + * @var string + * @since 1.7 + * @access private + */ + var $_lineEnd = "\12"; + + /** + * HTML comment on the object + * @var string + * @since 1.5 + * @access private + */ + var $_comment = ''; + + /** + * Class constructor + * @param mixed $attributes Associative array of table tag attributes + * or HTML attributes name="value" pairs + * @param int $tabOffset Indent offset in tabs + * @access public + */ + function HTML_Common($attributes = null, $tabOffset = 0) + { + $this->setAttributes($attributes); + $this->setTabOffset($tabOffset); + } // end constructor + + /** + * Returns the current API version + * @access public + * @returns double + */ + function apiVersion() + { + return 1.7; + } // end func apiVersion + + /** + * Returns the lineEnd + * + * @since 1.7 + * @access private + * @return string + */ + function _getLineEnd() + { + return $this->_lineEnd; + } // end func getLineEnd + + /** + * Returns a string containing the unit for indenting HTML + * + * @since 1.7 + * @access private + * @return string + */ + function _getTab() + { + return $this->_tab; + } // end func _getTab + + /** + * Returns a string containing the offset for the whole HTML code + * + * @return string + * @access private + */ + function _getTabs() + { + return str_repeat($this->_getTab(), $this->_tabOffset); + } // end func _getTabs + + /** + * Returns an HTML formatted attribute string + * @param array $attributes + * @return string + * @access private + */ + function _getAttrString($attributes) + { + $strAttr = ''; + + if (is_array($attributes)) { + $charset = HTML_Common::charset(); + foreach ($attributes as $key => $value) { + $strAttr .= ' ' . $key . '="' . htmlspecialchars($value, ENT_COMPAT, $charset) . '"'; + } + } + return $strAttr; + } // end func _getAttrString + + /** + * Returns a valid atrributes array from either a string or array + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access private + * @return array + */ + function _parseAttributes($attributes) + { + if (is_array($attributes)) { + $ret = array(); + foreach ($attributes as $key => $value) { + if (is_int($key)) { + $key = $value = strtolower($value); + } else { + $key = strtolower($key); + } + $ret[$key] = $value; + } + return $ret; + + } elseif (is_string($attributes)) { + $preg = "/(([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*)" . + "([ \\n\\t\\r]+)?(=([ \\n\\t\\r]+)?(\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]*))?/"; + if (preg_match_all($preg, $attributes, $regs)) { + for ($counter=0; $counter $value) { + $attr1[$key] = $value; + } + } // end func _updateAtrrArray + + /** + * Removes the given attribute from the given array + * + * @param string $attr Attribute name + * @param array $attributes Attribute array + * @since 1.4 + * @access private + * @return void + */ + function _removeAttr($attr, &$attributes) + { + $attr = strtolower($attr); + if (isset($attributes[$attr])) { + unset($attributes[$attr]); + } + } //end func _removeAttr + + /** + * Returns the value of the given attribute + * + * @param string $attr Attribute name + * @since 1.5 + * @access public + * @return string|null returns null if an attribute does not exist + */ + function getAttribute($attr) + { + $attr = strtolower($attr); + if (isset($this->_attributes[$attr])) { + return $this->_attributes[$attr]; + } + return null; + } //end func getAttribute + + /** + * Sets the value of the attribute + * + * @param string Attribute name + * @param string Attribute value (will be set to $name if omitted) + * @access public + */ + function setAttribute($name, $value = null) + { + $name = strtolower($name); + if (is_null($value)) { + $value = $name; + } + $this->_attributes[$name] = $value; + } // end func setAttribute + + /** + * Sets the HTML attributes + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access public + */ + function setAttributes($attributes) + { + $this->_attributes = $this->_parseAttributes($attributes); + } // end func setAttributes + + /** + * Returns the assoc array (default) or string of attributes + * + * @param bool Whether to return the attributes as string + * @since 1.6 + * @access public + * @return mixed attributes + */ + function getAttributes($asString = false) + { + if ($asString) { + return $this->_getAttrString($this->_attributes); + } else { + return $this->_attributes; + } + } //end func getAttributes + + /** + * Updates the passed attributes without changing the other existing attributes + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access public + */ + function updateAttributes($attributes) + { + $this->_updateAttrArray($this->_attributes, $this->_parseAttributes($attributes)); + } // end func updateAttributes + + /** + * Removes an attribute + * + * @param string $attr Attribute name + * @since 1.4 + * @access public + * @return void + */ + function removeAttribute($attr) + { + $this->_removeAttr($attr, $this->_attributes); + } //end func removeAttribute + + /** + * Sets the line end style to Windows, Mac, Unix or a custom string. + * + * @param string $style "win", "mac", "unix" or custom string. + * @since 1.7 + * @access public + * @return void + */ + function setLineEnd($style) + { + switch ($style) { + case 'win': + $this->_lineEnd = "\15\12"; + break; + case 'unix': + $this->_lineEnd = "\12"; + break; + case 'mac': + $this->_lineEnd = "\15"; + break; + default: + $this->_lineEnd = $style; + } + } // end func setLineEnd + + /** + * Sets the tab offset + * + * @param int $offset + * @access public + */ + function setTabOffset($offset) + { + $this->_tabOffset = $offset; + } // end func setTabOffset + + /** + * Returns the tabOffset + * + * @since 1.5 + * @access public + * @return int + */ + function getTabOffset() + { + return $this->_tabOffset; + } //end func getTabOffset + + /** + * Sets the string used to indent HTML + * + * @since 1.7 + * @param string $string String used to indent ("\11", "\t", ' ', etc.). + * @access public + * @return void + */ + function setTab($string) + { + $this->_tab = $string; + } // end func setTab + + /** + * Sets the HTML comment to be displayed at the beginning of the HTML string + * + * @param string + * @since 1.4 + * @access public + * @return void + */ + function setComment($comment) + { + $this->_comment = $comment; + } // end func setHtmlComment + + /** + * Returns the HTML comment + * + * @since 1.5 + * @access public + * @return string + */ + function getComment() + { + return $this->_comment; + } //end func getComment + + /** + * Abstract method. Must be extended to return the objects HTML + * + * @access public + * @return string + * @abstract + */ + function toHtml() + { + return ''; + } // end func toHtml + + /** + * Displays the HTML to the screen + * + * @access public + */ + function display() + { + print $this->toHtml(); + } // end func display + + /** + * Sets the charset to use by htmlspecialchars() function + * + * Since this parameter is expected to be global, the function is designed + * to be called statically: + * + * HTML_Common::charset('utf-8'); + * + * or + * + * $charset = HTML_Common::charset(); + * + * + * @param string New charset to use. Omit if just getting the + * current value. Consult the htmlspecialchars() docs + * for a list of supported character sets. + * @return string Current charset + * @access public + * @static + */ + function charset($newCharset = null) + { + static $charset = 'ISO-8859-1'; + + if (!is_null($newCharset)) { + $charset = $newCharset; + } + return $charset; + } // end func charset +} // end class HTML_Common +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm.php b/oss/piwik/trunk/libs/HTML/QuickForm.php new file mode 100644 index 00000000..4c4d3b95 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm.php @@ -0,0 +1,2065 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: QuickForm.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * PEAR and PEAR_Error classes, for error handling + */ +require_once dirname(__FILE__) . '/../PEAR.php'; +/** + * Base class for all HTML classes + */ +require_once dirname(__FILE__) . '/Common.php'; + +/** + * Element types known to HTML_QuickForm + * @see HTML_QuickForm::registerElementType(), HTML_QuickForm::getRegisteredTypes(), + * HTML_QuickForm::isTypeRegistered() + * @global array $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'] + */ +$GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'] = + array( + 'group' =>array('HTML/QuickForm/group.php','HTML_QuickForm_group'), + 'hidden' =>array('HTML/QuickForm/hidden.php','HTML_QuickForm_hidden'), + 'reset' =>array('HTML/QuickForm/reset.php','HTML_QuickForm_reset'), + 'checkbox' =>array('HTML/QuickForm/checkbox.php','HTML_QuickForm_checkbox'), + 'file' =>array('HTML/QuickForm/file.php','HTML_QuickForm_file'), + 'image' =>array('HTML/QuickForm/image.php','HTML_QuickForm_image'), + 'password' =>array('HTML/QuickForm/password.php','HTML_QuickForm_password'), + 'radio' =>array('HTML/QuickForm/radio.php','HTML_QuickForm_radio'), + 'button' =>array('HTML/QuickForm/button.php','HTML_QuickForm_button'), + 'submit' =>array('HTML/QuickForm/submit.php','HTML_QuickForm_submit'), + 'select' =>array('HTML/QuickForm/select.php','HTML_QuickForm_select'), + 'hiddenselect' =>array('HTML/QuickForm/hiddenselect.php','HTML_QuickForm_hiddenselect'), + 'text' =>array('HTML/QuickForm/text.php','HTML_QuickForm_text'), + 'textarea' =>array('HTML/QuickForm/textarea.php','HTML_QuickForm_textarea'), + 'link' =>array('HTML/QuickForm/link.php','HTML_QuickForm_link'), + 'advcheckbox' =>array('HTML/QuickForm/advcheckbox.php','HTML_QuickForm_advcheckbox'), + 'date' =>array('HTML/QuickForm/date.php','HTML_QuickForm_date'), + 'static' =>array('HTML/QuickForm/static.php','HTML_QuickForm_static'), + 'header' =>array('HTML/QuickForm/header.php', 'HTML_QuickForm_header'), + 'html' =>array('HTML/QuickForm/html.php', 'HTML_QuickForm_html'), + 'hierselect' =>array('HTML/QuickForm/hierselect.php', 'HTML_QuickForm_hierselect'), + 'autocomplete' =>array('HTML/QuickForm/autocomplete.php', 'HTML_QuickForm_autocomplete'), + 'xbutton' =>array('HTML/QuickForm/xbutton.php','HTML_QuickForm_xbutton') + ); + +/** + * Validation rules known to HTML_QuickForm + * @see HTML_QuickForm::registerRule(), HTML_QuickForm::getRegisteredRules(), + * HTML_QuickForm::isRuleRegistered() + * @global array $GLOBALS['_HTML_QuickForm_registered_rules'] + */ +$GLOBALS['_HTML_QuickForm_registered_rules'] = array( + 'required' => array('html_quickform_rule_required', 'HTML/QuickForm/Rule/Required.php'), + 'maxlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), + 'minlength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), + 'rangelength' => array('html_quickform_rule_range', 'HTML/QuickForm/Rule/Range.php'), + 'email' => array('html_quickform_rule_email', 'HTML/QuickForm/Rule/Email.php'), + 'regex' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'lettersonly' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'alphanumeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'numeric' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'nopunctuation' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'nonzero' => array('html_quickform_rule_regex', 'HTML/QuickForm/Rule/Regex.php'), + 'callback' => array('html_quickform_rule_callback', 'HTML/QuickForm/Rule/Callback.php'), + 'compare' => array('html_quickform_rule_compare', 'HTML/QuickForm/Rule/Compare.php') +); + +// {{{ error codes + +/**#@+ + * Error codes for HTML_QuickForm + * + * Codes are mapped to textual messages by errorMessage() method, if you add a + * new code be sure to add a new message for it to errorMessage() + * + * @see HTML_QuickForm::errorMessage() + */ +define('QUICKFORM_OK', 1); +define('QUICKFORM_ERROR', -1); +define('QUICKFORM_INVALID_RULE', -2); +define('QUICKFORM_NONEXIST_ELEMENT', -3); +define('QUICKFORM_INVALID_FILTER', -4); +define('QUICKFORM_UNREGISTERED_ELEMENT', -5); +define('QUICKFORM_INVALID_ELEMENT_NAME', -6); +define('QUICKFORM_INVALID_PROCESS', -7); +define('QUICKFORM_DEPRECATED', -8); +define('QUICKFORM_INVALID_DATASOURCE', -9); +/**#@-*/ + +// }}} + +/** + * Create, validate and process HTML forms + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.11 + */ +class HTML_QuickForm extends HTML_Common +{ + // {{{ properties + + /** + * Array containing the form fields + * @since 1.0 + * @var array + * @access private + */ + var $_elements = array(); + + /** + * Array containing element name to index map + * @since 1.1 + * @var array + * @access private + */ + var $_elementIndex = array(); + + /** + * Array containing indexes of duplicate elements + * @since 2.10 + * @var array + * @access private + */ + var $_duplicateIndex = array(); + + /** + * Array containing required field IDs + * @since 1.0 + * @var array + * @access private + */ + var $_required = array(); + + /** + * Prefix message in javascript alert if error + * @since 1.0 + * @var string + * @access public + */ + var $_jsPrefix = 'Invalid information entered.'; + + /** + * Postfix message in javascript alert if error + * @since 1.0 + * @var string + * @access public + */ + var $_jsPostfix = 'Please correct these fields.'; + + /** + * Datasource object implementing the informal + * datasource protocol + * @since 3.3 + * @var object + * @access private + */ + var $_datasource; + + /** + * Array of default form values + * @since 2.0 + * @var array + * @access private + */ + var $_defaultValues = array(); + + /** + * Array of constant form values + * @since 2.0 + * @var array + * @access private + */ + var $_constantValues = array(); + + /** + * Array of submitted form values + * @since 1.0 + * @var array + * @access private + */ + var $_submitValues = array(); + + /** + * Array of submitted form files + * @since 1.0 + * @var integer + * @access public + */ + var $_submitFiles = array(); + + /** + * Value for maxfilesize hidden element if form contains file input + * @since 1.0 + * @var integer + * @access public + */ + var $_maxFileSize = 1048576; // 1 Mb = 1048576 + + /** + * Flag to know if all fields are frozen + * @since 1.0 + * @var boolean + * @access private + */ + var $_freezeAll = false; + + /** + * Array containing the form rules + * @since 1.0 + * @var array + * @access private + */ + var $_rules = array(); + + /** + * Form rules, global variety + * @var array + * @access private + */ + var $_formRules = array(); + + /** + * Array containing the validation errors + * @since 1.0 + * @var array + * @access private + */ + var $_errors = array(); + + /** + * Note for required fields in the form + * @var string + * @since 1.0 + * @access private + */ + var $_requiredNote = '* denotes required field'; + + /** + * Whether the form was submitted + * @var boolean + * @access private + */ + var $_flagSubmitted = false; + + // }}} + // {{{ constructor + + /** + * Class constructor + * @param string $formName Form's name. + * @param string $method (optional)Form's method defaults to 'POST' + * @param string $action (optional)Form's action + * @param string $target (optional)Form's target defaults to '_self' + * @param mixed $attributes (optional)Extra attributes for
tag + * @param bool $trackSubmit (optional)Whether to track if the form was submitted by adding a special hidden field + * @access public + */ + function HTML_QuickForm($formName='', $method='post', $action='', $target='', $attributes=null, $trackSubmit = false) + { + HTML_Common::HTML_Common($attributes); + $method = (strtoupper($method) == 'GET') ? 'get' : 'post'; + $action = ($action == '') ? $_SERVER['PHP_SELF'] : $action; + $target = empty($target) ? array() : array('target' => $target); + $attributes = array('action'=>$action, 'method'=>$method, 'name'=>$formName, 'id'=>$formName) + $target; + $this->updateAttributes($attributes); + if (!$trackSubmit || isset($_REQUEST['_qf__' . $formName])) { + if (1 == get_magic_quotes_gpc()) { + $this->_submitValues = $this->_recursiveFilter('stripslashes', 'get' == $method? $_GET: $_POST); + foreach ($_FILES as $keyFirst => $valFirst) { + foreach ($valFirst as $keySecond => $valSecond) { + if ('name' == $keySecond) { + $this->_submitFiles[$keyFirst][$keySecond] = $this->_recursiveFilter('stripslashes', $valSecond); + } else { + $this->_submitFiles[$keyFirst][$keySecond] = $valSecond; + } + } + } + } else { + $this->_submitValues = 'get' == $method? $_GET: $_POST; + $this->_submitFiles = $_FILES; + } + $this->_flagSubmitted = count($this->_submitValues) > 0 || count($this->_submitFiles) > 0; + } + if ($trackSubmit) { + unset($this->_submitValues['_qf__' . $formName]); + $this->addElement('hidden', '_qf__' . $formName, null); + } + if (preg_match('/^([0-9]+)([a-zA-Z]*)$/', ini_get('upload_max_filesize'), $matches)) { + // see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes + switch (strtoupper($matches['2'])) { + case 'G': + $this->_maxFileSize = $matches['1'] * 1073741824; + break; + case 'M': + $this->_maxFileSize = $matches['1'] * 1048576; + break; + case 'K': + $this->_maxFileSize = $matches['1'] * 1024; + break; + default: + $this->_maxFileSize = $matches['1']; + } + } + } // end constructor + + // }}} + // {{{ apiVersion() + + /** + * Returns the current API version + * + * @since 1.0 + * @access public + * @return float + */ + function apiVersion() + { + return 3.2; + } // end func apiVersion + + // }}} + // {{{ registerElementType() + + /** + * Registers a new element type + * + * @param string $typeName Name of element type + * @param string $include Include path for element type + * @param string $className Element class name + * @since 1.0 + * @access public + * @return void + */ + function registerElementType($typeName, $include, $className) + { + $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][strtolower($typeName)] = array($include, $className); + } // end func registerElementType + + // }}} + // {{{ registerRule() + + /** + * Registers a new validation rule + * + * @param string $ruleName Name of validation rule + * @param string $type Either: 'regex', 'function' or 'rule' for an HTML_QuickForm_Rule object + * @param string $data1 Name of function, regular expression or HTML_QuickForm_Rule classname + * @param string $data2 Object parent of above function or HTML_QuickForm_Rule file path + * @since 1.0 + * @access public + * @return void + */ + function registerRule($ruleName, $type, $data1, $data2 = null) + { + include_once(dirname(__FILE__) . '/QuickForm/RuleRegistry.php'); + $registry =& HTML_QuickForm_RuleRegistry::singleton(); + $registry->registerRule($ruleName, $type, $data1, $data2); + } // end func registerRule + + // }}} + // {{{ elementExists() + + /** + * Returns true if element is in the form + * + * @param string $element form name of element to check + * @since 1.0 + * @access public + * @return boolean + */ + function elementExists($element=null) + { + return isset($this->_elementIndex[$element]); + } // end func elementExists + + // }}} + // {{{ setDatasource() + + /** + * Sets a datasource object for this form object + * + * Datasource default and constant values will feed the QuickForm object if + * the datasource implements defaultValues() and constantValues() methods. + * + * @param object $datasource datasource object implementing the informal datasource protocol + * @param mixed $defaultsFilter string or array of filter(s) to apply to default values + * @param mixed $constantsFilter string or array of filter(s) to apply to constants values + * @since 3.3 + * @access public + * @return void + * @throws HTML_QuickForm_Error + */ + function setDatasource(&$datasource, $defaultsFilter = null, $constantsFilter = null) + { + if (is_object($datasource)) { + $this->_datasource =& $datasource; + if (is_callable(array($datasource, 'defaultValues'))) { + $this->setDefaults($datasource->defaultValues($this), $defaultsFilter); + } + if (is_callable(array($datasource, 'constantValues'))) { + $this->setConstants($datasource->constantValues($this), $constantsFilter); + } + } else { + return PEAR::raiseError(null, QUICKFORM_INVALID_DATASOURCE, null, E_USER_WARNING, "Datasource is not an object in QuickForm::setDatasource()", 'HTML_QuickForm_Error', true); + } + } // end func setDatasource + + // }}} + // {{{ setDefaults() + + /** + * Initializes default form values + * + * @param array $defaultValues values used to fill the form + * @param mixed $filter (optional) filter(s) to apply to all default values + * @since 1.0 + * @access public + * @return void + * @throws HTML_QuickForm_Error + */ + function setDefaults($defaultValues = null, $filter = null) + { + if (is_array($defaultValues)) { + if (isset($filter)) { + if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) { + foreach ($filter as $val) { + if (!is_callable($val)) { + return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true); + } else { + $defaultValues = $this->_recursiveFilter($val, $defaultValues); + } + } + } elseif (!is_callable($filter)) { + return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setDefaults()", 'HTML_QuickForm_Error', true); + } else { + $defaultValues = $this->_recursiveFilter($filter, $defaultValues); + } + } + $this->_defaultValues = HTML_QuickForm::arrayMerge($this->_defaultValues, $defaultValues); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); + } + } + } // end func setDefaults + + // }}} + // {{{ setConstants() + + /** + * Initializes constant form values. + * These values won't get overridden by POST or GET vars + * + * @param array $constantValues values used to fill the form + * @param mixed $filter (optional) filter(s) to apply to all default values + * + * @since 2.0 + * @access public + * @return void + * @throws HTML_QuickForm_Error + */ + function setConstants($constantValues = null, $filter = null) + { + if (is_array($constantValues)) { + if (isset($filter)) { + if (is_array($filter) && (2 != count($filter) || !is_callable($filter))) { + foreach ($filter as $val) { + if (!is_callable($val)) { + return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true); + } else { + $constantValues = $this->_recursiveFilter($val, $constantValues); + } + } + } elseif (!is_callable($filter)) { + return PEAR::raiseError(null, QUICKFORM_INVALID_FILTER, null, E_USER_WARNING, "Callback function does not exist in QuickForm::setConstants()", 'HTML_QuickForm_Error', true); + } else { + $constantValues = $this->_recursiveFilter($filter, $constantValues); + } + } + $this->_constantValues = HTML_QuickForm::arrayMerge($this->_constantValues, $constantValues); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); + } + } + } // end func setConstants + + // }}} + // {{{ setMaxFileSize() + + /** + * Sets the value of MAX_FILE_SIZE hidden element + * + * @param int $bytes Size in bytes + * @since 3.0 + * @access public + * @return void + */ + function setMaxFileSize($bytes = 0) + { + if ($bytes > 0) { + $this->_maxFileSize = $bytes; + } + if (!$this->elementExists('MAX_FILE_SIZE')) { + $this->addElement('hidden', 'MAX_FILE_SIZE', $this->_maxFileSize); + } else { + $el =& $this->getElement('MAX_FILE_SIZE'); + $el->updateAttributes(array('value' => $this->_maxFileSize)); + } + } // end func setMaxFileSize + + // }}} + // {{{ getMaxFileSize() + + /** + * Returns the value of MAX_FILE_SIZE hidden element + * + * @since 3.0 + * @access public + * @return int max file size in bytes + */ + function getMaxFileSize() + { + return $this->_maxFileSize; + } // end func getMaxFileSize + + // }}} + // {{{ &createElement() + + /** + * Creates a new form element of the given type. + * + * This method accepts variable number of parameters, their + * meaning and count depending on $elementType + * + * @param string $elementType type of element to add (text, textarea, file...) + * @since 1.0 + * @access public + * @return HTML_QuickForm_Element + * @throws HTML_QuickForm_Error + */ + function &createElement($elementType) + { + $args = func_get_args(); + $element =& HTML_QuickForm::_loadElement('createElement', $elementType, array_slice($args, 1)); + return $element; + } // end func createElement + + // }}} + // {{{ _loadElement() + + /** + * Returns a form element of the given type + * + * @param string $event event to send to newly created element ('createElement' or 'addElement') + * @param string $type element type + * @param array $args arguments for event + * @since 2.0 + * @access private + * @return HTML_QuickForm_Element + * @throws HTML_QuickForm_Error + */ + function &_loadElement($event, $type, $args) + { + $type = strtolower($type); + if (!HTML_QuickForm::isTypeRegistered($type)) { + $error = PEAR::raiseError(null, QUICKFORM_UNREGISTERED_ELEMENT, null, E_USER_WARNING, "Element '$type' does not exist in HTML_QuickForm::_loadElement()", 'HTML_QuickForm_Error', true); + return $error; + } + $className = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][1]; + $includeFile = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][0]; + include_once(dirname(__FILE__) . '/../' . $includeFile); + $elementObject = new $className(); + for ($i = 0; $i < 5; $i++) { + if (!isset($args[$i])) { + $args[$i] = null; + } + } + $err = $elementObject->onQuickFormEvent($event, $args, $this); + if ($err !== true) { + return $err; + } + return $elementObject; + } // end func _loadElement + + // }}} + // {{{ addElement() + + /** + * Adds an element into the form + * + * If $element is a string representing element type, then this + * method accepts variable number of parameters, their meaning + * and count depending on $element + * + * @param mixed $element element object or type of element to add (text, textarea, file...) + * @since 1.0 + * @return HTML_QuickForm_Element a reference to newly added element + * @access public + * @throws HTML_QuickForm_Error + */ + function &addElement($element) + { + if (is_object($element) && is_subclass_of($element, 'html_quickform_element')) { + $elementObject = &$element; + $elementObject->onQuickFormEvent('updateValue', null, $this); + } else { + $args = func_get_args(); + $elementObject =& $this->_loadElement('addElement', $element, array_slice($args, 1)); + if (PEAR::isError($elementObject)) { + return $elementObject; + } + } + $elementName = $elementObject->getName(); + + // Add the element if it is not an incompatible duplicate + if (!empty($elementName) && isset($this->_elementIndex[$elementName])) { + if ($this->_elements[$this->_elementIndex[$elementName]]->getType() == + $elementObject->getType()) { + $this->_elements[] =& $elementObject; + $elKeys = array_keys($this->_elements); + $this->_duplicateIndex[$elementName][] = end($elKeys); + } else { + $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::addElement()", 'HTML_QuickForm_Error', true); + return $error; + } + } else { + $this->_elements[] =& $elementObject; + $elKeys = array_keys($this->_elements); + $this->_elementIndex[$elementName] = end($elKeys); + } + if ($this->_freezeAll) { + $elementObject->freeze(); + } + + return $elementObject; + } // end func addElement + + // }}} + // {{{ insertElementBefore() + + /** + * Inserts a new element right before the other element + * + * Warning: it is not possible to check whether the $element is already + * added to the form, therefore if you want to move the existing form + * element to a new position, you'll have to use removeElement(): + * $form->insertElementBefore($form->removeElement('foo', false), 'bar'); + * + * @access public + * @since 3.2.4 + * @param HTML_QuickForm_element Element to insert + * @param string Name of the element before which the new + * one is inserted + * @return HTML_QuickForm_element reference to inserted element + * @throws HTML_QuickForm_Error + */ + function &insertElementBefore(&$element, $nameAfter) + { + if (!empty($this->_duplicateIndex[$nameAfter])) { + $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, 'Several elements named "' . $nameAfter . '" exist in HTML_QuickForm::insertElementBefore().', 'HTML_QuickForm_Error', true); + return $error; + } elseif (!$this->elementExists($nameAfter)) { + $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$nameAfter' does not exist in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true); + return $error; + } + $elementName = $element->getName(); + $targetIdx = $this->_elementIndex[$nameAfter]; + $duplicate = false; + // Like in addElement(), check that it's not an incompatible duplicate + if (!empty($elementName) && isset($this->_elementIndex[$elementName])) { + if ($this->_elements[$this->_elementIndex[$elementName]]->getType() != $element->getType()) { + $error = PEAR::raiseError(null, QUICKFORM_INVALID_ELEMENT_NAME, null, E_USER_WARNING, "Element '$elementName' already exists in HTML_QuickForm::insertElementBefore()", 'HTML_QuickForm_Error', true); + return $error; + } + $duplicate = true; + } + // Move all the elements after added back one place, reindex _elementIndex and/or _duplicateIndex + $elKeys = array_keys($this->_elements); + for ($i = end($elKeys); $i >= $targetIdx; $i--) { + if (isset($this->_elements[$i])) { + $currentName = $this->_elements[$i]->getName(); + $this->_elements[$i + 1] =& $this->_elements[$i]; + if ($this->_elementIndex[$currentName] == $i) { + $this->_elementIndex[$currentName] = $i + 1; + } else { + $dupIdx = array_search($i, $this->_duplicateIndex[$currentName]); + $this->_duplicateIndex[$currentName][$dupIdx] = $i + 1; + } + unset($this->_elements[$i]); + } + } + // Put the element in place finally + $this->_elements[$targetIdx] =& $element; + if (!$duplicate) { + $this->_elementIndex[$elementName] = $targetIdx; + } else { + $this->_duplicateIndex[$elementName][] = $targetIdx; + } + $element->onQuickFormEvent('updateValue', null, $this); + if ($this->_freezeAll) { + $element->freeze(); + } + // If not done, the elements will appear in reverse order + ksort($this->_elements); + return $element; + } + + // }}} + // {{{ addGroup() + + /** + * Adds an element group + * @param array $elements array of elements composing the group + * @param string $name (optional)group name + * @param string $groupLabel (optional)group label + * @param string $separator (optional)string to separate elements + * @param string $appendName (optional)specify whether the group name should be + * used in the form element name ex: group[element] + * @return HTML_QuickForm_group reference to a newly added group + * @since 2.8 + * @access public + * @throws HTML_QuickForm_Error + */ + function &addGroup($elements, $name=null, $groupLabel='', $separator=null, $appendName = true) + { + static $anonGroups = 1; + + if (0 == strlen($name)) { + $name = 'qf_group_' . $anonGroups++; + $appendName = false; + } + $group =& $this->addElement('group', $name, $groupLabel, $elements, $separator, $appendName); + return $group; + } // end func addGroup + + // }}} + // {{{ &getElement() + + /** + * Returns a reference to the element + * + * @param string $element Element name + * @since 2.0 + * @access public + * @return HTML_QuickForm_element reference to element + * @throws HTML_QuickForm_Error + */ + function &getElement($element) + { + if (isset($this->_elementIndex[$element])) { + return $this->_elements[$this->_elementIndex[$element]]; + } else { + $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElement()", 'HTML_QuickForm_Error', true); + return $error; + } + } // end func getElement + + // }}} + // {{{ &getElementValue() + + /** + * Returns the element's raw value + * + * This returns the value as submitted by the form (not filtered) + * or set via setDefaults() or setConstants() + * + * @param string $element Element name + * @since 2.0 + * @access public + * @return mixed element value + * @throws HTML_QuickForm_Error + */ + function &getElementValue($element) + { + if (!isset($this->_elementIndex[$element])) { + $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::getElementValue()", 'HTML_QuickForm_Error', true); + return $error; + } + $value = $this->_elements[$this->_elementIndex[$element]]->getValue(); + if (isset($this->_duplicateIndex[$element])) { + foreach ($this->_duplicateIndex[$element] as $index) { + if (null !== ($v = $this->_elements[$index]->getValue())) { + if (is_array($value)) { + $value[] = $v; + } else { + $value = (null === $value)? $v: array($value, $v); + } + } + } + } + return $value; + } // end func getElementValue + + // }}} + // {{{ getSubmitValue() + + /** + * Returns the elements value after submit and filter + * + * @param string Element name + * @since 2.0 + * @access public + * @return mixed submitted element value or null if not set + */ + function getSubmitValue($elementName) + { + $value = null; + if (isset($this->_submitValues[$elementName]) || isset($this->_submitFiles[$elementName])) { + $value = isset($this->_submitValues[$elementName])? $this->_submitValues[$elementName]: array(); + if (is_array($value) && isset($this->_submitFiles[$elementName])) { + foreach ($this->_submitFiles[$elementName] as $k => $v) { + $value = HTML_QuickForm::arrayMerge($value, $this->_reindexFiles($this->_submitFiles[$elementName][$k], $k)); + } + } + + } elseif ('file' == $this->getElementType($elementName)) { + return $this->getElementValue($elementName); + + } elseif (false !== ($pos = strpos($elementName, '['))) { + $base = str_replace( + array('\\', '\''), array('\\\\', '\\\''), + substr($elementName, 0, $pos) + ); + $idx = "['" . str_replace( + array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), + substr($elementName, $pos + 1, -1) + ) . "']"; + if (isset($this->_submitValues[$base])) { + $value = eval("return (isset(\$this->_submitValues['{$base}']{$idx})) ? \$this->_submitValues['{$base}']{$idx} : null;"); + } + + if ((is_array($value) || null === $value) && isset($this->_submitFiles[$base])) { + $props = array('name', 'type', 'size', 'tmp_name', 'error'); + $code = "if (!isset(\$this->_submitFiles['{$base}']['name']{$idx})) {\n" . + " return null;\n" . + "} else {\n" . + " \$v = array();\n"; + foreach ($props as $prop) { + $code .= " \$v = HTML_QuickForm::arrayMerge(\$v, \$this->_reindexFiles(\$this->_submitFiles['{$base}']['{$prop}']{$idx}, '{$prop}'));\n"; + } + $fileValue = eval($code . " return \$v;\n}\n"); + if (null !== $fileValue) { + $value = null === $value? $fileValue: HTML_QuickForm::arrayMerge($value, $fileValue); + } + } + } + + // This is only supposed to work for groups with appendName = false + if (null === $value && 'group' == $this->getElementType($elementName)) { + $group =& $this->getElement($elementName); + $elements =& $group->getElements(); + foreach (array_keys($elements) as $key) { + $name = $group->getElementName($key); + // prevent endless recursion in case of radios and such + if ($name != $elementName) { + if (null !== ($v = $this->getSubmitValue($name))) { + $value[$name] = $v; + } + } + } + } + return $value; + } // end func getSubmitValue + + // }}} + // {{{ _reindexFiles() + + /** + * A helper function to change the indexes in $_FILES array + * + * @param mixed Some value from the $_FILES array + * @param string The key from the $_FILES array that should be appended + * @return array + */ + function _reindexFiles($value, $key) + { + if (!is_array($value)) { + return array($key => $value); + } else { + $ret = array(); + foreach ($value as $k => $v) { + $ret[$k] = $this->_reindexFiles($v, $key); + } + return $ret; + } + } + + // }}} + // {{{ getElementError() + + /** + * Returns error corresponding to validated element + * + * @param string $element Name of form element to check + * @since 1.0 + * @access public + * @return string error message corresponding to checked element + */ + function getElementError($element) + { + if (isset($this->_errors[$element])) { + return $this->_errors[$element]; + } + } // end func getElementError + + // }}} + // {{{ setElementError() + + /** + * Set error message for a form element + * + * @param string $element Name of form element to set error for + * @param string $message Error message, if empty then removes the current error message + * @since 1.0 + * @access public + * @return void + */ + function setElementError($element, $message = null) + { + if (!empty($message)) { + $this->_errors[$element] = $message; + } else { + unset($this->_errors[$element]); + } + } // end func setElementError + + // }}} + // {{{ getElementType() + + /** + * Returns the type of the given element + * + * @param string $element Name of form element + * @since 1.1 + * @access public + * @return string Type of the element, false if the element is not found + */ + function getElementType($element) + { + if (isset($this->_elementIndex[$element])) { + return $this->_elements[$this->_elementIndex[$element]]->getType(); + } + return false; + } // end func getElementType + + // }}} + // {{{ updateElementAttr() + + /** + * Updates Attributes for one or more elements + * + * @param mixed $elements Array of element names/objects or string of elements to be updated + * @param mixed $attrs Array or sting of html attributes + * @since 2.10 + * @access public + * @return void + */ + function updateElementAttr($elements, $attrs) + { + if (is_string($elements)) { + $elements = preg_split('/[ ]*,[ ]*/', $elements); + } + foreach (array_keys($elements) as $key) { + if (is_object($elements[$key]) && is_a($elements[$key], 'HTML_QuickForm_element')) { + $elements[$key]->updateAttributes($attrs); + } elseif (isset($this->_elementIndex[$elements[$key]])) { + $this->_elements[$this->_elementIndex[$elements[$key]]]->updateAttributes($attrs); + if (isset($this->_duplicateIndex[$elements[$key]])) { + foreach ($this->_duplicateIndex[$elements[$key]] as $index) { + $this->_elements[$index]->updateAttributes($attrs); + } + } + } + } + } // end func updateElementAttr + + // }}} + // {{{ removeElement() + + /** + * Removes an element + * + * The method "unlinks" an element from the form, returning the reference + * to the element object. If several elements named $elementName exist, + * it removes the first one, leaving the others intact. + * + * @param string $elementName The element name + * @param boolean $removeRules True if rules for this element are to be removed too + * @access public + * @since 2.0 + * @return HTML_QuickForm_element a reference to the removed element + * @throws HTML_QuickForm_Error + */ + function &removeElement($elementName, $removeRules = true) + { + if (!isset($this->_elementIndex[$elementName])) { + $error = PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$elementName' does not exist in HTML_QuickForm::removeElement()", 'HTML_QuickForm_Error', true); + return $error; + } + $el =& $this->_elements[$this->_elementIndex[$elementName]]; + unset($this->_elements[$this->_elementIndex[$elementName]]); + if (empty($this->_duplicateIndex[$elementName])) { + unset($this->_elementIndex[$elementName]); + } else { + $this->_elementIndex[$elementName] = array_shift($this->_duplicateIndex[$elementName]); + } + if ($removeRules) { + $this->_required = array_diff($this->_required, array($elementName)); + unset($this->_rules[$elementName], $this->_errors[$elementName]); + if ('group' == $el->getType()) { + foreach (array_keys($el->getElements()) as $key) { + unset($this->_rules[$el->getElementName($key)]); + } + } + } + return $el; + } // end func removeElement + + // }}} + // {{{ addRule() + + /** + * Adds a validation rule for the given field + * + * If the element is in fact a group, it will be considered as a whole. + * To validate grouped elements as separated entities, + * use addGroupRule instead of addRule. + * + * @param string $element Form element name + * @param string $message Message to display for invalid data + * @param string $type Rule type, use getRegisteredRules() to get types + * @param string $format (optional)Required for extra rule data + * @param string $validation (optional)Where to perform validation: "server", "client" + * @param boolean $reset Client-side validation: reset the form element to its original value if there is an error? + * @param boolean $force Force the rule to be applied, even if the target form element does not exist + * @since 1.0 + * @access public + * @throws HTML_QuickForm_Error + */ + function addRule($element, $message, $type, $format=null, $validation='server', $reset = false, $force = false) + { + if (!$force) { + if (!is_array($element) && !$this->elementExists($element)) { + return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$element' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); + } elseif (is_array($element)) { + foreach ($element as $el) { + if (!$this->elementExists($el)) { + return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Element '$el' does not exist in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); + } + } + } + } + if (false === ($newName = $this->isRuleRegistered($type, true))) { + return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addRule()", 'HTML_QuickForm_Error', true); + } elseif (is_string($newName)) { + $type = $newName; + } + if (is_array($element)) { + $dependent = $element; + $element = array_shift($dependent); + } else { + $dependent = null; + } + if ($type == 'required' || $type == 'uploadedfile') { + $this->_required[] = $element; + } + if (!isset($this->_rules[$element])) { + $this->_rules[$element] = array(); + } + if ($validation == 'client') { + $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);')); + } + $this->_rules[$element][] = array( + 'type' => $type, + 'format' => $format, + 'message' => $message, + 'validation' => $validation, + 'reset' => $reset, + 'dependent' => $dependent + ); + } // end func addRule + + // }}} + // {{{ addGroupRule() + + /** + * Adds a validation rule for the given group of elements + * + * Only groups with a name can be assigned a validation rule + * Use addGroupRule when you need to validate elements inside the group. + * Use addRule if you need to validate the group as a whole. In this case, + * the same rule will be applied to all elements in the group. + * Use addRule if you need to validate the group against a function. + * + * @param string $group Form group name + * @param mixed $arg1 Array for multiple elements or error message string for one element + * @param string $type (optional)Rule type use getRegisteredRules() to get types + * @param string $format (optional)Required for extra rule data + * @param int $howmany (optional)How many valid elements should be in the group + * @param string $validation (optional)Where to perform validation: "server", "client" + * @param bool $reset Client-side: whether to reset the element's value to its original state if validation failed. + * @since 2.5 + * @access public + * @throws HTML_QuickForm_Error + */ + function addGroupRule($group, $arg1, $type='', $format=null, $howmany=0, $validation = 'server', $reset = false) + { + if (!$this->elementExists($group)) { + return PEAR::raiseError(null, QUICKFORM_NONEXIST_ELEMENT, null, E_USER_WARNING, "Group '$group' does not exist in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); + } + + $groupObj =& $this->getElement($group); + if (is_array($arg1)) { + $required = 0; + foreach ($arg1 as $elementIndex => $rules) { + $elementName = $groupObj->getElementName($elementIndex); + foreach ($rules as $rule) { + $format = (isset($rule[2])) ? $rule[2] : null; + $validation = (isset($rule[3]) && 'client' == $rule[3])? 'client': 'server'; + $reset = isset($rule[4]) && $rule[4]; + $type = $rule[1]; + if (false === ($newName = $this->isRuleRegistered($type, true))) { + return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); + } elseif (is_string($newName)) { + $type = $newName; + } + + $this->_rules[$elementName][] = array( + 'type' => $type, + 'format' => $format, + 'message' => $rule[0], + 'validation' => $validation, + 'reset' => $reset, + 'group' => $group); + + if ('required' == $type || 'uploadedfile' == $type) { + $groupObj->_required[] = $elementName; + $this->_required[] = $elementName; + $required++; + } + if ('client' == $validation) { + $this->updateAttributes(array('onsubmit' => 'try { var myValidator = validate_' . $this->_attributes['id'] . '; } catch(e) { return true; } return myValidator(this);')); + } + } + } + if ($required > 0 && count($groupObj->getElements()) == $required) { + $this->_required[] = $group; + } + } elseif (is_string($arg1)) { + if (false === ($newName = $this->isRuleRegistered($type, true))) { + return PEAR::raiseError(null, QUICKFORM_INVALID_RULE, null, E_USER_WARNING, "Rule '$type' is not registered in HTML_QuickForm::addGroupRule()", 'HTML_QuickForm_Error', true); + } elseif (is_string($newName)) { + $type = $newName; + } + + // addGroupRule() should also handle form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for an elements + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_button extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $value (optional)Input field value + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_button($elementName=null, $value=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->_persistantFreeze = false; + $this->setValue($value); + $this->setType('button'); + } //end constructor + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + +} //end class HTML_QuickForm_button +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/checkbox.php b/oss/piwik/trunk/libs/HTML/QuickForm/checkbox.php new file mode 100644 index 00000000..ba3bc7c3 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/checkbox.php @@ -0,0 +1,277 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: checkbox.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for a checkbox type field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_checkbox extends HTML_QuickForm_input +{ + // {{{ properties + + /** + * Checkbox display text + * @var string + * @since 1.1 + * @access private + */ + var $_text = ''; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $elementLabel (optional)Input field value + * @param string $text (optional)Checkbox display text + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_checkbox($elementName=null, $elementLabel=null, $text='', $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_text = $text; + $this->setType('checkbox'); + $this->updateAttributes(array('value'=>1)); + $this->_generateId(); + } //end constructor + + // }}} + // {{{ setChecked() + + /** + * Sets whether a checkbox is checked + * + * @param bool $checked Whether the field is checked or not + * @since 1.0 + * @access public + * @return void + */ + function setChecked($checked) + { + if (!$checked) { + $this->removeAttribute('checked'); + } else { + $this->updateAttributes(array('checked'=>'checked')); + } + } //end func setChecked + + // }}} + // {{{ getChecked() + + /** + * Returns whether a checkbox is checked + * + * @since 1.0 + * @access public + * @return bool + */ + function getChecked() + { + return (bool)$this->getAttribute('checked'); + } //end func getChecked + + // }}} + // {{{ toHtml() + + /** + * Returns the checkbox element in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if (0 == strlen($this->_text)) { + $label = ''; + } elseif ($this->_flagFrozen) { + $label = $this->_text; + } else { + $label = ''; + } + return HTML_QuickForm_input::toHtml() . $label; + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + if ($this->getChecked()) { + return '[x]' . + $this->_getPersistantData(); + } else { + return '[ ]'; + } + } //end func getFrozenHtml + + // }}} + // {{{ setText() + + /** + * Sets the checkbox text + * + * @param string $text + * @since 1.1 + * @access public + * @return void + */ + function setText($text) + { + $this->_text = $text; + } //end func setText + + // }}} + // {{{ getText() + + /** + * Returns the checkbox text + * + * @since 1.1 + * @access public + * @return string + */ + function getText() + { + return $this->_text; + } //end func getText + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param string $value Default value of the form element + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + return $this->setChecked($value); + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return bool + */ + function getValue() + { + return $this->getChecked(); + } // end func getValue + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + // constant values override both default and submitted ones + // default values are overriden by submitted + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + // if no boxes were checked, then there is no value in the array + // yet we don't want to display default value in this case + if ($caller->isSubmitted()) { + $value = $this->_findValue($caller->_submitValues); + } else { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (null !== $value || $caller->isSubmitted()) { + $this->setChecked($value); + } + break; + case 'setGroupValue': + $this->setChecked($arg); + break; + default: + parent::onQuickFormEvent($event, $arg, $caller); + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ exportValue() + + /** + * Return true if the checkbox is checked, null if it is not checked (getValue() returns false) + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (null === $value) { + $value = $this->getChecked()? true: null; + } + return $this->_prepareValue($value, $assoc); + } + + // }}} +} //end class HTML_QuickForm_checkbox +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/date.php b/oss/piwik/trunk/libs/HTML/QuickForm/date.php new file mode 100644 index 00000000..ed80642f --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/date.php @@ -0,0 +1,528 @@ + + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: date.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Class for a group of form elements + */ +require_once dirname(__FILE__) . '/group.php'; +/** + * Class for elements + */ +require_once dirname(__FILE__) . '/select.php'; + +/** + * Class for a group of elements used to input dates (and times). + * + * Inspired by original 'date' element but reimplemented as a subclass + * of HTML_QuickForm_group + * + * @category HTML + * @package HTML_QuickForm + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 3.1 + */ +class HTML_QuickForm_date extends HTML_QuickForm_group +{ + // {{{ properties + + /** + * Various options to control the element's display. + * + * @access private + * @var array + */ + var $_options = array( + 'language' => 'en', + 'format' => 'dMY', + 'minYear' => 2001, + 'maxYear' => 2010, + 'addEmptyOption' => false, + 'emptyOptionValue' => '', + 'emptyOptionText' => ' ', + 'optionIncrement' => array('i' => 1, 's' => 1) + ); + + /** + * These complement separators, they are appended to the resultant HTML + * @access private + * @var array + */ + var $_wrap = array('', ''); + + /** + * Options in different languages + * + * Note to potential translators: to avoid encoding problems please send + * your translations with "weird" letters encoded as HTML Unicode entities + * + * @access private + * @var array + */ + var $_locale = array( + 'en' => array ( + 'weekdays_short'=> array ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'), + 'weekdays_long' => array ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), + 'months_long' => array ('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') + ), + 'de' => array ( + 'weekdays_short'=> array ('So', 'Mon', 'Di', 'Mi', 'Do', 'Fr', 'Sa'), + 'weekdays_long' => array ('Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'), + 'months_short' => array ('Jan', 'Feb', 'März', 'April', 'Mai', 'Juni', 'Juli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dez'), + 'months_long' => array ('Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember') + ), + 'fr' => array ( + 'weekdays_short'=> array ('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'), + 'weekdays_long' => array ('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'), + 'months_short' => array ('Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc'), + 'months_long' => array ('Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre') + ), + 'hu' => array ( + 'weekdays_short'=> array ('V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'), + 'weekdays_long' => array ('vasárnap', 'hétfő', 'kedd', 'szerda', 'csütörtök', 'péntek', 'szombat'), + 'months_short' => array ('jan', 'feb', 'márc', 'ápr', 'máj', 'jún', 'júl', 'aug', 'szept', 'okt', 'nov', 'dec'), + 'months_long' => array ('január', 'február', 'március', 'április', 'május', 'június', 'július', 'augusztus', 'szeptember', 'október', 'november', 'december') + ), + 'pl' => array ( + 'weekdays_short'=> array ('Nie', 'Pn', 'Wt', 'Śr', 'Czw', 'Pt', 'Sob'), + 'weekdays_long' => array ('Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'), + 'months_short' => array ('Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'), + 'months_long' => array ('Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień') + ), + 'sl' => array ( + 'weekdays_short'=> array ('Ned', 'Pon', 'Tor', 'Sre', 'Cet', 'Pet', 'Sob'), + 'weekdays_long' => array ('Nedelja', 'Ponedeljek', 'Torek', 'Sreda', 'Cetrtek', 'Petek', 'Sobota'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Avg', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januar', 'Februar', 'Marec', 'April', 'Maj', 'Junij', 'Julij', 'Avgust', 'September', 'Oktober', 'November', 'December') + ), + 'ru' => array ( + 'weekdays_short'=> array ('Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'), + 'weekdays_long' => array ('Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'), + 'months_short' => array ('Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'), + 'months_long' => array ('Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь') + ), + 'es' => array ( + 'weekdays_short'=> array ('Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'), + 'weekdays_long' => array ('Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'), + 'months_short' => array ('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'), + 'months_long' => array ('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre') + ), + 'da' => array ( + 'weekdays_short'=> array ('Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'), + 'weekdays_long' => array ('Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December') + ), + 'is' => array ( + 'weekdays_short'=> array ('Sun', 'Mán', 'Þri', 'Mið', 'Fim', 'Fös', 'Lau'), + 'weekdays_long' => array ('Sunnudagur', 'Mánudagur', 'Þriðjudagur', 'Miðvikudagur', 'Fimmtudagur', 'Föstudagur', 'Laugardagur'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maí', 'Jún', 'Júl', 'Ágú', 'Sep', 'Okt', 'Nóv', 'Des'), + 'months_long' => array ('Janúar', 'Febrúar', 'Mars', 'Apríl', 'Maí', 'Júní', 'Júlí', 'Ágúst', 'September', 'Október', 'Nóvember', 'Desember') + ), + 'it' => array ( + 'weekdays_short'=> array ('Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab'), + 'weekdays_long' => array ('Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'), + 'months_short' => array ('Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'), + 'months_long' => array ('Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre') + ), + 'sk' => array ( + 'weekdays_short'=> array ('Ned', 'Pon', 'Uto', 'Str', 'Štv', 'Pia', 'Sob'), + 'weekdays_long' => array ('Nedeža', 'Pondelok', 'Utorok', 'Streda', 'Štvrtok', 'Piatok', 'Sobota'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Máj', 'Jún', 'Júl', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Január', 'Február', 'Marec', 'Apríl', 'Máj', 'Jún', 'Júl', 'August', 'September', 'Október', 'November', 'December') + ), + 'cs' => array ( + 'weekdays_short'=> array ('Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'), + 'weekdays_long' => array ('Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota'), + 'months_short' => array ('Led', 'Úno', 'Bře', 'Dub', 'Kvě', 'Čen', 'Čec', 'Srp', 'Zář', 'Říj', 'Lis', 'Pro'), + 'months_long' => array ('Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec') + ), + 'hy' => array ( + 'weekdays_short'=> array ('Կրկ', 'Երկ', 'Երք', 'Չրք', 'Հնգ', 'Ուր', 'Շբթ'), + 'weekdays_long' => array ('Կիրակի', 'Երկուշաբթի', 'Երեքշաբթի', 'Չորեքշաբթի', 'Հինգշաբթի', 'Ուրբաթ', 'Շաբաթ'), + 'months_short' => array ('Հնվ', 'Փտր', 'Մրտ', 'Ապր', 'Մյս', 'Հնս', 'Հլս', 'Օգս', 'Սպտ', 'Հկտ', 'Նյմ', 'Դկտ'), + 'months_long' => array ('Հունվար', 'Փետրվար', 'Մարտ', 'Ապրիլ', 'Մայիս', 'Հունիս', 'Հուլիս', 'Օգոստոս', 'Սեպտեմբեր', 'Հոկտեմբեր', 'Նոյեմբեր', 'Դեկտեմբեր') + ), + 'nl' => array ( + 'weekdays_short'=> array ('Zo', 'Ma', 'Di', 'Wo', 'Do', 'Vr', 'Za'), + 'weekdays_long' => array ('Zondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December') + ), + 'et' => array ( + 'weekdays_short'=> array ('P', 'E', 'T', 'K', 'N', 'R', 'L'), + 'weekdays_long' => array ('Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'), + 'months_short' => array ('Jaan', 'Veebr', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'), + 'months_long' => array ('Jaanuar', 'Veebruar', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'August', 'September', 'Oktoober', 'November', 'Detsember') + ), + 'tr' => array ( + 'weekdays_short'=> array ('Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cts'), + 'weekdays_long' => array ('Pazar', 'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi'), + 'months_short' => array ('Ock', 'Şbt', 'Mrt', 'Nsn', 'Mys', 'Hzrn', 'Tmmz', 'Ağst', 'Eyl', 'Ekm', 'Ksm', 'Arlk'), + 'months_long' => array ('Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık') + ), + 'no' => array ( + 'weekdays_short'=> array ('Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'), + 'weekdays_long' => array ('Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'), + 'months_long' => array ('Januar', 'Februar', 'Mars', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Desember') + ), + 'eo' => array ( + 'weekdays_short'=> array ('Dim', 'Lun', 'Mar', 'Mer', 'Ĵaŭ', 'Ven', 'Sab'), + 'weekdays_long' => array ('Dimanĉo', 'Lundo', 'Mardo', 'Merkredo', 'Ĵaŭdo', 'Vendredo', 'Sabato'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aŭg', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januaro', 'Februaro', 'Marto', 'Aprilo', 'Majo', 'Junio', 'Julio', 'Aŭgusto', 'Septembro', 'Oktobro', 'Novembro', 'Decembro') + ), + 'ua' => array ( + 'weekdays_short'=> array('Ндл', 'Пнд', 'Втр', 'Срд', 'Чтв', 'Птн', 'Сбт'), + 'weekdays_long' => array('Неділя', 'Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П\'ятниця', 'Субота'), + 'months_short' => array('Січ', 'Лют', 'Бер', 'Кві', 'Тра', 'Чер', 'Лип', 'Сер', 'Вер', 'Жов', 'Лис', 'Гру'), + 'months_long' => array('Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень') + ), + 'ro' => array ( + 'weekdays_short'=> array ('Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sam'), + 'weekdays_long' => array ('Duminica', 'Luni', 'Marti', 'Miercuri', 'Joi', 'Vineri', 'Sambata'), + 'months_short' => array ('Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'), + 'months_long' => array ('Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie') + ), + 'he' => array ( + 'weekdays_short'=> array ('ראשון', 'שני', 'שלישי', 'רביעי', 'חמישי', 'שישי', 'שבת'), + 'weekdays_long' => array ('יום ראשון', 'יום שני', 'יום שלישי', 'יום רביעי', 'יום חמישי', 'יום שישי', 'שבת'), + 'months_short' => array ('ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר'), + 'months_long' => array ('ינואר', 'פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר', 'דצמבר') + ), + 'sv' => array ( + 'weekdays_short'=> array ('Sön', 'Mån', 'Tis', 'Ons', 'Tor', 'Fre', 'Lör'), + 'weekdays_long' => array ('Söndag', 'Måndag', 'Tisdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lördag'), + 'months_short' => array ('Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'), + 'months_long' => array ('Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December') + ), + 'pt' => array ( + 'weekdays_short'=> array ('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'), + 'weekdays_long' => array ('Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'), + 'months_short' => array ('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'), + 'months_long' => array ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro') + ), + 'tw' => array ( + 'weekdays_short'=> array ('週日','週一', '週二','週三', '週四','週五', '週六'), + 'weekdays_long' => array ('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'), + 'months_short' => array ('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'), + 'months_long' => array ('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月') + ), + 'pt-br' => array ( + 'weekdays_short'=> array ('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'), + 'weekdays_long' => array ('Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'), + 'months_short' => array ('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'), + 'months_long' => array ('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro') + ) + ); + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * The following keys may appear in $options array: + * - 'language': date language + * - 'format': Format of the date, based on PHP's date() function. + * The following characters are currently recognised in format string: + *
  
+    *       D => Short names of days
+    *       l => Long names of days
+    *       d => Day numbers
+    *       M => Short names of months
+    *       F => Long names of months
+    *       m => Month numbers
+    *       Y => Four digit year
+    *       y => Two digit year
+    *       h => 12 hour format
+    *       H => 23 hour  format
+    *       i => Minutes
+    *       s => Seconds
+    *       a => am/pm
+    *       A => AM/PM
+    *   
+ * - 'minYear': Minimum year in year select + * - 'maxYear': Maximum year in year select + * - 'addEmptyOption': Should an empty option be added to the top of + * each select box? + * - 'emptyOptionValue': The value passed by the empty option. + * - 'emptyOptionText': The text displayed for the empty option. + * - 'optionIncrement': Step to increase the option values by (works for 'i' and 's') + * + * @access public + * @param string Element's name + * @param mixed Label(s) for an element + * @param array Options to control the element's display + * @param mixed Either a typical HTML attribute string or an associative array + */ + function HTML_QuickForm_date($elementName = null, $elementLabel = null, $options = array(), $attributes = null) + { + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_appendName = true; + $this->_type = 'date'; + // set the options, do not bother setting bogus ones + if (is_array($options)) { + foreach ($options as $name => $value) { + if ('language' == $name) { + $this->_options['language'] = isset($this->_locale[$value])? $value: 'en'; + } elseif (isset($this->_options[$name])) { + if (is_array($value) && is_array($this->_options[$name])) { + $this->_options[$name] = @array_merge($this->_options[$name], $value); + } else { + $this->_options[$name] = $value; + } + } + } + } + } + + // }}} + // {{{ _createElements() + + function _createElements() + { + $this->_separator = $this->_elements = array(); + $separator = ''; + $locale =& $this->_locale[$this->_options['language']]; + $backslash = false; + for ($i = 0, $length = strlen($this->_options['format']); $i < $length; $i++) { + $sign = $this->_options['format']{$i}; + if ($backslash) { + $backslash = false; + $separator .= $sign; + } else { + $loadSelect = true; + switch ($sign) { + case 'D': + // Sunday is 0 like with 'w' in date() + $options = $locale['weekdays_short']; + break; + case 'l': + $options = $locale['weekdays_long']; + break; + case 'd': + $options = $this->_createOptionList(1, 31); + break; + case 'M': + $options = $locale['months_short']; + array_unshift($options , ''); + unset($options[0]); + break; + case 'm': + $options = $this->_createOptionList(1, 12); + break; + case 'F': + $options = $locale['months_long']; + array_unshift($options , ''); + unset($options[0]); + break; + case 'Y': + $options = $this->_createOptionList( + $this->_options['minYear'], + $this->_options['maxYear'], + $this->_options['minYear'] > $this->_options['maxYear']? -1: 1 + ); + break; + case 'y': + $options = $this->_createOptionList( + $this->_options['minYear'], + $this->_options['maxYear'], + $this->_options['minYear'] > $this->_options['maxYear']? -1: 1 + ); + array_walk($options, create_function('&$v,$k','$v = substr($v,-2);')); + break; + case 'h': + $options = $this->_createOptionList(1, 12); + break; + case 'g': + $options = $this->_createOptionList(1, 12); + array_walk($options, create_function('&$v,$k', '$v = intval($v);')); + break; + case 'H': + $options = $this->_createOptionList(0, 23); + break; + case 'i': + $options = $this->_createOptionList(0, 59, $this->_options['optionIncrement']['i']); + break; + case 's': + $options = $this->_createOptionList(0, 59, $this->_options['optionIncrement']['s']); + break; + case 'a': + $options = array('am' => 'am', 'pm' => 'pm'); + break; + case 'A': + $options = array('AM' => 'AM', 'PM' => 'PM'); + break; + case 'W': + $options = $this->_createOptionList(1, 53); + break; + case '\\': + $backslash = true; + $loadSelect = false; + break; + default: + $separator .= (' ' == $sign? ' ': $sign); + $loadSelect = false; + } + + if ($loadSelect) { + if (0 < count($this->_elements)) { + $this->_separator[] = $separator; + } else { + $this->_wrap[0] = $separator; + } + $separator = ''; + // Should we add an empty option to the top of the select? + if (!is_array($this->_options['addEmptyOption']) && $this->_options['addEmptyOption'] || + is_array($this->_options['addEmptyOption']) && !empty($this->_options['addEmptyOption'][$sign])) { + + // Using '+' array operator to preserve the keys + if (is_array($this->_options['emptyOptionText']) && !empty($this->_options['emptyOptionText'][$sign])) { + $options = array($this->_options['emptyOptionValue'] => $this->_options['emptyOptionText'][$sign]) + $options; + } else { + $options = array($this->_options['emptyOptionValue'] => $this->_options['emptyOptionText']) + $options; + } + } + $this->_elements[] = new HTML_QuickForm_select($sign, null, $options, $this->getAttributes()); + } + } + } + $this->_wrap[1] = $separator . ($backslash? '\\': ''); + } + + // }}} + // {{{ _createOptionList() + + /** + * Creates an option list containing the numbers from the start number to the end, inclusive + * + * @param int The start number + * @param int The end number + * @param int Increment by this value + * @access private + * @return array An array of numeric options. + */ + function _createOptionList($start, $end, $step = 1) + { + for ($i = $start, $options = array(); $start > $end? $i >= $end: $i <= $end; $i += $step) { + $options[$i] = sprintf('%02d', $i); + } + return $options; + } + + // }}} + // {{{ _trimLeadingZeros() + + /** + * Trims leading zeros from the (numeric) string + * + * @param string A numeric string, possibly with leading zeros + * @return string String with leading zeros removed + */ + function _trimLeadingZeros($str) + { + if (0 == strcmp($str, $this->_options['emptyOptionValue'])) { + return $str; + } + $trimmed = ltrim($str, '0'); + return strlen($trimmed)? $trimmed: '0'; + } + + // }}} + // {{{ setValue() + + function setValue($value) + { + if (empty($value)) { + $value = array(); + } elseif (is_scalar($value)) { + if (!is_numeric($value)) { + $value = strtotime($value); + } + // might be a unix epoch, then we fill all possible values + $arr = explode('-', date('w-j-n-Y-g-G-i-s-a-A-W', (int)$value)); + $value = array( + 'D' => $arr[0], + 'l' => $arr[0], + 'd' => $arr[1], + 'M' => $arr[2], + 'm' => $arr[2], + 'F' => $arr[2], + 'Y' => $arr[3], + 'y' => $arr[3], + 'h' => $arr[4], + 'g' => $arr[4], + 'H' => $arr[5], + 'i' => $this->_trimLeadingZeros($arr[6]), + 's' => $this->_trimLeadingZeros($arr[7]), + 'a' => $arr[8], + 'A' => $arr[9], + 'W' => $this->_trimLeadingZeros($arr[10]) + ); + } else { + $value = array_map(array($this, '_trimLeadingZeros'), $value); + } + parent::setValue($value); + } + + // }}} + // {{{ toHtml() + + function toHtml() + { + include_once(dirname(__FILE__) . '/Renderer/Default.php'); + $renderer = new HTML_QuickForm_Renderer_Default(); + $renderer->setElementTemplate('{element}'); + parent::accept($renderer); + return $this->_wrap[0] . $renderer->toHtml() . $this->_wrap[1]; + } + + // }}} + // {{{ accept() + + function accept(&$renderer, $required = false, $error = null) + { + $renderer->renderElement($this, $required, $error); + } + + // }}} + // {{{ onQuickFormEvent() + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' == $event) { + // we need to call setValue(), 'cause the default/constant value + // may be in fact a timestamp, not an array + return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller); + } else { + return parent::onQuickFormEvent($event, $arg, $caller); + } + } + + // }}} +} +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/element.php b/oss/piwik/trunk/libs/HTML/QuickForm/element.php new file mode 100644 index 00000000..0972e865 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/element.php @@ -0,0 +1,494 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: element.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for all HTML classes + */ +require_once dirname(__FILE__) . '/../Common.php'; + +/** + * Base class for form elements + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 1.0 + * @abstract + */ +class HTML_QuickForm_element extends HTML_Common +{ + // {{{ properties + + /** + * Label of the field + * @var string + * @since 1.3 + * @access private + */ + var $_label = ''; + + /** + * Form element type + * @var string + * @since 1.0 + * @access private + */ + var $_type = ''; + + /** + * Flag to tell if element is frozen + * @var boolean + * @since 1.0 + * @access private + */ + var $_flagFrozen = false; + + /** + * Does the element support persistant data when frozen + * @var boolean + * @since 1.3 + * @access private + */ + var $_persistantFreeze = false; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Name of the element + * @param mixed Label(s) for the element + * @param mixed Associative array of tag attributes or HTML attributes name="value" pairs + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_element($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_Common::HTML_Common($attributes); + if (isset($elementName)) { + $this->setName($elementName); + } + if (isset($elementLabel)) { + $this->setLabel($elementLabel); + } + } //end constructor + + // }}} + // {{{ apiVersion() + + /** + * Returns the current API version + * + * @since 1.0 + * @access public + * @return float + */ + function apiVersion() + { + return 3.2; + } // end func apiVersion + + // }}} + // {{{ getType() + + /** + * Returns element type + * + * @since 1.0 + * @access public + * @return string + */ + function getType() + { + return $this->_type; + } // end func getType + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + // interface method + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + // interface method + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param string $value Default value of the form element + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + // interface + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return mixed + */ + function getValue() + { + // interface + return null; + } // end func getValue + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + $this->_flagFrozen = true; + } //end func freeze + + // }}} + // {{{ unfreeze() + + /** + * Unfreezes the element so that it becomes editable + * + * @access public + * @return void + * @since 3.2.4 + */ + function unfreeze() + { + $this->_flagFrozen = false; + } + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + $value = $this->getValue(); + return (strlen($value)? htmlspecialchars($value): ' ') . + $this->_getPersistantData(); + } //end func getFrozenHtml + + // }}} + // {{{ _getPersistantData() + + /** + * Used by getFrozenHtml() to pass the element's value if _persistantFreeze is on + * + * @access private + * @return string + */ + function _getPersistantData() + { + if (!$this->_persistantFreeze) { + return ''; + } else { + $id = $this->getAttribute('id'); + return '_getAttrString(array( + 'type' => 'hidden', + 'name' => $this->getName(), + 'value' => $this->getValue() + ) + (isset($id)? array('id' => $id): array())) . ' />'; + } + } + + // }}} + // {{{ isFrozen() + + /** + * Returns whether or not the element is frozen + * + * @since 1.3 + * @access public + * @return bool + */ + function isFrozen() + { + return $this->_flagFrozen; + } // end func isFrozen + + // }}} + // {{{ setPersistantFreeze() + + /** + * Sets wether an element value should be kept in an hidden field + * when the element is frozen or not + * + * @param bool $persistant True if persistant value + * @since 2.0 + * @access public + * @return void + */ + function setPersistantFreeze($persistant=false) + { + $this->_persistantFreeze = $persistant; + } //end func setPersistantFreeze + + // }}} + // {{{ setLabel() + + /** + * Sets display text for the element + * + * @param string $label Display text for the element + * @since 1.3 + * @access public + * @return void + */ + function setLabel($label) + { + $this->_label = $label; + } //end func setLabel + + // }}} + // {{{ getLabel() + + /** + * Returns display text for the element + * + * @since 1.3 + * @access public + * @return string + */ + function getLabel() + { + return $this->_label; + } //end func getLabel + + // }}} + // {{{ _findValue() + + /** + * Tries to find the element value from the values array + * + * @since 2.7 + * @access private + * @return mixed + */ + function _findValue(&$values) + { + if (empty($values)) { + return null; + } + $elementName = $this->getName(); + if (isset($values[$elementName])) { + return $values[$elementName]; + } elseif (strpos($elementName, '[')) { + $myVar = "['" . str_replace( + array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), + $elementName + ) . "']"; + return eval("return (isset(\$values$myVar)) ? \$values$myVar : null;"); + } else { + return null; + } + } //end func _findValue + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'createElement': + $className = get_class($this); + $this->$className($arg[0], $arg[1], $arg[2], $arg[3], $arg[4]); + break; + case 'addElement': + $this->onQuickFormEvent('createElement', $arg, $caller); + $this->onQuickFormEvent('updateValue', null, $caller); + break; + case 'updateValue': + // constant values override both default and submitted ones + // default values are overriden by submitted + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_submitValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (null !== $value) { + $this->setValue($value); + } + break; + case 'setGroupValue': + $this->setValue($arg); + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object + * @param bool Whether an element is required + * @param string An error message associated with an element + * @access public + * @return void + */ + function accept(&$renderer, $required=false, $error=null) + { + $renderer->renderElement($this, $required, $error); + } // end func accept + + // }}} + // {{{ _generateId() + + /** + * Automatically generates and assigns an 'id' attribute for the element. + * + * Currently used to ensure that labels work on radio buttons and + * checkboxes. Per idea of Alexander Radivanovich. + * + * @access private + * @return void + */ + function _generateId() + { + static $idx = 1; + + if (!$this->getAttribute('id')) { + $this->updateAttributes(array('id' => 'qf_' . substr(md5(microtime() . $idx++), 0, 6))); + } + } // end func _generateId + + // }}} + // {{{ exportValue() + + /** + * Returns a 'safe' element's value + * + * @param array array of submitted values to search + * @param bool whether to return the value as associative array + * @access public + * @return mixed + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (null === $value) { + $value = $this->getValue(); + } + return $this->_prepareValue($value, $assoc); + } + + // }}} + // {{{ _prepareValue() + + /** + * Used by exportValue() to prepare the value for returning + * + * @param mixed the value found in exportValue() + * @param bool whether to return the value as associative array + * @access private + * @return mixed + */ + function _prepareValue($value, $assoc) + { + if (null === $value) { + return null; + } elseif (!$assoc) { + return $value; + } else { + $name = $this->getName(); + if (!strpos($name, '[')) { + return array($name => $value); + } else { + $valueAry = array(); + $myIndex = "['" . str_replace( + array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), + $name + ) . "']"; + eval("\$valueAry$myIndex = \$value;"); + return $valueAry; + } + } + } + + // }}} +} // end class HTML_QuickForm_element +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/file.php b/oss/piwik/trunk/libs/HTML/QuickForm/file.php new file mode 100644 index 00000000..9338cf48 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/file.php @@ -0,0 +1,358 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: file.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +// register file-related rules +if (class_exists('HTML_QuickForm')) { + HTML_QuickForm::registerRule('uploadedfile', 'callback', '_ruleIsUploadedFile', 'HTML_QuickForm_file'); + HTML_QuickForm::registerRule('maxfilesize', 'callback', '_ruleCheckMaxFileSize', 'HTML_QuickForm_file'); + HTML_QuickForm::registerRule('mimetype', 'callback', '_ruleCheckMimeType', 'HTML_QuickForm_file'); + HTML_QuickForm::registerRule('filename', 'callback', '_ruleCheckFileName', 'HTML_QuickForm_file'); +} + +/** + * HTML class for a file upload field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_file extends HTML_QuickForm_input +{ + // {{{ properties + + /** + * Uploaded file data, from $_FILES + * @var array + */ + var $_value = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param string Input field label + * @param mixed (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + */ + function HTML_QuickForm_file($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes); + $this->setType('file'); + } //end constructor + + // }}} + // {{{ setSize() + + /** + * Sets size of file element + * + * @param int Size of file element + * @since 1.0 + * @access public + */ + function setSize($size) + { + $this->updateAttributes(array('size' => $size)); + } //end func setSize + + // }}} + // {{{ getSize() + + /** + * Returns size of file element + * + * @since 1.0 + * @access public + * @return int + */ + function getSize() + { + return $this->getAttribute('size'); + } //end func getSize + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return bool + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + // {{{ setValue() + + /** + * Sets value for file element. + * + * Actually this does nothing. The function is defined here to override + * HTML_Quickform_input's behaviour of setting the 'value' attribute. As + * no sane user-agent uses 's value for anything + * (because of security implications) we implement file's value as a + * read-only property with a special meaning. + * + * @param mixed Value for file element + * @since 3.0 + * @access public + */ + function setValue($value) + { + return null; + } //end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns information about the uploaded file + * + * @since 3.0 + * @access public + * @return array + */ + function getValue() + { + return $this->_value; + } // end func getValue + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string Name of event + * @param mixed event arguments + * @param object calling object + * @since 1.0 + * @access public + * @return bool + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + if ($caller->getAttribute('method') == 'get') { + return PEAR::raiseError('Cannot add a file upload field to a GET method form'); + } + $this->_value = $this->_findValue(); + $caller->updateAttributes(array('enctype' => 'multipart/form-data')); + $caller->setMaxFileSize(); + break; + case 'addElement': + $this->onQuickFormEvent('createElement', $arg, $caller); + return $this->onQuickFormEvent('updateValue', null, $caller); + break; + case 'createElement': + $className = get_class($this); + $this->$className($arg[0], $arg[1], $arg[2]); + break; + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ moveUploadedFile() + + /** + * Moves an uploaded file into the destination + * + * @param string Destination directory path + * @param string New file name + * @access public + * @return bool Whether the file was moved successfully + */ + function moveUploadedFile($dest, $fileName = '') + { + if ($dest != '' && substr($dest, -1) != '/') { + $dest .= '/'; + } + $fileName = ($fileName != '') ? $fileName : basename($this->_value['name']); + return move_uploaded_file($this->_value['tmp_name'], $dest . $fileName); + } // end func moveUploadedFile + + // }}} + // {{{ isUploadedFile() + + /** + * Checks if the element contains an uploaded file + * + * @access public + * @return bool true if file has been uploaded, false otherwise + */ + function isUploadedFile() + { + return $this->_ruleIsUploadedFile($this->_value); + } // end func isUploadedFile + + // }}} + // {{{ _ruleIsUploadedFile() + + /** + * Checks if the given element contains an uploaded file + * + * @param array Uploaded file info (from $_FILES) + * @access private + * @return bool true if file has been uploaded, false otherwise + */ + function _ruleIsUploadedFile($elementValue) + { + if ((isset($elementValue['error']) && $elementValue['error'] == 0) || + (!empty($elementValue['tmp_name']) && $elementValue['tmp_name'] != 'none')) { + return is_uploaded_file($elementValue['tmp_name']); + } else { + return false; + } + } // end func _ruleIsUploadedFile + + // }}} + // {{{ _ruleCheckMaxFileSize() + + /** + * Checks that the file does not exceed the max file size + * + * @param array Uploaded file info (from $_FILES) + * @param int Max file size + * @access private + * @return bool true if filesize is lower than maxsize, false otherwise + */ + function _ruleCheckMaxFileSize($elementValue, $maxSize) + { + if (!empty($elementValue['error']) && + (UPLOAD_ERR_FORM_SIZE == $elementValue['error'] || UPLOAD_ERR_INI_SIZE == $elementValue['error'])) { + return false; + } + if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) { + return true; + } + return ($maxSize >= @filesize($elementValue['tmp_name'])); + } // end func _ruleCheckMaxFileSize + + // }}} + // {{{ _ruleCheckMimeType() + + /** + * Checks if the given element contains an uploaded file of the right mime type + * + * @param array Uploaded file info (from $_FILES) + * @param mixed Mime Type (can be an array of allowed types) + * @access private + * @return bool true if mimetype is correct, false otherwise + */ + function _ruleCheckMimeType($elementValue, $mimeType) + { + if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) { + return true; + } + if (is_array($mimeType)) { + return in_array($elementValue['type'], $mimeType); + } + return $elementValue['type'] == $mimeType; + } // end func _ruleCheckMimeType + + // }}} + // {{{ _ruleCheckFileName() + + /** + * Checks if the given element contains an uploaded file of the filename regex + * + * @param array Uploaded file info (from $_FILES) + * @param string Regular expression + * @access private + * @return bool true if name matches regex, false otherwise + */ + function _ruleCheckFileName($elementValue, $regex) + { + if (!HTML_QuickForm_file::_ruleIsUploadedFile($elementValue)) { + return true; + } + return (bool)preg_match($regex, $elementValue['name']); + } // end func _ruleCheckFileName + + // }}} + // {{{ _findValue() + + /** + * Tries to find the element value from the values array + * + * Needs to be redefined here as $_FILES is populated differently from + * other arrays when element name is of the form foo[bar] + * + * @access private + * @return mixed + */ + function _findValue() + { + if (empty($_FILES)) { + return null; + } + $elementName = $this->getName(); + if (isset($_FILES[$elementName])) { + return $_FILES[$elementName]; + } elseif (false !== ($pos = strpos($elementName, '['))) { + $base = str_replace( + array('\\', '\''), array('\\\\', '\\\''), + substr($elementName, 0, $pos) + ); + $idx = "['" . str_replace( + array('\\', '\'', ']', '['), array('\\\\', '\\\'', '', "']['"), + substr($elementName, $pos + 1, -1) + ) . "']"; + $props = array('name', 'type', 'size', 'tmp_name', 'error'); + $code = "if (!isset(\$_FILES['{$base}']['name']{$idx})) {\n" . + " return null;\n" . + "} else {\n" . + " \$value = array();\n"; + foreach ($props as $prop) { + $code .= " \$value['{$prop}'] = \$_FILES['{$base}']['{$prop}']{$idx};\n"; + } + return eval($code . " return \$value;\n}\n"); + } else { + return null; + } + } + + // }}} +} // end class HTML_QuickForm_file +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/group.php b/oss/piwik/trunk/libs/HTML/QuickForm/group.php new file mode 100644 index 00000000..dfa9b92c --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/group.php @@ -0,0 +1,588 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: group.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/element.php'; + +/** + * HTML class for a form element group + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_group extends HTML_QuickForm_element +{ + // {{{ properties + + /** + * Name of the element + * @var string + * @since 1.0 + * @access private + */ + var $_name = ''; + + /** + * Array of grouped elements + * @var array + * @since 1.0 + * @access private + */ + var $_elements = array(); + + /** + * String to separate elements + * @var mixed + * @since 2.5 + * @access private + */ + var $_separator = null; + + /** + * Required elements in this group + * @var array + * @since 2.5 + * @access private + */ + var $_required = array(); + + /** + * Whether to change elements' names to $groupName[$elementName] or leave them as is + * @var bool + * @since 3.0 + * @access private + */ + var $_appendName = true; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Group name + * @param array $elementLabel (optional)Group label + * @param array $elements (optional)Group elements + * @param mixed $separator (optional)Use a string for one separator, + * use an array to alternate the separators. + * @param bool $appendName (optional)whether to change elements' names to + * the form $groupName[$elementName] or leave + * them as is. + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_group($elementName=null, $elementLabel=null, $elements=null, $separator=null, $appendName = true) + { + $this->HTML_QuickForm_element($elementName, $elementLabel); + $this->_type = 'group'; + if (isset($elements) && is_array($elements)) { + $this->setElements($elements); + } + if (isset($separator)) { + $this->_separator = $separator; + } + if (isset($appendName)) { + $this->_appendName = $appendName; + } + } //end constructor + + // }}} + // {{{ setName() + + /** + * Sets the group name + * + * @param string $name Group name + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->_name = $name; + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the group name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->_name; + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets values for group's elements + * + * @param mixed Values for group's elements + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->_createElementsIfNotExist(); + foreach (array_keys($this->_elements) as $key) { + if (!$this->_appendName) { + $v = $this->_elements[$key]->_findValue($value); + if (null !== $v) { + $this->_elements[$key]->onQuickFormEvent('setGroupValue', $v, $this); + } + + } else { + $elementName = $this->_elements[$key]->getName(); + $index = strlen($elementName) ? $elementName : $key; + if (is_array($value)) { + if (isset($value[$index])) { + $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value[$index], $this); + } + } elseif (isset($value)) { + $this->_elements[$key]->onQuickFormEvent('setGroupValue', $value, $this); + } + } + } + } //end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the group + * + * @since 1.0 + * @access public + * @return mixed + */ + function getValue() + { + $value = null; + foreach (array_keys($this->_elements) as $key) { + $element =& $this->_elements[$key]; + switch ($element->getType()) { + case 'radio': + $v = $element->getChecked()? $element->getValue(): null; + break; + case 'checkbox': + $v = $element->getChecked()? true: null; + break; + default: + $v = $element->getValue(); + } + if (null !== $v) { + $elementName = $element->getName(); + if (is_null($elementName)) { + $value = $v; + } else { + if (!is_array($value)) { + $value = is_null($value)? array(): array($value); + } + if ('' === $elementName) { + $value[] = $v; + } else { + $value[$elementName] = $v; + } + } + } + } + return $value; + } // end func getValue + + // }}} + // {{{ setElements() + + /** + * Sets the grouped elements + * + * @param array $elements Array of elements + * @since 1.1 + * @access public + * @return void + */ + function setElements($elements) + { + $this->_elements = array_values($elements); + if ($this->_flagFrozen) { + $this->freeze(); + } + } // end func setElements + + // }}} + // {{{ getElements() + + /** + * Gets the grouped elements + * + * @since 2.4 + * @access public + * @return array + */ + function &getElements() + { + $this->_createElementsIfNotExist(); + return $this->_elements; + } // end func getElements + + // }}} + // {{{ getGroupType() + + /** + * Gets the group type based on its elements + * Will return 'mixed' if elements contained in the group + * are of different types. + * + * @access public + * @return string group elements type + */ + function getGroupType() + { + $this->_createElementsIfNotExist(); + $prevType = ''; + foreach (array_keys($this->_elements) as $key) { + $type = $this->_elements[$key]->getType(); + if ($type != $prevType && $prevType != '') { + return 'mixed'; + } + $prevType = $type; + } + return $type; + } // end func getGroupType + + // }}} + // {{{ toHtml() + + /** + * Returns Html for the group + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + include_once(dirname(__FILE__) . '/Renderer/Default.php'); + $renderer = new HTML_QuickForm_Renderer_Default(); + $renderer->setElementTemplate('{element}'); + $this->accept($renderer); + return $renderer->toHtml(); + } //end func toHtml + + // }}} + // {{{ getElementName() + + /** + * Returns the element name inside the group such as found in the html form + * + * @param mixed $index Element name or element index in the group + * @since 3.0 + * @access public + * @return mixed string with element name, false if not found + */ + function getElementName($index) + { + $this->_createElementsIfNotExist(); + $elementName = false; + if (is_int($index) && isset($this->_elements[$index])) { + $elementName = $this->_elements[$index]->getName(); + if (isset($elementName) && $elementName == '') { + $elementName = $index; + } + if ($this->_appendName) { + if (is_null($elementName)) { + $elementName = $this->getName(); + } else { + $elementName = $this->getName().'['.$elementName.']'; + } + } + + } elseif (is_string($index)) { + foreach (array_keys($this->_elements) as $key) { + $elementName = $this->_elements[$key]->getName(); + if ($index == $elementName) { + if ($this->_appendName) { + $elementName = $this->getName().'['.$elementName.']'; + } + break; + } elseif ($this->_appendName && $this->getName().'['.$elementName.']' == $index) { + break; + } + } + } + return $elementName; + } //end func getElementName + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.3 + * @access public + * @return string + */ + function getFrozenHtml() + { + $flags = array(); + $this->_createElementsIfNotExist(); + foreach (array_keys($this->_elements) as $key) { + if (false === ($flags[$key] = $this->_elements[$key]->isFrozen())) { + $this->_elements[$key]->freeze(); + } + } + $html = $this->toHtml(); + foreach (array_keys($this->_elements) as $key) { + if (!$flags[$key]) { + $this->_elements[$key]->unfreeze(); + } + } + return $html; + } //end func getFrozenHtml + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + $this->_createElementsIfNotExist(); + foreach (array_keys($this->_elements) as $key) { + if ($this->_appendName) { + $elementName = $this->_elements[$key]->getName(); + if (is_null($elementName)) { + $this->_elements[$key]->setName($this->getName()); + } elseif ('' === $elementName) { + $this->_elements[$key]->setName($this->getName() . '[' . $key . ']'); + } else { + $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']'); + } + } + $this->_elements[$key]->onQuickFormEvent('updateValue', $arg, $caller); + if ($this->_appendName) { + $this->_elements[$key]->setName($elementName); + } + } + break; + + default: + parent::onQuickFormEvent($event, $arg, $caller); + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object + * @param bool Whether a group is required + * @param string An error message associated with a group + * @access public + * @return void + */ + function accept(&$renderer, $required = false, $error = null) + { + $this->_createElementsIfNotExist(); + $renderer->startGroup($this, $required, $error); + $name = $this->getName(); + foreach (array_keys($this->_elements) as $key) { + $element =& $this->_elements[$key]; + + if ($this->_appendName) { + $elementName = $element->getName(); + if (isset($elementName)) { + $element->setName($name . '['. (strlen($elementName)? $elementName: $key) .']'); + } else { + $element->setName($name); + } + } + + $required = !$element->isFrozen() && in_array($element->getName(), $this->_required); + + $element->accept($renderer, $required); + + // restore the element's name + if ($this->_appendName) { + $element->setName($elementName); + } + } + $renderer->finishGroup($this); + } // end func accept + + // }}} + // {{{ exportValue() + + /** + * As usual, to get the group's value we access its elements and call + * their exportValue() methods + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = null; + foreach (array_keys($this->_elements) as $key) { + $elementName = $this->_elements[$key]->getName(); + if ($this->_appendName) { + if (is_null($elementName)) { + $this->_elements[$key]->setName($this->getName()); + } elseif ('' === $elementName) { + $this->_elements[$key]->setName($this->getName() . '[' . $key . ']'); + } else { + $this->_elements[$key]->setName($this->getName() . '[' . $elementName . ']'); + } + } + $v = $this->_elements[$key]->exportValue($submitValues, $assoc); + if ($this->_appendName) { + $this->_elements[$key]->setName($elementName); + } + if (null !== $v) { + // Make $value an array, we will use it like one + if (null === $value) { + $value = array(); + } + if ($assoc) { + // just like HTML_QuickForm::exportValues() + $value = HTML_QuickForm::arrayMerge($value, $v); + } else { + // just like getValue(), but should work OK every time here + if (is_null($elementName)) { + $value = $v; + } elseif ('' === $elementName) { + $value[] = $v; + } else { + $value[$elementName] = $v; + } + } + } + } + // do not pass the value through _prepareValue, we took care of this already + return $value; + } + + // }}} + // {{{ _createElements() + + /** + * Creates the group's elements. + * + * This should be overriden by child classes that need to create their + * elements. The method will be called automatically when needed, calling + * it from the constructor is discouraged as the constructor is usually + * called _twice_ on element creation, first time with _no_ parameters. + * + * @access private + * @abstract + */ + function _createElements() + { + // abstract + } + + // }}} + // {{{ _createElementsIfNotExist() + + /** + * A wrapper around _createElements() + * + * This method calls _createElements() if the group's _elements array + * is empty. It also performs some updates, e.g. freezes the created + * elements if the group is already frozen. + * + * @access private + */ + function _createElementsIfNotExist() + { + if (empty($this->_elements)) { + $this->_createElements(); + if ($this->_flagFrozen) { + $this->freeze(); + } + } + } + + // }}} + // {{{ freeze() + + function freeze() + { + parent::freeze(); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->freeze(); + } + } + + // }}} + // {{{ unfreeze() + + function unfreeze() + { + parent::unfreeze(); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->unfreeze(); + } + } + + // }}} + // {{{ setPersistantFreeze() + + function setPersistantFreeze($persistant = false) + { + parent::setPersistantFreeze($persistant); + foreach (array_keys($this->_elements) as $key) { + $this->_elements[$key]->setPersistantFreeze($persistant); + } + } + + // }}} +} //end class HTML_QuickForm_group +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/header.php b/oss/piwik/trunk/libs/HTML/QuickForm/header.php new file mode 100644 index 00000000..64e8e8d9 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/header.php @@ -0,0 +1,74 @@ + + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: header.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * HTML class for static data + */ +require_once dirname(__FILE__) . '/static.php'; + +/** + * A pseudo-element used for adding headers to form + * + * @category HTML + * @package HTML_QuickForm + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 3.0 + */ +class HTML_QuickForm_header extends HTML_QuickForm_static +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName Header name + * @param string $text Header text + * @access public + * @return void + */ + function HTML_QuickForm_header($elementName = null, $text = null) + { + $this->HTML_QuickForm_static($elementName, null, $text); + $this->_type = 'header'; + } + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object + * @access public + * @return void + */ + function accept(&$renderer) + { + $renderer->renderHeader($this); + } // end func accept + + // }}} + +} //end class HTML_QuickForm_header +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/hidden.php b/oss/piwik/trunk/libs/HTML/QuickForm/hidden.php new file mode 100644 index 00000000..c1a111d6 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/hidden.php @@ -0,0 +1,94 @@ + + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: hidden.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for a hidden type element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_hidden extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $value (optional)Input field value + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_hidden($elementName=null, $value='', $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->setType('hidden'); + $this->setValue($value); + } //end constructor + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object + * @access public + * @return void + */ + function accept(&$renderer) + { + $renderer->renderHidden($this); + } // end func accept + + // }}} + +} //end class HTML_QuickForm_hidden +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/hiddenselect.php b/oss/piwik/trunk/libs/HTML/QuickForm/hiddenselect.php new file mode 100644 index 00000000..db6c4c6d --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/hiddenselect.php @@ -0,0 +1,118 @@ + + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: hiddenselect.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Class for elements + */ +require_once dirname(__FILE__) . '/select.php'; + +/** + * Hidden select pseudo-element + * + * This class takes the same arguments as a select element, but instead + * of creating a select ring it creates hidden elements for all values + * already selected with setDefault or setConstant. This is useful if + * you have a select ring that you don't want visible, but you need all + * selected values to be passed. + * + * @category HTML + * @package HTML_QuickForm + * @author Isaac Shepard + * @version Release: 3.2.11 + * @since 2.1 + */ +class HTML_QuickForm_hiddenselect extends HTML_QuickForm_select +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string Select name attribute + * @param mixed Label(s) for the select (not used) + * @param mixed Data to be used to populate options + * @param mixed Either a typical HTML attribute string or an associative array (not used) + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_hiddenselect($elementName=null, $elementLabel=null, $options=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_type = 'hiddenselect'; + if (isset($options)) { + $this->load($options); + } + } //end constructor + + // }}} + // {{{ toHtml() + + /** + * Returns the SELECT in HTML + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function toHtml() + { + if (empty($this->_values)) { + return ''; + } + + $tabs = $this->_getTabs(); + $name = $this->getPrivateName(); + $strHtml = ''; + + foreach ($this->_values as $key => $val) { + for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) { + if ($val == $this->_options[$i]['attr']['value']) { + $strHtml .= $tabs . '_getAttrString(array( + 'type' => 'hidden', + 'name' => $name, + 'value' => $val + )) . " />\n" ; + } + } + } + + return $strHtml; + } //end func toHtml + + // }}} + // {{{ accept() + + /** + * This is essentially a hidden element and should be rendered as one + */ + function accept(&$renderer) + { + $renderer->renderHidden($this); + } + + // }}} +} //end class HTML_QuickForm_hiddenselect +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/hierselect.php b/oss/piwik/trunk/libs/HTML/QuickForm/hierselect.php new file mode 100644 index 00000000..56abf372 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/hierselect.php @@ -0,0 +1,596 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: hierselect.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Class for a group of form elements + */ +require_once dirname(__FILE__) . '/group.php'; +/** + * Class for elements + */ +require_once dirname(__FILE__) . '/select.php'; + +/** + * Hierarchical select element + * + * Class to dynamically create two or more HTML Select elements + * The first select changes the content of the second select and so on. + * This element is considered as a group. Selects will be named + * groupName[0], groupName[1], groupName[2]... + * + * @category HTML + * @package HTML_QuickForm + * @author Herim Vasquez + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 3.1 + */ +class HTML_QuickForm_hierselect extends HTML_QuickForm_group +{ + // {{{ properties + + /** + * Options for all the select elements + * + * @see setOptions() + * @var array + * @access private + */ + var $_options = array(); + + /** + * Number of select elements on this group + * + * @var int + * @access private + */ + var $_nbElements = 0; + + /** + * The javascript used to set and change the options + * + * @var string + * @access private + */ + var $_js = ''; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $elementLabel (optional)Input field label in form + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array. Date format is passed along the attributes. + * @param mixed $separator (optional)Use a string for one separator, + * use an array to alternate the separators. + * @access public + * @return void + */ + function HTML_QuickForm_hierselect($elementName=null, $elementLabel=null, $attributes=null, $separator=null) + { + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + if (isset($separator)) { + $this->_separator = $separator; + } + $this->_type = 'hierselect'; + $this->_appendName = true; + } //end constructor + + // }}} + // {{{ setOptions() + + /** + * Initialize the array structure containing the options for each select element. + * Call the functions that actually do the magic. + * + * Format is a bit more complex than for a simple select as we need to know + * which options are related to the ones in the previous select: + * + * Ex: + * + * // first select + * $select1[0] = 'Pop'; + * $select1[1] = 'Classical'; + * $select1[2] = 'Funeral doom'; + * + * // second select + * $select2[0][0] = 'Red Hot Chil Peppers'; + * $select2[0][1] = 'The Pixies'; + * $select2[1][0] = 'Wagner'; + * $select2[1][1] = 'Strauss'; + * $select2[2][0] = 'Pantheist'; + * $select2[2][1] = 'Skepticism'; + * + * // If only need two selects + * // - and using the deprecated functions + * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:'); + * $sel->setMainOptions($select1); + * $sel->setSecOptions($select2); + * + * // - and using the new setOptions function + * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:'); + * $sel->setOptions(array($select1, $select2)); + * + * // If you have a third select with prices for the cds + * $select3[0][0][0] = '15.00$'; + * $select3[0][0][1] = '17.00$'; + * // etc + * + * // You can now use + * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:'); + * $sel->setOptions(array($select1, $select2, $select3)); + * + * + * @param array $options Array of options defining each element + * @access public + * @return void + */ + function setOptions($options) + { + $this->_options = $options; + + if (empty($this->_elements)) { + $this->_nbElements = count($this->_options); + $this->_createElements(); + } else { + // setDefaults has probably been called before this function + // check if all elements have been created + $totalNbElements = count($this->_options); + for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) { + $this->_elements[] = new HTML_QuickForm_select($i, null, array(), $this->getAttributes()); + $this->_nbElements++; + } + } + + $this->_setOptions(); + } // end func setMainOptions + + // }}} + // {{{ setMainOptions() + + /** + * Sets the options for the first select element. Deprecated. setOptions() should be used. + * + * @param array $array Options for the first select element + * + * @access public + * @deprecated Deprecated since release 3.2.2 + * @return void + */ + function setMainOptions($array) + { + $this->_options[0] = $array; + + if (empty($this->_elements)) { + $this->_nbElements = 2; + $this->_createElements(); + } + } // end func setMainOptions + + // }}} + // {{{ setSecOptions() + + /** + * Sets the options for the second select element. Deprecated. setOptions() should be used. + * The main _options array is initialized and the _setOptions function is called. + * + * @param array $array Options for the second select element + * + * @access public + * @deprecated Deprecated since release 3.2.2 + * @return void + */ + function setSecOptions($array) + { + $this->_options[1] = $array; + + if (empty($this->_elements)) { + $this->_nbElements = 2; + $this->_createElements(); + } else { + // setDefaults has probably been called before this function + // check if all elements have been created + $totalNbElements = 2; + for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) { + $this->_elements[] = new HTML_QuickForm_select($i, null, array(), $this->getAttributes()); + $this->_nbElements++; + } + } + + $this->_setOptions(); + } // end func setSecOptions + + // }}} + // {{{ _setOptions() + + /** + * Sets the options for each select element + * + * @access private + * @return void + */ + function _setOptions() + { + $toLoad = ''; + foreach (array_keys($this->_elements) AS $key) { + $array = eval("return isset(\$this->_options[{$key}]{$toLoad})? \$this->_options[{$key}]{$toLoad}: null;"); + if (is_array($array)) { + $select =& $this->_elements[$key]; + $select->_options = array(); + $select->loadArray($array); + + $value = is_array($v = $select->getValue()) ? $v[0] : key($array); + $toLoad .= '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $value) . '\']'; + } + } + } // end func _setOptions + + // }}} + // {{{ setValue() + + /** + * Sets values for group's elements + * + * @param array $value An array of 2 or more values, for the first, + * the second, the third etc. select + * + * @access public + * @return void + */ + function setValue($value) + { + // fix for bug #6766. Hope this doesn't break anything more + // after bug #7961. Forgot that _nbElements was used in + // _createElements() called in several places... + $this->_nbElements = max($this->_nbElements, count($value)); + parent::setValue($value); + $this->_setOptions(); + } // end func setValue + + // }}} + // {{{ _createElements() + + /** + * Creates all the elements for the group + * + * @access private + * @return void + */ + function _createElements() + { + for ($i = 0; $i < $this->_nbElements; $i++) { + $this->_elements[] = new HTML_QuickForm_select($i, null, array(), $this->getAttributes()); + } + } // end func _createElements + + // }}} + // {{{ toHtml() + + function toHtml() + { + $this->_js = ''; + if (!$this->_flagFrozen) { + // set the onchange attribute for each element except last + $keys = array_keys($this->_elements); + $onChange = array(); + for ($i = 0; $i < count($keys) - 1; $i++) { + $select =& $this->_elements[$keys[$i]]; + $onChange[$i] = $select->getAttribute('onchange'); + $select->updateAttributes( + array('onchange' => '_hs_swapOptions(this.form, \'' . $this->_escapeString($this->getName()) . '\', ' . $keys[$i] . ');' . $onChange[$i]) + ); + } + + // create the js function to call + if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) { + $this->_js .= <<_nbElements; $i++) { + $jsParts[] = $this->_convertArrayToJavascript($this->_options[$i]); + } + $this->_js .= "\n_hs_options['" . $this->_escapeString($this->getName()) . "'] = [\n" . + implode(",\n", $jsParts) . + "\n];\n"; + // default value; if we don't actually have any values yet just use + // the first option (for single selects) or empty array (for multiple) + $values = array(); + foreach (array_keys($this->_elements) as $key) { + if (is_array($v = $this->_elements[$key]->getValue())) { + $values[] = count($v) > 1? $v: $v[0]; + } else { + // XXX: accessing the supposedly private _options array + $values[] = $this->_elements[$key]->getMultiple() || empty($this->_elements[$key]->_options[0])? + array(): + $this->_elements[$key]->_options[0]['attr']['value']; + } + } + $this->_js .= "_hs_defaults['" . $this->_escapeString($this->getName()) . "'] = " . + $this->_convertArrayToJavascript($values, false) . ";\n"; + } + include_once(dirname(__FILE__) . '/Renderer/Default.php'); + $renderer = new HTML_QuickForm_Renderer_Default(); + $renderer->setElementTemplate('{element}'); + parent::accept($renderer); + + if (!empty($onChange)) { + $keys = array_keys($this->_elements); + for ($i = 0; $i < count($keys) - 1; $i++) { + $this->_elements[$keys[$i]]->updateAttributes(array('onchange' => $onChange[$i])); + } + } + return (empty($this->_js)? '': "") . + $renderer->toHtml(); + } // end func toHtml + + // }}} + // {{{ accept() + + function accept(&$renderer, $required = false, $error = null) + { + $renderer->renderElement($this, $required, $error); + } // end func accept + + // }}} + // {{{ onQuickFormEvent() + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' == $event) { + // we need to call setValue() so that the secondary option + // matches the main option + return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller); + } else { + $ret = parent::onQuickFormEvent($event, $arg, $caller); + // add onreset handler to form to properly reset hierselect (see bug #2970) + if ('addElement' == $event) { + $onReset = $caller->getAttribute('onreset'); + if (strlen($onReset)) { + if (strpos($onReset, '_hs_setupOnReset')) { + $caller->updateAttributes(array('onreset' => str_replace('_hs_setupOnReset(this, [', "_hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "', ", $onReset))); + } else { + $caller->updateAttributes(array('onreset' => "var temp = function() { {$onReset} } ; if (!temp()) { return false; } ; if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } ")); + } + } else { + $caller->updateAttributes(array('onreset' => "if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } ")); + } + } + return $ret; + } + } // end func onQuickFormEvent + + // }}} + // {{{ _convertArrayToJavascript() + + /** + * Converts PHP array to its Javascript analog + * + * @access private + * @param array PHP array to convert + * @param bool Generate Javascript object literal (default, works like PHP's associative array) or array literal + * @return string Javascript representation of the value + */ + function _convertArrayToJavascript($array, $assoc = true) + { + if (!is_array($array)) { + return $this->_convertScalarToJavascript($array); + } else { + $items = array(); + foreach ($array as $key => $val) { + $item = $assoc? "'" . $this->_escapeString($key) . "': ": ''; + if (is_array($val)) { + $item .= $this->_convertArrayToJavascript($val, $assoc); + } else { + $item .= $this->_convertScalarToJavascript($val); + } + $items[] = $item; + } + } + $js = implode(', ', $items); + return $assoc? '{ ' . $js . ' }': '[' . $js . ']'; + } + + // }}} + // {{{ _convertScalarToJavascript() + + /** + * Converts PHP's scalar value to its Javascript analog + * + * @access private + * @param mixed PHP value to convert + * @return string Javascript representation of the value + */ + function _convertScalarToJavascript($val) + { + if (is_bool($val)) { + return $val ? 'true' : 'false'; + } elseif (is_int($val) || is_double($val)) { + return $val; + } elseif (is_string($val)) { + return "'" . $this->_escapeString($val) . "'"; + } elseif (is_null($val)) { + return 'null'; + } else { + // don't bother + return '{}'; + } + } + + // }}} + // {{{ _escapeString() + + /** + * Quotes the string so that it can be used in Javascript string constants + * + * @access private + * @param string + * @return string + */ + function _escapeString($str) + { + return strtr($str,array( + "\r" => '\r', + "\n" => '\n', + "\t" => '\t', + "'" => "\\'", + '"' => '\"', + '\\' => '\\\\' + )); + } + + // }}} +} // end class HTML_QuickForm_hierselect +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/html.php b/oss/piwik/trunk/libs/HTML/QuickForm/html.php new file mode 100644 index 00000000..7abc2a66 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/html.php @@ -0,0 +1,77 @@ + + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: html.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * HTML class for static data + */ +require_once dirname(__FILE__) . '/static.php'; + +/** + * A pseudo-element used for adding raw HTML to form + * + * Intended for use with the default renderer only, template-based + * ones may (and probably will) completely ignore this + * + * @category HTML + * @package HTML_QuickForm + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 3.0 + * @deprecated Please use the templates rather than add raw HTML via this element + */ +class HTML_QuickForm_html extends HTML_QuickForm_static +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $text raw HTML to add + * @access public + * @return void + */ + function HTML_QuickForm_html($text = null) + { + $this->HTML_QuickForm_static(null, null, $text); + $this->_type = 'html'; + } + + // }}} + // {{{ accept() + + /** + * Accepts a renderer + * + * @param HTML_QuickForm_Renderer renderer object (only works with Default renderer!) + * @access public + * @return void + */ + function accept(&$renderer) + { + $renderer->renderHtml($this); + } // end func accept + + // }}} + +} //end class HTML_QuickForm_html +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/image.php b/oss/piwik/trunk/libs/HTML/QuickForm/image.php new file mode 100644 index 00000000..9b093aff --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/image.php @@ -0,0 +1,127 @@ + element + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.01 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_01.txt If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: image.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for an element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_image extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Element name attribute + * @param string $src (optional)Image source + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_image($elementName=null, $src='', $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->setType('image'); + $this->setSource($src); + } // end class constructor + + // }}} + // {{{ setSource() + + /** + * Sets source for image element + * + * @param string $src source for image element + * @since 1.0 + * @access public + * @return void + */ + function setSource($src) + { + $this->updateAttributes(array('src' => $src)); + } // end func setSource + + // }}} + // {{{ setBorder() + + /** + * Sets border size for image element + * + * @param string $border border for image element + * @since 1.0 + * @access public + * @return void + */ + function setBorder($border) + { + $this->updateAttributes(array('border' => $border)); + } // end func setBorder + + // }}} + // {{{ setAlign() + + /** + * Sets alignment for image element + * + * @param string $align alignment for image element + * @since 1.0 + * @access public + * @return void + */ + function setAlign($align) + { + $this->updateAttributes(array('align' => $align)); + } // end func setAlign + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + +} // end class HTML_QuickForm_image +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/input.php b/oss/piwik/trunk/libs/HTML/QuickForm/input.php new file mode 100644 index 00000000..9c75a638 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/input.php @@ -0,0 +1,209 @@ + form elements + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.01 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_01.txt If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: input.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/element.php'; + +/** + * Base class for form elements + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + * @abstract + */ +class HTML_QuickForm_input extends HTML_QuickForm_element +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param mixed Label(s) for the input field + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_input($elementName=null, $elementLabel=null, $attributes=null) + { + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); + } //end constructor + + // }}} + // {{{ setType() + + /** + * Sets the element type + * + * @param string $type Element type + * @since 1.0 + * @access public + * @return void + */ + function setType($type) + { + $this->_type = $type; + $this->updateAttributes(array('type'=>$type)); + } // end func setType + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name'=>$name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param string $value Default value of the form element + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->updateAttributes(array('value'=>$value)); + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return string + */ + function getValue() + { + return $this->getAttribute('value'); + } // end func getValue + + // }}} + // {{{ toHtml() + + /** + * Returns the input field in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if ($this->_flagFrozen) { + return $this->getFrozenHtml(); + } else { + return $this->_getTabs() . '_getAttrString($this->_attributes) . ' />'; + } + } //end func toHtml + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + * @throws + */ + function onQuickFormEvent($event, $arg, &$caller) + { + // do not use submit values for button-type elements + $type = $this->getType(); + if (('updateValue' != $event) || + ('submit' != $type && 'reset' != $type && 'image' != $type && 'button' != $type)) { + parent::onQuickFormEvent($event, $arg, $caller); + } else { + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + if (null !== $value) { + $this->setValue($value); + } + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ exportValue() + + /** + * We don't need values from button-type elements (except submit) and files + */ + function exportValue(&$submitValues, $assoc = false) + { + $type = $this->getType(); + if ('reset' == $type || 'image' == $type || 'button' == $type || 'file' == $type) { + return null; + } else { + return parent::exportValue($submitValues, $assoc); + } + } + + // }}} +} // end class HTML_QuickForm_element +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/link.php b/oss/piwik/trunk/libs/HTML/QuickForm/link.php new file mode 100644 index 00000000..ba9be134 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/link.php @@ -0,0 +1,200 @@ + + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: link.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * HTML class for static data + */ +require_once dirname(__FILE__) . '/static.php'; + +/** + * HTML class for a link type field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 2.0 + */ +class HTML_QuickForm_link extends HTML_QuickForm_static +{ + // {{{ properties + + /** + * Link display text + * @var string + * @since 1.0 + * @access private + */ + var $_text = ""; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementLabel (optional)Link label + * @param string $href (optional)Link href + * @param string $text (optional)Link display text + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + * @throws + */ + function HTML_QuickForm_link($elementName=null, $elementLabel=null, $href=null, $text=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = false; + $this->_type = 'link'; + $this->setHref($href); + $this->_text = $text; + } //end constructor + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + * @throws + */ + function setName($name) + { + $this->updateAttributes(array('name'=>$name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets value for textarea element + * + * @param string $value Value for password element + * @since 1.0 + * @access public + * @return void + * @throws + */ + function setValue($value) + { + return; + } //end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return void + * @throws + */ + function getValue() + { + return; + } // end func getValue + + + // }}} + // {{{ setHref() + + /** + * Sets the links href + * + * @param string $href + * @since 1.0 + * @access public + * @return void + * @throws + */ + function setHref($href) + { + $this->updateAttributes(array('href'=>$href)); + } // end func setHref + + // }}} + // {{{ toHtml() + + /** + * Returns the textarea element in HTML + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function toHtml() + { + $tabs = $this->_getTabs(); + $html = "$tabs_getAttrString($this->_attributes).">"; + $html .= $this->_text; + $html .= ""; + return $html; + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags (in this case, value is changed to a mask) + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function getFrozenHtml() + { + return; + } //end func getFrozenHtml + + // }}} + +} //end class HTML_QuickForm_textarea +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/password.php b/oss/piwik/trunk/libs/HTML/QuickForm/password.php new file mode 100644 index 00000000..47b57601 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/password.php @@ -0,0 +1,115 @@ + + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: password.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for a password type field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_password extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $elementLabel (optional)Input field label + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + * @throws + */ + function HTML_QuickForm_password($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes); + $this->setType('password'); + } //end constructor + + // }}} + // {{{ setSize() + + /** + * Sets size of password element + * + * @param string $size Size of password field + * @since 1.0 + * @access public + * @return void + */ + function setSize($size) + { + $this->updateAttributes(array('size'=>$size)); + } //end func setSize + + // }}} + // {{{ setMaxlength() + + /** + * Sets maxlength of password element + * + * @param string $maxlength Maximum length of password field + * @since 1.0 + * @access public + * @return void + */ + function setMaxlength($maxlength) + { + $this->updateAttributes(array('maxlength'=>$maxlength)); + } //end func setMaxlength + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags (in this case, value is changed to a mask) + * + * @since 1.0 + * @access public + * @return string + * @throws + */ + function getFrozenHtml() + { + $value = $this->getValue(); + return ('' != $value? '**********': ' ') . + $this->_getPersistantData(); + } //end func getFrozenHtml + + // }}} + +} //end class HTML_QuickForm_password +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/radio.php b/oss/piwik/trunk/libs/HTML/QuickForm/radio.php new file mode 100644 index 00000000..be98cd1f --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/radio.php @@ -0,0 +1,251 @@ + + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: radio.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for a radio type element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_radio extends HTML_QuickForm_input +{ + // {{{ properties + + /** + * Radio display text + * @var string + * @since 1.1 + * @access private + */ + var $_text = ''; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param mixed Label(s) for a field + * @param string Text to display near the radio + * @param string Input field value + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_radio($elementName=null, $elementLabel=null, $text=null, $value=null, $attributes=null) + { + $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes); + if (isset($value)) { + $this->setValue($value); + } + $this->_persistantFreeze = true; + $this->setType('radio'); + $this->_text = $text; + $this->_generateId(); + } //end constructor + + // }}} + // {{{ setChecked() + + /** + * Sets whether radio button is checked + * + * @param bool $checked Whether the field is checked or not + * @since 1.0 + * @access public + * @return void + */ + function setChecked($checked) + { + if (!$checked) { + $this->removeAttribute('checked'); + } else { + $this->updateAttributes(array('checked'=>'checked')); + } + } //end func setChecked + + // }}} + // {{{ getChecked() + + /** + * Returns whether radio button is checked + * + * @since 1.0 + * @access public + * @return string + */ + function getChecked() + { + return $this->getAttribute('checked'); + } //end func getChecked + + // }}} + // {{{ toHtml() + + /** + * Returns the radio element in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if (0 == strlen($this->_text)) { + $label = ''; + } elseif ($this->_flagFrozen) { + $label = $this->_text; + } else { + $label = ''; + } + return HTML_QuickForm_input::toHtml() . $label; + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + if ($this->getChecked()) { + return '(x)' . + $this->_getPersistantData(); + } else { + return '( )'; + } + } //end func getFrozenHtml + + // }}} + // {{{ setText() + + /** + * Sets the radio text + * + * @param string $text Text to display near the radio button + * @since 1.1 + * @access public + * @return void + */ + function setText($text) + { + $this->_text = $text; + } //end func setText + + // }}} + // {{{ getText() + + /** + * Returns the radio text + * + * @since 1.1 + * @access public + * @return string + */ + function getText() + { + return $this->_text; + } //end func getText + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + // constant values override both default and submitted ones + // default values are overriden by submitted + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_submitValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (!is_null($value) && $value == $this->getValue()) { + $this->setChecked(true); + } else { + $this->setChecked(false); + } + break; + case 'setGroupValue': + if ($arg == $this->getValue()) { + $this->setChecked(true); + } else { + $this->setChecked(false); + } + break; + default: + parent::onQuickFormEvent($event, $arg, $caller); + } + return true; + } // end func onQuickFormLoad + + // }}} + // {{{ exportValue() + + /** + * Returns the value attribute if the radio is checked, null if it is not + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (null === $value) { + $value = $this->getChecked()? $this->getValue(): null; + } elseif ($value != $this->getValue()) { + $value = null; + } + return $this->_prepareValue($value, $assoc); + } + + // }}} +} //end class HTML_QuickForm_radio +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/reset.php b/oss/piwik/trunk/libs/HTML/QuickForm/reset.php new file mode 100644 index 00000000..766398d0 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/reset.php @@ -0,0 +1,79 @@ + + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: reset.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for a reset type element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_reset extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $value (optional)Input field value + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_reset($elementName=null, $value=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->setValue($value); + $this->setType('reset'); + } //end constructor + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + +} //end class HTML_QuickForm_reset +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/select.php b/oss/piwik/trunk/libs/HTML/QuickForm/select.php new file mode 100644 index 00000000..b80adccd --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/select.php @@ -0,0 +1,719 @@ + + * @author Bertrand Mansion + * @author Alexey Borzov + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: select.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/element.php'; + +/** + * Class to dynamically create an HTML SELECT + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @author Alexey Borzov + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_select extends HTML_QuickForm_element { + + // {{{ properties + + /** + * Contains the select options + * + * @var array + * @since 1.0 + * @access private + */ + var $_options = array(); + + /** + * Default values of the SELECT + * + * @var string + * @since 1.0 + * @access private + */ + var $_values = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Select name attribute + * @param mixed Label(s) for the select + * @param mixed Data to be used to populate options + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_select($elementName=null, $elementLabel=null, $options=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_type = 'select'; + if (isset($options)) { + $this->load($options); + } + } //end constructor + + // }}} + // {{{ apiVersion() + + /** + * Returns the current API version + * + * @since 1.0 + * @access public + * @return double + */ + function apiVersion() + { + return 2.3; + } //end func apiVersion + + // }}} + // {{{ setSelected() + + /** + * Sets the default values of the select box + * + * @param mixed $values Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return void + */ + function setSelected($values) + { + if (is_string($values) && $this->getMultiple()) { + $values = preg_split('/[ ]*,[ ]*/', $values); + } + if (is_array($values)) { + $this->_values = array_values($values); + } else { + $this->_values = array($values); + } + } //end func setSelected + + // }}} + // {{{ getSelected() + + /** + * Returns an array of the selected values + * + * @since 1.0 + * @access public + * @return array of selected values + */ + function getSelected() + { + return $this->_values; + } // end func getSelected + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name' => $name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ getPrivateName() + + /** + * Returns the element name (possibly with brackets appended) + * + * @since 1.0 + * @access public + * @return string + */ + function getPrivateName() + { + if ($this->getAttribute('multiple')) { + return $this->getName() . '[]'; + } else { + return $this->getName(); + } + } //end func getPrivateName + + // }}} + // {{{ setValue() + + /** + * Sets the value of the form element + * + * @param mixed $values Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->setSelected($value); + } // end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns an array of the selected values + * + * @since 1.0 + * @access public + * @return array of selected values + */ + function getValue() + { + return $this->_values; + } // end func getValue + + // }}} + // {{{ setSize() + + /** + * Sets the select field size, only applies to 'multiple' selects + * + * @param int $size Size of select field + * @since 1.0 + * @access public + * @return void + */ + function setSize($size) + { + $this->updateAttributes(array('size' => $size)); + } //end func setSize + + // }}} + // {{{ getSize() + + /** + * Returns the select field size + * + * @since 1.0 + * @access public + * @return int + */ + function getSize() + { + return $this->getAttribute('size'); + } //end func getSize + + // }}} + // {{{ setMultiple() + + /** + * Sets the select mutiple attribute + * + * @param bool $multiple Whether the select supports multi-selections + * @since 1.2 + * @access public + * @return void + */ + function setMultiple($multiple) + { + if ($multiple) { + $this->updateAttributes(array('multiple' => 'multiple')); + } else { + $this->removeAttribute('multiple'); + } + } //end func setMultiple + + // }}} + // {{{ getMultiple() + + /** + * Returns the select mutiple attribute + * + * @since 1.2 + * @access public + * @return bool true if multiple select, false otherwise + */ + function getMultiple() + { + return (bool)$this->getAttribute('multiple'); + } //end func getMultiple + + // }}} + // {{{ addOption() + + /** + * Adds a new OPTION to the SELECT + * + * @param string $text Display text for the OPTION + * @param string $value Value for the OPTION + * @param mixed $attributes Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + + // CLY - modification to allow optgroups + // function addOption($text, $value, $attributes=null) + function addOption($text, $value, $attributes=null, &$optGroup=null) { + // if text is an array, start an optgroup + if (is_array($text)) { + if (is_array($optGroup)) { + $optGroup[$value]['options'] = array(); + $optGroup =& $optGroup[$value]['options']; + } + else { + $this->_options[$value]['options'] = array(); + $optGroup =& $this->_options[$value]['options']; + }; + foreach($text as $key=>$val) { + $this->addOption($val, $key, null, $optGroup); + } + // done all the options in the optgroup + return; + } + // end mod + if (null === $attributes) { + $attributes = array('value' => (string)$value); + } else { + $attributes = $this->_parseAttributes($attributes); + if (isset($attributes['selected'])) { + // the 'selected' attribute will be set in toHtml() + $this->_removeAttr('selected', $attributes); + if (is_null($this->_values)) { + $this->_values = array($value); + } elseif (!in_array($value, $this->_values)) { + $this->_values[] = $value; + } + } + $this->_updateAttrArray($attributes, array('value' => (string)$value)); + } + // CLY - modification to allow optgroups + // if $optGroup is an array, add the option to it + if (is_array($optGroup)) { + $optGroup[$text]['attr'] = $attributes; + } + // if $optGroup is a string, add the option to the option group + // used if directly adding an option to an optgroup + elseif (is_string($optGroup)) { + $optGroups = explode($optGroup, ','); + $target =& $this->_options; + foreach($optGroups as $group) { + // create the option group if it does not exist + if (empty($target[$group]['options'])) { + $target[$group]['options'] = array(); + } + $target =& $target[$group]['options']; + } + // foreach + // add the option + $target[$text]['attr'] = $attributes; + } + // else if there are attributes, add them to the option + elseif (is_array($attributes)) { + $this->_options[$text]['attr'] = $attributes; + } + // $this->_options[] = array('text' => $text, 'attr' => $attributes); + // end mod + } // end func addOption + + // }}} + // {{{ loadArray() + + /** + * Loads the options from an associative array + * + * @param array $arr Associative array of options + * @param mixed $values (optional) Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return PEAR_Error on error or true + * @throws PEAR_Error + */ + function loadArray($arr, $values=null) + { + if (!is_array($arr)) { + return PEAR::raiseError('Argument 1 of HTML_Select::loadArray is not a valid array'); + } + if (isset($values)) { + $this->setSelected($values); + } + foreach ($arr as $key => $val) { + // Warning: new API since release 2.3 + $this->addOption($val, $key); + } + return true; + } // end func loadArray + + // }}} + // {{{ loadDbResult() + + /** + * Loads the options from DB_result object + * + * If no column names are specified the first two columns of the result are + * used as the text and value columns respectively + * @param object $result DB_result object + * @param string $textCol (optional) Name of column to display as the OPTION text + * @param string $valueCol (optional) Name of column to use as the OPTION value + * @param mixed $values (optional) Array or comma delimited string of selected values + * @since 1.0 + * @access public + * @return PEAR_Error on error or true + * @throws PEAR_Error + */ + function loadDbResult(&$result, $textCol=null, $valueCol=null, $values=null) + { + if (!is_object($result) || !is_a($result, 'db_result')) { + return PEAR::raiseError('Argument 1 of HTML_Select::loadDbResult is not a valid DB_result'); + } + if (isset($values)) { + $this->setValue($values); + } + $fetchMode = ($textCol && $valueCol) ? DB_FETCHMODE_ASSOC : DB_FETCHMODE_ORDERED; + while (is_array($row = $result->fetchRow($fetchMode)) ) { + if ($fetchMode == DB_FETCHMODE_ASSOC) { + $this->addOption($row[$textCol], $row[$valueCol]); + } else { + $this->addOption($row[0], $row[1]); + } + } + return true; + } // end func loadDbResult + + // }}} + // {{{ loadQuery() + + /** + * Queries a database and loads the options from the results + * + * @param mixed $conn Either an existing DB connection or a valid dsn + * @param string $sql SQL query string + * @param string $textCol (optional) Name of column to display as the OPTION text + * @param string $valueCol (optional) Name of column to use as the OPTION value + * @param mixed $values (optional) Array or comma delimited string of selected values + * @since 1.1 + * @access public + * @return void + * @throws PEAR_Error + */ + function loadQuery(&$conn, $sql, $textCol=null, $valueCol=null, $values=null) + { + if (is_string($conn)) { + require_once(dirname(__FILE__) . '/../../DB.php'); + $dbConn = &DB::connect($conn, true); + if (DB::isError($dbConn)) { + return $dbConn; + } + } elseif (is_subclass_of($conn, "db_common")) { + $dbConn = &$conn; + } else { + return PEAR::raiseError('Argument 1 of HTML_Select::loadQuery is not a valid type'); + } + $result = $dbConn->query($sql); + if (DB::isError($result)) { + return $result; + } + $this->loadDbResult($result, $textCol, $valueCol, $values); + $result->free(); + if (is_string($conn)) { + $dbConn->disconnect(); + } + return true; + } // end func loadQuery + + // }}} + // {{{ load() + + /** + * Loads options from different types of data sources + * + * This method is a simulated overloaded method. The arguments, other than the + * first are optional and only mean something depending on the type of the first argument. + * If the first argument is an array then all arguments are passed in order to loadArray. + * If the first argument is a db_result then all arguments are passed in order to loadDbResult. + * If the first argument is a string or a DB connection then all arguments are + * passed in order to loadQuery. + * @param mixed $options Options source currently supports assoc array or DB_result + * @param mixed $param1 (optional) See function detail + * @param mixed $param2 (optional) See function detail + * @param mixed $param3 (optional) See function detail + * @param mixed $param4 (optional) See function detail + * @since 1.1 + * @access public + * @return PEAR_Error on error or true + * @throws PEAR_Error + */ + function load(&$options, $param1=null, $param2=null, $param3=null, $param4=null) + { + switch (true) { + case is_array($options): + return $this->loadArray($options, $param1); + break; + case (is_a($options, 'db_result')): + return $this->loadDbResult($options, $param1, $param2, $param3); + break; + case (is_string($options) && !empty($options) || is_subclass_of($options, "db_common")): + return $this->loadQuery($options, $param1, $param2, $param3, $param4); + break; + } + } // end func load + + // }}} + // {{{ toHtml() + + /** + * Returns the SELECT in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if ($this->_flagFrozen) { + return $this->getFrozenHtml(); + } else { + $tabs = $this->_getTabs(); + $strHtml = ''; + + if ($this->getComment() != '') { + $strHtml .= $tabs . '\n"; + } + + if (!$this->getMultiple()) { + $attrString = $this->_getAttrString($this->_attributes); + } else { + $myName = $this->getName(); + $this->setName($myName . '[]'); + $attrString = $this->_getAttrString($this->_attributes); + $this->setName($myName); + } + $strHtml .= $tabs . '\n"; + + // CLY - modified to allow optgroups + foreach ($this->_options as $text=>$option) { + $strHtml .= $tabs . $this->_optionToHtml($text, $option); + } + /* $strValues = is_array($this->_values)? array_map('strval', $this->_values): array(); + foreach ($this->_options as $option) { + if (!empty($strValues) && in_array($option['attr']['value'], $strValues, true)) { + $option['attr']['selected'] = 'selected'; + } + $strHtml .= $tabs . "\t_getAttrString($option['attr']) . '>' . + $option['text'] . "\n"; + } + */ + // end mod + return $strHtml . $tabs . ''; + } + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + +// CLY - new function to allow optgroups + /** + * Returns an OPTION in HTML + * + * This function is called recursively to support optgroups + * + * @param string $text Display text for the option + * @param array $option The option + * @since ?? + * @access private + * @return string + */ + // Creates the HTML for an option + function _optionToHtml($text, $option) + { + $tabs = $this->_getTabs(); + // if an option has options it's an optgroup + if (isset($option['options'])) { + $strHtml = $tabs . "\n"; + foreach($option['options'] as $txt=>$opt) { + $strHtml .= $tabs . $this->_optionToHtml($txt, $opt); + } + $strHtml .= $tabs . "\n"; + return($strHtml); + } + // else it's an option + else { + if (is_array($this->_values) && in_array((string)$option['attr']['value'], $this->_values)) { + $this->_updateAttrArray($option['attr'], array('selected' => 'selected')); + } + return("\t_getAttrString($option['attr']) . ">$text\n"); + } + } + + /** + * Returns the value of field without HTML tags + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + $value = array(); + if (is_array($this->_values)) { + foreach ($this->_values as $key => $val) { + for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) { + if (0 == strcmp($val, $this->_options[$i]['attr']['value'])) { + $value[$key] = $this->_options[$i]['text']; + break; + } + } + } + } + $html = empty($value)? ' ': join('
', $value); + if ($this->_persistantFreeze) { + $name = $this->getPrivateName(); + // Only use id attribute if doing single hidden input + if (1 == count($value)) { + $id = $this->getAttribute('id'); + $idAttr = isset($id)? array('id' => $id): array(); + } else { + $idAttr = array(); + } + foreach ($value as $key => $item) { + $html .= '_getAttrString(array( + 'type' => 'hidden', + 'name' => $name, + 'value' => $this->_values[$key] + ) + $idAttr) . ' />'; + } + } + return $html; + } //end func getFrozenHtml + + // }}} + // {{{ exportValue() + + /** + * We check the options and return only the values that _could_ have been + * selected. We also return a scalar value if select is not "multiple" + */ + function exportValue(&$submitValues, $assoc = false) + { + $value = $this->_findValue($submitValues); + if (is_null($value)) { + $value = $this->getValue(); + } elseif(!is_array($value)) { + $value = array($value); + } + if (is_array($value) && !empty($this->_options)) { + $cleanValue = null; + foreach ($value as $v) { + // CLY - modified to allow optgroups + if ($this->_isInOptGroup($v, $this->_options)) { + $cleanValue[] = $v; + } +// for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) { +// if (0 == strcmp($v, $this->_options[$i]['attr']['value'])) { +// $cleanValue[] = $v; +// break; +// } +// } + // end mod + } + } else { + $cleanValue = $value; + } + if (is_array($cleanValue) && !$this->getMultiple()) { + return $this->_prepareValue($cleanValue[0], $assoc); + } else { + return $this->_prepareValue($cleanValue, $assoc); + } + } + + // }}} + // {{{ onQuickFormEvent() + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' == $event) { + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_submitValues); + // Fix for bug #4465 & #5269 + // XXX: should we push this to element::onQuickFormEvent()? + if (null === $value && (!$caller->isSubmitted() || !$this->getMultiple())) { + $value = $this->_findValue($caller->_defaultValues); + } + } + if (null !== $value) { + $this->setValue($value); + } + return true; + } else { + return parent::onQuickFormEvent($event, $arg, $caller); + } + } + + function _isInOptGroup($v, $opts) { + $isInOptGroup = false; + foreach ($opts as $opt) { + if (isset($opt['options'])) { + $isInOptGroup = $this->_isInOptGroup($v, $opt['options']); + } + else { + if ($v == $opt['attr']['value']) { + $isInOptGroup = true; + } + } + if ($isInOptGroup) break; + } + return $isInOptGroup; + } + + // }}} +} //end class HTML_QuickForm_select +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/static.php b/oss/piwik/trunk/libs/HTML/QuickForm/static.php new file mode 100644 index 00000000..8f116e13 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/static.php @@ -0,0 +1,201 @@ + + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: static.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/element.php'; + +/** + * HTML class for static data + * + * @category HTML + * @package HTML_QuickForm + * @author Wojciech Gdela + * @version Release: 3.2.11 + * @since 2.7 + */ +class HTML_QuickForm_static extends HTML_QuickForm_element { + + // {{{ properties + + /** + * Display text + * @var string + * @access private + */ + var $_text = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementLabel (optional)Label + * @param string $text (optional)Display text + * @access public + * @return void + */ + function HTML_QuickForm_static($elementName=null, $elementLabel=null, $text=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel); + $this->_persistantFreeze = false; + $this->_type = 'static'; + $this->_text = $text; + } //end constructor + + // }}} + // {{{ setName() + + /** + * Sets the element name + * + * @param string $name Element name + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name'=>$name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ setText() + + /** + * Sets the text + * + * @param string $text + * @access public + * @return void + */ + function setText($text) + { + $this->_text = $text; + } // end func setText + + // }}} + // {{{ setValue() + + /** + * Sets the text (uses the standard setValue call to emulate a form element. + * + * @param string $text + * @access public + * @return void + */ + function setValue($text) + { + $this->setText($text); + } // end func setValue + + // }}} + // {{{ toHtml() + + /** + * Returns the static text element in HTML + * + * @access public + * @return string + */ + function toHtml() + { + return $this->_getTabs() . $this->_text; + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags + * + * @access public + * @return string + */ + function getFrozenHtml() + { + return $this->toHtml(); + } //end func getFrozenHtml + + // }}} + // {{{ onQuickFormEvent() + + /** + * Called by HTML_QuickForm whenever form event is made on this element + * + * @param string $event Name of event + * @param mixed $arg event arguments + * @param object &$caller calling object + * @since 1.0 + * @access public + * @return void + * @throws + */ + function onQuickFormEvent($event, $arg, &$caller) + { + switch ($event) { + case 'updateValue': + // do NOT use submitted values for static elements + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + if (null !== $value) { + $this->setValue($value); + } + break; + default: + parent::onQuickFormEvent($event, $arg, $caller); + } + return true; + } // end func onQuickFormEvent + + // }}} + // {{{ exportValue() + + /** + * We override this here because we don't want any values from static elements + */ + function exportValue(&$submitValues, $assoc = false) + { + return null; + } + + // }}} +} //end class HTML_QuickForm_static +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/submit.php b/oss/piwik/trunk/libs/HTML/QuickForm/submit.php new file mode 100644 index 00000000..45bae9e3 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/submit.php @@ -0,0 +1,89 @@ + + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: submit.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for a submit type element + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_submit extends HTML_QuickForm_input +{ + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param string Input field value + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_submit($elementName=null, $value=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, null, $attributes); + $this->setValue($value); + $this->setType('submit'); + } //end constructor + + // }}} + // {{{ freeze() + + /** + * Freeze the element so that only its value is returned + * + * @access public + * @return void + */ + function freeze() + { + return false; + } //end func freeze + + // }}} + // {{{ exportValue() + + /** + * Only return the value if it is found within $submitValues (i.e. if + * this particular submit button was clicked) + */ + function exportValue(&$submitValues, $assoc = false) + { + return $this->_prepareValue($this->_findValue($submitValues), $assoc); + } + + // }}} +} //end class HTML_QuickForm_submit +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/text.php b/oss/piwik/trunk/libs/HTML/QuickForm/text.php new file mode 100644 index 00000000..59b8ac4e --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/text.php @@ -0,0 +1,98 @@ + + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: text.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/input.php'; + +/** + * HTML class for a text field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_text extends HTML_QuickForm_input +{ + + // {{{ constructor + + /** + * Class constructor + * + * @param string $elementName (optional)Input field name attribute + * @param string $elementLabel (optional)Input field label + * @param mixed $attributes (optional)Either a typical HTML attribute string + * or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_text($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_QuickForm_input::HTML_QuickForm_input($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->setType('text'); + } //end constructor + + // }}} + // {{{ setSize() + + /** + * Sets size of text field + * + * @param string $size Size of text field + * @since 1.3 + * @access public + * @return void + */ + function setSize($size) + { + $this->updateAttributes(array('size'=>$size)); + } //end func setSize + + // }}} + // {{{ setMaxlength() + + /** + * Sets maxlength of text field + * + * @param string $maxlength Maximum length of text field + * @since 1.3 + * @access public + * @return void + */ + function setMaxlength($maxlength) + { + $this->updateAttributes(array('maxlength'=>$maxlength)); + } //end func setMaxlength + + // }}} + +} //end class HTML_QuickForm_text +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/textarea.php b/oss/piwik/trunk/libs/HTML/QuickForm/textarea.php new file mode 100644 index 00000000..baa672d3 --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/textarea.php @@ -0,0 +1,229 @@ + + * @author Bertrand Mansion + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: textarea.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/element.php'; + +/** + * HTML class for a textarea type field + * + * @category HTML + * @package HTML_QuickForm + * @author Adam Daniel + * @author Bertrand Mansion + * @version Release: 3.2.11 + * @since 1.0 + */ +class HTML_QuickForm_textarea extends HTML_QuickForm_element +{ + // {{{ properties + + /** + * Field value + * @var string + * @since 1.0 + * @access private + */ + var $_value = null; + + // }}} + // {{{ constructor + + /** + * Class constructor + * + * @param string Input field name attribute + * @param mixed Label(s) for a field + * @param mixed Either a typical HTML attribute string or an associative array + * @since 1.0 + * @access public + * @return void + */ + function HTML_QuickForm_textarea($elementName=null, $elementLabel=null, $attributes=null) + { + HTML_QuickForm_element::HTML_QuickForm_element($elementName, $elementLabel, $attributes); + $this->_persistantFreeze = true; + $this->_type = 'textarea'; + } //end constructor + + // }}} + // {{{ setName() + + /** + * Sets the input field name + * + * @param string $name Input field name attribute + * @since 1.0 + * @access public + * @return void + */ + function setName($name) + { + $this->updateAttributes(array('name'=>$name)); + } //end func setName + + // }}} + // {{{ getName() + + /** + * Returns the element name + * + * @since 1.0 + * @access public + * @return string + */ + function getName() + { + return $this->getAttribute('name'); + } //end func getName + + // }}} + // {{{ setValue() + + /** + * Sets value for textarea element + * + * @param string $value Value for textarea element + * @since 1.0 + * @access public + * @return void + */ + function setValue($value) + { + $this->_value = $value; + } //end func setValue + + // }}} + // {{{ getValue() + + /** + * Returns the value of the form element + * + * @since 1.0 + * @access public + * @return string + */ + function getValue() + { + return $this->_value; + } // end func getValue + + // }}} + // {{{ setWrap() + + /** + * Sets wrap type for textarea element + * + * @param string $wrap Wrap type + * @since 1.0 + * @access public + * @return void + */ + function setWrap($wrap) + { + $this->updateAttributes(array('wrap' => $wrap)); + } //end func setWrap + + // }}} + // {{{ setRows() + + /** + * Sets height in rows for textarea element + * + * @param string $rows Height expressed in rows + * @since 1.0 + * @access public + * @return void + */ + function setRows($rows) + { + $this->updateAttributes(array('rows' => $rows)); + } //end func setRows + + // }}} + // {{{ setCols() + + /** + * Sets width in cols for textarea element + * + * @param string $cols Width expressed in cols + * @since 1.0 + * @access public + * @return void + */ + function setCols($cols) + { + $this->updateAttributes(array('cols' => $cols)); + } //end func setCols + + // }}} + // {{{ toHtml() + + /** + * Returns the textarea element in HTML + * + * @since 1.0 + * @access public + * @return string + */ + function toHtml() + { + if ($this->_flagFrozen) { + return $this->getFrozenHtml(); + } else { + return $this->_getTabs() . + '_getAttrString($this->_attributes) . '>' . + // because we wrap the form later we don't want the text indented + preg_replace("/(\r\n|\n|\r)/", ' ', htmlspecialchars($this->_value)) . + ''; + } + } //end func toHtml + + // }}} + // {{{ getFrozenHtml() + + /** + * Returns the value of field without HTML tags (in this case, value is changed to a mask) + * + * @since 1.0 + * @access public + * @return string + */ + function getFrozenHtml() + { + $value = htmlspecialchars($this->getValue()); + if ($this->getAttribute('wrap') == 'off') { + $html = $this->_getTabs() . '
' . $value."
\n"; + } else { + $html = nl2br($value)."\n"; + } + return $html . $this->_getPersistantData(); + } //end func getFrozenHtml + + // }}} + +} //end class HTML_QuickForm_textarea +?> diff --git a/oss/piwik/trunk/libs/HTML/QuickForm/xbutton.php b/oss/piwik/trunk/libs/HTML/QuickForm/xbutton.php new file mode 100644 index 00000000..407da7cc --- /dev/null +++ b/oss/piwik/trunk/libs/HTML/QuickForm/xbutton.php @@ -0,0 +1,153 @@ + element + * + * PHP versions 4 and 5 + * + * LICENSE: This source file is subject to version 3.01 of the PHP license + * that is available through the world-wide-web at the following URI: + * http://www.php.net/license/3_01.txt If you did not receive a copy of + * the PHP License and are unable to obtain it through the web, please + * send a note to license@php.net so we can mail you a copy immediately. + * + * @category HTML + * @package HTML_QuickForm + * @author Alexey Borzov + * @copyright 2001-2009 The PHP Group + * @license http://www.php.net/license/3_01.txt PHP License 3.01 + * @version CVS: $Id: xbutton.php 2118 2010-04-24 06:02:35Z vipsoft $ + * @link http://pear.php.net/package/HTML_QuickForm + */ + +/** + * Base class for form elements + */ +require_once dirname(__FILE__) . '/element.php'; + +/** + * Class for HTML 4.0 tags) + * @param mixed Either a typical HTML attribute string or an associative array + * @access public + */ + function HTML_QuickForm_xbutton($elementName = null, $elementContent = null, $attributes = null) + { + $this->HTML_QuickForm_element($elementName, null, $attributes); + $this->setContent($elementContent); + $this->setPersistantFreeze(false); + $this->_type = 'xbutton'; + } + + + function toHtml() + { + return 'getAttributes(true) . '>' . $this->_content . ''; + } + + + function getFrozenHtml() + { + return $this->toHtml(); + } + + + function freeze() + { + return false; + } + + + function setName($name) + { + $this->updateAttributes(array( + 'name' => $name + )); + } + + + function getName() + { + return $this->getAttribute('name'); + } + + + function setValue($value) + { + $this->updateAttributes(array( + 'value' => $value + )); + } + + + function getValue() + { + return $this->getAttribute('value'); + } + + + /** + * Sets the contents of the button element + * + * @param string Button content (HTML to add between tags) + */ + function setContent($content) + { + $this->_content = $content; + } + + + function onQuickFormEvent($event, $arg, &$caller) + { + if ('updateValue' != $event) { + return parent::onQuickFormEvent($event, $arg, $caller); + } else { + $value = $this->_findValue($caller->_constantValues); + if (null === $value) { + $value = $this->_findValue($caller->_defaultValues); + } + if (null !== $value) { + $this->setValue($value); + } + } + return true; + } + + + /** + * Returns a 'safe' element's value + * + * The value is only returned if the button's type is "submit" and if this + * particlular button was clicked + */ + function exportValue(&$submitValues, $assoc = false) + { + if ('submit' == $this->getAttribute('type')) { + return $this->_prepareValue($this->_findValue($submitValues), $assoc); + } else { + return null; + } + } +} +?> diff --git a/oss/piwik/trunk/libs/Zend/Loader/Autoloader.php b/oss/piwik/trunk/libs/Zend/Loader/Autoloader.php new file mode 100644 index 00000000..11ddf6ec --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Loader/Autoloader.php @@ -0,0 +1,584 @@ + true, + 'ZendX_' => true, + ); + + /** + * @var array Namespace-specific autoloaders + */ + protected $_namespaceAutoloaders = array(); + + /** + * @var bool Whether or not to suppress file not found warnings + */ + protected $_suppressNotFoundWarnings = false; + + /** + * @var null|string + */ + protected $_zfPath; + + /** + * Retrieve singleton instance + * + * @return Zend_Loader_Autoloader + */ + public static function getInstance() + { + if (null === self::$_instance) { + self::$_instance = new self(); + } + return self::$_instance; + } + + /** + * Reset the singleton instance + * + * @return void + */ + public static function resetInstance() + { + self::$_instance = null; + } + + /** + * Autoload a class + * + * @param string $class + * @return bool + */ + public static function autoload($class) + { + $self = self::getInstance(); + + foreach ($self->getClassAutoloaders($class) as $autoloader) { + if ($autoloader instanceof Zend_Loader_Autoloader_Interface) { + if ($autoloader->autoload($class)) { + return true; + } + } elseif (is_string($autoloader)) { + if ($autoloader($class)) { + return true; + } + } elseif (is_array($autoloader)) { + $object = array_shift($autoloader); + $method = array_shift($autoloader); + if (call_user_func(array($object, $method), $class)) { + return true; + } + } + } + + return false; + } + + /** + * Set the default autoloader implementation + * + * @param string|array $callback PHP callback + * @return void + */ + public function setDefaultAutoloader($callback) + { + if (!is_callable($callback)) { + throw new Zend_Loader_Exception('Invalid callback specified for default autoloader'); + } + + $this->_defaultAutoloader = $callback; + return $this; + } + + /** + * Retrieve the default autoloader callback + * + * @return string|array PHP Callback + */ + public function getDefaultAutoloader() + { + return $this->_defaultAutoloader; + } + + /** + * Set several autoloader callbacks at once + * + * @param array $autoloaders Array of PHP callbacks (or Zend_Loader_Autoloader_Interface implementations) to act as autoloaders + * @return Zend_Loader_Autoloader + */ + public function setAutoloaders(array $autoloaders) + { + $this->_autoloaders = $autoloaders; + return $this; + } + + /** + * Get attached autoloader implementations + * + * @return array + */ + public function getAutoloaders() + { + return $this->_autoloaders; + } + + /** + * Return all autoloaders for a given namespace + * + * @param string $namespace + * @return array + */ + public function getNamespaceAutoloaders($namespace) + { + $namespace = (string) $namespace; + if (!array_key_exists($namespace, $this->_namespaceAutoloaders)) { + return array(); + } + return $this->_namespaceAutoloaders[$namespace]; + } + + /** + * Register a namespace to autoload + * + * @param string|array $namespace + * @return Zend_Loader_Autoloader + */ + public function registerNamespace($namespace) + { + if (is_string($namespace)) { + $namespace = (array) $namespace; + } elseif (!is_array($namespace)) { + throw new Zend_Loader_Exception('Invalid namespace provided'); + } + + foreach ($namespace as $ns) { + if (!isset($this->_namespaces[$ns])) { + $this->_namespaces[$ns] = true; + } + } + return $this; + } + + /** + * Unload a registered autoload namespace + * + * @param string|array $namespace + * @return Zend_Loader_Autoloader + */ + public function unregisterNamespace($namespace) + { + if (is_string($namespace)) { + $namespace = (array) $namespace; + } elseif (!is_array($namespace)) { + throw new Zend_Loader_Exception('Invalid namespace provided'); + } + + foreach ($namespace as $ns) { + if (isset($this->_namespaces[$ns])) { + unset($this->_namespaces[$ns]); + } + } + return $this; + } + + /** + * Get a list of registered autoload namespaces + * + * @return array + */ + public function getRegisteredNamespaces() + { + return array_keys($this->_namespaces); + } + + public function setZfPath($spec, $version = 'latest') + { + $path = $spec; + if (is_array($spec)) { + if (!isset($spec['path'])) { + throw new Zend_Loader_Exception('No path specified for ZF'); + } + $path = $spec['path']; + if (isset($spec['version'])) { + $version = $spec['version']; + } + } + + $this->_zfPath = $this->_getVersionPath($path, $version); + set_include_path(implode(PATH_SEPARATOR, array( + $this->_zfPath, + get_include_path(), + ))); + return $this; + } + + public function getZfPath() + { + return $this->_zfPath; + } + + /** + * Get or set the value of the "suppress not found warnings" flag + * + * @param null|bool $flag + * @return bool|Zend_Loader_Autoloader Returns boolean if no argument is passed, object instance otherwise + */ + public function suppressNotFoundWarnings($flag = null) + { + if (null === $flag) { + return $this->_suppressNotFoundWarnings; + } + $this->_suppressNotFoundWarnings = (bool) $flag; + return $this; + } + + /** + * Indicate whether or not this autoloader should be a fallback autoloader + * + * @param bool $flag + * @return Zend_Loader_Autoloader + */ + public function setFallbackAutoloader($flag) + { + $this->_fallbackAutoloader = (bool) $flag; + return $this; + } + + /** + * Is this instance acting as a fallback autoloader? + * + * @return bool + */ + public function isFallbackAutoloader() + { + return $this->_fallbackAutoloader; + } + + /** + * Get autoloaders to use when matching class + * + * Determines if the class matches a registered namespace, and, if so, + * returns only the autoloaders for that namespace. Otherwise, it returns + * all non-namespaced autoloaders. + * + * @param string $class + * @return array Array of autoloaders to use + */ + public function getClassAutoloaders($class) + { + $namespace = false; + $autoloaders = array(); + + // Add concrete namespaced autoloaders + foreach (array_keys($this->_namespaceAutoloaders) as $ns) { + if ('' == $ns) { + continue; + } + if (0 === strpos($class, $ns)) { + $namespace = $ns; + $autoloaders = $autoloaders + $this->getNamespaceAutoloaders($ns); + break; + } + } + + // Add internal namespaced autoloader + foreach ($this->getRegisteredNamespaces() as $ns) { + if (0 === strpos($class, $ns)) { + $namespace = $ns; + $autoloaders[] = $this->_internalAutoloader; + break; + } + } + + // Add non-namespaced autoloaders + $autoloaders = $autoloaders + $this->getNamespaceAutoloaders(''); + + // Add fallback autoloader + if (!$namespace && $this->isFallbackAutoloader()) { + $autoloaders[] = $this->_internalAutoloader; + } + + return $autoloaders; + } + + /** + * Add an autoloader to the beginning of the stack + * + * @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation + * @param string|array $namespace Specific namespace(s) under which to register callback + * @return Zend_Loader_Autoloader + */ + public function unshiftAutoloader($callback, $namespace = '') + { + $autoloaders = $this->getAutoloaders(); + array_unshift($autoloaders, $callback); + $this->setAutoloaders($autoloaders); + + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + array_unshift($autoloaders, $callback); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + + return $this; + } + + /** + * Append an autoloader to the autoloader stack + * + * @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation + * @param string|array $namespace Specific namespace(s) under which to register callback + * @return Zend_Loader_Autoloader + */ + public function pushAutoloader($callback, $namespace = '') + { + $autoloaders = $this->getAutoloaders(); + array_push($autoloaders, $callback); + $this->setAutoloaders($autoloaders); + + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + array_push($autoloaders, $callback); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + + return $this; + } + + /** + * Remove an autoloader from the autoloader stack + * + * @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation + * @param null|string|array $namespace Specific namespace(s) from which to remove autoloader + * @return Zend_Loader_Autoloader + */ + public function removeAutoloader($callback, $namespace = null) + { + if (null === $namespace) { + $autoloaders = $this->getAutoloaders(); + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->setAutoloaders($autoloaders); + } + + foreach ($this->_namespaceAutoloaders as $ns => $autoloaders) { + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + } + } else { + $namespace = (array) $namespace; + foreach ($namespace as $ns) { + $autoloaders = $this->getNamespaceAutoloaders($ns); + if (false !== ($index = array_search($callback, $autoloaders, true))) { + unset($autoloaders[$index]); + $this->_setNamespaceAutoloaders($autoloaders, $ns); + } + } + } + + return $this; + } + + /** + * Constructor + * + * Registers instance with spl_autoload stack + * + * @return void + */ + protected function __construct() + { + spl_autoload_register(array(__CLASS__, 'autoload')); + $this->_internalAutoloader = array($this, '_autoload'); + } + + /** + * Internal autoloader implementation + * + * @param string $class + * @return bool + */ + protected function _autoload($class) + { + $callback = $this->getDefaultAutoloader(); + try { + if ($this->suppressNotFoundWarnings()) { + @call_user_func($callback, $class); + } else { + call_user_func($callback, $class); + } + return $class; + } catch (Zend_Exception $e) { + return false; + } + } + + /** + * Set autoloaders for a specific namespace + * + * @param array $autoloaders + * @param string $namespace + * @return Zend_Loader_Autoloader + */ + protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '') + { + $namespace = (string) $namespace; + $this->_namespaceAutoloaders[$namespace] = $autoloaders; + return $this; + } + + /** + * Retrieve the filesystem path for the requested ZF version + * + * @param string $path + * @param string $version + * @return void + */ + protected function _getVersionPath($path, $version) + { + $type = $this->_getVersionType($version); + + if ($type == 'latest') { + $version = 'latest'; + } + + $availableVersions = $this->_getAvailableVersions($path, $version); + if (empty($availableVersions)) { + throw new Zend_Loader_Exception('No valid ZF installations discovered'); + } + + $matchedVersion = array_pop($availableVersions); + return $matchedVersion; + } + + /** + * Retrieve the ZF version type + * + * @param string $version + * @return string "latest", "major", "minor", or "specific" + * @throws Zend_Loader_Exception if version string contains too many dots + */ + protected function _getVersionType($version) + { + if (strtolower($version) == 'latest') { + return 'latest'; + } + + $parts = explode('.', $version); + $count = count($parts); + if (1 == $count) { + return 'major'; + } + if (2 == $count) { + return 'minor'; + } + if (3 < $count) { + throw new Zend_Loader_Exception('Invalid version string provided'); + } + return 'specific'; + } + + /** + * Get available versions for the version type requested + * + * @param string $path + * @param string $version + * @return array + */ + protected function _getAvailableVersions($path, $version) + { + if (!is_dir($path)) { + throw new Zend_Loader_Exception('Invalid ZF path provided'); + } + + $path = rtrim($path, '/'); + $path = rtrim($path, '\\'); + $versionLen = strlen($version); + $versions = array(); + $dirs = glob("$path/*", GLOB_ONLYDIR); + foreach ($dirs as $dir) { + $dirName = substr($dir, strlen($path) + 1); + if (!preg_match('/^(?:ZendFramework-)?(\d+\.\d+\.\d+((a|b|pl|pr|p|rc)\d+)?)(?:-minimal)?$/i', $dirName, $matches)) { + continue; + } + + $matchedVersion = $matches[1]; + + if (('latest' == $version) + || ((strlen($matchedVersion) >= $versionLen) + && (0 === strpos($matchedVersion, $version))) + ) { + $versions[$matchedVersion] = $dir . '/library'; + } + } + + uksort($versions, 'version_compare'); + return $versions; + } +} diff --git a/oss/piwik/trunk/libs/Zend/Loader/Autoloader/Interface.php b/oss/piwik/trunk/libs/Zend/Loader/Autoloader/Interface.php new file mode 100644 index 00000000..8bcaf14f --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Loader/Autoloader/Interface.php @@ -0,0 +1,34 @@ +toArray(); + } + if (!is_array($options)) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception('Options must be passed to resource loader constructor'); + } + + $this->setOptions($options); + + $namespace = $this->getNamespace(); + if ((null === $namespace) + || (null === $this->getBasePath()) + ) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception('Resource loader requires both a namespace and a base path for initialization'); + } + + if (!empty($namespace)) { + $namespace .= '_'; + } + Zend_Loader_Autoloader::getInstance()->unshiftAutoloader($this, $namespace); + } + + /** + * Overloading: methods + * + * Allow retrieving concrete resource object instances using 'get()' + * syntax. Example: + * + * $loader = new Zend_Loader_Autoloader_Resource(array( + * 'namespace' => 'Stuff_', + * 'basePath' => '/path/to/some/stuff', + * )) + * $loader->addResourceType('Model', 'models', 'Model'); + * + * $foo = $loader->getModel('Foo'); // get instance of Stuff_Model_Foo class + * + * + * @param string $method + * @param array $args + * @return mixed + * @throws Zend_Loader_Exception if method not beginning with 'get' or not matching a valid resource type is called + */ + public function __call($method, $args) + { + if ('get' == substr($method, 0, 3)) { + $type = strtolower(substr($method, 3)); + if (!$this->hasResourceType($type)) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception("Invalid resource type $type; cannot load resource"); + } + if (empty($args)) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception("Cannot load resources; no resource specified"); + } + $resource = array_shift($args); + return $this->load($resource, $type); + } + + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception("Method '$method' is not supported"); + } + + /** + * Helper method to calculate the correct class path + * + * @param string $class + * @return False if not matched other wise the correct path + */ + public function getClassPath($class) + { + $segments = explode('_', $class); + $namespaceTopLevel = $this->getNamespace(); + $namespace = ''; + + if (!empty($namespaceTopLevel)) { + $namespace = array_shift($segments); + if ($namespace != $namespaceTopLevel) { + // wrong prefix? we're done + return false; + } + } + + if (count($segments) < 2) { + // assumes all resources have a component and class name, minimum + return false; + } + + $final = array_pop($segments); + $component = $namespace; + $lastMatch = false; + do { + $segment = array_shift($segments); + $component .= empty($component) ? $segment : '_' . $segment; + if (isset($this->_components[$component])) { + $lastMatch = $component; + } + } while (count($segments)); + + if (!$lastMatch) { + return false; + } + + $final = substr($class, strlen($lastMatch) + 1); + $path = $this->_components[$lastMatch]; + $classPath = $path . '/' . str_replace('_', '/', $final) . '.php'; + + if (Zend_Loader::isReadable($classPath)) { + return $classPath; + } + + return false; + } + + /** + * Attempt to autoload a class + * + * @param string $class + * @return mixed False if not matched, otherwise result if include operation + */ + public function autoload($class) + { + $classPath = $this->getClassPath($class); + if (false !== $classPath) { + return include $classPath; + } + return false; + } + + /** + * Set class state from options + * + * @param array $options + * @return Zend_Loader_Autoloader_Resource + */ + public function setOptions(array $options) + { + $methods = get_class_methods($this); + foreach ($options as $key => $value) { + $method = 'set' . ucfirst($key); + if (in_array($method, $methods)) { + $this->$method($value); + } + } + return $this; + } + + /** + * Set namespace that this autoloader handles + * + * @param string $namespace + * @return Zend_Loader_Autoloader_Resource + */ + public function setNamespace($namespace) + { + $this->_namespace = rtrim((string) $namespace, '_'); + return $this; + } + + /** + * Get namespace this autoloader handles + * + * @return string + */ + public function getNamespace() + { + return $this->_namespace; + } + + /** + * Set base path for this set of resources + * + * @param string $path + * @return Zend_Loader_Autoloader_Resource + */ + public function setBasePath($path) + { + $this->_basePath = (string) $path; + return $this; + } + + /** + * Get base path to this set of resources + * + * @return string + */ + public function getBasePath() + { + return $this->_basePath; + } + + /** + * Add resource type + * + * @param string $type identifier for the resource type being loaded + * @param string $path path relative to resource base path containing the resource types + * @param null|string $namespace sub-component namespace to append to base namespace that qualifies this resource type + * @return Zend_Loader_Autoloader_Resource + */ + public function addResourceType($type, $path, $namespace = null) + { + $type = strtolower($type); + if (!isset($this->_resourceTypes[$type])) { + if (null === $namespace) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception('Initial definition of a resource type must include a namespace'); + } + $namespaceTopLevel = $this->getNamespace(); + $namespace = ucfirst(trim($namespace, '_')); + $this->_resourceTypes[$type] = array( + 'namespace' => empty($namespaceTopLevel) ? $namespace : $namespaceTopLevel . '_' . $namespace, + ); + } + if (!is_string($path)) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception('Invalid path specification provided; must be string'); + } + $this->_resourceTypes[$type]['path'] = $this->getBasePath() . '/' . rtrim($path, '\/'); + + $component = $this->_resourceTypes[$type]['namespace']; + $this->_components[$component] = $this->_resourceTypes[$type]['path']; + return $this; + } + + /** + * Add multiple resources at once + * + * $types should be an associative array of resource type => specification + * pairs. Each specification should be an associative array containing + * minimally the 'path' key (specifying the path relative to the resource + * base path) and optionally the 'namespace' key (indicating the subcomponent + * namespace to append to the resource namespace). + * + * As an example: + * + * $loader->addResourceTypes(array( + * 'model' => array( + * 'path' => 'models', + * 'namespace' => 'Model', + * ), + * 'form' => array( + * 'path' => 'forms', + * 'namespace' => 'Form', + * ), + * )); + * + * + * @param array $types + * @return Zend_Loader_Autoloader_Resource + */ + public function addResourceTypes(array $types) + { + foreach ($types as $type => $spec) { + if (!is_array($spec)) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception('addResourceTypes() expects an array of arrays'); + } + if (!isset($spec['path'])) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception('addResourceTypes() expects each array to include a paths element'); + } + $paths = $spec['path']; + $namespace = null; + if (isset($spec['namespace'])) { + $namespace = $spec['namespace']; + } + $this->addResourceType($type, $paths, $namespace); + } + return $this; + } + + /** + * Overwrite existing and set multiple resource types at once + * + * @see Zend_Loader_Autoloader_Resource::addResourceTypes() + * @param array $types + * @return Zend_Loader_Autoloader_Resource + */ + public function setResourceTypes(array $types) + { + $this->clearResourceTypes(); + return $this->addResourceTypes($types); + } + + /** + * Retrieve resource type mappings + * + * @return array + */ + public function getResourceTypes() + { + return $this->_resourceTypes; + } + + /** + * Is the requested resource type defined? + * + * @param string $type + * @return bool + */ + public function hasResourceType($type) + { + return isset($this->_resourceTypes[$type]); + } + + /** + * Remove the requested resource type + * + * @param string $type + * @return Zend_Loader_Autoloader_Resource + */ + public function removeResourceType($type) + { + if ($this->hasResourceType($type)) { + $namespace = $this->_resourceTypes[$type]['namespace']; + unset($this->_components[$namespace]); + unset($this->_resourceTypes[$type]); + } + return $this; + } + + /** + * Clear all resource types + * + * @return Zend_Loader_Autoloader_Resource + */ + public function clearResourceTypes() + { + $this->_resourceTypes = array(); + $this->_components = array(); + return $this; + } + + /** + * Set default resource type to use when calling load() + * + * @param string $type + * @return Zend_Loader_Autoloader_Resource + */ + public function setDefaultResourceType($type) + { + if ($this->hasResourceType($type)) { + $this->_defaultResourceType = $type; + } + return $this; + } + + /** + * Get default resource type to use when calling load() + * + * @return string|null + */ + public function getDefaultResourceType() + { + return $this->_defaultResourceType; + } + + /** + * Object registry and factory + * + * Loads the requested resource of type $type (or uses the default resource + * type if none provided). If the resource has been loaded previously, + * returns the previous instance; otherwise, instantiates it. + * + * @param string $resource + * @param string $type + * @return object + * @throws Zend_Loader_Exception if resource type not specified or invalid + */ + public function load($resource, $type = null) + { + if (null === $type) { + $type = $this->getDefaultResourceType(); + if (empty($type)) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception('No resource type specified'); + } + } + if (!$this->hasResourceType($type)) { + // require_once 'Zend/Loader/Exception.php'; + throw new Zend_Loader_Exception('Invalid resource type specified'); + } + $namespace = $this->_resourceTypes[$type]['namespace']; + $class = $namespace . '_' . ucfirst($resource); + if (!isset($this->_resources[$class])) { + $this->_resources[$class] = new $class; + } + return $this->_resources[$class]; + } +} diff --git a/oss/piwik/trunk/libs/Zend/Loader/Exception.php b/oss/piwik/trunk/libs/Zend/Loader/Exception.php new file mode 100644 index 00000000..84d40420 --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Loader/Exception.php @@ -0,0 +1,35 @@ +_useStaticRegistry = $staticRegistryName; + if(!isset(self::$_staticPrefixToPaths[$staticRegistryName])) { + self::$_staticPrefixToPaths[$staticRegistryName] = array(); + } + if(!isset(self::$_staticLoadedPlugins[$staticRegistryName])) { + self::$_staticLoadedPlugins[$staticRegistryName] = array(); + } + } + + foreach ($prefixToPaths as $prefix => $path) { + $this->addPrefixPath($prefix, $path); + } + } + + /** + * Format prefix for internal use + * + * @param string $prefix + * @return string + */ + protected function _formatPrefix($prefix) + { + if($prefix == "") { + return $prefix; + } + + $last = strlen($prefix) - 1; + if ($prefix{$last} == '\\') { + return $prefix; + } + + return rtrim($prefix, '_') . '_'; + } + + /** + * Add prefixed paths to the registry of paths + * + * @param string $prefix + * @param string $path + * @return Zend_Loader_PluginLoader + */ + public function addPrefixPath($prefix, $path) + { + if (!is_string($prefix) || !is_string($path)) { + // require_once 'Zend/Loader/PluginLoader/Exception.php'; + throw new Zend_Loader_PluginLoader_Exception('Zend_Loader_PluginLoader::addPrefixPath() method only takes strings for prefix and path.'); + } + + $prefix = $this->_formatPrefix($prefix); + $path = rtrim($path, '/\\') . '/'; + + if ($this->_useStaticRegistry) { + self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix][] = $path; + } else { + if (!isset($this->_prefixToPaths[$prefix])) { + $this->_prefixToPaths[$prefix] = array(); + } + if (!in_array($path, $this->_prefixToPaths[$prefix])) { + $this->_prefixToPaths[$prefix][] = $path; + } + } + return $this; + } + + /** + * Get path stack + * + * @param string $prefix + * @return false|array False if prefix does not exist, array otherwise + */ + public function getPaths($prefix = null) + { + if ((null !== $prefix) && is_string($prefix)) { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) { + return self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]; + } + + return false; + } + + if (isset($this->_prefixToPaths[$prefix])) { + return $this->_prefixToPaths[$prefix]; + } + + return false; + } + + if ($this->_useStaticRegistry) { + return self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } + + return $this->_prefixToPaths; + } + + /** + * Clear path stack + * + * @param string $prefix + * @return bool False only if $prefix does not exist + */ + public function clearPaths($prefix = null) + { + if ((null !== $prefix) && is_string($prefix)) { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + if (isset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix])) { + unset(self::$_staticPrefixToPaths[$this->_useStaticRegistry][$prefix]); + return true; + } + + return false; + } + + if (isset($this->_prefixToPaths[$prefix])) { + unset($this->_prefixToPaths[$prefix]); + return true; + } + + return false; + } + + if ($this->_useStaticRegistry) { + self::$_staticPrefixToPaths[$this->_useStaticRegistry] = array(); + } else { + $this->_prefixToPaths = array(); + } + + return true; + } + + /** + * Remove a prefix (or prefixed-path) from the registry + * + * @param string $prefix + * @param string $path OPTIONAL + * @return Zend_Loader_PluginLoader + */ + public function removePrefixPath($prefix, $path = null) + { + $prefix = $this->_formatPrefix($prefix); + if ($this->_useStaticRegistry) { + $registry =& self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } else { + $registry =& $this->_prefixToPaths; + } + + if (!isset($registry[$prefix])) { + // require_once 'Zend/Loader/PluginLoader/Exception.php'; + throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' was not found in the PluginLoader.'); + } + + if ($path != null) { + $pos = array_search($path, $registry[$prefix]); + if ($pos === null) { + // require_once 'Zend/Loader/PluginLoader/Exception.php'; + throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' / Path ' . $path . ' was not found in the PluginLoader.'); + } + unset($registry[$prefix][$pos]); + } else { + unset($registry[$prefix]); + } + + return $this; + } + + /** + * Normalize plugin name + * + * @param string $name + * @return string + */ + protected function _formatName($name) + { + return ucfirst((string) $name); + } + + /** + * Whether or not a Plugin by a specific name is loaded + * + * @param string $name + * @return Zend_Loader_PluginLoader + */ + public function isLoaded($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry) { + return isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]); + } + + return isset($this->_loadedPlugins[$name]); + } + + /** + * Return full class name for a named plugin + * + * @param string $name + * @return string|false False if class not found, class name otherwise + */ + public function getClassName($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry + && isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]) + ) { + return self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name]; + } elseif (isset($this->_loadedPlugins[$name])) { + return $this->_loadedPlugins[$name]; + } + + return false; + } + + /** + * Get path to plugin class + * + * @param mixed $name + * @return string|false False if not found + */ + public function getClassPath($name) + { + $name = $this->_formatName($name); + if ($this->_useStaticRegistry + && !empty(self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name]) + ) { + return self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name]; + } elseif (!empty($this->_loadedPluginPaths[$name])) { + return $this->_loadedPluginPaths[$name]; + } + + if ($this->isLoaded($name)) { + $class = $this->getClassName($name); + $r = new ReflectionClass($class); + $path = $r->getFileName(); + if ($this->_useStaticRegistry) { + self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = $path; + } else { + $this->_loadedPluginPaths[$name] = $path; + } + return $path; + } + + return false; + } + + /** + * Load a plugin via the name provided + * + * @param string $name + * @param bool $throwExceptions Whether or not to throw exceptions if the + * class is not resolved + * @return string|false Class name of loaded class; false if $throwExceptions + * if false and no class found + * @throws Zend_Loader_Exception if class not found + */ + public function load($name, $throwExceptions = true) + { + $name = $this->_formatName($name); + if ($this->isLoaded($name)) { + return $this->getClassName($name); + } + + if ($this->_useStaticRegistry) { + $registry = self::$_staticPrefixToPaths[$this->_useStaticRegistry]; + } else { + $registry = $this->_prefixToPaths; + } + + $registry = array_reverse($registry, true); + $found = false; + $classFile = str_replace('_', DIRECTORY_SEPARATOR, $name) . '.php'; + $incFile = self::getIncludeFileCache(); + foreach ($registry as $prefix => $paths) { + $className = $prefix . $name; + + if (class_exists($className, false)) { + $found = true; + break; + } + + $paths = array_reverse($paths, true); + + foreach ($paths as $path) { + $loadFile = $path . $classFile; + if (Zend_Loader::isReadable($loadFile)) { + include_once $loadFile; + if (class_exists($className, false)) { + if (null !== $incFile) { + self::_appendIncFile($loadFile); + } + $found = true; + break 2; + } + } + } + } + + if (!$found) { + if (!$throwExceptions) { + return false; + } + + $message = "Plugin by name '$name' was not found in the registry; used paths:"; + foreach ($registry as $prefix => $paths) { + $message .= "\n$prefix: " . implode(PATH_SEPARATOR, $paths); + } + // require_once 'Zend/Loader/PluginLoader/Exception.php'; + throw new Zend_Loader_PluginLoader_Exception($message); + } + + if ($this->_useStaticRegistry) { + self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name] = $className; + } else { + $this->_loadedPlugins[$name] = $className; + } + return $className; + } + + /** + * Set path to class file cache + * + * Specify a path to a file that will add include_once statements for each + * plugin class loaded. This is an opt-in feature for performance purposes. + * + * @param string $file + * @return void + * @throws Zend_Loader_PluginLoader_Exception if file is not writeable or path does not exist + */ + public static function setIncludeFileCache($file) + { + if (null === $file) { + self::$_includeFileCache = null; + return; + } + + if (!file_exists($file) && !file_exists(dirname($file))) { + // require_once 'Zend/Loader/PluginLoader/Exception.php'; + throw new Zend_Loader_PluginLoader_Exception('Specified file does not exist and/or directory does not exist (' . $file . ')'); + } + if (file_exists($file) && !is_writable($file)) { + // require_once 'Zend/Loader/PluginLoader/Exception.php'; + throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')'); + } + if (!file_exists($file) && file_exists(dirname($file)) && !is_writable(dirname($file))) { + // require_once 'Zend/Loader/PluginLoader/Exception.php'; + throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')'); + } + + self::$_includeFileCache = $file; + } + + /** + * Retrieve class file cache path + * + * @return string|null + */ + public static function getIncludeFileCache() + { + return self::$_includeFileCache; + } + + /** + * Append an include_once statement to the class file cache + * + * @param string $incFile + * @return void + */ + protected static function _appendIncFile($incFile) + { + if (!file_exists(self::$_includeFileCache)) { + $file = 'toArray(); + } + + if (!is_array($config)) { + // require_once 'Zend/Log/Exception.php'; + throw new Zend_Log_Exception('Configuration must be an array or instance of Zend_Config'); + } + + return $config; + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Filter/Interface.php b/oss/piwik/trunk/libs/Zend/Log/Filter/Interface.php new file mode 100644 index 00000000..c2165d2b --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Filter/Interface.php @@ -0,0 +1,40 @@ +_regexp = $regexp; + } + + /** + * Create a new instance of Zend_Log_Filter_Message + * + * @param array|Zend_Config $config + * @return Zend_Log_Filter_Message + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + $config = self::_parseConfig($config); + $config = array_merge(array( + 'regexp' => null + ), $config); + + return new self( + $config['regexp'] + ); + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event event data + * @return boolean accepted? + */ + public function accept($event) + { + return preg_match($this->_regexp, $event['message']) > 0; + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Filter/Priority.php b/oss/piwik/trunk/libs/Zend/Log/Filter/Priority.php new file mode 100644 index 00000000..45ba7c95 --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Filter/Priority.php @@ -0,0 +1,101 @@ +_priority = $priority; + $this->_operator = is_null($operator) ? '<=' : $operator; + } + + /** + * Create a new instance of Zend_Log_Filter_Priority + * + * @param array|Zend_Config $config + * @return Zend_Log_Filter_Priority + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + $config = self::_parseConfig($config); + $config = array_merge(array( + 'priority' => null, + 'operator' => null, + ), $config); + + // Add support for constants + if (!is_numeric($config['priority']) && isset($config['priority']) && defined($config['priority'])) { + $config['priority'] = constant($config['priority']); + } + + return new self( + (int) $config['priority'], + $config['operator'] + ); + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event event data + * @return boolean accepted? + */ + public function accept($event) + { + return version_compare($event['priority'], $this->_priority, $this->_operator); + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Filter/Suppress.php b/oss/piwik/trunk/libs/Zend/Log/Filter/Suppress.php new file mode 100644 index 00000000..d87d2720 --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Filter/Suppress.php @@ -0,0 +1,77 @@ +_accept = (! $suppress); + } + + /** + * Returns TRUE to accept the message, FALSE to block it. + * + * @param array $event event data + * @return boolean accepted? + */ + public function accept($event) + { + return $this->_accept; + } + + /** + * Create a new instance of Zend_Log_Filter_Suppress + * + * @param array|Zend_Config $config + * @return Zend_Log_Filter_Suppress + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + return new self(); + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Formatter/Firebug.php b/oss/piwik/trunk/libs/Zend/Log/Formatter/Firebug.php new file mode 100644 index 00000000..a0238935 --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Formatter/Firebug.php @@ -0,0 +1,50 @@ +_format = $format; + } + + /** + * Formats data into a single line to be written by the writer. + * + * @param array $event event data + * @return string formatted line to write to the log + */ + public function format($event) + { + $output = $this->_format; + foreach ($event as $name => $value) { + + if ((is_object($value) && !method_exists($value,'__toString')) + || is_array($value)) { + + $value = gettype($value); + } + + $output = str_replace("%$name%", $value, $output); + } + return $output; + } + +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Formatter/Xml.php b/oss/piwik/trunk/libs/Zend/Log/Formatter/Xml.php new file mode 100644 index 00000000..ebf3c29e --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Formatter/Xml.php @@ -0,0 +1,121 @@ +_rootElement = $rootElement; + $this->_elementMap = $elementMap; + $this->setEncoding($encoding); + } + + /** + * Get encoding + * + * @return string + */ + public function getEncoding() + { + return $this->_encoding; + } + + /** + * Set encoding + * + * @param string $value + * @return Zend_Log_Formatter_Xml + */ + public function setEncoding($value) + { + $this->_encoding = (string) $value; + return $this; + } + + /** + * Formats data into a single line to be written by the writer. + * + * @param array $event event data + * @return string formatted line to write to the log + */ + public function format($event) + { + if ($this->_elementMap === null) { + $dataToInsert = $event; + } else { + $dataToInsert = array(); + foreach ($this->_elementMap as $elementName => $fieldKey) { + $dataToInsert[$elementName] = $event[$fieldKey]; + } + } + + $enc = $this->getEncoding(); + $dom = new DOMDocument('1.0', $enc); + $elt = $dom->appendChild(new DOMElement($this->_rootElement)); + + foreach ($dataToInsert as $key => $value) { + if($key == "message") { + $value = htmlspecialchars($value, ENT_COMPAT, $enc); + } + $elt->appendChild(new DOMElement($key, $value)); + } + + $xml = $dom->saveXML(); + $xml = preg_replace('/<\?xml version="1.0"( encoding="[^\"]*")?\?>\n/u', '', $xml); + + return $xml . PHP_EOL; + } + +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Writer/Abstract.php b/oss/piwik/trunk/libs/Zend/Log/Writer/Abstract.php new file mode 100644 index 00000000..80b939db --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Writer/Abstract.php @@ -0,0 +1,129 @@ +_filters[] = $filter; + } + + /** + * Log a message to this writer. + * + * @param array $event log data event + * @return void + */ + public function write($event) + { + foreach ($this->_filters as $filter) { + if (! $filter->accept($event)) { + return; + } + } + + // exception occurs on error + $this->_write($event); + } + + /** + * Set a new formatter for this writer + * + * @param Zend_Log_Formatter_Interface $formatter + * @return void + */ + public function setFormatter($formatter) + { + $this->_formatter = $formatter; + } + + /** + * Perform shutdown activites such as closing open resources + * + * @return void + */ + public function shutdown() + {} + + /** + * Write a message to the log. + * + * @param array $event log data event + * @return void + */ + abstract protected function _write($event); + + /** + * Validate and optionally convert the config to array + * + * @param array|Zend_Config $config Zend_Config or Array + * @return array + * @throws Zend_Log_Exception + */ + static protected function _parseConfig($config) + { + if ($config instanceof Zend_Config) { + $config = $config->toArray(); + } + + if (!is_array($config)) { + // require_once 'Zend/Log/Exception.php'; + throw new Zend_Log_Exception( + 'Configuration must be an array or instance of Zend_Config' + ); + } + + return $config; + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Writer/Db.php b/oss/piwik/trunk/libs/Zend/Log/Writer/Db.php new file mode 100644 index 00000000..6f77a12c --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Writer/Db.php @@ -0,0 +1,139 @@ +_db = $db; + $this->_table = $table; + $this->_columnMap = $columnMap; + } + + /** + * Create a new instance of Zend_Log_Writer_Db + * + * @param array|Zend_Config $config + * @return Zend_Log_Writer_Db + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + $config = self::_parseConfig($config); + $config = array_merge(array( + 'db' => null, + 'table' => null, + 'columnMap' => null, + ), $config); + + if (isset($config['columnmap'])) { + $config['columnMap'] = $config['columnmap']; + } + + return new self( + $config['db'], + $config['table'], + $config['columnMap'] + ); + } + + /** + * Formatting is not possible on this writer + */ + public function setFormatter($formatter) + { + // require_once 'Zend/Log/Exception.php'; + throw new Zend_Log_Exception(get_class() . ' does not support formatting'); + } + + /** + * Remove reference to database adapter + * + * @return void + */ + public function shutdown() + { + $this->_db = null; + } + + /** + * Write a message to the log. + * + * @param array $event event data + * @return void + */ + protected function _write($event) + { + if ($this->_db === null) { + // require_once 'Zend/Log/Exception.php'; + throw new Zend_Log_Exception('Database adapter is null'); + } + + if ($this->_columnMap === null) { + $dataToInsert = $event; + } else { + $dataToInsert = array(); + foreach ($this->_columnMap as $columnName => $fieldKey) { + $dataToInsert[$columnName] = $event[$fieldKey]; + } + } + + $this->_db->insert($this->_table, $dataToInsert); + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Writer/Firebug.php b/oss/piwik/trunk/libs/Zend/Log/Writer/Firebug.php new file mode 100644 index 00000000..585f6a3d --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Writer/Firebug.php @@ -0,0 +1,200 @@ + Zend_Wildfire_Plugin_FirePhp::ERROR, + Zend_Log::ALERT => Zend_Wildfire_Plugin_FirePhp::ERROR, + Zend_Log::CRIT => Zend_Wildfire_Plugin_FirePhp::ERROR, + Zend_Log::ERR => Zend_Wildfire_Plugin_FirePhp::ERROR, + Zend_Log::WARN => Zend_Wildfire_Plugin_FirePhp::WARN, + Zend_Log::NOTICE => Zend_Wildfire_Plugin_FirePhp::INFO, + Zend_Log::INFO => Zend_Wildfire_Plugin_FirePhp::INFO, + Zend_Log::DEBUG => Zend_Wildfire_Plugin_FirePhp::LOG); + + /** + * The default logging style for un-mapped priorities + * @var string + */ + protected $_defaultPriorityStyle = Zend_Wildfire_Plugin_FirePhp::LOG; + + /** + * Flag indicating whether the log writer is enabled + * @var boolean + */ + protected $_enabled = true; + + /** + * Class constructor + */ + public function __construct() + { + if (php_sapi_name() == 'cli') { + $this->setEnabled(false); + } + + $this->_formatter = new Zend_Log_Formatter_Firebug(); + } + + /** + * Create a new instance of Zend_Log_Writer_Firebug + * + * @param array|Zend_Config $config + * @return Zend_Log_Writer_Firebug + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + return new self(); + } + + /** + * Enable or disable the log writer. + * + * @param boolean $enabled Set to TRUE to enable the log writer + * @return boolean The previous value. + */ + public function setEnabled($enabled) + { + $previous = $this->_enabled; + $this->_enabled = $enabled; + return $previous; + } + + /** + * Determine if the log writer is enabled. + * + * @return boolean Returns TRUE if the log writer is enabled. + */ + public function getEnabled() + { + return $this->_enabled; + } + + /** + * Set the default display style for user-defined priorities + * + * @param string $style The default log display style + * @return string Returns previous default log display style + */ + public function setDefaultPriorityStyle($style) + { + $previous = $this->_defaultPriorityStyle; + $this->_defaultPriorityStyle = $style; + return $previous; + } + + /** + * Get the default display style for user-defined priorities + * + * @return string Returns the default log display style + */ + public function getDefaultPriorityStyle() + { + return $this->_defaultPriorityStyle; + } + + /** + * Set a display style for a logging priority + * + * @param int $priority The logging priority + * @param string $style The logging display style + * @return string|boolean The previous logging display style if defined or TRUE otherwise + */ + public function setPriorityStyle($priority, $style) + { + $previous = true; + if (array_key_exists($priority,$this->_priorityStyles)) { + $previous = $this->_priorityStyles[$priority]; + } + $this->_priorityStyles[$priority] = $style; + return $previous; + } + + /** + * Get a display style for a logging priority + * + * @param int $priority The logging priority + * @return string|boolean The logging display style if defined or FALSE otherwise + */ + public function getPriorityStyle($priority) + { + if (array_key_exists($priority,$this->_priorityStyles)) { + return $this->_priorityStyles[$priority]; + } + return false; + } + + /** + * Log a message to the Firebug Console. + * + * @param array $event The event data + * @return void + */ + protected function _write($event) + { + if (!$this->getEnabled()) { + return; + } + + if (array_key_exists($event['priority'],$this->_priorityStyles)) { + $type = $this->_priorityStyles[$event['priority']]; + } else { + $type = $this->_defaultPriorityStyle; + } + + $message = $this->_formatter->format($event); + + $label = isset($event['firebugLabel'])?$event['firebugLabel']:null; + + Zend_Wildfire_Plugin_FirePhp::getInstance()->send($message, + $label, + $type, + array('traceOffset'=>6)); + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Writer/Mail.php b/oss/piwik/trunk/libs/Zend/Log/Writer/Mail.php new file mode 100644 index 00000000..70f57b86 --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Writer/Mail.php @@ -0,0 +1,307 @@ +_layout->events will be set for use in the layout template. + * + * @param Zend_Mail $mail Mail instance + * @param Zend_Layout $layout Layout instance; optional + * @return void + */ + public function __construct(Zend_Mail $mail, Zend_Layout $layout = null) + { + $this->_mail = $mail; + $this->_layout = $layout; + $this->_formatter = new Zend_Log_Formatter_Simple(); + } + + /** + * Create a new instance of Zend_Log_Writer_Mail + * + * @param array|Zend_Config $config + * @return Zend_Log_Writer_Mail + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + throw new Zend_Exception('Zend_Log_Writer_Mail does not currently implement a factory'); + } + + /** + * Places event line into array of lines to be used as message body. + * + * Handles the formatting of both plaintext entries, as well as those + * rendered with Zend_Layout. + * + * @param array $event Event data + * @return void + */ + protected function _write($event) + { + // Track the number of entries per priority level. + if (!isset($this->_numEntriesPerPriority[$event['priorityName']])) { + $this->_numEntriesPerPriority[$event['priorityName']] = 1; + } else { + $this->_numEntriesPerPriority[$event['priorityName']]++; + } + + $formattedEvent = $this->_formatter->format($event); + + // All plaintext events are to use the standard formatter. + $this->_eventsToMail[] = $formattedEvent; + + // If we have a Zend_Layout instance, use a specific formatter for the + // layout if one exists. Otherwise, just use the event with its + // default format. + if ($this->_layout) { + if ($this->_layoutFormatter) { + $this->_layoutEventsToMail[] = + $this->_layoutFormatter->format($event); + } else { + $this->_layoutEventsToMail[] = $formattedEvent; + } + } + } + + /** + * Gets instance of Zend_Log_Formatter_Instance used for formatting a + * message using Zend_Layout, if applicable. + * + * @return Zend_Log_Formatter_Interface|null The formatter, or null. + */ + public function getLayoutFormatter() + { + return $this->_layoutFormatter; + } + + /** + * Sets a specific formatter for use with Zend_Layout events. + * + * Allows use of a second formatter on lines that will be rendered with + * Zend_Layout. In the event that Zend_Layout is not being used, this + * formatter cannot be set, so an exception will be thrown. + * + * @param Zend_Log_Formatter_Interface $formatter + * @return Zend_Log_Writer_Mail + * @throws Zend_Log_Exception + */ + public function setLayoutFormatter(Zend_Log_Formatter_Interface $formatter) + { + if (!$this->_layout) { + throw new Zend_Log_Exception( + 'cannot set formatter for layout; ' . + 'a Zend_Layout instance is not in use'); + } + + $this->_layoutFormatter = $formatter; + return $this; + } + + /** + * Allows caller to have the mail subject dynamically set to contain the + * entry counts per-priority level. + * + * Sets the text for use in the subject, with entry counts per-priority + * level appended to the end. Since a Zend_Mail subject can only be set + * once, this method cannot be used if the Zend_Mail object already has a + * subject set. + * + * @param string $subject Subject prepend text. + * @return Zend_Log_Writer_Mail + */ + public function setSubjectPrependText($subject) + { + if ($this->_mail->getSubject()) { + throw new Zend_Log_Exception( + 'subject already set on mail; ' . + 'cannot set subject prepend text'); + } + + $this->_subjectPrependText = (string) $subject; + return $this; + } + + /** + * Sends mail to recipient(s) if log entries are present. Note that both + * plaintext and HTML portions of email are handled here. + * + * @return void + */ + public function shutdown() + { + // If there are events to mail, use them as message body. Otherwise, + // there is no mail to be sent. + if (empty($this->_eventsToMail)) { + return; + } + + if ($this->_subjectPrependText !== null) { + // Tack on the summary of entries per-priority to the subject + // line and set it on the Zend_Mail object. + $numEntries = $this->_getFormattedNumEntriesPerPriority(); + $this->_mail->setSubject( + "{$this->_subjectPrependText} ({$numEntries})"); + } + + + // Always provide events to mail as plaintext. + $this->_mail->setBodyText(implode('', $this->_eventsToMail)); + + // If a Zend_Layout instance is being used, set its "events" + // value to the lines formatted for use with the layout. + if ($this->_layout) { + // Set the required "messages" value for the layout. Here we + // are assuming that the layout is for use with HTML. + $this->_layout->events = + implode('', $this->_layoutEventsToMail); + + // If an exception occurs during rendering, convert it to a notice + // so we can avoid an exception thrown without a stack frame. + try { + $this->_mail->setBodyHtml($this->_layout->render()); + } catch (Exception $e) { + trigger_error( + "exception occurred when rendering layout; " . + "unable to set html body for message; " . + "message = {$e->getMessage()}; " . + "code = {$e->getCode()}; " . + "exception class = " . get_class($e), + E_USER_NOTICE); + } + } + + // Finally, send the mail. If an exception occurs, convert it into a + // warning-level message so we can avoid an exception thrown without a + // stack frame. + try { + $this->_mail->send(); + } catch (Exception $e) { + trigger_error( + "unable to send log entries via email; " . + "message = {$e->getMessage()}; " . + "code = {$e->getCode()}; " . + "exception class = " . get_class($e), + E_USER_WARNING); + } + } + + /** + * Gets a string of number of entries per-priority level that occurred, or + * an emptry string if none occurred. + * + * @return string + */ + protected function _getFormattedNumEntriesPerPriority() + { + $strings = array(); + + foreach ($this->_numEntriesPerPriority as $priority => $numEntries) { + $strings[] = "{$priority}={$numEntries}"; + } + + return implode(', ', $strings); + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Writer/Mock.php b/oss/piwik/trunk/libs/Zend/Log/Writer/Mock.php new file mode 100644 index 00000000..1e14a2f0 --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Writer/Mock.php @@ -0,0 +1,78 @@ +events[] = $event; + } + + /** + * Record shutdown + * + * @return void + */ + public function shutdown() + { + $this->shutdown = true; + } + + /** + * Create a new instance of Zend_Log_Writer_Mock + * + * @param array|Zend_Config $config + * @return Zend_Log_Writer_Mock + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + return new self(); + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Writer/Null.php b/oss/piwik/trunk/libs/Zend/Log/Writer/Null.php new file mode 100644 index 00000000..f281883f --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Writer/Null.php @@ -0,0 +1,57 @@ +_stream = $streamOrUrl; + } else { + if (is_array($streamOrUrl) && isset($streamOrUrl['stream'])) { + $streamOrUrl = $streamOrUrl['stream']; + } + + if (! $this->_stream = @fopen($streamOrUrl, $mode, false)) { + // require_once 'Zend/Log/Exception.php'; + $msg = "\"$streamOrUrl\" cannot be opened with mode \"$mode\""; + throw new Zend_Log_Exception($msg); + } + } + + $this->_formatter = new Zend_Log_Formatter_Simple(); + } + + /** + * Create a new instance of Zend_Log_Writer_Mock + * + * @param array|Zend_Config $config + * @return Zend_Log_Writer_Mock + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + $config = self::_parseConfig($config); + $config = array_merge(array( + 'stream' => null, + 'mode' => null, + ), $config); + + $streamOrUrl = isset($config['url']) ? $config['url'] : $config['stream']; + + return new self( + $streamOrUrl, + $config['mode'] + ); + } + + /** + * Close the stream resource. + * + * @return void + */ + public function shutdown() + { + if (is_resource($this->_stream)) { + fclose($this->_stream); + } + } + + /** + * Write a message to the log. + * + * @param array $event event data + * @return void + */ + protected function _write($event) + { + $line = $this->_formatter->format($event); + + if (false === @fwrite($this->_stream, $line)) { + // require_once 'Zend/Log/Exception.php'; + throw new Zend_Log_Exception("Unable to write to stream"); + } + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Writer/Syslog.php b/oss/piwik/trunk/libs/Zend/Log/Writer/Syslog.php new file mode 100644 index 00000000..310bcf54 --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Writer/Syslog.php @@ -0,0 +1,187 @@ + LOG_EMERG, + Zend_Log::ALERT => LOG_ALERT, + Zend_Log::CRIT => LOG_CRIT, + Zend_Log::ERR => LOG_ERR, + Zend_Log::WARN => LOG_WARNING, + Zend_Log::NOTICE => LOG_NOTICE, + Zend_Log::INFO => LOG_INFO, + Zend_Log::DEBUG => LOG_DEBUG, + ); + + /** + * The default log priority - for unmapped custom priorities + * @var string + */ + protected $_defaultPriority = LOG_NOTICE; + + /** + * Last application name set by a syslog-writer instance + * @var string + */ + protected static $_lastApplication; + + /** + * Last facility name set by a syslog-writer instance + * @var string + */ + protected static $_lastFacility; + + /** + * Application name used by this syslog-writer instance + * @var string + */ + protected $_application = 'Zend_Log'; + + /** + * Facility used by this syslog-writer instance + * @var string + */ + protected $_facility = LOG_USER; + + /** + * Class constructor + * + * @param array $options Array of options; may include "application" and "facility" keys + * @return void + */ + public function __construct(array $params = array()) + { + if (isset($params['application'])) { + $this->_application = $params['application']; + } + if (isset($params['facility'])) { + $this->_facility = $params['facility']; + } + $this->_initializeSyslog(); + } + + /** + * Create a new instance of Zend_Log_Writer_Syslog + * + * @param array|Zend_Config $config + * @return Zend_Log_Writer_Syslog + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + return new self(self::_parseConfig($config)); + } + + /** + * Initialize syslog / set application name and facility + * + * @param string $application Application name + * @param string $facility Syslog facility + * @return void + */ + protected function _initializeSyslog() + { + self::$_lastApplication = $this->_application; + self::$_lastFacility = $this->_facility; + openlog($this->_application, LOG_PID, $this->_facility); + } + + /** + * Set syslog facility + * + * @param string $facility Syslog facility + * @return void + */ + public function setFacility($facility) + { + if ($this->_facility === $facility) { + return; + } + $this->_facility = $facility; + $this->_initializeSyslog(); + } + + /** + * Set application name + * + * @param string $application Application name + * @return void + */ + public function setApplicationName($application) + { + if ($this->_application === $application) { + return; + } + $this->_application = $application; + $this->_initializeSyslog(); + } + + /** + * Close syslog. + * + * @return void + */ + public function shutdown() + { + closelog(); + } + + /** + * Write a message to syslog. + * + * @param array $event event data + * @return void + */ + protected function _write($event) + { + if (array_key_exists($event['priority'], $this->_priorities)) { + $priority = $this->_priorities[$event['priority']]; + } else { + $priority = $this->_defaultPriority; + } + + if ($this->_application !== self::$_lastApplication + || $this->_facility !== self::$_lastFacility) + { + $this->_initializeSyslog(); + } + + syslog($priority, $event['message']); + } +} diff --git a/oss/piwik/trunk/libs/Zend/Log/Writer/ZendMonitor.php b/oss/piwik/trunk/libs/Zend/Log/Writer/ZendMonitor.php new file mode 100644 index 00000000..59a648fa --- /dev/null +++ b/oss/piwik/trunk/libs/Zend/Log/Writer/ZendMonitor.php @@ -0,0 +1,111 @@ +_isEnabled = false; + } + } + + /** + * Create a new instance of Zend_Log_Writer_ZendMonitor + * + * @param array|Zend_Config $config + * @return Zend_Log_Writer_Syslog + * @throws Zend_Log_Exception + */ + static public function factory($config) + { + return new self(); + } + + /** + * Is logging to this writer enabled? + * + * If the Zend Monitor extension is not enabled, this log writer will + * fail silently. You can query this method to determine if the log + * writer is enabled. + * + * @return bool + */ + public function isEnabled() + { + return $this->_isEnabled; + } + + /** + * Log a message to this writer. + * + * @param array $event log data event + * @return void + */ + public function write($event) + { + if (!$this->isEnabled()) { + return; + } + + parent::write($event); + } + + /** + * Write a message to the log. + * + * @param array $event log data event + * @return void + */ + protected function _write($event) + { + $priority = $event['priority']; + $message = $event['message']; + unset($event['priority'], $event['message']); + + if (!empty($event)) { + monitor_custom_event($priority, $message, $event); + } else { + monitor_custom_event($priority, $message); + } + } +}