Ejemplo n.º 1
0
 /**
  * Retrieves HTML code of relating elements of initially related or
  * explicitly selected element.
  *
  * @param array $data custom data to be passed to template on rendering
  * @param string $template name of custom template to use instead of default one on rendering
  * @param int $listNodeAtIndex index of node to list properties of
  *        (default: node at opposite end of relation)
  * @return string rendering result
  */
 public function render($data = array(), $template = null, $listNodeAtIndex = -1)
 {
     $query = $this->query();
     // extend query to fetch all properties of selected node's model
     $query->addProperty($this->datasource->qualifyDatasetName($this->nodeAtIndex($listNodeAtIndex)->getName()) . '.*');
     // process query
     $matches = $query->execute()->all();
     // start variable space initialized using provided set of custom data
     $data = variable_space::fromArray($data);
     // add fetched relation instances to variable space
     $data->update('matches', $matches);
     // add reference on current relation manager instance
     $data->update('relation', $this);
     // render variable space using selected or default template
     return view::render($template ? $template : 'model/relation/generic', $data);
 }
Ejemplo n.º 2
0
 /**
  * Processes input while editing/adding user record.
  *
  * @param sql_user $provider provider used on creating new user record
  * @param int|false $userId ID of user to edit, false/0 on adding new user
  * @return sql_user|null edited or created user, null if creating user failed
  */
 protected function processInputOnEditing($provider, $userId)
 {
     if ($userId) {
         $user = user::load($userId);
         $userData = array('id' => $user->getID(), 'loginname' => $user->getLoginName(), 'name' => $user->getName(), 'email' => $user->getProperty('email'));
     } else {
         $user = null;
         $userData = array();
     }
     $form = $this->getForm($userData);
     if ($form->hasInput()) {
         if (input::vget('submit') == 'cancel') {
             txf::redirectTo($this->getUrls()->list);
         }
         /*
          * read in and normalize all provided information on user
          */
         $loginName = $user ? $userData['loginname'] : trim(input::vget('loginname'));
         $name = trim(input::vget('name'));
         $email = trim(input::vget('email'));
         $passwordA = trim(input::vget('password'));
         $passwordB = trim(input::vget('repeat'));
         /*
          * validate all information on user
          */
         if ($loginName === '') {
             $form->setRowError('loginname', \de\toxa\txf\_L('Provide login name of user!'));
         } else {
             if (strlen($loginName) > 64) {
                 $form->setRowError('loginname', \de\toxa\txf\_L('Provided login name is too long!'));
             }
         }
         if ($name && strlen($name) > 128) {
             $form->setRowError('loginname', \de\toxa\txf\_L('Provided full name is too long!'));
         }
         if ($email) {
             if (strlen($name) > 128) {
                 $form->setRowError('loginname', \de\toxa\txf\_L('Provided mail address is too long!'));
             } else {
                 if (!\de\toxa\txf\mail::isValidAddress($email)) {
                     $form->setRowError('email', \de\toxa\txf\_L('Provided mail address is invalid!'));
                 }
             }
         }
         // validate optionally provided password
         if (!$user || $passwordA || $passwordB) {
             if ($passwordA === '' || $passwordB === '') {
                 if ($user) {
                     $form->setRowError('password', \de\toxa\txf\_l('Provide new password twice for excluding typos.'));
                 } else {
                     $form->setRowError('password', \de\toxa\txf\_l('Provide password of new user and repeat for excluding typos.'));
                 }
             } else {
                 if ($passwordA !== $passwordB) {
                     $form->setRowError('password', \de\toxa\txf\_L('Doubly entered passwords don\'t match.'));
                 } else {
                     try {
                         if (is_callable($this->passwordValidator)) {
                             call_user_func($this->passwordValidator, $passwordA);
                         } else {
                             $this->passwordValidatorDefault($passwordA);
                         }
                     } catch (\InvalidArgumentException $e) {
                         $form->setRowError('password', $e->getMessage());
                     }
                 }
             }
         }
         /*
          * save changes to datasource
          */
         $hasError = $form->hasAnyRowError();
         if (!$hasError) {
             exception::enterSensitive();
             if ($user) {
                 try {
                     $user->datasource()->transaction()->wrap(function (datasource\connection $conn) use($user, $name, $email, $passwordA) {
                         $user->setProperty('name', $name);
                         $user->setProperty('email', $email);
                         if (trim($passwordA) !== '') {
                             $user->changePassword($passwordA);
                             if ($user->getUUID() === user::current()->getUUID()) {
                                 try {
                                     user::current()->authenticate($passwordA);
                                 } catch (unauthorized_exception $e) {
                                     view::flash(\de\toxa\txf\_L('Updating current session for using changed password failed. Probably you need to login, again.'), 'error');
                                 }
                             }
                         }
                         view::flash(\de\toxa\txf\_L('Successfully changed information on selected user.'));
                         return true;
                     });
                 } catch (\Exception $e) {
                     $hasError = true;
                     view::flash(\de\toxa\txf\_L('Failed to save information on user in datasource.'), 'error');
                 }
             } else {
                 try {
                     $user = $provider->create(array('loginname' => $loginName, 'name' => $name, 'password' => $passwordA, 'email' => $email, 'lock' => ''));
                     view::flash(\de\toxa\txf\_L('Successfully created new user.'));
                 } catch (\Exception $e) {
                     $hasError = true;
                     view::flash(\de\toxa\txf\_L('Failed to create new user record in datasource.'), 'error');
                 }
             }
             exception::leaveSensitive();
         }
         if (!$hasError) {
             txf::redirectTo($this->getUrls()->list);
         }
     }
     return $user;
 }
