You are here

class ContactMessageResource in Contact message REST 8

Creates a resource for adding contact Message entities and sending them.

Plugin annotation


@RestResource(
  id = "contact_message",
  label = @Translation("Contact message"),
  serialization_class = "Drupal\contact\Entity\Message",
  uri_paths = {
    "canonical" = "/contact_message/{entity}"
  }
)

Hierarchy

Expanded class hierarchy of ContactMessageResource

File

src/Plugin/rest/resource/ContactMessageResource.php, line 37
Contains \Drupal\contact_message_rest\Plugin\rest\resource\ContactMessageResource.

Namespace

Drupal\contact_message_rest\Plugin\rest\resource
View source
class ContactMessageResource extends ResourceBase {

  /**
   * A curent user instance.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * A configuration object.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $config;

  /**
   * The flood control mechanism.
   *
   * @var \Drupal\Core\Flood\FloodInterface
   */
  protected $flood;

  /**
   * The contact mail handler service.
   *
   * @var \Drupal\contact\MailHandlerInterface
   */
  protected $mailHandler;

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateFormatter;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->getParameter('serializer.formats'), $container
      ->get('logger.factory')
      ->get('rest'), $container
      ->get('config.factory'), $container
      ->get('current_user'), $container
      ->get('flood'), $container
      ->get('contact.mail_handler'), $container
      ->get('date.formatter'));
  }

  /**
   * Constructs a Drupal\rest\Plugin\ResourceBase object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param array $serializer_formats
   *   The available serialization formats.
   * @param \Psr\Log\LoggerInterface $logger
   *   A logger instance.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration factory.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   The current user.
   * @param \Drupal\Core\Flood\FloodInterface $flood
   *   The flood control mechanism.
   * @param \Drupal\contact\MailHandlerInterface $mail_handler
   *   The contact mail handler service.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, ConfigFactoryInterface $config_factory, AccountProxyInterface $current_user, FloodInterface $flood, MailHandlerInterface $mail_handler, DateFormatterInterface $date_formatter) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
    $this->config = $config_factory
      ->get('contact.settings');
    $this->currentUser = $current_user;
    $this->flood = $flood;
    $this->mailHandler = $mail_handler;
    $this->dateFormatter = $date_formatter;
  }

  /**
   * Responds to entity POST requests and saves the new entity.
   *
   * @param \Drupal\contact\MessageInterface $message
   *   The Message entity.
   *
   * @return \Drupal\rest\ResourceResponse
   *   The HTTP response object.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   Throws HttpException in case of error.
   */
  public function post(MessageInterface $message = NULL) {
    if ($message == NULL) {
      throw new BadRequestHttpException('No entity content received.');
    }
    if (!$message
      ->access('create')) {
      throw new AccessDeniedHttpException();
    }

    // POSTed entities must not have an ID set, because we always want to create
    // new entities here.
    if (!$message
      ->isNew()) {
      throw new BadRequestHttpException('Only new entities can be created');
    }

    // Only check 'edit' permissions for fields that were actually
    // submitted by the user. Field access makes no difference between 'create'
    // and 'update', so the 'edit' operation is used here.
    foreach ($message->_restSubmittedFields as $key => $field_name) {
      if (!$message
        ->get($field_name)
        ->access('edit')) {
        throw new AccessDeniedHttpException("Access denied on creating field '{$field_name}'");
      }
    }

    // Validate the received data before saving.
    $this
      ->validate($message);

    // Send out the contact message via mail.
    $this->mailHandler
      ->sendMailMessages($message, $this->currentUser);

    // Register submission with the flood service.
    $this->flood
      ->register('contact', $this->config
      ->get('flood.interval'));

    // Try saving the message entity. This will only be useful when
    // contact_storage module is installed.
    try {
      $message
        ->save();
    } catch (EntityStorageException $e) {
      throw new HttpException(500, 'Internal Server Error', $e);
    }
    return new Response('', 200);
  }

  /**
   * Verifies that the whole entity does not violate any validation constraints.
   *
   * Copied from Drupal\rest\Plugin\rest\resource\EntityResource::validate.
   *
   * @param \Drupal\contact\MessageInterface $message
   *   The message entity object.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   If validation errors are found.
   */
  protected function validate(MessageInterface $message = NULL) {
    $violations = $message
      ->validate();

    // Remove violations of inaccessible fields as they cannot stem from our
    // changes.
    $violations
      ->filterByFieldAccess();
    if (count($violations) > 0) {
      $error_message = "Unprocessable Entity: validation failed.\n";
      foreach ($violations as $violation) {
        $error_message .= $violation
          ->getPropertyPath() . ': ' . $violation
          ->getMessage() . "\n";
      }

      // Instead of returning a generic 400 response we use the more specific
      // 422 Unprocessable Entity code from RFC 4918. That way clients can
      // distinguish between general syntax errors in bad serializations (code
      // 400) and semantic errors in well-formed requests (code 422).
      throw new HttpException(422, $error_message);
    }

    // Check if flood control has been activated for sending emails.
    if (!$this->currentUser
      ->hasPermission('administer contact forms') && (!$message
      ->isPersonal() || !$this->currentUser
      ->hasPermission('administer users'))) {
      $limit = $this->config
        ->get('flood.limit');
      $interval = $this->config
        ->get('flood.interval');
      if (!$this->flood
        ->isAllowed('contact', $limit, $interval)) {
        $flood_error = $this
          ->t('You cannot send more than %limit messages in @interval. Try again later.', array(
          '%limit' => $limit,
          '@interval' => $this->dateFormatter
            ->formatInterval($interval),
        ));
        throw new AccessDeniedHttpException($flood_error);
      }
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ContactMessageResource::$config protected property A configuration object.
ContactMessageResource::$currentUser protected property A curent user instance.
ContactMessageResource::$dateFormatter protected property The date formatter service.
ContactMessageResource::$flood protected property The flood control mechanism.
ContactMessageResource::$mailHandler protected property The contact mail handler service.
ContactMessageResource::create public static function Creates an instance of the plugin. Overrides ResourceBase::create
ContactMessageResource::post public function Responds to entity POST requests and saves the new entity.
ContactMessageResource::validate protected function Verifies that the whole entity does not violate any validation constraints.
ContactMessageResource::__construct public function Constructs a Drupal\rest\Plugin\ResourceBase object. Overrides ResourceBase::__construct
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
ResourceBase::$logger protected property A logger instance.
ResourceBase::$serializerFormats protected property The available serialization formats.
ResourceBase::availableMethods public function Returns the available HTTP request methods on this plugin. Overrides ResourceInterface::availableMethods 1
ResourceBase::getBaseRoute protected function Gets the base route for a particular method. 2
ResourceBase::getBaseRouteRequirements protected function Gets the base route requirements for a particular method. 1
ResourceBase::permissions public function Implements ResourceInterface::permissions(). Overrides ResourceInterface::permissions 2
ResourceBase::requestMethods protected function Provides predefined HTTP request methods.
ResourceBase::routes public function Returns a collection of routes with URL path information for the resource. Overrides ResourceInterface::routes
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.