#StackBounty: #8 Capture IP and URL of referrer

Bounty: 50

This code is adapted from /core/modules/statistics/statistics.php. It uses a JavaScript file that sends an uncached POST request to the server (to ensure the code within gets run for every page request).

I want my code within to capture the IP and URL of the referrer. I’ve tried many things to grab this information and write it to the log, but no luck.

Whatever I do, I get a variation on Error: Call to a member function *something* on null in.... Like, I’m not getting anything. For example, the below throws: Error: Call to a member function getClientIp() on null in main() (line 26 of....

Any ideas?

<?php

/**
 * @file
 * Store access data.
 */

use DrupalCoreDrupalKernel;
use SymfonyComponentHttpFoundationRequest;
// use SymfonyComponentHttpFoundationRequestStack;
// use SymfonyComponentHttpFoundation;

chdir('../..');

$autoloader = require_once 'autoload.php';

$kernel = DrupalKernel::createFromRequest(Request::createFromGlobals(), $autoloader, 'prod');
$kernel->boot();

// $container = $kernel->getContainer;

// $request = $kernel->getContainer()->get('request_stack')->getCurrentRequest();
// $request = $kernel->requestStack->getCurrentRequest();

// $url = Drupal::request()->server->get('HTTP_REFERER');

// $hostname = $request->getClientIP();
// $hostname = Drupal::request()->getClientIp();

Drupal::logger('sitelog')->notice(REQUEST_TIME);


Get this bounty!!!

#StackBounty: #8 #forms #ajax Ajax Form submit doesn't work second time

Bounty: 50

I’m loading the node/edit form in a block and I add ajax on submit.

I add the Ajax in the hook_form_alter.

$form['#prefix'] = '
'; $form['#suffix'] = '
'; $form['actions']['submit']['#submit'][] = 'submitForm'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'my_ajax_callback', 'wrapper' => $form_wrapper, 'effect' => 'fade', );

The SubmitForm:

function submitForm(array &$form, FormStateInterface $form_state){
  $input = $form_state->getUserInput();
  $form_state->setUserInput($input);
  $form_state->setRebuild(TRUE);
}

And the callback :

function my_ajax_callback(&$form, FormStateInterface $form_state, $form_id) {
   $form_state->setRebuild();
   return $form;
}

The first time works fine. The second time seems to work without any error but it doesn’t submit my new data.

I checked this comment How can I implement AJAX form submission? but I don’t know if I have to set the values to the form_state. Also i use this callback for multiple content types. Should I check and set the value for each field? Is there a better way?

Thanks for your help!

—— EDIT —–

I added the submitForm function and now the second time I submit I get ‘The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.’.

Also, should I get/set each one of my fields or $input = $form_state->getUserInput(); $form_state->setUserInput($input); are enough?

——– UPDATE ——

I managed to make it work for forms that I need to be empty after the ajax submit using the below code :

In hook_form_alter:

$form['wrapper'] = array(
    '#type' => 'container',
    '#attributes' => array('id' => $form_wrapper),
  );

$prefix = '
'; $form['#prefix'] = $prefix; $form['#suffix'] = '
'; $form['actions']['submit']['#submit'][] = 'DrupalMY_MODULEPluginFormFormAlter::ajaxFormEntityFormSubmitEmptyForm'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'DrupalMY_MODULEPluginFormFormAlter::ajaxFormEntityCallbackEmptyForm', 'wrapper' => $form_wrapper, 'effect' => 'fade', );

And in the FormAlter.php :

/**
 * Rebuild the form - Empty form.
 */
 public static function ajaxFormEntityFormSubmitEmptyForm($form, &$form_state){
  $entity = $form_state->getBuildInfo()['callback_object']->getEntity();
  $entity_type = $entity->getEntityTypeId();
  $bundle = $entity->bundle();
  $new_entity = Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle]);
  $form_state->getBuildInfo()['callback_object']->setEntity($new_entity);

  // Clear user input.
  $input = $form_state->getUserInput();
  $clean_keys = $form_state->getCleanValueKeys();
  $clean_keys[] = 'ajax_page_state';
  foreach ($input as $key => $item) {
    if (!in_array($key, $clean_keys) && substr($key, 0, 1) !== '_') {
      unset($input[$key]);
    }
  }

  $input['entity'] = $entity;
  $form_state->setUserInput($input);

  // Rebuild the form state values.
  $form_state->setRebuild();
  $form_state->setStorage([]);
}

/**
 * Ajax callback to handle just returns the form
 */
 public static function ajaxFormEntityCallbackEmptyForm(&$form, DrupalCoreFormFormStateInterface $form_state) {
   if ($form_state->hasAnyErrors()) {
     return $form;
   }
   else {
     return $form;
    }
  }

Now I’m trying to do something similar but I want the form populated with the new values. So I created two new functions in FormAlter:

 /**
  * Rebuild the form.
  */
  public static function ajaxFormEntityFormSubmit($form, &$form_state) {
    $entity = $form_state->getBuildInfo()['callback_object']->getEntity();
    $entity_type = $entity->getEntityTypeId();
    $bundle = $entity->bundle();

    $new_entity = Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle]);
    $form_state->getBuildInfo()['callback_object']->setEntity($new_entity);

    $input = $form_state->getUserInput();
    $input['entity'] = $entity;

    $form_state->setUserInput($input);
    if(!$form_state->hasValue('title')){
      $form_state->setValue('title',$entity->getTitle());
    }

    // Rebuild the form state values.
    $form_state->setRebuild(TRUE);
    $form_state->setStorage([]);
  }

 /**
  * Ajax callback to handle special ajax form entity magic.
  */
  public static function ajaxFormEntityCallback(&$form, DrupalCoreFormFormStateInterface $form_state) {
  // If errors, returns the form with errors and messages.
  if ($form_state->hasAnyErrors()) {
    return $form;
  }
  // Else show the result.
  else {
    $userInputs = $form_state->getUserInput();
    $entity = $userInputs['entity'];
    $entity_type = $entity->getEntityTypeId();

    $response = new AjaxResponse();
    if ($entity_type == 'node') {
      $title = $entity->getTitle();
    }
    return $form;
  }
}

