web-dev-qa-db-ja.com

ConstraintValidatorから他の送信された値にどのようにアクセスしますか?

ここに明らかなものが欠けているかもしれません。したがって、Drupal 8にはコンテンツタイプがあります。これには、日付範囲フィールドがあり、段落を使用します。段落には、日付フィールドを含む複数のフィールドがあります。

したがって、日付範囲フィールド(field_A)が開始と終了が正しいことを確認できるように、検証する必要があります。つまり、開始は終了時または終了前です。問題ありません、それが行われ、散りばめられます-FirstConstraintValidator.php

次に(SecondConstraintValidator.php)そのコンテンツタイプの段落について、日付フィールドを確認する必要があります。これをfield_Bと呼び、Field_Bの開始日と終了日の間またはその間にあります。これは私が問題を抱えているところです。できない方法でやろうとしているのかもしれません。

だから私は持っています(私はそれが乱雑で不完全であることを知っています):

my_module.module

function my_module_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type, $bundle) {
  if ($entity_type->id() === 'paragraph' && $bundle === 'bundle_B') {
    $fields['field_B']->addConstraint('SecondConstraint', []);
  } else if ($entity_type->id() === 'node' && $bundle === 'bundle_A') {
    $fields['field_A']->addConstraint('FirstConstraint', []);
  }
}

FirstConstraintValidator.php

class FirstConstraintValidator extends ConstraintValidator {
  public function validate($items, Constraint $constraint) {

    $entity = $items->getEntity();

    $start_date = date("Y-m-d",strtotime($entity->get('field_A')->getValue()[0]['value']));    
    $end_date = date("Y-m-d",strtotime($entity->get('field_A')->getValue()[0]['end_value']));

    if ($start_date > $end_date) {
      // Start date must be on or before end date...
      $this->context->addViolation( xxxxxx );
    }
  }
}

SecondConstraintValidator.php

class SecondConstraintValidator extends ConstraintValidator {
  public function validate($items, Constraint $constraint) {

    $entity = $items->getEntity();
    $parentEntity = $entity->getParentEntity();

    // THIS IS WHERE I NEED TO GET SUBMITTED VALUES.
    // LINES BELOW RETURNED ORIGINAL STORED VALUE, NOT UPDATED VALUE
    $start_date = date("Y-m-d",strtotime($parentEntity->get('field_A')->getValue()[0]['value']));   
    $end_date = date("Y-m-d",strtotime($parentEntity->get('field_A')->getValue()[0]['end_value']);

    // field_a is valid (i.e. start date is before or on end date)
    if ($start_date <= $end_date) {

      if ($items->value > $end_date || $items->value < $start_date) {
        // The date is after the end date of field_a 
        // OR
        // the date is before the start date of field_a
        $this->context->addViolation( xxxxx );
      }
    }
  }
}

ノードを保存すると、残りのノードの前に段落が検証されることに気づきました。とにかく、代わりの方法はform_alterと$ form ['#validate'] []を使用することですが、私の理解はD8であったため、ConstraintValidatorなどを使用する必要があります。質問は、私はこれを正しい方法でやっているのですか?何か不足していますか?

ありがとう

-------更新-部分的に解決-------

@ 4k4のおかげで部分的に機能するソリューションがあります。これは他の人を助けるかもしれません。

my_module.moduleがオリジナルから(つまり、段落フィールドに制約を追加する)に変更されました。

function my_module_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type, $bundle) {
 if ($entity_type->id() === 'node' && $bundle === 'bundle_A') {
    $fields['field_A']->addConstraint('FirstConstraint', []);
    $fields['field_B']->addConstraint('SecondConstraint', []);
  }
}

field_Aは日付範囲ですfield_Bは、日付フィールドなどが含まれる段落を参照します。

SecondConstraintValidator.phpに変更:

