protected function getJavascriptCallback() { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_JavascriptBuilder'); $config = $this->getConfig(); $arguments = array($this->owner->getJavascriptValue()); foreach ($config['arguments'] as $arg) { $arguments[] = HTML_QuickForm2_JavascriptBuilder::encode($arg); } return "function() { return !" . $this->findJavascriptName() . "(" . implode(', ', $arguments) . "); }"; }
/** * Returns the javascript builder object * * @return HTML_QuickForm2_JavascriptBuilder */ public function getJavascriptBuilder() { if (empty($this->jsBuilder)) { if (!class_exists('HTML_QuickForm2_JavascriptBuilder')) { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_JavascriptBuilder'); } $this->jsBuilder = new HTML_QuickForm2_JavascriptBuilder(); } return $this->jsBuilder; }
/** * Class constructor * * Possible keys in $data array are: * - 'messageProvider': an instance of a class implementing * HTML_QuickForm2_MessageProvider interface, this will be used to get * localized error messages. Default will be used if not given. * - 'language': language to display error messages in, will be passed to * message provider. * - 'errorMessages': (DEPRECATED, use messageProvider) an array of error * messages with the following format * <pre> * 'language code 1' => array( * UPLOAD_ERR_... => 'message', * ... * UPLOAD_ERR_... => 'message' * ), * ... * 'language code N' => array( * ... * ) * </pre> * Note that error messages for UPLOAD_ERR_INI_SIZE and UPLOAD_ERR_FORM_SIZE * may contain '%d' placeholders that will be automatically replaced by the * appropriate size limits. Note also that you don't need to provide messages * for every possible error code in the arrays, you may e.g. override just * one error message for a particular language. * * @param string Element name * @param mixed Attributes (either a string or an array) * @param array Data used to set up error messages for PHP's file * upload errors. */ public function __construct($name = null, $attributes = null, array $data = array()) { // Using deprecated 'errorMessages' key, let's keep this separate to remove later if (isset($data['errorMessages'])) { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_MessageProvider_Default'); $this->messageProvider = HTML_QuickForm2_MessageProvider_Default::getInstance(); // neither array_merge() nor array_merge_recursive will do foreach ($data['errorMessages'] as $lang => $ary) { foreach ($ary as $code => $message) { $this->messageProvider->set(array('file', $code), $lang, $message); } } } elseif (isset($data['messageProvider'])) { if (!is_callable($data['messageProvider']) && !$data['messageProvider'] instanceof HTML_QuickForm2_MessageProvider) { throw new HTML_QuickForm2_InvalidArgumentException("messageProvider: expecting a callback or an implementation" . " of HTML_QuickForm2_MessageProvider"); } $this->messageProvider = $data['messageProvider']; } else { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_MessageProvider_Default'); $this->messageProvider = HTML_QuickForm2_MessageProvider_Default::getInstance(); } if (isset($data['language'])) { $this->language = $data['language']; } unset($data['messageProvider'], $data['errorMessages'], $data['language']); parent::__construct($name, $attributes, $data); }
/** * Creates a new renderer instance of the given type * * A renderer is always wrapped by a Proxy, which handles calling its * "published" methods and methods of its plugins. Registered plugins are * added automagically to the existing renderer instances so that * <code> * $foo = HTML_QuickForm2_Renderer::factory('foo'); * // Plugin implementing bar() method * HTML_QuickForm2_Renderer::registerPlugin('foo', 'Plugin_Foo_Bar'); * $foo->bar(); * </code> * will work. * * @param string Type name (treated case-insensitively) * @return HTML_QuickForm2_Renderer_Proxy A renderer instance of the given * type wrapped by a Proxy * @throws HTML_QuickForm2_InvalidArgumentException If type name is unknown * @throws HTML_QuickForm2_NotFoundException If class for the renderer can * not be found and/or loaded from file */ public static final function factory($type) { $type = strtolower($type); if (!isset(self::$_types[$type])) { throw new HTML_QuickForm2_InvalidArgumentException("Renderer type '{$type}' is not known"); } list($className, $includeFile) = self::$_types[$type]; HTML_QuickForm2_Loader::loadClass($className, $includeFile); HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_Renderer_Proxy'); return new HTML_QuickForm2_Renderer_Proxy(new $className(), self::$_pluginClasses[$type]); }
/** * Handles an action * * This will be called if the page itself does not have a handler for a * specific action. The method also loads and uses default handlers for * common actions, if specific ones were not added. * * @param HTML_QuickForm2_Controller_Page $page form page * @param string $actionName action name * * @return mixed Return value of action handler * @throws HTML_QuickForm2_NotFoundException if handler for an action is missing */ public function handle(HTML_QuickForm2_Controller_Page $page, $actionName) { if (!isset($this->handlers[$actionName]) && in_array($actionName, array('next', 'back', 'submit', 'display', 'jump'))) { $className = 'HTML_QuickForm2_Controller_Action_' . ucfirst($actionName); HTML_QuickForm2_Loader::loadClass($className); $this->addHandler($actionName, new $className()); } if (isset($this->handlers[$actionName])) { return $this->handlers[$actionName]->perform($page, $actionName); } else { throw new HTML_QuickForm2_NotFoundException("Unhandled action '{$actionName}' for page '{$page->getForm()->getId()}'"); } }
/** * Class constructor * * Possible keys in $data array are: * - 'messageProvider': an instance of a class implementing * HTML_QuickForm2_MessageProvider interface, this will be used to get * localized error messages. Default will be used if not given. * - 'language': language to display error messages in, will be passed to * message provider. * * @param string $name Element name * @param string|array $attributes Attributes (either a string or an array) * @param array $data Data used to set up error messages for PHP's * file upload errors. */ public function __construct($name = null, $attributes = null, array $data = array()) { if (isset($data['messageProvider'])) { if (!is_callable($data['messageProvider']) && !$data['messageProvider'] instanceof HTML_QuickForm2_MessageProvider) { throw new HTML_QuickForm2_InvalidArgumentException("messageProvider: expecting a callback or an implementation" . " of HTML_QuickForm2_MessageProvider"); } $this->messageProvider = $data['messageProvider']; } else { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_MessageProvider_Default'); $this->messageProvider = HTML_QuickForm2_MessageProvider_Default::getInstance(); } if (isset($data['language'])) { $this->language = $data['language']; } unset($data['messageProvider'], $data['language']); parent::__construct($name, $attributes, $data); }
/** * Creates a new Rule of the given type * * @param string Rule type name (treated case-insensitively) * @param HTML_QuickForm2_Node Element to validate by the rule * @param string Message to display if validation fails * @param mixed Configuration data for the rule * @return HTML_QuickForm2_Rule A created Rule * @throws HTML_QuickForm2_InvalidArgumentException If rule type is unknown * @throws HTML_QuickForm2_NotFoundException If class for the rule * can't be found and/or loaded from file * @todo Remove the trigger_error() call after release 0.4.0 */ public static function createRule($type, HTML_QuickForm2_Node $owner, $message = '', $config = null) { $type = strtolower($type); if (!isset(self::$registeredRules[$type])) { throw new HTML_QuickForm2_InvalidArgumentException("Rule '{$type}' is not known"); } list($className, $includeFile) = self::$registeredRules[$type]; HTML_QuickForm2_Loader::loadClass($className, $includeFile); if (isset(self::$registeredRules[$type][2])) { $config = call_user_func(array($className, 'mergeConfig'), $config, self::$registeredRules[$type][2]); if (method_exists($className, 'checkValue')) { trigger_error("{$className} may need a custom mergeConfig() method implemented", E_USER_NOTICE); } } return new $className($owner, $message, $config); }
/** * Updates the list of plugins for the current renderer instance * * This method checks whether any new plugin classes were registered * since its previous invocation and adds instances of these classes to * the list. Plugins' methods are imported and can be later called as * this object's own. * * @throws HTML_QuickForm2_InvalidArgumentException if a plugin has already * imported name */ protected function updatePlugins() { for ($i = count($this->_plugins); $i < count($this->_pluginClasses); $i++) { list($className, $includeFile) = $this->_pluginClasses[$i]; HTML_QuickForm2_Loader::loadClass($className, $includeFile); $methods = array(); $plugin = new $className(); $reflection = new ReflectionObject($plugin); foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { $lower = strtolower($method->getName()); if ('HTML_QuickForm2_Renderer_Plugin' == $method->getDeclaringClass()->getName()) { continue; } elseif (!isset($this->_rendererMethods[$lower]) && !isset($this->_pluginMethods[$lower])) { $methods[$lower] = $i; } else { throw new HTML_QuickForm2_InvalidArgumentException('Duplicate method name: name ' . $method->getName() . ' in plugin ' . get_class($plugin) . ' already taken by ' . (isset($this->_rendererMethods[$lower]) ? get_class($this->_renderer) : get_class($this->_plugins[$this->_pluginMethods[$lower]]))); } } $plugin->setRenderer($this->_renderer); $this->_plugins[$i] = $plugin; $this->_pluginMethods += $methods; } }
/** * Returns the client-side representation of the Rule * * The Javascript object returned contains the following fields: * - callback: {@see getJavascriptCallback()} * - elementId: element ID to set error for if validation fails * - errorMessage: error message to set if validation fails * - chained: chained rules, array of arrays like in $chainedRules property * * @return string * @throws HTML_QuickForm2_Exception if Rule or its chained Rules can only * be run server-side */ public function getJavascript($outputTriggers = true) { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_JavascriptBuilder'); $js = $this->getJavascriptCallback() . ",\n\t'" . $this->owner->getId() . "', " . HTML_QuickForm2_JavascriptBuilder::encode($this->getMessage()); $js = $outputTriggers && count($triggers = $this->getJavascriptTriggers()) ? 'new qf.LiveRule(' . $js . ', ' . HTML_QuickForm2_JavascriptBuilder::encode($triggers) : 'new qf.Rule(' . $js; if (count($this->chainedRules) > 1 || count($this->chainedRules[0]) > 0) { $chained = array(); foreach ($this->chainedRules as $item) { $multipliers = array(); foreach ($item as $multiplier) { $multipliers[] = $multiplier->getJavascript(false); } $chained[] = '[' . implode(",\n", $multipliers) . ']'; } $js .= ",\n\t [" . implode(",\n", $chained) . "]"; } return $js . ')'; }
/** * Returns the client-side representation of the Rule * * The Javascript object returned contains the following fields: * - callback: {@see getJavascriptCallback()} * - elementId: element ID to set error for if validation fails * - errorMessage: error message to set if validation fails * - chained: chained rules, array of arrays like in $chainedRules property * * @return string * @throws HTML_QuickForm2_Exception if Rule or its chained Rules can only * be run server-side */ public function getJavascript() { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_JavascriptBuilder'); $js = "{\n\tcallback: " . $this->getJavascriptCallback() . ",\n" . "\towner: '" . $this->owner->getId() . "',\n" . "\tmessage: " . HTML_QuickForm2_JavascriptBuilder::encode($this->getMessage()); if (count($this->chainedRules) > 1 || count($this->chainedRules[0]) > 0) { $chained = array(); foreach ($this->chainedRules as $item) { $multipliers = array(); foreach ($item as $multiplier) { $multipliers[] = $multiplier->getJavascript(); } $chained[] = '[' . implode(",\n", $multipliers) . ']'; } $js .= ",\n\tchained: [" . implode(",\n", $chained) . "]"; } return $js . "\n}"; }
/** * Class constructor * * The following keys may appear in $data array: * - 'messageProvider': a callback or an instance of a class implementing * HTML_QuickForm2_MessageProvider interface, this will be used to get * localized names of months and weekdays. Some of the default ones will * be used if not given. * - 'language': date language, use 'locale' here to display month / weekday * names according to the current locale. * - 'format': Format of the date, based on PHP's date() function. * The following characters are currently recognised in format string: * <pre> * 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 => 24 hour format * i => Minutes * s => Seconds * a => am/pm * A => AM/PM * </pre> * - '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') * - 'minHour': Minimum hour in hour select (only for 24 hour format!) * - 'maxHour': Maximum hour in hour select (only for 24 hour format!) * - 'minMonth': Minimum month in month select * - 'maxMonth': Maximum month in month select * * @param string Element name * @param mixed Attributes (either a string or an array) * @param array Element data (label, options and data used for element creation) */ public function __construct($name = null, $attributes = null, array $data = array()) { if (isset($data['messageProvider'])) { if (!is_callable($data['messageProvider']) && !$data['messageProvider'] instanceof HTML_QuickForm2_MessageProvider) { throw new HTML_QuickForm2_InvalidArgumentException("messageProvider: expecting a callback or an implementation" . " of HTML_QuickForm2_MessageProvider"); } $this->messageProvider = $data['messageProvider']; } else { if (isset($data['language']) && 'locale' == $data['language']) { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_MessageProvider_Strftime'); $this->messageProvider = new HTML_QuickForm2_MessageProvider_Strftime(); } else { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_MessageProvider_Default'); $this->messageProvider = HTML_QuickForm2_MessageProvider_Default::getInstance(); } } if (isset($data['language'])) { $this->language = $data['language']; } unset($data['messageProvider'], $data['language']); // http://pear.php.net/bugs/bug.php?id=18171 $this->data['maxYear'] = date('Y'); parent::__construct($name, $attributes, $data); $backslash = false; $separators = array(); $separator = ''; for ($i = 0, $length = strlen($this->data['format']); $i < $length; $i++) { $sign = $this->data['format'][$i]; if ($backslash) { $backslash = false; $separator .= $sign; } else { $loadSelect = true; switch ($sign) { case 'D': // Sunday is 0 like with 'w' in date() $options = $this->messageProvider instanceof HTML_QuickForm2_MessageProvider ? $this->messageProvider->get(array('date', 'weekdays_short'), $this->language) : call_user_func($this->messageProvider, array('date', 'weekdays_short'), $this->language); break; case 'l': $options = $this->messageProvider instanceof HTML_QuickForm2_MessageProvider ? $this->messageProvider->get(array('date', 'weekdays_long'), $this->language) : call_user_func($this->messageProvider, array('date', 'weekdays_long'), $this->language); break; case 'd': $options = $this->createOptionList(1, 31); break; case 'M': case 'm': case 'F': $options = $this->createOptionList($this->data['minMonth'], $this->data['maxMonth'], $this->data['minMonth'] > $this->data['maxMonth'] ? -1 : 1); if ('M' == $sign || 'F' == $sign) { $key = 'M' == $sign ? 'months_short' : 'months_long'; $names = $this->messageProvider instanceof HTML_QuickForm2_MessageProvider ? $this->messageProvider->get(array('date', $key), $this->language) : call_user_func($this->messageProvider, array('date', $key), $this->language); foreach ($options as $k => &$v) { $v = $names[$k - 1]; } } break; case 'Y': $options = $this->createOptionList($this->data['minYear'], $this->data['maxYear'], $this->data['minYear'] > $this->data['maxYear'] ? -1 : 1); break; case 'y': $options = $this->createOptionList($this->data['minYear'], $this->data['maxYear'], $this->data['minYear'] > $this->data['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($this->data['minHour'], $this->data['maxHour'], $this->data['minHour'] > $this->data['maxHour'] ? -1 : 1); break; case 'i': $options = $this->createOptionList(0, 59, $this->data['optionIncrement']['i']); break; case 's': $options = $this->createOptionList(0, 59, $this->data['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)) { $separators[] = $separator; } $separator = ''; // Should we add an empty option to the top of the select? if (!is_array($this->data['addEmptyOption']) && $this->data['addEmptyOption'] || is_array($this->data['addEmptyOption']) && !empty($this->data['addEmptyOption'][$sign])) { // Using '+' array operator to preserve the keys if (is_array($this->data['emptyOptionText']) && !empty($this->data['emptyOptionText'][$sign])) { $options = array($this->data['emptyOptionValue'] => $this->data['emptyOptionText'][$sign]) + $options; } else { $options = array($this->data['emptyOptionValue'] => $this->data['emptyOptionText']) + $options; } } $this->addSelect($sign, array('id' => self::generateId($this->getName() . "[{$sign}]")) + $this->getAttributes())->loadOptions($options); } } } $separators[] = $separator . ($backslash ? '\\' : ''); $this->setSeparator($separators); }
protected function getJavascriptCallback() { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_JavascriptBuilder'); $config = $this->getConfig(); $operand1 = $this->owner->getJavascriptValue(); $operand2 = $config['operand'] instanceof HTML_QuickForm2_Node ? $config['operand']->getJavascriptValue() : HTML_QuickForm2_JavascriptBuilder::encode($config['operand']); if (!in_array($config['operator'], array('===', '!=='))) { $check = "Number({$operand1}) {$config['operator']} Number({$operand2})"; } else { $check = "String({$operand1}) {$config['operator']} String({$operand2})"; } return "function () { return {$check}; }"; }
/** * Magic function; call an imported method of a renderer or its plugin * * @param string method name * @param array method arguments * @return mixed */ public function __call($name, $arguments) { $lower = strtolower($name); if (isset($this->_rendererMethods[$lower])) { // support fluent interfaces $ret = call_user_func_array(array($this->_renderer, $name), $arguments); return $ret === $this->_renderer ? $this : $ret; } // any additional plugins since last __call()? for ($i = count($this->_plugins); $i < count($this->_pluginClasses); $i++) { list($className, $includeFile) = $this->_pluginClasses[$i]; if (!class_exists($className)) { HTML_QuickForm2_Loader::loadClass($className, $includeFile); } $this->addPlugin($i, new $className()); } if (isset($this->_pluginMethods[$lower])) { return call_user_func_array(array($this->_plugins[$this->_pluginMethods[$lower]], $name), $arguments); } trigger_error("Fatal error: Call to undefined method " . get_class($this->_renderer) . "::" . $name . "()", E_USER_ERROR); }
/** * Generates a javascript function call to initialize hierselect behaviour * * @return string */ private function _generateInitScript() { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_JavascriptBuilder'); $ids = array(); /* @var $element HTML_QuickForm2_Element */ foreach ($this as $element) { $ids[] = $element->getId(); } return 'qf.elements.hierselect.init(' . HTML_QuickForm2_JavascriptBuilder::encode($ids) . (empty($this->jsCallback) ? '' : ", {$this->jsCallback}") . ');'; }
public function __toString() { HTML_QuickForm2_Loader::loadClass('HTML_QuickForm2_Renderer'); $renderer = $this->render(HTML_QuickForm2_Renderer::factory('default')); return $renderer->__toString() . $renderer->getJavascriptBuilder()->getSetupCode(null, true); }
/** * Creates a new Rule of the given type * * @param string Rule type name (treated case-insensitively) * @param HTML_QuickForm2_Node Element to validate by the rule * @param string Message to display if validation fails * @param mixed Configuration data for the rule * @return HTML_QuickForm2_Rule A created Rule * @throws HTML_QuickForm2_InvalidArgumentException If rule type is unknown * @throws HTML_QuickForm2_NotFoundException If class for the rule * can't be found and/or loaded from file */ public static function createRule($type, HTML_QuickForm2_Node $owner, $message = '', $config = null) { $type = strtolower($type); if (!isset(self::$registeredRules[$type])) { throw new HTML_QuickForm2_InvalidArgumentException("Rule '{$type}' is not known"); } list($className, $includeFile) = self::$registeredRules[$type]; HTML_QuickForm2_Loader::loadClass($className, $includeFile); if (isset(self::$registeredRules[$type][2])) { $config = call_user_func(array($className, 'mergeConfig'), $config, self::$registeredRules[$type][2]); } return new $className($owner, $message, $config); }
/** * Creates a new Rule of the given type * * @param string Rule type name (treated case-insensitively) * @param HTML_QuickForm2_Node Element to validate by the rule * @param string Message to display if validation fails * @param mixed Additional data for the rule * @return HTML_QuickForm2_Rule A created Rule * @throws HTML_QuickForm2_InvalidArgumentException If rule type is unknown * @throws HTML_QuickForm2_NotFoundException If class for the rule * can't be found and/or loaded from file */ public static function createRule($type, HTML_QuickForm2_Node $owner, $message = '', $options = null) { $type = strtolower($type); if (!isset(self::$registeredRules[$type])) { throw new HTML_QuickForm2_InvalidArgumentException("Rule '{$type}' is not known"); } list($className, $includeFile) = self::$registeredRules[$type]; HTML_QuickForm2_Loader::loadClass($className, $includeFile); return new $className($owner, $message, $options, $type); }