If I return the $form in the callback, the first time works fine but the second I’m getting two errors in the log:

DrupalCoreDatabaseIntegrityConstraintViolationException:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column ‘title’
cannot be null: INSERT INTO {node_field_data} (nid, vid, type,
langcode, status, title, uid, created, changed, promote, sticky,
revision_translation_affected, default_langcode) VALUES
(:db_insert_placeholder_0, :db_insert_placeholder_1,
:db_insert_placeholder_2, :db_insert_placeholder_3,
:db_insert_placeholder_4, :db_insert_placeholder_5,
:db_insert_placeholder_6, :db_insert_placeholder_7,
:db_insert_placeholder_8, :db_insert_placeholder_9,
:db_insert_placeholder_10, :db_insert_placeholder_11,
:db_insert_placeholder_12); Array ( [:db_insert_placeholder_0] => 201
[:db_insert_placeholder_1] => 258 [:db_insert_placeholder_2] =>
my_estate_details [:db_insert_placeholder_3] => en
[:db_insert_placeholder_4] => 1 [:db_insert_placeholder_5] =>
[:db_insert_placeholder_6] => 5 [:db_insert_placeholder_7] =>
1500889059 [:db_insert_placeholder_8] => 1500889066
[:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10] => 0
[:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 ) in
DrupalCoreDatabaseConnection->handleQueryException()

And

DrupalCoreEntityEntityStorageException: SQLSTATE[23000]: Integrity
constraint violation: 1048 Column ‘title’ cannot be null: INSERT INTO
{node_field_data} (nid, vid, type, langcode, status, title, uid,
created, changed, promote, sticky, revision_translation_affected,
default_langcode) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4,
:db_insert_placeholder_5, :db_insert_placeholder_6,
:db_insert_placeholder_7, :db_insert_placeholder_8,
:db_insert_placeholder_9, :db_insert_placeholder_10,
:db_insert_placeholder_11, :db_insert_placeholder_12); Array (
[:db_insert_placeholder_0] => 201 [:db_insert_placeholder_1] => 258
[:db_insert_placeholder_2] => my_estate_details
[:db_insert_placeholder_3] => en [:db_insert_placeholder_4] => 1
[:db_insert_placeholder_5] => [:db_insert_placeholder_6] => 5
[:db_insert_placeholder_7] => 1500889059 [:db_insert_placeholder_8] =>
1500889066 [:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10]
=> 0 [:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 ) in DrupalCoreEntitySqlSqlContentEntityStorage->save()

In case I return $response (which is what I prefer in order to be able to alter the message etc), the first time works fine but the second I get the message:

The content has either been modified by another user, or you have
already submitted modifications. As a result, your changes cannot be
saved.’.

Apologies for the long message. Any idea/help will be helpful!

Thanks in advance.


Get this bounty!!!

#StackBounty: #8 #forms #ajax Ajax Form submit doesn't work second time

Bounty: 50

I’m loading the node/edit form in a block and I add ajax on submit.

I add the Ajax in the hook_form_alter.

$form['#prefix'] = '
'; $form['#suffix'] = '
'; $form['actions']['submit']['#submit'][] = 'submitForm'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'my_ajax_callback', 'wrapper' => $form_wrapper, 'effect' => 'fade', );

The SubmitForm:

function submitForm(array &$form, FormStateInterface $form_state){
  $input = $form_state->getUserInput();
  $form_state->setUserInput($input);
  $form_state->setRebuild(TRUE);
}

And the callback :

function my_ajax_callback(&$form, FormStateInterface $form_state, $form_id) {
   $form_state->setRebuild();
   return $form;
}

The first time works fine. The second time seems to work without any error but it doesn’t submit my new data.

I checked this comment How can I implement AJAX form submission? but I don’t know if I have to set the values to the form_state. Also i use this callback for multiple content types. Should I check and set the value for each field? Is there a better way?

Thanks for your help!

—— EDIT —–

I added the submitForm function and now the second time I submit I get ‘The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.’.

Also, should I get/set each one of my fields or $input = $form_state->getUserInput(); $form_state->setUserInput($input); are enough?

——– UPDATE ——

I managed to make it work for forms that I need to be empty after the ajax submit using the below code :

In hook_form_alter:

$form['wrapper'] = array(
    '#type' => 'container',
    '#attributes' => array('id' => $form_wrapper),
  );

$prefix = '
'; $form['#prefix'] = $prefix; $form['#suffix'] = '
'; $form['actions']['submit']['#submit'][] = 'DrupalMY_MODULEPluginFormFormAlter::ajaxFormEntityFormSubmitEmptyForm'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'DrupalMY_MODULEPluginFormFormAlter::ajaxFormEntityCallbackEmptyForm', 'wrapper' => $form_wrapper, 'effect' => 'fade', );

And in the FormAlter.php :

/**
 * Rebuild the form - Empty form.
 */
 public static function ajaxFormEntityFormSubmitEmptyForm($form, &$form_state){
  $entity = $form_state->getBuildInfo()['callback_object']->getEntity();
  $entity_type = $entity->getEntityTypeId();
  $bundle = $entity->bundle();
  $new_entity = Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle]);
  $form_state->getBuildInfo()['callback_object']->setEntity($new_entity);

  // Clear user input.
  $input = $form_state->getUserInput();
  $clean_keys = $form_state->getCleanValueKeys();
  $clean_keys[] = 'ajax_page_state';
  foreach ($input as $key => $item) {
    if (!in_array($key, $clean_keys) && substr($key, 0, 1) !== '_') {
      unset($input[$key]);
    }
  }

  $input['entity'] = $entity;
  $form_state->setUserInput($input);

  // Rebuild the form state values.
  $form_state->setRebuild();
  $form_state->setStorage([]);
}

/**
 * Ajax callback to handle just returns the form
 */
 public static function ajaxFormEntityCallbackEmptyForm(&$form, DrupalCoreFormFormStateInterface $form_state) {
   if ($form_state->hasAnyErrors()) {
     return $form;
   }
   else {
     return $form;
    }
  }