Ejemplo n.º 3
0
 public function performDelete()
 {
     if (!user::current()->isAuthenticated()) {
         throw new http_exception(403);
     }
     $this->prepareControl();
     try {
         $this->getSelectedItem()->delete();
     } catch (datasource_exception $e) {
         view::flash(\de\toxa\txf\_L('Failed deleting selected item.'), 'error');
     } catch (\RuntimeException $e) {
         view::flash(\de\toxa\txf\_L('Selected item does not exist (anymore).'), 'error');
     }
     txf::redirectTo($this->getUrls()->list);
 }
Ejemplo n.º 4
0
 /**
  * Maps viewports onto regions of page.
  *
  * This mapping is supported to improve content/view abstraction by enabling
  * content of viewports being assembled into code of page's regions in a
  * configurable way ...
  *
  * @param array $viewports content of viewports
  * @return array content of regions
  */
 protected function collectRegions($viewports)
 {
     $configs = array(config::getList('view.region'), array(array('name' => 'main', 'viewport' => array('flash', 'title', 'error', 'main')), array('name' => 'head', 'viewport' => array('header')), array('name' => 'foot', 'viewport' => array('footer', 'debug')), array('name' => 'left', 'viewport' => array('navigation')), array('name' => 'right', 'viewport' => array('aside'))));
     $regions = array();
     foreach ($configs as $config) {
         if (is_array($config)) {
             foreach ($config as $region) {
                 // get name of region to customize
                 $name = trim(@$region['name']);
                 if ($name === '') {
                     log::debug('ignoring nameless region configuration');
                     continue;
                 }
                 if (!array_key_exists($name, $regions)) {
                     // region haven't been collected before ...
                     if (array_key_exists('code', $region)) {
                         // there is a line of code containing markers selecting viewports to collect their content in current region
                         // e.g. "{{title}}<some-literal-content-to-insert/>{{main}}"
                         $regions[$name] = data::qualifyString($region['code'], $viewports);
                     } else {
                         if (is_array(@$region['viewport'])) {
                             // collect set of viewports named in configuration
                             foreach (@$region['viewport'] as $viewportName) {
                                 $regions[$name] .= \de\toxa\txf\view::wrapNotEmpty(@$viewports[$viewportName], config::get('view.viewport.wrap.' . $viewportName, ''));
                             }
                         }
                     }
                     // support default content to show if a region keeps empty finally
                     if (trim($regions[$name]) === '') {
                         $regions[$name] = trim(@$region['default']);
                     }
                     // process any additionally contained markers
                     $regions[$name] = data::qualifyString($regions[$name]);
                 }
             }
         }
     }
     return $regions;
 }
