/** * Run the web application for the current request. * * NOTE: Both a module and page must be specified in the URL. If they are not BOTH specified, the server will REDIRECT the request to the full URL. * Therefore, you should be sure that when posting form data to a module/page, you use a full path. {@link WFRequestController::WFURL} * * Will pass control onto the current module for processing. * * Create a WFModuleInvocation based on the current HTTP Request, get the results, and output the completed web page. * * @todo Handle 404 situation better -- need to be able to detect this nicely from WFModuleInvocation.. maybe an Exception subclass? * @todo PATH_INFO with multiple params, where one is blank, isn't working correctly. IE, /url/a//c gets turned into /url/a/c for PATH_INFO thus we skip a "null" param. * NOTE: Partial solution; use /WFNull/ to indicate NULL param instead of // until we figure something out. * NOTE: Recent change to REQUEST_URI instead of PATH_INFO to solve decoding problem seems to have also solved the // => / conversion problem... test more! * WORRY: That the new PATH_INFO calculation will fail when using aliases other than WWW_ROOT. IE: /products/myProduct might break it... * @todo The set_error_handler doesn't seem to work very well. PHP issue? Or am I doing it wrong? For instance, it doesn't catch $obj->nonExistantMethod(). */ function handleHTTPRequest() { // point all error handling to phocoa's internal mechanisms since anything that happens after this line (try) will be routed through the framework's handler $this->registerErrorHandlers(); try { $relativeURI = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); // need to run this to convert absolute URI's to relative ones (sent by SOME http clients) if ($relativeURI === false) { throw new WFRequestController_NotFoundException("Malformed URI: {$_SERVER['REQUEST_URI']}"); } $modInvocationPath = ltrim(substr($relativeURI, strlen(WWW_ROOT)), '/'); $paramsPos = strpos($modInvocationPath, '?'); if ($paramsPos !== false) { $modInvocationPath = substr($modInvocationPath, 0, $paramsPos); } if ($modInvocationPath == '') { $modInvocationPath = WFWebApplication::sharedWebApplication()->defaultInvocationPath(); } // allow routing delegate to munge modInvocationPath $webAppDelegate = WFWebApplication::sharedWebApplication()->delegate(); if (is_object($webAppDelegate) && method_exists($webAppDelegate, 'rerouteInvocationPath')) { $newInvocationPath = $webAppDelegate->rerouteInvocationPath($modInvocationPath); if ($newInvocationPath) { $modInvocationPath = $newInvocationPath; } } // create the root invocation; only skin if we're not in an XHR $this->rootModuleInvocation = new WFModuleInvocation($modInvocationPath, NULL, $this->isAjax() ? NULL : WFWebApplication::sharedWebApplication()->defaultSkinDelegate()); // get HTML result of the module, and output it $html = $this->rootModuleInvocation->execute(); // respond to WFRPC::PARAM_ENABLE_AJAX_IFRAME_RESPONSE_MODE for iframe-targeted XHR. Some XHR requests (ie uploads) must be done by creating an iframe and targeting the form // post to the iframe rather than using XHR (since XHR doesn't support uploads methinks). This WFRPC flag makes these such "ajax" requests need to be wrapped slightly differently // to prevent the HTML returned in the IFRAME from executing in the IFRAME which would cause errors. if (isset($_REQUEST[WFRPC::PARAM_ENABLE_AJAX_IFRAME_RESPONSE_MODE]) && $_REQUEST[WFRPC::PARAM_ENABLE_AJAX_IFRAME_RESPONSE_MODE] == 1) { header('Content-Type: text/xml'); $html = "<" . "?xml version=\"1.0\"?" . "><raw><![CDATA[\n{$html}\n]]></raw>"; } print $html; } catch (WFPaginatorException $e) { // paginator fails by default should "route" to bad request. This keeps bots from going crazy. header("HTTP/1.0 400 Bad Request"); print "Bad Request: " . $e->getMessage(); } catch (WFRequestController_RedirectException $e) { header("HTTP/1.1 {$e->getCode()}"); header("Location: {$e->getRedirectURL()}"); } catch (WFRequestController_HTTPException $e) { header("HTTP/1.0 {$e->getCode()}"); print $e->getMessage(); } catch (WFRequestController_BadRequestException $e) { header("HTTP/1.0 400 Bad Request"); print "Bad Request: " . $e->getMessage(); } catch (WFRequestController_NotFoundException $e) { header("HTTP/1.0 404 Not Found"); print $e->getMessage(); } catch (WFRequestController_InternalRedirectException $e) { // internal redirect are handled without going back to the browser... a little bit of hacking here to process a new invocationPath as a "request" // @todo - not sure what consequences this has on $_REQUEST; seems that they'd probably stay intact which could foul things up? $_SERVER['REQUEST_URI'] = $e->getRedirectURL(); WFLog::log("Internal redirect to: {$_SERVER['REQUEST_URI']}"); self::handleHTTPRequest(); } catch (WFRedirectRequestException $e) { header("Location: " . $e->getRedirectURL()); } catch (Exception $e) { $this->handleException($e); } }
/** * Load the shared.config file for the module and process it. * * The shared.config file is an OPTIONAL component. * If your module has no instances, or the instances don't need configuration, you don't need a shared.config file. * * The shared.config file can only configure properties of objects at this time. * Only primitive value types may be used. String, boolean, integer, double, NULL. NO arrays or objects allowed. * * <code> * $__config = array( * 'instanceID' => array( * 'properties' => array( * 'propName' => 'Property Value', * 'propName2' => 123 * ) * ), * 'instanceID2' => array( * 'properties' => array( * 'propName' => 'Property Value', * 'propName2' => true * ) * ) * ); * </code> * * @param string The absolute path to the config file. * @throws Various errors if configs are encountered for for non-existant instances, etc. A properly config'd page should never throw. * @see loadConfigYAML */ protected function loadConfigPHP($configFile) { // be graceful; if there is no config file, no biggie, just don't load config! if (!file_exists($configFile)) { return; } include $configFile; foreach ($__config as $id => $config) { WFLog::log("loading config for id '{$id}'", WFLog::TRACE_LOG); // get the instance to apply config to if (!isset($this->{$id})) { throw new WFException("Couldn't find shared instance with ID '{$id}' to configure."); } $configObject = $this->{$id}; // atrributes if (isset($config['properties'])) { foreach ($config['properties'] as $keyPath => $value) { switch (gettype($value)) { case "boolean": case "integer": case "double": case "string": case "NULL": // these are all OK, fall through break; default: throw new WFException("Config value for shared instance id::property '{$id}::{$keyPath}' is not a vaild type (" . gettype($value) . "). Only boolean, integer, double, string, or NULL allowed."); break; } WFLog::log("SharedConfig:: Setting '{$id}' property, {$keyPath} => {$value}", WFLog::TRACE_LOG); $configObject->setValueForKeyPath($value, $keyPath); } } } }
function willNotRunAction() { WFLog::log("Running willNotRunAction...", WFLog::TRACE_LOG); if ($this->delegate && method_exists($this->delegate, 'willNotRunAction')) { $this->delegate->willNotRunAction($this, $this->parameters()); } }
function processBindingOptions($boundProperty, $options, &$boundValue) { parent::processBindingOptions($boundProperty, $options, $boundValue); switch ($boundProperty) { case 'contentValues': if ($options[WFBindingSetup::WFBINDINGSETUP_INSERTS_NULL_PLACEHOLDER]) { $defaultValue = $options[WFBindingSetup::WFBINDINGSETUP_NULL_PLACEHOLDER]; $boundValue = array_merge(array($defaultValue), $boundValue); } break; case 'contentLabels': if ($options[WFBindingSetup::WFBINDINGSETUP_INSERTS_NULL_PLACEHOLDER]) { $defaultLabel = $options[WFBindingSetup::WFBINDINGSETUP_NULL_PLACEHOLDER]; $boundValue = array_merge(array($defaultLabel), $boundValue); } break; case 'options': if ($options[WFBindingSetup::WFBINDINGSETUP_INSERTS_NULL_PLACEHOLDER]) { $defaultLabel = $options[WFBindingSetup::WFBINDINGSETUP_NULL_PLACEHOLDER]; WFLog::log("BEFORE: " . var_export($boundValue, true)); $boundValue = array('' => $defaultLabel) + $boundValue; WFLog::log("AFTER: " . var_export($boundValue, true)); } break; } }
/** * Execute the RPC. This function is called by the PHOCOA infrastructure to "execute" the RPC request in the PHOCOA infrastructure. * * If the target/action method returns a {@link WFActionResponse} object, the response will be sent and execution will stop. * If the target/action method returns NULL, execution will fall through to the caller. * * @param object WFPage The current page. * @return void */ function execute($page) { $bcMode = false; // setup backwards-compatibility for really old-school if (!$page->delegate() and strncmp($this->target, WFRPC::TARGET_PAGE, strlen(WFRPC::TARGET_PAGE)) == 0) { $bcMode = true; $this->action = $page->pageName() . '_' . $this->action . '_Action'; $this->target = '#module#'; } // calculate target $matches = array(); if (!preg_match('/^(#page#|#module#)([^\\.]+)?(.*)/', $this->target, $matches)) { throw new WFException("Couldn't parse target: {$this->target}."); } list($targetStr, $pageOrModule, $outletId, $keyPath) = $matches; $targetObj = NULL; switch ($pageOrModule) { case WFRPC::TARGET_PAGE: $targetObj = $page; break; case WFRPC::TARGET_MODULE: $targetObj = $page->module(); break; default: throw new WFException("Couldn't parse target: {$this->target}."); } if ($outletId) { $targetObj = $targetObj->outlet($outletId); } else { if ($targetObj instanceof WFPage && $this->action !== 'noAction') { $targetObj = $targetObj->delegate(); } } if ($keyPath) { $targetObj = $targetObj->valueForKeyPath($keyPath); } $rpcCall = array($targetObj, $this->action); if (!is_callable($rpcCall)) { if ($bcMode) { // old-school throw new WFException("Backwards-compatibility mode WFRPC: action is not callable: " . $this->action); } else { // new school throw new WFException("WFRPC Invocation is not callable: " . $this->target . "->" . $this->action . "(). Please ensure that there is a method of that name on the specified object."); } } WFLog::log("Running target/action: '{$this->target}/{$this->action}'", WFLog::TRACE_LOG); $result = call_user_func_array($rpcCall, array_merge(array($page, $page->parameters()), $this->args)); if ($result !== NULL) { if (!$this->isAjax()) { throw new WFException("Functions shouldn't return WFActionResponse objects if not in AJAX mode."); } // if the action method returned a WFActionResponse if (gettype($result) == 'string') { $result = new WFActionResponsePlain($result); } if (!$result instanceof WFActionResponse) { throw new WFException("Unexpected WFActionResponse."); } $result->send(); } }
function addChild(WFView $view) { parent::addChild($view); if ($view instanceof WFSubmit) { $this->numberOfSubmitButtons++; // if if the FIRST one, save it; otherwise, if ($this->calculatedDefaultSubmitID === WFForm::CALCULATED_DEFAULT_SUBMIT_ID_NONE) { $this->calculatedDefaultSubmitID = $view->id(); } else { if (!$this->defaultSubmitID) { $this->calculatedDefaultSubmitID = WFForm::CALCULATED_DEFAULT_SUBMIT_ID_CANNOT_DETERMINE; WFLog::log("Form id: '{$this->id}' is unable to determine the default button for the form. You should set one via defaultSubmitID to avoid errors in some browsers.", WFLog::WARN_LOG); } } } }
/** * Create the dynamic widgets. * * Allows for creation of n widgets based on an WFArrayController. Various options allow you to set up nearly any type * of widget that is repeated for all objects in an array. Great for managing selection, editing data from joins, etc. * * Once the objects are instantiated, configured, and bound as appropriate, restoreState() will be called. You can be sure that * when this function exits that your widgets are in the same state as statically instantiated widgets from the page. * * This will be called AFTER the _PageDidLoad method... which is what we need to wait for before creating our widgets. WFPage makes this call. * * Module code may need to call this function again, particularly if the content of they arrayController is changed by the current action. * * @return assoc_array An array of 'widgetID' => widget for all newly created widgets. * @todo Anything else wrong with calling more than once? This should be idempotent as well as re-callable with different data. */ function createWidgets() { // check params if (!is_object($this->arrayController)) { throw new Exception("No WFArrayController assigned to WFDynamic. Set the arrayController object for WFDynamic '{$this->id}'."); } if (!$this->arrayController instanceof WFArrayController) { throw new Exception("arrayController must be a WFArrayController instance."); } // have we already done createWidgets for this version of the arrayController? if ($this->arrayController->changeCount() == $this->createdWidgetsChangeCount) { WFLog::log("Not rebuilding widgets because changeCount has not changed... " . $this->arrayController->changeCount() . ' ' . $this->id(), WFLog::TRACE_LOG); return; } else { WFLog::log("rebuilding widgets because changeCount changed... " . $this->arrayController->changeCount() . ' ' . $this->id(), WFLog::TRACE_LOG); } // update change count $this->createdWidgetsChangeCount = $this->arrayController->changeCount(); // remove existing widgets from page foreach ($this->createdWidgets as $existingWidget) { WFLog::log("Removing dynamically created widget: " . $existingWidget->id(), WFLog::WARN_LOG); $this->page->removeInstance($existingWidget->id()); if ($this->parent) { $this->parent->removeChild($existingWidget); } } $arrayController = $this->arrayController; $widgetClass = $this->widgetClass; $widgetBaseName = $this->id; $useUniqueNames = $this->useUniqueNames; $parentView = $this->calculateParent(); $this->createdWidgets = array(); // check params if (!class_exists($widgetClass)) { throw new Exception("There is no widget class '{$widgetClass}'."); } $this->processWidgetConfig(); $currentIndex = 0; foreach ($arrayController->arrangedObjects() as $object) { // instantiate the widget with a unique ID if ($arrayController->usingIndexedMode()) { $id = $widgetBaseName . '_' . $currentIndex; } else { $id = $widgetBaseName . '_' . $arrayController->identifierHashForObject($object); } // instantiate widget if (!is_null($this->prototype)) { $widget = $this->prototype->cloneWithID($id); // copy onEvent script to the clone $widget->setOnEvent($this->prototype->getOnEvent()); } else { $widget = new $widgetClass($id, $this->page()); } // add to form if needed if ($parentView) { $parentView->addChild($widget); } // add to our list $this->createdWidgets[] = $widget; // set up the name if (!$useUniqueNames) { $widget->setName($widgetBaseName); } WFLog::log("WFDynamic:: created {$widgetClass} id={$id} name=" . $widget->name()); // set up properties if ($this->formatter) { $widget->setFormatter($this->formatter); } foreach ($this->widgetConfig as $propName => $propInfo) { // set up custom value and/or binding if (!isset($propInfo['custom']) and !isset($propInfo['bind'])) { throw new Exception("You must supply either 'custom' or 'bind' information. (propName: {$propName})"); } $customValue = NULL; if (isset($propInfo['custom'])) { $customSettings = $propInfo['custom']; // make sure it has all expected pieces if (!isset($customSettings['iterate'])) { throw new Exception("An 'iterate' setting must be provided. (propName: {$propName})"); } // use a different value for each iteration if ($customSettings['iterate']) { // use the keyPath of the current object if (isset($customSettings['keyPath']) and $customSettings['keyPath'] !== false) { if ($customSettings['keyPath'] == '#identifier#') { if ($arrayController->usingIndexedMode()) { $customValue = $currentIndex; } else { $customValue = $arrayController->identifierHashForObject($object); } } else { $customValue = $object->valueForKeyPath($customSettings['keyPath']); } } else { if (!is_array($customSettings['value'])) { throw new Exception('If iterate and you supply a value, value must be an array. (propName: {$propName})'); } $customValue = $customSettings['value'][$currentIndex]; } } else { if (!isset($customSettings['value'])) { throw new Exception("If not iterate, a 'value' must be provided. (propName: {$propName})"); } $customValue = $customSettings['value']; } WFLog::log("WFDynamic:: setting {$propName} to {$customValue} for {$id}", WFLog::TRACE_LOG); $widget->setValueForKey($customValue, $propName); } // or are we using bindings if (isset($propInfo['bind'])) { $bindingInfo = $propInfo['bind']; WFLog::log("WFDynamic:: Binding property '{$propName}' to {$bindingInfo['instanceID']} => {$bindingInfo['controllerKey']}::{$bindingInfo['modelKeyPath']}", WFLog::TRACE_LOG); // determine object to bind to: if (!isset($bindingInfo['instanceID'])) { throw new Exception("No instance id specified for binding property '{$propName}'."); } $bindToObject = NULL; if ($bindingInfo['instanceID'] == '#module#') { $bindToObject = $parentView->page()->module(); } else { if ($bindingInfo['instanceID'] == '#custom#') { if (!is_object($customValue)) { throw new Exception("Could not determine custom bindToObject ({$bindingInfo['instanceID']}) for binding property '{$propName}'."); } $bindToObject = $customValue; } else { if ($bindingInfo['instanceID'] == '#current#') { $bindToObject = $object; } else { $bindToObject = $parentView->page()->outlet($bindingInfo['instanceID']); } } } if (is_null($bindToObject)) { throw new Exception("Could not determine bindToObject ({$bindingInfo['instanceID']}) for binding property '{$propName}'."); } $fullKeyPath = ''; if (isset($bindingInfo['controllerKey'])) { $fullKeyPath .= $bindingInfo['controllerKey']; } if (isset($bindingInfo['modelKeyPath'])) { if (!empty($fullKeyPath)) { $fullKeyPath .= '.'; } $fullKeyPath .= $bindingInfo['modelKeyPath']; } if (empty($fullKeyPath)) { throw new Exception("No keyPath specified for binding property '{$propName}'"); } // process options $options = NULL; if (isset($bindingInfo['options'])) { $options = $bindingInfo['options']; } try { $widget->bind($propName, $bindToObject, $fullKeyPath, $options); } catch (Exception $e) { throw $e; } } } // now that we've loaded all widget options (config), call the callback so that the widget can set itself up. $widget->allConfigFinishedLoading(); // OH BOY. This used to work the first way, and the 2nd way was commented out. But I ran into a bug (calling restoreState when not on proper form would restore incorrect state). No idea why it was the other way... // switching to the 2nd state probably broke something else :( BEWARE! // @todo RESOLVE this issue and leave correct code and remove incorrect code. if (0) { $this->restoreState(); } else { // have widget restore state, only if we've posted! otherwise it will grab improper state if ($parentView and $parentView->page()->submittedFormName()) { $widget->restoreState(); } } $currentIndex++; } return $this->createdWidgets; }
/** * Set the value of the checkbox control. What this does basically, is that if the passed value is the same as the checkedValue, then * the checkbox will become checked. Otherwise, it will become unchecked. * @param mixed The value to set for the control. */ function setValue($v) { if ($v == $this->checkedValue) { $this->setChecked(true); } else { if ($v == $this->uncheckedValue) { $this->setChecked(false); } else { WFLog::log('Warning!!! Checkbox ID ' . $this->id . " checked state not restored because passed value '{$v}' is not equal to checked ({$this->checkedValue}) or unchecked ({$this->uncheckedValue}) value."); } } }
public function deprecated($message) { // intersects with E_DEPRECATED? http://php.net/manual/en/errorfunc.constants.php WFLog::log($message, 'deprecated', PEAR_LOG_NOTICE); }
/** * Constructor. * * Sets up the smarty object for this module. */ function __construct($id, $page) { parent::__construct(); if (is_null($id)) { throw new Exception("id required for new " . get_class($this) . '.'); } if (!$page instanceof WFPage) { throw new Exception("page must be a WFPage."); } // warn about invalid ID's switch ($id) { case 'new': case 'delete': WFLog::log("The id '{$id}' is dangerous to use because it is a reserved word in some browsers Javascript engines. For best compatibility, use a different ID.", WFLog::WARN_LOG); break; } $this->id = $id; $this->enabled = true; $this->children = array(); $this->parent = NULL; $this->page = $page; $this->setId($id); $this->jsActions = array(); $this->jsEvents = array(); $this->originalOnEvent = NULL; // js/css import infrastructure $this->importInHead = false; $this->jsImports = array(); $this->cssImports = array(); }
/** * Propagate the value from the UI widget to the bound object. * * This method will automatically call the validator for the binding, if it exists. * If the value is valid, it will also push the value onto the bound object with setValueForKeyPath. * * Any validation errors are stored in the widget's error list. * * If the value of the widget is equivalent to an empty string ($value === '') then value is converted into PHP NULL. * Since all values in widgets come from the UI, and there is no distinction in the UI world b/w "" and NULL, we normalize all "" values to NULL. * It is left up to objects to then distinguish between NULL and "" (via normalization in Key-Value Validation). * * @param string The name of the binding to propagate back to the bound object. * @param mixed The value from the UI widget (submitted by the form). * @return mixed The cleaned-up value from validateValueForKeyPath() */ function propagateValueToBinding($bindingName, $value) { // the bindable property may not be bound! The is legitimate, so be graceful about it. $binding = $this->bindingByName($bindingName); if (is_null($binding)) { return $value; } // check OPTION_DO_NOT_PUSH_VALUE_SEMAPHORE if ($binding->hasCoalescedOption(WFBinding::OPTION_DO_NOT_PUSH_VALUE_SEMAPHORE) and $binding->coalescedOption(WFBinding::OPTION_DO_NOT_PUSH_VALUE_SEMAPHORE) === $value) { $func = WFFunction::create('return "propagateValueToBinding() skipping push for {$bindingName} since value matched OPTION_DO_NOT_PUSH_VALUE_SEMAPHORE for for widget id \'{$id}\'";')->withArguments('bindingName', 'id')->curry($bindingName, $this->id); WFLog::log($func, WFLog::TRACE_LOG); return $value; } // assert for r/o bindings. if ($binding->bindingSetup()->readOnly()) { throw new Exception("Attempt to propagateValueToBinding for a read-only binding: {$this->id} / {$bindingName}."); } if (!$binding->canWriteBoundValue()) { throw new Exception("Attempt to propagateValueToBinding for a binding with that doesn't allow writing."); } // normalize "" string values to NULL. Do this pre-validation; that function can do normalization etc. // we simply cover the case of TOTALLY EMPTY STRING is equivalent to NULL here. if ($value === '') { $value = NULL; } $edited = false; $func = WFFunction::create('return "propagateValueToBinding() validating value \'$value\' for bound object \'" . $class . "\' for widget id \'{$id}\' binding: \'{$bindingName}\'";')->withArguments('value', 'class', 'id', 'bindingName')->curry($value, get_class($this), $this->id, $bindingName); WFLog::log($func, WFLog::TRACE_LOG); $errors = array(); $valid = $binding->bindToObject()->validateValueForKeyPath($value, $binding->bindToKeyPath(), $edited, $errors); if ($valid) { $func = WFFunction::create('return "propagateValueToBinding() Pushing value \'$value\' for bound object \'" . $class . "\' for widget id \'{$id}\' binding: \'{$bindingName}\'";')->withArguments('value', 'class', 'id', 'bindingName')->curry($value, get_class($this), $this->id, $bindingName); WFLog::log($func, WFLog::TRACE_LOG); $binding->bindToObject()->setValueForKeyPath($value, $binding->bindToKeyPath()); } else { $func = WFFunction::create('return "propagateValueToBinding() WILL NOT (did not validate) push value \'$value\' for bound object \'" . $class . "\' for widget id \'{$id}\' binding: \'{$bindingName}\'";')->withArguments('value', 'class', 'id', 'bindingName')->curry($value, get_class($this), $this->id, $bindingName); WFLog::log($func, WFLog::TRACE_LOG); // keep all returned errors $this->addErrors($errors); } // return cleaned-up value so UI can update return $value; }
/** * Validate the given value for the given key. * * Clients can normalize the value, and also report and error if the value is not valid. * * If the value is valid without modificiation, return TRUE and do not alter $edited or $error. * If the value is valid after being modified, return TRUE, and $edited to true. * IF the value is not valid, do not alter $value or $edited, but fill out the $error object with desired information. * * The default implementation (in WFObject) looks for a method named validate<key> and calls it, otherwise it returns TRUE. Here is the prototype: * <code> * (boolean) function(&$value, &$edited, &$errors) * </code> * * @param mixed A reference to value to check. Passed by reference so that the implementation can normalize the data. * @param string keyPath the keyPath for the value. * @param boolean A reference to a boolean. This value will always be FALSE when the method is called. If the implementation edits the $value, set to TRUE. * @param array An array of WFError objects describing the error. The array is empty by default; you can add new error entries with: * <code> * $error[] = new WFError('My error message'); // could also add an error code (string) parameter. * </code> * @return boolean TRUE indicates a valid value, FALSE indicates an error. */ function validateValueForKey(&$value, $key, &$edited, &$errors) { $valid = true; // try calling validator $validatorMethod = 'validate' . ucfirst($key); if (method_exists($this, $validatorMethod)) { // track whether or not validator lies $errCount = count($errors); // run validator $valid = $this->{$validatorMethod}($value, $edited, $errors); // check for mismatch b/w $valid and errors generated $errCount = count($errors) - $errCount; if ($valid && $errCount) { throw new WFException("Validator for key '{$key}' returned TRUE but also returned errors."); } else { if (!$valid && $errCount === 0) { throw new WFException("Validator for key '{$key}' returned FALSE but didn't provide any errors."); } } } if (!$valid) { WFLog::log("Errors: " . print_r($errors, true), WFLog::TRACE_LOG); } return $valid; }
function restoreState() { parent::restoreState(); WFLog::log("WFCheckboxGroup restoreState()<bR>"); // restore state of all children foreach ($this->children() as $checkbox) { $checkbox->restoreState(); } // rebuild our meta-value $this->updateGroupValues(); WFLog::log("WFCheckboxGroup restoreState() done, value now:" . $this->values); }
function handleUploadedFile() { if ($this->hasUpload()) { try { call_user_func($this->hasUploadCallback, $this->page(), $this->page()->parameters(), $this); // send back success print "UPLOAD OK"; } catch (Exception $e) { // send back error+noretry print "UPLOAD ERROR: " . $e->getMessage(); WFLog::log("UPLOAD ERROR: {$e->getMessage()}", WFLog::TRACE_LOG, PEAR_LOG_ERR); } exit; } }