Now I’m trying to do something similar but I want the form populated with the new values. So I created two new functions in FormAlter:

 /**
  * Rebuild the form.
  */
  public static function ajaxFormEntityFormSubmit($form, &$form_state) {
    $entity = $form_state->getBuildInfo()['callback_object']->getEntity();
    $entity_type = $entity->getEntityTypeId();
    $bundle = $entity->bundle();

    $new_entity = Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle]);
    $form_state->getBuildInfo()['callback_object']->setEntity($new_entity);

    $input = $form_state->getUserInput();
    $input['entity'] = $entity;

    $form_state->setUserInput($input);
    if(!$form_state->hasValue('title')){
      $form_state->setValue('title',$entity->getTitle());
    }

    // Rebuild the form state values.
    $form_state->setRebuild(TRUE);
    $form_state->setStorage([]);
  }

 /**
  * Ajax callback to handle special ajax form entity magic.
  */
  public static function ajaxFormEntityCallback(&$form, DrupalCoreFormFormStateInterface $form_state) {
  // If errors, returns the form with errors and messages.
  if ($form_state->hasAnyErrors()) {
    return $form;
  }
  // Else show the result.
  else {
    $userInputs = $form_state->getUserInput();
    $entity = $userInputs['entity'];
    $entity_type = $entity->getEntityTypeId();

    $response = new AjaxResponse();
    if ($entity_type == 'node') {
      $title = $entity->getTitle();
    }
    return $form;
  }
}

If I return the $form in the callback, the first time works fine but the second I’m getting two errors in the log:

DrupalCoreDatabaseIntegrityConstraintViolationException:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column ‘title’
cannot be null: INSERT INTO {node_field_data} (nid, vid, type,
langcode, status, title, uid, created, changed, promote, sticky,
revision_translation_affected, default_langcode) VALUES
(:db_insert_placeholder_0, :db_insert_placeholder_1,
:db_insert_placeholder_2, :db_insert_placeholder_3,
:db_insert_placeholder_4, :db_insert_placeholder_5,
:db_insert_placeholder_6, :db_insert_placeholder_7,
:db_insert_placeholder_8, :db_insert_placeholder_9,
:db_insert_placeholder_10, :db_insert_placeholder_11,
:db_insert_placeholder_12); Array ( [:db_insert_placeholder_0] => 201
[:db_insert_placeholder_1] => 258 [:db_insert_placeholder_2] =>
my_estate_details [:db_insert_placeholder_3] => en
[:db_insert_placeholder_4] => 1 [:db_insert_placeholder_5] =>
[:db_insert_placeholder_6] => 5 [:db_insert_placeholder_7] =>
1500889059 [:db_insert_placeholder_8] => 1500889066
[:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10] => 0
[:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 ) in
DrupalCoreDatabaseConnection->handleQueryException()

And

DrupalCoreEntityEntityStorageException: SQLSTATE[23000]: Integrity
constraint violation: 1048 Column ‘title’ cannot be null: INSERT INTO
{node_field_data} (nid, vid, type, langcode, status, title, uid,
created, changed, promote, sticky, revision_translation_affected,
default_langcode) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4,
:db_insert_placeholder_5, :db_insert_placeholder_6,
:db_insert_placeholder_7, :db_insert_placeholder_8,
:db_insert_placeholder_9, :db_insert_placeholder_10,
:db_insert_placeholder_11, :db_insert_placeholder_12); Array (
[:db_insert_placeholder_0] => 201 [:db_insert_placeholder_1] => 258
[:db_insert_placeholder_2] => my_estate_details
[:db_insert_placeholder_3] => en [:db_insert_placeholder_4] => 1
[:db_insert_placeholder_5] => [:db_insert_placeholder_6] => 5
[:db_insert_placeholder_7] => 1500889059 [:db_insert_placeholder_8] =>
1500889066 [:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10]
=> 0 [:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 ) in DrupalCoreEntitySqlSqlContentEntityStorage->save()

In case I return $response (which is what I prefer in order to be able to alter the message etc), the first time works fine but the second I get the message:

The content has either been modified by another user, or you have
already submitted modifications. As a result, your changes cannot be
saved.’.

Apologies for the long message. Any idea/help will be helpful!

Thanks in advance.


Get this bounty!!!

#StackBounty: #8 #forms #ajax Ajax Form submit doesn't work second time

Bounty: 50

I’m loading the node/edit form in a block and I add ajax on submit.

I add the Ajax in the hook_form_alter.

$form['#prefix'] = '
'; $form['#suffix'] = '
'; $form['actions']['submit']['#submit'][] = 'submitForm'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'my_ajax_callback', 'wrapper' => $form_wrapper, 'effect' => 'fade', );

The SubmitForm:

function submitForm(array &$form, FormStateInterface $form_state){
  $input = $form_state->getUserInput();
  $form_state->setUserInput($input);
  $form_state->setRebuild(TRUE);
}

And the callback :

function my_ajax_callback(&$form, FormStateInterface $form_state, $form_id) {
   $form_state->setRebuild();
   return $form;
}

The first time works fine. The second time seems to work without any error but it doesn’t submit my new data.

I checked this comment How can I implement AJAX form submission? but I don’t know if I have to set the values to the form_state. Also i use this callback for multiple content types. Should I check and set the value for each field? Is there a better way?

Thanks for your help!

—— EDIT —–

I added the submitForm function and now the second time I submit I get ‘The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.’.

Also, should I get/set each one of my fields or $input = $form_state->getUserInput(); $form_state->setUserInput($input); are enough?

——– UPDATE ——

I managed to make it work for forms that I need to be empty after the ajax submit using the below code :

In hook_form_alter:

$form['wrapper'] = array(
    '#type' => 'container',
    '#attributes' => array('id' => $form_wrapper),
  );

$prefix = '
'; $form['#prefix'] = $prefix; $form['#suffix'] = '
'; $form['actions']['submit']['#submit'][] = 'DrupalMY_MODULEPluginFormFormAlter::ajaxFormEntityFormSubmitEmptyForm'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'DrupalMY_MODULEPluginFormFormAlter::ajaxFormEntityCallbackEmptyForm', 'wrapper' => $form_wrapper, 'effect' => 'fade', );

And in the FormAlter.php :

/**
 * Rebuild the form - Empty form.
 */
 public static function ajaxFormEntityFormSubmitEmptyForm($form, &$form_state){
  $entity = $form_state->getBuildInfo()['callback_object']->getEntity();
  $entity_type = $entity->getEntityTypeId();
  $bundle = $entity->bundle();
  $new_entity = Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle]);
  $form_state->getBuildInfo()['callback_object']->setEntity($new_entity);

  // Clear user input.
  $input = $form_state->getUserInput();
  $clean_keys = $form_state->getCleanValueKeys();
  $clean_keys[] = 'ajax_page_state';
  foreach ($input as $key => $item) {
    if (!in_array($key, $clean_keys) && substr($key, 0, 1) !== '_') {
      unset($input[$key]);
    }
  }

  $input['entity'] = $entity;
  $form_state->setUserInput($input);

  // Rebuild the form state values.
  $form_state->setRebuild();
  $form_state->setStorage([]);
}