Ejemplo n.º 5
0
 /**
  * Processes input on current editor.
  *
  * @param callable $validatorCallback
  * @return bool|string false on input failures requiring user action,
  *                     "saved" on input successfully saved to data source,
  *                     "cancel" on user pressing cancel button,
  *                     "delete" on user deleting record
  */
 public function processInput($validatorCallback = null)
 {
     if ($this->hasInput()) {
         switch (input::vget('_cmd')) {
             case 'cancel':
                 // permit closing editor due to user requesting to cancel editing
                 return 'cancel';
             case 'delete':
                 // delete current edited item
                 if ($this->may['delete'] && $this->item) {
                     $ctx = $this;
                     $item = $this->item;
                     $fields = $this->fields;
                     $this->datasource->transaction()->wrap(function () use($ctx, $item, $fields) {
                         foreach ($fields as $field) {
                             /** @var model_editor_field $field */
                             $field->type()->onDeleting($ctx, $item, $field);
                         }
                         $item->delete();
                         return true;
                     });
                     $this->item = null;
                     return 'delete';
                 }
                 view::flash(\de\toxa\txf\_L('You must not delete this item.'), 'error');
                 return false;
             case 'save':
                 // extract some protected properties from current instance to be used in transaction-wrapped callback
                 $ctx = $this;
                 $class = $this->class;
                 $source = $this->datasource;
                 $fields = $this->fields;
                 $enabled = $this->enabled;
                 $item = $this->item;
                 $fixed = $this->getFixed();
                 $errors = array();
                 $this->onCreating = !$this->hasItem();
                 if (!$this->onCreating && !$this->may['edit']) {
                     view::flash(\de\toxa\txf\_L('You must not edit this item.'), 'error');
                     return false;
                 }
                 // wrap modification on model in transaction
                 $success = $source->transaction()->wrap(function () use($ctx, $class, $source, $fields, $enabled, $fixed, &$item, &$errors, $validatorCallback) {
                     $properties = array();
                     foreach ($fields as $property => $definition) {
                         /** @var model_editor_field $definition */
                         if (!count($enabled) || !@$enabled[$property]) {
                             try {
                                 // normalize input
                                 $input = call_user_func(array($definition->type(), 'normalize'), $ctx->getValue($property, $definition->isCustom()), $property, $ctx);
                                 // validate input
                                 $success = call_user_func(array($definition->type(), 'validate'), $input, $property, $ctx);
                                 // save input if valid
                                 if ($success) {
                                     $properties[$property] = $input;
                                 } else {
                                     $errors[$property] = \de\toxa\txf\_L('Your input is invalid.');
                                 }
                             } catch (\Exception $e) {
                                 $errors[$property] = $e->getMessage();
                             }
                         }
                     }
                     if (count($errors)) {
                         return false;
                     }
                     if (is_callable($validatorCallback)) {
                         // provide opportunity to qualify properties for validation
                         $qualified = $properties;
                         foreach ($fields as $field) {
                             /** @var model_editor_field $field */
                             $qualified = $field->type()->beforeValidating($ctx, $item, $qualified, $field);
                         }
                         // invoke custom callback given those qualified copy of properties for validating
                         $localErrors = call_user_func($validatorCallback, $qualified, $errors, $item ? $item->id() : null);
                         if ($localErrors === false || is_string($localErrors) || is_array($localErrors) && count($localErrors)) {
                             if (is_array($localErrors)) {
                                 $errors = array_merge($errors, $localErrors);
                             } else {
                                 if (is_string($localErrors)) {
                                     view::flash($localErrors, 'error');
                                 }
                             }
                             return false;
                         }
                     }
                     if ($item) {
                         // on updating item -> don't adjust values of
                         // properties marked as fixed
                         foreach ($fixed as $name => $value) {
                             unset($properties[$name]);
                         }
                     } else {
                         // creating new item -> ensure to use fixed initial
                         // values provided additionally
                         foreach ($fixed as $name => $value) {
                             $properties[$name] = $value;
                         }
                     }
                     // optionally pre-process saving properties of item
                     foreach ($fields as $field) {
                         /** @var model_editor_field $field */
                         $properties = $field->type()->beforeStoring($ctx, $item, $properties, $field);
                     }
                     if ($item) {
                         // update properties of existing item
                         foreach ($properties as $name => $value) {
                             $item->__set($name, $value);
                         }
                     } else {
                         // create new item
                         $item = $class->getMethod('create')->invoke(null, $source, $properties);
                         // tell all elements to have item now
                         foreach ($fields as $field) {
                             /** @var model_editor_field $field */
                             $field->type()->onSelectingItem($ctx, $item, $field);
                         }
                     }
                     // optionally post-process saving properties of item
                     foreach ($fields as $field) {
                         /** @var model_editor_field $field */
                         $item = $field->type()->afterStoring($ctx, $item, $properties, $field);
                     }
                     return true;
                 });
                 // transfer adjusted properties back to protected scope of current instance
                 $this->errors = $errors;
                 // write back item created or probably replaced by afterStoring() call in transaction
                 $this->item = $item;
                 if ($success) {
                     // permit closing editor after having saved all current input
                     view::flash(\de\toxa\txf\_L('Your changes have been saved.'));
                     return 'saved';
                 }
                 view::flash(\de\toxa\txf\_L('Failed to save your changes.'), 'error');
         }
     }
     // don't close editor
     return false;
 }
