Fehlerbehandlung Formulare

Template

<label for="email"><f:translate key="tx_rsysworkbook_domain_model_frontenduser.email" /><span class="required">*</span></label>
<div class="formfields">
    <f:form.textfield property="email" />
    <f:render partial="FieldError" arguments="{ fieldName: 'email' }" />
</div>

Partial

Resources/Private/Partials/FormError.html


<f:form.errors>
    <f:if condition="{error.propertyName}">           
            <f:for each="{error.errors}" as="errorDetail">           
                <f:if condition="{0:errorDetail.propertyName} == {0:'{fieldName}'}">
                    <f:for each="{errorDetail.errors}" as="errorDetailParts">       
                        <div class="error">               
                            <f:translate key="{errorDetail.propertyName}.{errorDetailParts.code}" />
                            <!--  {errorDetail.propertyName}.{errorDetailParts.code}   {errorDetailParts.message}-->
                        </div>
                    </f:for>
                </f:if>
            </f:for>
    </f:if>
</f:form.errors>

Texte

Resources/Private/Language/language.xlf

<trans-unit id="email.1301599608">
    <source>Email ist bereits vergeben</source>
</trans-unit>

<trans-unit id="email.1221559976">
    <source>Ungültige Emailadresse</source>
</trans-unit>

 Model

Classes/Domain/Model/FrondendUser.php

 /**
 * email
 *
 * @var string
 * @validate emailAddress(optional=true), Tx_Rsysworkbook_Domain_Validator_UniqueValidator(fieldname=email)
 */
protected $email = '';

Eigener Validator

Classes/Validator/UniqueValidator.php

<?php

/**
 * A validator for unique email
 *
 * @scope singleton
 */
class Tx_Rsysworkbook_Domain_Validator_UniqueValidator extends Tx_Extbase_Validation_Validator_AbstractValidator {
    /**
     * Frontend user repository
     *
     * @var Tx_SfRegister_Domain_Repository_FrontendUserRepository
     */
    protected $userRepository = NULL;

    /**
     * Inject frontend user repository
     *
     * @param Tx_Rsysworkbook_Domain_Repository_FrontendUserRepository $repository
     * @return void
     */
    public function injectUserRepository(Tx_Rsysworkbook_Domain_Repository_FrontendUserRepository $repository) {
        $this->userRepository = $repository;
    }
   
    /**
     * If the given passwords are valid
     *
     * @param string $value The value
     * @return boolean
     */
    public function isValid($value) {
        $result = TRUE;

        if ($this->userRepository->countByField($this->options['fieldname'], $value)) {
            $this->addError($this->options['fieldname'] . ' is not unique', '1301599608');
            $result = FALSE;
        }
        return $result;
    }
}
?>

Repository

Classes/Domain/Repository/FrontendUserRepository.php

/**
 * Count users in storagefolder which have a field that contains the value
 *
 * @param string $field
 * @param string $value
 * @return integer
 */
public function countByField($field, $value) {
    $query = $this->createQuery();
    $query->getQuerySettings()->setRespectEnableFields(FALSE);

    return $query
    ->matching(
            $query->logicalAnd(
                    $query->equals($field, $value),
                    $query->equals('deleted', 0)
            )
    )
    ->setLimit(1)
    ->execute()
    ->count();
}

Erstellt: 09/2012| Geändert: 10/2015

Eigener Validator - Nachtrag

Der Validator oben zählt die Datensätze und wenn die Treffer > 0 sind gibt er falsch zurück, da nicht "unique". Soweit ja in Ordnung, aber wenn man den Datensatz später editiert, kommt derselbe Validator zum Einsatz. Jetzt gibt's das Problem, daß er den aktuell angezeigten Datensatz mitzählt und dann 1 Treffer zustande kommt und er meint, die Email wäre nicht "unique". Was aber falsch ist!

Eine elegante Lösung habe ich nicht gefunden, die Notlösung hier:

$result = TRUE;
$propertyName = $this->options['fieldname'];