/**
 * Ajax callback to handle just returns the form
 */
 public static function ajaxFormEntityCallbackEmptyForm(&$form, DrupalCoreFormFormStateInterface $form_state) {
   if ($form_state->hasAnyErrors()) {
     return $form;
   }
   else {
     return $form;
    }
  }

Now I’m trying to do something similar but I want the form populated with the new values. So I created two new functions in FormAlter:

 /**
  * Rebuild the form.
  */
  public static function ajaxFormEntityFormSubmit($form, &$form_state) {
    $entity = $form_state->getBuildInfo()['callback_object']->getEntity();
    $entity_type = $entity->getEntityTypeId();
    $bundle = $entity->bundle();

    $new_entity = Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle]);
    $form_state->getBuildInfo()['callback_object']->setEntity($new_entity);

    $input = $form_state->getUserInput();
    $input['entity'] = $entity;

    $form_state->setUserInput($input);
    if(!$form_state->hasValue('title')){
      $form_state->setValue('title',$entity->getTitle());
    }

    // Rebuild the form state values.
    $form_state->setRebuild(TRUE);
    $form_state->setStorage([]);
  }

 /**
  * Ajax callback to handle special ajax form entity magic.
  */
  public static function ajaxFormEntityCallback(&$form, DrupalCoreFormFormStateInterface $form_state) {
  // If errors, returns the form with errors and messages.
  if ($form_state->hasAnyErrors()) {
    return $form;
  }
  // Else show the result.
  else {
    $userInputs = $form_state->getUserInput();
    $entity = $userInputs['entity'];
    $entity_type = $entity->getEntityTypeId();

    $response = new AjaxResponse();
    if ($entity_type == 'node') {
      $title = $entity->getTitle();
    }
    return $form;
  }
}

If I return the $form in the callback, the first time works fine but the second I’m getting two errors in the log:

DrupalCoreDatabaseIntegrityConstraintViolationException:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column ‘title’
cannot be null: INSERT INTO {node_field_data} (nid, vid, type,
langcode, status, title, uid, created, changed, promote, sticky,
revision_translation_affected, default_langcode) VALUES
(:db_insert_placeholder_0, :db_insert_placeholder_1,
:db_insert_placeholder_2, :db_insert_placeholder_3,
:db_insert_placeholder_4, :db_insert_placeholder_5,
:db_insert_placeholder_6, :db_insert_placeholder_7,
:db_insert_placeholder_8, :db_insert_placeholder_9,
:db_insert_placeholder_10, :db_insert_placeholder_11,
:db_insert_placeholder_12); Array ( [:db_insert_placeholder_0] => 201
[:db_insert_placeholder_1] => 258 [:db_insert_placeholder_2] =>
my_estate_details [:db_insert_placeholder_3] => en
[:db_insert_placeholder_4] => 1 [:db_insert_placeholder_5] =>
[:db_insert_placeholder_6] => 5 [:db_insert_placeholder_7] =>
1500889059 [:db_insert_placeholder_8] => 1500889066
[:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10] => 0
[:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 ) in
DrupalCoreDatabaseConnection->handleQueryException()

And

DrupalCoreEntityEntityStorageException: SQLSTATE[23000]: Integrity
constraint violation: 1048 Column ‘title’ cannot be null: INSERT INTO
{node_field_data} (nid, vid, type, langcode, status, title, uid,
created, changed, promote, sticky, revision_translation_affected,
default_langcode) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4,
:db_insert_placeholder_5, :db_insert_placeholder_6,
:db_insert_placeholder_7, :db_insert_placeholder_8,
:db_insert_placeholder_9, :db_insert_placeholder_10,
:db_insert_placeholder_11, :db_insert_placeholder_12); Array (
[:db_insert_placeholder_0] => 201 [:db_insert_placeholder_1] => 258
[:db_insert_placeholder_2] => my_estate_details
[:db_insert_placeholder_3] => en [:db_insert_placeholder_4] => 1
[:db_insert_placeholder_5] => [:db_insert_placeholder_6] => 5
[:db_insert_placeholder_7] => 1500889059 [:db_insert_placeholder_8] =>
1500889066 [:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10]
=> 0 [:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 ) in DrupalCoreEntitySqlSqlContentEntityStorage->save()

In case I return $response (which is what I prefer in order to be able to alter the message etc), the first time works fine but the second I get the message:

The content has either been modified by another user, or you have
already submitted modifications. As a result, your changes cannot be
saved.’.

Apologies for the long message. Any idea/help will be helpful!

Thanks in advance.


Get this bounty!!!

#StackBounty: #8 #forum Restrict access to child forum topics

Bounty: 50

I have restricted (or granted) access to specific forums based on user roles via taxonomy (Using TAC Lite module), however, a user may still directly “create” forum topics in restricted forums and even view them by explicitly navigating to the url of the specific forum topic.

How do I go about restricting read and right permissions dynamically based on a user’s permissions for the parent forum taxonomy?

I want it to be dynamic as It should be possible for a moderator to move a forum topic to a different parent forum and access rights should change.

I understand from the module page I need to:

To use, configure Drupal to not grant the permission, then configure
tac_lite to grant via the node_access table.

But I am having trouble finding good information on how this is done. This question covers what, I assume, are the the functions involved but I am not clear where or how I should implement this. How do I allow non-technical admin users to modify the access permissions on forum topics at a later date without having to go in to module code?

Are there any clear guides for drupal 8 on how to user the node_access table in this way?

I will add some extra information in case it helps with making suggestions.

I auto generate the url path for each of my forum topics using the pattern:

private/forum/[node:taxonomy_forums:entity:name]/[node:nid]/[node:title]

I have access control on the forums by their taxonomy term, so I assume, the process for handling users permissions on visiting a forum topic node would be to:

  1. Get the [node:taxonomy_forums:entity:name] when the user visits a forum node (from the url or is there a better way?)
  2. Get the permissions of the current user from the node_access table
  3. 403 the user if they do not have a permission corresponding to the taxonomy term

I am not sure how to start doing any of the above. Any help is appreciated (and currently subject to a bounty). If there is a better way to do this I would also love to hear it.


Get this bounty!!!

#StackBounty: #8 #forms #ajax Ajax Form submit doesn't work second time

Bounty: 50

I’m loading the node/edit form in a block and I add ajax on submit.

I add the Ajax in the hook_form_alter.

$form['#prefix'] = '
'; $form['#suffix'] = '
'; $form['actions']['submit']['#submit'][] = 'submitForm'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'my_ajax_callback', 'wrapper' => $form_wrapper, 'effect' => 'fade', );

The SubmitForm:

function submitForm(array &$form, FormStateInterface $form_state){
  $input = $form_state->getUserInput();
  $form_state->setUserInput($input);
  $form_state->setRebuild(TRUE);
}

And the callback :

function my_ajax_callback(&$form, FormStateInterface $form_state, $form_id) {
   $form_state->setRebuild();
   return $form;
}

The first time works fine. The second time seems to work without any error but it doesn’t submit my new data.

I checked this comment How can I implement AJAX form submission? but I don’t know if I have to set the values to the form_state. Also i use this callback for multiple content types. Should I check and set the value for each field? Is there a better way?

Thanks for your help!

—— EDIT —–

I added the submitForm function and now the second time I submit I get ‘The content has either been modified by another user, or you have already submitted modifications. As a result, your changes cannot be saved.’.

Also, should I get/set each one of my fields or $input = $form_state->getUserInput(); $form_state->setUserInput($input); are enough?

——– UPDATE ——

I managed to make it work for forms that I need to be empty after the ajax submit using the below code :

In hook_form_alter:

$form['wrapper'] = array(
    '#type' => 'container',
    '#attributes' => array('id' => $form_wrapper),
  );

$prefix = '
'; $form['#prefix'] = $prefix; $form['#suffix'] = '
'; $form['actions']['submit']['#submit'][] = 'DrupalMY_MODULEPluginFormFormAlter::ajaxFormEntityFormSubmitEmptyForm'; $form['actions']['submit']['#ajax'] = array( 'callback' => 'DrupalMY_MODULEPluginFormFormAlter::ajaxFormEntityCallbackEmptyForm', 'wrapper' => $form_wrapper, 'effect' => 'fade', );

And in the FormAlter.php :

/**
 * Rebuild the form - Empty form.
 */
 public static function ajaxFormEntityFormSubmitEmptyForm($form, &$form_state){
  $entity = $form_state->getBuildInfo()['callback_object']->getEntity();
  $entity_type = $entity->getEntityTypeId();
  $bundle = $entity->bundle();
  $new_entity = Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle]);
  $form_state->getBuildInfo()['callback_object']->setEntity($new_entity);

  // Clear user input.
  $input = $form_state->getUserInput();
  $clean_keys = $form_state->getCleanValueKeys();
  $clean_keys[] = 'ajax_page_state';
  foreach ($input as $key => $item) {
    if (!in_array($key, $clean_keys) && substr($key, 0, 1) !== '_') {
      unset($input[$key]);
    }
  }

  $input['entity'] = $entity;
  $form_state->setUserInput($input);

  // Rebuild the form state values.
  $form_state->setRebuild();
  $form_state->setStorage([]);
}

/**
 * Ajax callback to handle just returns the form
 */
 public static function ajaxFormEntityCallbackEmptyForm(&$form, DrupalCoreFormFormStateInterface $form_state) {
   if ($form_state->hasAnyErrors()) {
     return $form;
   }
   else {
     return $form;
    }
  }

Now I’m trying to do something similar but I want the form populated with the new values. So I created two new functions in FormAlter:

 /**
  * Rebuild the form.
  */
  public static function ajaxFormEntityFormSubmit($form, &$form_state) {
    $entity = $form_state->getBuildInfo()['callback_object']->getEntity();
    $entity_type = $entity->getEntityTypeId();
    $bundle = $entity->bundle();

    $new_entity = Drupal::entityTypeManager()->getStorage($entity_type)->create(['type' => $bundle]);
    $form_state->getBuildInfo()['callback_object']->setEntity($new_entity);

    $input = $form_state->getUserInput();
    $input['entity'] = $entity;

    $form_state->setUserInput($input);
    if(!$form_state->hasValue('title')){
      $form_state->setValue('title',$entity->getTitle());
    }

    // Rebuild the form state values.
    $form_state->setRebuild(TRUE);
    $form_state->setStorage([]);
  }

 /**
  * Ajax callback to handle special ajax form entity magic.
  */
  public static function ajaxFormEntityCallback(&$form, DrupalCoreFormFormStateInterface $form_state) {
  // If errors, returns the form with errors and messages.
  if ($form_state->hasAnyErrors()) {
    return $form;
  }
  // Else show the result.
  else {
    $userInputs = $form_state->getUserInput();
    $entity = $userInputs['entity'];
    $entity_type = $entity->getEntityTypeId();

    $response = new AjaxResponse();
    if ($entity_type == 'node') {
      $title = $entity->getTitle();
    }
    return $form;
  }
}

