2

I am creating a configuration entity for a module and in my config/schema.yml has as field as,

mymodule.connection.* :
  type: config_entity
  label: SSO connection
  mapping:
    name:
      type: label
      label: 'Name'
    id:
      type: string
      label: 'Machine name'
    url:
      type: string
      label: 'URL of the endpoint'
    consumerSettings:
      type: text
      label: 'Advanced storage for Consumer like key and secret'

In my Entity class I have written the following,

class SSOConnectionEntity extends ConfigEntityBase implements SSOConnectionInterface {
  /**
   * The connector machine name.
   *
   * @var string
   */
  protected $id;

  /**
   * The name of the connection.
   *
   * @var string
   */
  protected $name;

  /**
   * OAuth consumer id.
   *
   * @var integer
   */
  protected $cid;

  /**
   * URL endpoint of the connection provider.
   *
   * @var string
   */
  protected $url;

  /**
   * Serialized consumer settings for a connection.
   *
   * @var array
   */
  protected $consumerSettings = array();
}

And in the add-form,

class SSOConnectionFormBase extends EntityForm {
  /**
   * @var \Drupal\Core\Entity\Query\QueryFactory
   */
  protected $entityQueryFactory;

  /**
   * Construct the SSOConnection base form.
   *
   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
   */
  public function __construct(QueryFactory $query_factory) {
    $this->entityQueryFactory = $query_factory;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container->get('entity.query'));
  }

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

  /**
   * Builds the default form to add/edit connections.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param FormStateInterface $form_state
   *   An associative array containing the current state of the form.
   *
   * @return array
   *   An associative array containing the connection add/edit form.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);
    // Get the entity.
    $connection = $this->entity;

    $form['name'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Connection title'),
      '#maxlength' => 255,
      '#size' => 60,
      '#default_value' => '',
      '#required' => TRUE,
    );
    // The unique machine name of the connection.
    $form['id'] = array(
      '#type' => 'machine_name',
      '#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
      '#default_value' => '',
      '#disabled' => !$connection->isNew(),
      '#machine_name' => array(
        'source' => array('name'),
        'exists' => 'sso_connection_load'
      ),
    );

    $form['url'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Base URL'),
      '#maxlength' => 255,
      '#size' => 60,
      '#default_value' => '',
      '#required' => TRUE,
    );

    $form['key'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Consumer Key'),
      '#maxlength' => 255,
      '#size' => 60,
      '#default_value' => '',
      '#required' => TRUE,
    );

    $form['secret'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('Consumer Secret'),
      '#maxlength' => 255,
      '#size' => 60,
      '#default_value' => '',
      '#required' => TRUE,
    );

    // @todo: The advanced settings and field mappings.

    return $form;
  }

  public function save(array $form, FormStateInterface $form_state) {
    $connection = $this->entity;

    $status = $connection->save();
  }
}

Now I want to save the 2 fields values (key & secret) to the single schema "consumerSettings". How can I do that, the simple $entity->save() is not doing it. What is needed to be changed? FYI, I saw the cheatsheet http://hojtsy.hu/files/ConfigSchemaCheatSheet1.3.pdf but not getting it to work properly. Please help.

Thanks!

  • Are you sure you're extending the correct class? Seems like what you're trying to accomplish can be done with ConfigFormBase using ConfigFormBase::buildForm and ConfigFormBase::submitForm, but I'm never sure because the class documentation doesn't say "Use this class when..." Anyway if you're just trying to present a form to the user and save the values, this worked for me. – Webdrips Mar 8 '15 at 10:34
  • @Webdrips: The form methods are in a different class, it's just not visible here. – Berdir Mar 8 '15 at 13:49
3

Don't serialize.

It's a config entity, there is no need for a config entity to have a flat structure. Instead, use type mapping with sub-keys.

To actually get your values that way in the config entity, the easiest way is to have the same structure in the form, with #tree => TRUE. Or you can set the values in the buildEntity method.

  • I edited the code with the class skeleton. I hope it will be better for every one to understand. Can you please help me with some snippets? Thanks! I'd really love to talk with you on this in #drupal-contribute soon. :-) – Aneek Mukhopadhyay Mar 8 '15 at 18:21
  • Just change it to $form['consumerSettings']['secret'] and so on and set $form['consumerSettings']['#tree'] = TRUE. Also, another note: Core usually uses consumer_settings for config entity properties that map to Yaml, although there are discussions on changing it and making the mapping more flexible. and change that in your schema to type mapping with a mapping of the keys below it. – Berdir Mar 8 '15 at 21:38
  • Thanks Berdir, for showing me the way. I changed "consumerSettings" to type "sequence" and added proper mapping to it. The value is saved. Also used #tree = TRUE. – Aneek Mukhopadhyay Mar 9 '15 at 15:36
  • type mapping I assume? sequence is a list of identical items, mapping is a key/value thing (where value can be another mapping or sequence), with explicitly defined keys. – Berdir Mar 9 '15 at 15:48
  • yes. Here is what I added. gist.github.com/aneek/6256e9af4bd03daa2b91 – Aneek Mukhopadhyay Mar 9 '15 at 18:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.