Ejemplo n.º 6
0
 /**
  * Processes input of widget updating its internal state.
  *
  * @return $this current instance
  */
 public function processInput()
 {
     if (user::current()->isAuthenticated()) {
         view::flash(\de\toxa\txf\_L('You are logged in, already.'));
         $this->redirect();
     }
     $form = $this->getForm();
     if ($form->hasInput()) {
         if (input::vget('submit') == 'cancel') {
             $this->redirect();
         }
         $username = input::vget('name');
         if ($username) {
             try {
                 user::setCurrent(user::load($username), input::vget('token'));
                 $this->redirect();
             } catch (unauthorized_exception $ex) {
                 if ($ex->isAccountLocked()) {
                     if ($this->resendUnlockMailUrl) {
                         view::flash(sprintf(\de\toxa\txf\_L('Your account is locked! <a href="%s">Resend unlock mail now.</a>'), sprintf($this->resendUnlockMailUrl, $ex->getUser()->getID())), 'error');
                     } else {
                         view::flash(sprintf(\de\toxa\txf\_L('Your account is locked!')), 'error');
                     }
                 } else {
                     sleep(3);
                     if ($ex->isUserNotFound()) {
                         view::flash(\de\toxa\txf\_L('User does not exist.'), 'error');
                     } else {
                         view::flash(\de\toxa\txf\_L('Authentication failed.'), 'error');
                     }
                 }
             }
         } else {
             view::flash(\de\toxa\txf\_L('Provide login name and password!'));
         }
     } else {
         $session =& txf::session();
         $referrer = input::vget('referrer');
         $session['referrer'] = url::isRelative($referrer) ? $referrer : null;
     }
     return $this;
 }
Ejemplo n.º 7
0
 /**
  * Processes input of widget updating its internal state.
  *
  * @return $this current instance
  */
 public function processInput()
 {
     if (!user::current()->isAuthenticated()) {
         view::flash(\de\toxa\txf\_L('You must be logged in.'));
         $this->redirect();
     }
     $form = $this->getForm();
     if ($form->hasInput()) {
         if (input::vget('submit') == 'cancel') {
             $this->redirect();
         }
         $passwordOld = trim(input::vget('old'));
         $passwordNewA = trim(input::vget('new'));
         $passwordNewB = trim(input::vget('repeat'));
         if ($passwordOld === '') {
             $form->setRowError('old', \de\toxa\txf\_L('Provide current password!'));
         }
         if ($passwordNewA === '' || $passwordNewB === '') {
             $form->setRowError('new', \de\toxa\txf\_l('Provide new password twice for excluding typos.'));
         } else {
             if ($passwordNewA !== $passwordNewB) {
                 $form->setRowError('new', \de\toxa\txf\_L('Doubly entered passwords don\'t match.'));
             } else {
                 try {
                     if (is_callable($this->passwordValidator)) {
                         call_user_func($this->passwordValidator, $passwordNewA);
                     } else {
                         $this->passwordValidatorDefault($passwordNewA);
                     }
                 } catch (\InvalidArgumentException $e) {
                     $form->setRowError('new', $e->getMessage());
                 }
             }
         }
         exception::enterSensitive();
         if (!$form->hasAnyRowError()) {
             try {
                 $user = user::load(user::current()->getID());
                 try {
                     $user->authenticate($passwordOld);
                 } catch (unauthorized_exception $e) {
                     $form->setRowError('old', \de\toxa\txf\_L('Authenticating request using old password failed.'));
                 }
             } catch (unauthorized_exception $e) {
                 $form->setRowError('old', \de\toxa\txf\_L('Current user isn\'t available.'));
             }
         }
         $hasError = false;
         if (!$form->hasAnyRowError()) {
             try {
                 user::current()->changePassword($passwordNewA);
                 view::flash(\de\toxa\txf\_L('Password has been changed successfully.'));
                 try {
                     user::current()->authenticate($passwordNewA);
                 } catch (unauthorized_exception $e) {
                     view::flash(\de\toxa\txf\_L('Updating current session for using changed password failed. Probably you need to login, again.'), 'error');
                 }
             } catch (\RuntimeException $e) {
                 $hasError = true;
                 view::flash(\de\toxa\txf\_L('Your input is okay, but changing password failed nevertheless.'), 'error');
             }
         }
         exception::leaveSensitive();
         if (!$hasError && !$form->hasAnyRowError()) {
             $this->redirect();
         }
     } else {
         $session =& txf::session();
         $referrer = input::vget('referrer');
         $session['referrer'] = url::isRelative($referrer) ? $referrer : null;
     }
     return $this;
 }
Ejemplo n.º 8
-1
 /**
  * Processes input of widget updating its internal state.
  *
  * @return widget current instance
  */
 public function processInput()
 {
     if (user::current()->isAuthenticated()) {
         user::dropCurrent();
     }
     view::flash(\de\toxa\txf\_L('You logged out successfully.'));
     $referrer = input::vget('referrer');
     $referrer = url::isRelative($referrer) ? $referrer : null;
     txf::redirectTo(\de\toxa\txf\_1($referrer, 'home'));
 }