If I return the $form in the callback, the first time works fine but the second I’m getting two errors in the log:

DrupalCoreDatabaseIntegrityConstraintViolationException:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column ‘title’
cannot be null: INSERT INTO {node_field_data} (nid, vid, type,
langcode, status, title, uid, created, changed, promote, sticky,
revision_translation_affected, default_langcode) VALUES
(:db_insert_placeholder_0, :db_insert_placeholder_1,
:db_insert_placeholder_2, :db_insert_placeholder_3,
:db_insert_placeholder_4, :db_insert_placeholder_5,
:db_insert_placeholder_6, :db_insert_placeholder_7,
:db_insert_placeholder_8, :db_insert_placeholder_9,
:db_insert_placeholder_10, :db_insert_placeholder_11,
:db_insert_placeholder_12); Array ( [:db_insert_placeholder_0] => 201
[:db_insert_placeholder_1] => 258 [:db_insert_placeholder_2] =>
my_estate_details [:db_insert_placeholder_3] => en
[:db_insert_placeholder_4] => 1 [:db_insert_placeholder_5] =>
[:db_insert_placeholder_6] => 5 [:db_insert_placeholder_7] =>
1500889059 [:db_insert_placeholder_8] => 1500889066
[:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10] => 0
[:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 ) in
DrupalCoreDatabaseConnection->handleQueryException()

And

DrupalCoreEntityEntityStorageException: SQLSTATE[23000]: Integrity
constraint violation: 1048 Column ‘title’ cannot be null: INSERT INTO
{node_field_data} (nid, vid, type, langcode, status, title, uid,
created, changed, promote, sticky, revision_translation_affected,
default_langcode) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4,
:db_insert_placeholder_5, :db_insert_placeholder_6,
:db_insert_placeholder_7, :db_insert_placeholder_8,
:db_insert_placeholder_9, :db_insert_placeholder_10,
:db_insert_placeholder_11, :db_insert_placeholder_12); Array (
[:db_insert_placeholder_0] => 201 [:db_insert_placeholder_1] => 258
[:db_insert_placeholder_2] => my_estate_details
[:db_insert_placeholder_3] => en [:db_insert_placeholder_4] => 1
[:db_insert_placeholder_5] => [:db_insert_placeholder_6] => 5
[:db_insert_placeholder_7] => 1500889059 [:db_insert_placeholder_8] =>
1500889066 [:db_insert_placeholder_9] => 0 [:db_insert_placeholder_10]
=> 0 [:db_insert_placeholder_11] => 1 [:db_insert_placeholder_12] => 1 ) in DrupalCoreEntitySqlSqlContentEntityStorage->save()

In case I return $response (which is what I prefer in order to be able to alter the message etc), the first time works fine but the second I get the message:

The content has either been modified by another user, or you have
already submitted modifications. As a result, your changes cannot be
saved.’.

Apologies for the long message. Any idea/help will be helpful!

Thanks in advance.


Get this bounty!!!

#StackBounty: #8 #drupal-commerce $promotion->apply($order) doesn't work in commerce v2.0-rc1

Bounty: 100

I have a redemption form that I want to enter a coupon code and then an order should be created automatically, then the coupon code applied to the order as well.

The order gets created successfully but $promotion->apply($order) does not work.

enter image description here

As you can see in the image above, I have a promotion containing coupon code Z-8FDA5A218B44 . In the condition section, this promotion is limited to a product called Monthly.

I want to create a redemption form in which when a user enters a coupon code, an order and an order item that contains my product (Monthly) will be automatically created. (picture below)

enter image description here
As you can see when I submit the redemption form with a coupon code, an order will be created, but I want to apply the coupon code to the order too.

Here’s my code:

namespace Drupalmy_subscriptionForm;

use SymfonyComponentDependencyInjectionContainerInterface;
use DrupalCoreFormFormBase;
use DrupalCoreFormFormStateInterface;
use DrupalCoreSessionAccountProxy;
use Drupalcommerce_productPluginCommerceConditionOrderItemProduct as OrderItemProductCondition;
use Drupalcommerce_orderEntityOrder;
use Drupalcommerce_productEntityProductVariation;


/**
 * Class RedemptionForm.
 *
 * @package Drupalmy_subscriptionForm
 */
class RedemptionForm extends FormBase {

  /**
   * DrupalCoreSessionAccountProxy definition.
   *
   * @var DrupalCoreSessionAccountProxy
   */
  protected $currentUser;

  public function __construct(
    AccountProxy $current_user
  ) {
    $this->currentUser = $current_user;
  }

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('current_user')
    );
  }


  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'meditation_redemption_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['coupon_code'] = [
      '#type' => 'textfield',
      '#title' => t('Coupon code'),
      '#description' => t('Enter your coupon code to redeem a promotion.'),
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $coupon_code = $form_state->getValue('coupon_code');
    /** @var Drupalcommerce_promotionCouponStorageInterface $coupon_storage */
    $coupon_storage = Drupal::entityTypeManager()->getStorage('commerce_promotion_coupon');

    $coupon = $coupon_storage->loadByCode($coupon_code);
    if (empty($coupon)) {
      $form_state->setErrorByName('coupon_code', t('The provided coupon code is invalid.'));
      return;
    }
    else {
      $form_state->set('coupon', $coupon);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    /** @var Drupalcommerce_promotionEntityCoupon $coupon */
    $coupon = $form_state->get('coupon');
    /** @var Drupalcommerce_promotionEntityPromotion $promotion */
    $promotion = $coupon->getPromotion();

    $conditions = $promotion->getConditions();
    if ($conditions[0] instanceof OrderItemProductCondition) {
      $uid = $this->currentUser->id();

      $configuration = $conditions[0]->getConfiguration();
      $subscription_product_id = $configuration['products'][0]['product_id'];

      $subscription = ProductVariation::load($subscription_product_id);

      $order_item_storage = Drupal::entityManager()->getStorage('commerce_order_item');

      $order_item = $order_item_storage->createFromPurchasableEntity($subscription, [
        'quantity' => 1,
      ]);

      /** @var Drupalcommerce_orderEntityOrder $order */
      $order = Order::create([
        'type' => 'default',
      ]);
      $order->addItem($order_item);
      $order->setCustomerId($uid);
      $order->set('store_id', 1);
      $order->save();
      ///** @var  Drupalcommerce_ORDEROrderAssignment $order_assignment */
      //$order_assignment = Drupal::service('commerce_order.order_assignment');
      //$order_assignment->assign($order, $account);

      if ($coupon->available($order) && $promotion->applies($order)) {
        $promotion->apply($order);
      }
    }

  }

}