// edit
$paramsEdit = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tx_rsysoffer_frontenduserprofile');
$paramsEdit = isset($paramsEdit['frontendUser']) ? $paramsEdit['frontendUser'] : '';
if(!empty($paramsEdit)) {
    $uid = isset($paramsEdit['__identity']) ? $paramsEdit['__identity'] : '';
    if ($this->frontendUserRepository->countByProperty($propertyName, $value, $uid)) {
        $ret = $this->addError($this->options['fieldname'] . ' is not unique', '1301599608');
        $result = FALSE;
    }
}

// new
$paramsNew = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tx_rsysoffer_frontendusercreate');
$paramsNew = isset($paramsNew['newFrontendUser']) ? $paramsNew['newFrontendUser'] : '';
if(!empty($paramsNew)) {          
    if ($this->frontendUserRepository->countByProperty($propertyName, $value)) {
        $ret = $this->addError($this->options['fieldname'] . ' is not unique', '1301599608');
        $result = FALSE;
    }
}
return $result;

Er sieht in den normalen GET Parametern nach, ob es ein neuer Datensatz ist, oder ein existierender editiert wird und zählt dann im letzteren Fall die eigne uid ($paramsEdit['__identity']) nicht mit.

Die Query sieht so aus (mit der Möglichkeit die eigene uid auszuschliessen):

public function countByProperty($property, $value, $uid = 0) {
    $query = $this->createQuery();
   
    $constraints = array();
    $constraints[] = $query->equals('isParent', 0);
    $constraints[] = $query->equals($property, $value);
    if( $uid > 0) {
        $constraints[] = $query->logicalNot($query->equals('uid', $uid));
    }
    $query->matching($query->logicalAnd($constraints));
    return $query->execute()->count();
}

Erstellt: 07/2015| Geändert: 10/2015

TYPO3 V11

Hier der Validator in aktueller Version

<?php
namespace RSYS\RsystemplateBootstrap\Domain\Validator;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
 * A validator for unique email
 *
 * @scope singleton
 */
class UniqueValidator extends \TYPO3\CMS\Extbase\Validation\Validator\AbstractValidator {
  /**
   * @var array
   */
  protected $supportedOptions = array(
      'fieldname' => array(NULL, 'The validator type to use for the unique elements', 'string'),
  );
    /**
     * userRepository
     *
     * @var \RSYS\RsystemplateBootstrap\Domain\Repository\UserRepository
     * @TYPO3\CMS\Extbase\Annotation\Inject
     */
    protected $userRepository = null;
   /**
     * Constructor
     */
    public function __construct(
     $params
  )
    {
    $this->options = $params;
    $this->userRepository = GeneralUtility::makeInstance(\RSYS\RsystemplateBootstrap\Domain\Repository\UserRepository::class);
    }
  /**
   * If the given email is unique
   *
   * @param string $value The value
   * @return boolean
   */
  public function isValid($value) {
    $result = TRUE;
    $propertyName = $this->options['fieldname'];
    // edit
    $paramsEdit = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tx_rsystemplatebootstrap_user');
    $paramsEdit = isset($paramsEdit['user']) ? $paramsEdit['user'] : '';
    if(!empty($paramsEdit)) {
      $uid = isset($paramsEdit['__identity']) ? $paramsEdit['__identity'] : '';
      if ($this->userRepository->countByProperty($propertyName, $value, $uid)) {
        $ret = $this->addError($this->options['fieldname'] . ' is not unique' , '1301599608');
        $result = FALSE;
      }
    }
    // new
    $paramsNew = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tx_rsystemplatebootstrap_user');
    $paramsNew = isset($paramsNew['newUser']) ? $paramsNew['newUser'] : '';
    if(!empty($paramsNew)) {
      if ($this->userRepository->countByProperty($propertyName, $value)) {
        $ret = $this->addError($this->options['fieldname'] . ' is not unique', '1301599608');
        $result = FALSE;
      }
    }
    // print_r($ret);
    return $result;
  }
}
?>

Erstellt: 03/2023| Geändert: 03/2023