class SecondConstraintValidator extends ConstraintValidator {
  public function validate($items, Constraint $constraint) {

    $entity = $items->getEntity();

    $start_date = date("Y-m-d",strtotime($parentEntity->get('field_A')->getValue()[0]['value']));   
    $end_date = date("Y-m-d",strtotime($parentEntity->get('field_A')->getValue()[0]['end_value']);

    // field_a is valid (i.e. start date is before or on end date)
    if ($start_date <= $end_date) {

      if ($items->value > $end_date || $items->value < $start_date) {

        // field_A is valid, but field_B is not. show an error for field_B
        $this->context->addViolation( xxxxx );
      }
    }
  }
}

上記は問題なく、段落が1つしかない場合に機能します。複数を許可する場合、これが正しく機能していないことに注意してください。次のようなものが必要です。

SecondConstraintValidator.php

class SecondConstraintValidator extends ConstraintValidator {
  public function validate($items, Constraint $constraint) {

    $entity = $items->getEntity();

    $start_date = date("Y-m-d",strtotime($entity->get('field_a')->getValue()[0]['value'])); 
    $end_date = date("Y-m-d",strtotime($entity->get('field_a')->getValue()[0]['end_value']));

    // field_a is valid (i.e. start date is before or on end date)
    if ($start_date <= $end_date) {
        foreach ($items as $activity) {

          $date = $activity->getValue()['subform']['field_b'][0]['value']->format('Y-m-d');  
          if ($date > $end_date || $date < $start_date) {
            $this->context->addViolation( xxxxx );
          }
        }
    }
  }
}

上記も、最善の解決策ではない可能性があります。これはすべてのfield_Bに違反を追加するため、段落のコピーを2つ追加し、そのうちの1つだけを検証しないと、すべてにエラーが表示されます。 $ this-> context-> addViolation(xxxxx);変更を加えて、その段落のフィールドにのみ違反を追加する必要があります。

3
nickbits

すべてのコメントのおかげで、他の人を助けることができる実用的な解決策があります。

my_module.moduleがオリジナルから(つまり、段落フィールドに制約を追加する)に変更されました。

function my_module_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type, $bundle) {
 if ($entity_type->id() === 'node' && $bundle === 'bundle_A') {
    $fields['field_A']->addConstraint('FirstConstraint', []);
    $fields['field_B']->addConstraint('SecondConstraint', []);
  }
}

field_Aは日付範囲ですfield_Bは、日付フィールドなどが含まれる段落を参照します。 field_Cは段落内の日付フィールドです

SecondConstraintValidator.phpに変更:

class SecondConstraintValidator extends ConstraintValidator {
  public function validate($items, Constraint $constraint) {

    $entity = $items->getEntity();

    $start_date = date("Y-m-d",strtotime($parentEntity->get('field_A')->getValue()[0]['value']));   
    $end_date = date("Y-m-d",strtotime($parentEntity->get('field_A')->getValue()[0]['end_value']);

    // field_a is valid (i.e. start date is before or on end date)
    if ($start_date <= $end_date) {

      if ($items->value > $end_date || $items->value < $start_date) {

        // field_A is valid, but field_B is not. show an error for field_B
        $this->context->addViolation( xxxxx );
      }
    }
  }
}

上記は問題なく、段落が1つしかない場合に機能します。複数を許可する場合は、次のようなものが必要です。

SecondConstraintValidator.php

class SecondConstraintValidator extends ConstraintValidator {
  public function validate($items, Constraint $constraint) {

    $entity = $items->getEntity();

    $start_date = date("Y-m-d",strtotime($entity->get('field_a')->getValue()[0]['value'])); 
    $end_date = date("Y-m-d",strtotime($entity->get('field_a')->getValue()[0]['end_value']));

    // field_a is valid (i.e. start date is before or on end date)
    if ($start_date <= $end_date) {
        foreach ($items as $key as $activity) {

          $date = $activity->getValue()['subform']['field_c'][0]['value']->format('Y-m-d');  
          if ($date > $end_date || $date < $start_date) {
            $this->context->buildViolation("message")->atPath($key.'.field_c')->addViolation();
          }
        }
    }
  }
}

上記も、最善の解決策ではない可能性があります。コメントを受け付けますが、機能します!

2
nickbits