Get this bounty!!!

#StackBounty: #8 #drupal-commerce $promotion->apply($order) doesn't work in commerce v2.0-rc1

Bounty: 100

I have a redemption form that I want to enter a coupon code and then an order should be created automatically, then the coupon code applied to the order as well.

The order gets created successfully but $promotion->apply($order) does not work.

enter image description here

As you can see in the image above, I have a promotion containing coupon code Z-8FDA5A218B44 . In the condition section, this promotion is limited to a product called Monthly.

I want to create a redemption form in which when a user enters a coupon code, an order and an order item that contains my product (Monthly) will be automatically created. (picture below)

enter image description here
As you can see when I submit the redemption form with a coupon code, an order will be created, but I want to apply the coupon code to the order too.

Here’s my code:

namespace Drupalmy_subscriptionForm;

use SymfonyComponentDependencyInjectionContainerInterface;
use DrupalCoreFormFormBase;
use DrupalCoreFormFormStateInterface;
use DrupalCoreSessionAccountProxy;
use Drupalcommerce_productPluginCommerceConditionOrderItemProduct as OrderItemProductCondition;
use Drupalcommerce_orderEntityOrder;
use Drupalcommerce_productEntityProductVariation;


/**
 * Class RedemptionForm.
 *
 * @package Drupalmy_subscriptionForm
 */
class RedemptionForm extends FormBase {

  /**
   * DrupalCoreSessionAccountProxy definition.
   *
   * @var DrupalCoreSessionAccountProxy
   */
  protected $currentUser;

  public function __construct(
    AccountProxy $current_user
  ) {
    $this->currentUser = $current_user;
  }

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('current_user')
    );
  }


  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'meditation_redemption_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['coupon_code'] = [
      '#type' => 'textfield',
      '#title' => t('Coupon code'),
      '#description' => t('Enter your coupon code to redeem a promotion.'),
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $coupon_code = $form_state->getValue('coupon_code');
    /** @var Drupalcommerce_promotionCouponStorageInterface $coupon_storage */
    $coupon_storage = Drupal::entityTypeManager()->getStorage('commerce_promotion_coupon');

    $coupon = $coupon_storage->loadByCode($coupon_code);
    if (empty($coupon)) {
      $form_state->setErrorByName('coupon_code', t('The provided coupon code is invalid.'));
      return;
    }
    else {
      $form_state->set('coupon', $coupon);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    /** @var Drupalcommerce_promotionEntityCoupon $coupon */
    $coupon = $form_state->get('coupon');
    /** @var Drupalcommerce_promotionEntityPromotion $promotion */
    $promotion = $coupon->getPromotion();

    $conditions = $promotion->getConditions();
    if ($conditions[0] instanceof OrderItemProductCondition) {
      $uid = $this->currentUser->id();

      $configuration = $conditions[0]->getConfiguration();
      $subscription_product_id = $configuration['products'][0]['product_id'];

      $subscription = ProductVariation::load($subscription_product_id);

      $order_item_storage = Drupal::entityManager()->getStorage('commerce_order_item');

      $order_item = $order_item_storage->createFromPurchasableEntity($subscription, [
        'quantity' => 1,
      ]);

      /** @var Drupalcommerce_orderEntityOrder $order */
      $order = Order::create([
        'type' => 'default',
      ]);
      $order->addItem($order_item);
      $order->setCustomerId($uid);
      $order->set('store_id', 1);
      $order->save();
      ///** @var  Drupalcommerce_ORDEROrderAssignment $order_assignment */
      //$order_assignment = Drupal::service('commerce_order.order_assignment');
      //$order_assignment->assign($order, $account);

      if ($coupon->available($order) && $promotion->applies($order)) {
        $promotion->apply($order);
      }
    }

  }

}


Get this bounty!!!

#StackBounty: #8 #drupal-commerce $promotion->apply($order) doesn't work in commerce v2.0-rc1

Bounty: 100

I have a redemption form that I want to enter a coupon code and then an order should be created automatically, then the coupon code applied to the order as well.

The order gets created successfully but $promotion->apply($order) does not work.

enter image description here

As you can see in the image above, I have a promotion containing coupon code Z-8FDA5A218B44 . In the condition section, this promotion is limited to a product called Monthly.

I want to create a redemption form in which when a user enters a coupon code, an order and an order item that contains my product (Monthly) will be automatically created. (picture below)

enter image description here
As you can see when I submit the redemption form with a coupon code, an order will be created, but I want to apply the coupon code to the order too.

Here’s my code:

namespace Drupalmy_subscriptionForm;

use SymfonyComponentDependencyInjectionContainerInterface;
use DrupalCoreFormFormBase;
use DrupalCoreFormFormStateInterface;
use DrupalCoreSessionAccountProxy;
use Drupalcommerce_productPluginCommerceConditionOrderItemProduct as OrderItemProductCondition;
use Drupalcommerce_orderEntityOrder;
use Drupalcommerce_productEntityProductVariation;


/**
 * Class RedemptionForm.
 *
 * @package Drupalmy_subscriptionForm
 */
class RedemptionForm extends FormBase {

  /**
   * DrupalCoreSessionAccountProxy definition.
   *
   * @var DrupalCoreSessionAccountProxy
   */
  protected $currentUser;

  public function __construct(
    AccountProxy $current_user
  ) {
    $this->currentUser = $current_user;
  }

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('current_user')
    );
  }


  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'meditation_redemption_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['coupon_code'] = [
      '#type' => 'textfield',
      '#title' => t('Coupon code'),
      '#description' => t('Enter your coupon code to redeem a promotion.'),
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $coupon_code = $form_state->getValue('coupon_code');
    /** @var Drupalcommerce_promotionCouponStorageInterface $coupon_storage */
    $coupon_storage = Drupal::entityTypeManager()->getStorage('commerce_promotion_coupon');

    $coupon = $coupon_storage->loadByCode($coupon_code);
    if (empty($coupon)) {
      $form_state->setErrorByName('coupon_code', t('The provided coupon code is invalid.'));
      return;
    }
    else {
      $form_state->set('coupon', $coupon);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    /** @var Drupalcommerce_promotionEntityCoupon $coupon */
    $coupon = $form_state->get('coupon');
    /** @var Drupalcommerce_promotionEntityPromotion $promotion */
    $promotion = $coupon->getPromotion();

    $conditions = $promotion->getConditions();
    if ($conditions[0] instanceof OrderItemProductCondition) {
      $uid = $this->currentUser->id();

      $configuration = $conditions[0]->getConfiguration();
      $subscription_product_id = $configuration['products'][0]['product_id'];

      $subscription = ProductVariation::load($subscription_product_id);

      $order_item_storage = Drupal::entityManager()->getStorage('commerce_order_item');

      $order_item = $order_item_storage->createFromPurchasableEntity($subscription, [
        'quantity' => 1,
      ]);

      /** @var Drupalcommerce_orderEntityOrder $order */
      $order = Order::create([
        'type' => 'default',
      ]);
      $order->addItem($order_item);
      $order->setCustomerId($uid);
      $order->set('store_id', 1);
      $order->save();
      ///** @var  Drupalcommerce_ORDEROrderAssignment $order_assignment */
      //$order_assignment = Drupal::service('commerce_order.order_assignment');
      //$order_assignment->assign($order, $account);

      if ($coupon->available($order) && $promotion->applies($order)) {
        $promotion->apply($order);
      }
    }

  }

}


Get this bounty!!!

#StackBounty: #8 #drupal-commerce $promotion->apply($order) doesn't work in commerce v2.0-rc1

Bounty: 100

I have a redemption form that I want to enter a coupon code and then an order should be created automatically, then the coupon code applied to the order as well.

The order gets created successfully but $promotion->apply($order) does not work.

enter image description here

As you can see in the image above, I have a promotion containing coupon code Z-8FDA5A218B44 . In the condition section, this promotion is limited to a product called Monthly.

I want to create a redemption form in which when a user enters a coupon code, an order and an order item that contains my product (Monthly) will be automatically created. (picture below)

enter image description here
As you can see when I submit the redemption form with a coupon code, an order will be created, but I want to apply the coupon code to the order too.

Here’s my code:

namespace Drupalmy_subscriptionForm;

use SymfonyComponentDependencyInjectionContainerInterface;
use DrupalCoreFormFormBase;
use DrupalCoreFormFormStateInterface;
use DrupalCoreSessionAccountProxy;
use Drupalcommerce_productPluginCommerceConditionOrderItemProduct as OrderItemProductCondition;
use Drupalcommerce_orderEntityOrder;
use Drupalcommerce_productEntityProductVariation;


/**
 * Class RedemptionForm.
 *
 * @package Drupalmy_subscriptionForm
 */
class RedemptionForm extends FormBase {

  /**
   * DrupalCoreSessionAccountProxy definition.
   *
   * @var DrupalCoreSessionAccountProxy
   */
  protected $currentUser;

  public function __construct(
    AccountProxy $current_user
  ) {
    $this->currentUser = $current_user;
  }

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('current_user')
    );
  }


  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'meditation_redemption_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['coupon_code'] = [
      '#type' => 'textfield',
      '#title' => t('Coupon code'),
      '#description' => t('Enter your coupon code to redeem a promotion.'),
    ];

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $coupon_code = $form_state->getValue('coupon_code');
    /** @var Drupalcommerce_promotionCouponStorageInterface $coupon_storage */
    $coupon_storage = Drupal::entityTypeManager()->getStorage('commerce_promotion_coupon');

    $coupon = $coupon_storage->loadByCode($coupon_code);
    if (empty($coupon)) {
      $form_state->setErrorByName('coupon_code', t('The provided coupon code is invalid.'));
      return;
    }
    else {
      $form_state->set('coupon', $coupon);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    /** @var Drupalcommerce_promotionEntityCoupon $coupon */
    $coupon = $form_state->get('coupon');
    /** @var Drupalcommerce_promotionEntityPromotion $promotion */
    $promotion = $coupon->getPromotion();

    $conditions = $promotion->getConditions();
    if ($conditions[0] instanceof OrderItemProductCondition) {
      $uid = $this->currentUser->id();

      $configuration = $conditions[0]->getConfiguration();
      $subscription_product_id = $configuration['products'][0]['product_id'];

      $subscription = ProductVariation::load($subscription_product_id);

      $order_item_storage = Drupal::entityManager()->getStorage('commerce_order_item');

      $order_item = $order_item_storage->createFromPurchasableEntity($subscription, [
        'quantity' => 1,
      ]);

      /** @var Drupalcommerce_orderEntityOrder $order */
      $order = Order::create([
        'type' => 'default',
      ]);
      $order->addItem($order_item);
      $order->setCustomerId($uid);
      $order->set('store_id', 1);
      $order->save();
      ///** @var  Drupalcommerce_ORDEROrderAssignment $order_assignment */
      //$order_assignment = Drupal::service('commerce_order.order_assignment');
      //$order_assignment->assign($order, $account);

      if ($coupon->available($order) && $promotion->applies($order)) {
        $promotion->apply($order);
      }
    }

  }

}


Get this bounty!!!