Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
novicell/custom_forms / src / CustomFormItem.php
Size: Mime:
<?php

namespace Drupal\custom_forms;

use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Form\FormStateInterface;
use Drupal\custom_forms\Entity\CustomForm;
use Drupal\custom_forms\Entity\CustomFormType;
use Serializable;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class CustomFormItem
 *
 * A custom form item can represent either a field or a group used by a custom
 * form.
 * It is done this way to avoid having to use Drupal's entity system, as that
 * can add a lot of heavy overhead that we do not need or want.
 *
 * @package Drupal\custom_forms
 */
class CustomFormItem implements Serializable {

  /**
   * @var integer
   *   The revision ID of the item.
   */
  protected $revision;

  /**
   * @var integer
   *   The ID of the item.
   */
  protected $id;

  /**
   * @var integer
   *   The ID of the custom form this field is associated with.
   */
  protected $formId;

  /**
   * @var integer
   *   The ID for the revision of the custom form this field is associated
   *   with.
   */
  protected $formRevision;

  /**
   * @var integer
   *   The timestamp for when the item was created.
   */
  protected $created;

  /**
   * @var integer
   *   The timestamp for when the item was last changed.
   */
  protected $changed;

  /**
   * @var string
   *   The language code that the field is in.
   */
  protected $langcode;

  /**
   * @var string
   *   The type of the item.
   *   Can be either "field" or "group".
   */
  protected $type;

  /**
   * @var string
   *   The plugin ID that the item uses.
   */
  protected $pluginId;

  /**
   * @var string|null
   *   The plugin ID used for mapping functionality.
   *   Is only used when type is "field".
   */
  protected $mappingId;

  /**
   * @var string
   *   The machine name of the item.
   */
  protected $machineName;

  /**
   * @var integer
   *   The weight of the item.
   */
  protected $weight;

  /**
   * @var integer
   *   The item ID for the parent.
   */
  protected $parentId;

  /**
   * @var integer
   *   The depth of the item.
   */
  protected $depth;

  /**
   * @var array
   *   The settings for the item.
   */
  protected $settings;

  /**
   * @var array
   *   The states array for the item.
   */
  protected $states;

  /**
   * @var array
   *   An array of child items.
   */
  protected $childItems;

  /**
   * @var \Drupal\custom_forms\CustomFormItemFactory|null $factory
   *   The custom form item factory.
   */
  protected $factory;

  /**
   * CustomFormItem constructor.
   * Creates an instance of the CustomFormItem.
   *
   * @param integer $formId
   *   The ID of the custom form the item is associated with.
   * @param integer $form_revision
   *   The ID for the revision of the custom form the item is associated with.
   * @param integer $created
   *   The timestamp the item was created.
   * @param integer $changed
   *   The timestamp the item was last changed.
   * @param string $langcode
   *   The language code the field is in.
   * @param string $type
   *   The type of the item. Can be either "field" or "group".
   * @param string $pluginId
   *   The ID of the plugin used by the item.
   * @param string $machineName
   *   The machine readable name for the item.
   * @param string $settings
   *   The serialized settings for the item.
   * @param array $states
   *   The serialized states for the item.
   * @param string $mappingId
   *   The ID of the mapping plugin used when $type is "field".
   * @param integer $weight
   *   The weight of the item.
   * @param integer $parentId
   *   The ID of the parent of the item.
   * @param integer $revision
   *   The item revision ID.
   * @param integer $id
   *   The item ID.
   */
  public function __construct(
    $formId,
    $form_revision,
    $created,
    $changed,
    $langcode,
    $type,
    $pluginId,
    $machineName,
    $settings = NULL,
    $states = NULL,
    $mappingId = NULL,
    $weight = 0,
    $parentId = 0,
    $revision = NULL,
    $id = NULL
  ) {

    // Set values.
    $this->revision       = $revision;
    $this->id             = $id;
    $this->formId         = $formId;
    $this->formRevision   = $form_revision;
    $this->created        = $created;
    $this->changed        = $changed;
    $this->langcode       = $langcode;
    $this->type           = $type;
    $this->pluginId       = $pluginId;
    $this->mappingId      = $mappingId;
    $this->machineName    = $machineName;
    $this->weight         = $weight;
    $this->parentId       = $parentId;

    // If the $settings value is not null we unserialize it, otherwise we set it to an empty array.
    if ($settings !== NULL) {
      $this->settings = unserialize($settings,['allowed_classes' => FALSE]);
      $this->settings['machine_name'] = $machineName;
    } else {
      $this->settings = [];
    }

    if ($states !== NULL) {
      if (is_array($states)) {
        $this->states = $states;
      }
      else if (is_string($states)) {
        $this->states = unserialize((string)$states, ['allowed_classes' => FALSE]);
      }
    }
  }

  /**
   * Saves the item to the database.
   *
   * @param bool $create_new_revision
   *   Whether a new revision should be created of the field when saved.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   *
   * @throws \Exception If the insert failed, an exception is thrown.
   */
  public function save($create_new_revision = TRUE): CustomFormItem {
    $item_factory = $this->getFactory();
    return $item_factory->saveItem($this, $create_new_revision);
  }

  /**
   * Deletes the item from the database.
   */
  public function delete(): void {
    $item_factory = $this->getFactory();
    $item_factory->deleteItem($this);
  }

  /**
   * Get the factory in charge of handling all CRUD operations.
   *
   * @return \Drupal\custom_forms\CustomFormItemFactory
   */
  public function getFactory() : CustomFormItemFactory {
    if ($this->factory === NULL) {
      $this->factory = \Drupal::service('custom_forms.factory.item');
    }
    return $this->factory;
  }

  /**
   * Gets the ID of the item.
   *
   * @return null|integer
   */
  public function id(): ?int {
    return $this->id;
  }

  /**
   * Gets the revision ID of the item.
   *
   * @return integer
   */
  public function getRevision(): int {
    return $this->revision;
  }

  /**
   * Gets the ID of the associated custom form.
   *
   * @return integer
   */
  public function getFormId(): int {
    return $this->formId;
  }

  /**
   * Gets the associated custom form instance.
   *
   * @return \Drupal\Core\Entity\EntityInterface|\Drupal\custom_forms\Entity\CustomForm|null
   *   Returns NULL if no form was found.
   */
  public function getForm() {
    return CustomForm::load($this->formId);
  }

  /**
   * Gets the revision id for the associated custom form.
   *
   * @return int
   */
  public function getFormRevisionId(): int {
    return $this->formRevision;
  }

  /**
   * Gets the datetime when the item was created
   *
   * @return \Drupal\Core\Datetime\DrupalDateTime
   */
  public function getCreated(): DrupalDateTime {
    $item_factory = $this->getFactory();
    return DrupalDateTime::createFromTimestamp(
      $this->created,
      new \DateTimeZone(date_default_timezone_get()),
      [
        'langcode' => $item_factory->getLanguageManager()->getCurrentLanguage()->getId(),
      ]
    );
  }

  /**
   * Gets the datetime when the item was last changed.
   *
   * @return \Drupal\Core\Datetime\DrupalDateTime
   */
  public function getChanged(): DrupalDateTime {
    $item_factory = $this->getFactory();
    return DrupalDateTime::createFromTimestamp(
      $this->changed,
      new \DateTimeZone(date_default_timezone_get()),
      [
        'langcode' => $item_factory->getLanguageManager()->getCurrentLanguage()->getId(),
      ]
    );
  }

  /**
   * Gets the language code used by the item.
   *
   * @return string
   */
  public function getLangcode(): string {
    return $this->langcode;
  }

  /**
   * Gets the weight of the item.
   *
   * @return integer
   *   The weight of the item.
   */
  public function getWeight(): int {
    return $this->weight;
  }

  /**
   * Gets the id of the parent item.
   *
   * @return integer
   *   If it is 0 (zero) it means no parent is defined.
   */
  public function getParentId(): int {
    return $this->parentId;
  }

  /**
   * Gets an instance of the parent item.
   *
   * @return bool|\Drupal\custom_forms\CustomFormItem
   *   Returns a CustomFormItem if the parent exists, otherwise FALSE.
   */
  public function getParent() {
    return $this->getFactory()->loadItem($this->parentId);
  }

  /**
   * Gets the depth of the item.
   *
   * @return integer
   *   Returns the depth of the item.
   */
  public function getDepth(): int {
    return $this->depth;
  }

  /**
   * Gets the type of the item.
   *
   * @return string
   *   Can be either "field" or "group"
   */
  public function getType(): string {
    return $this->type;
  }

  /**
   * Gets the definition of the plugin used by the item.
   *
   * @return array
   */
  public function getPluginDefinition(): ?array {
    $item_factory = $this->getFactory();
    return $item_factory->getItemPluginDefinition($this->type, $this->pluginId);
  }

  /**
   * Gets the plugin manager for the item.
   *
   * @return \Drupal\Component\Plugin\PluginManagerInterface
   */
  public function getPluginManager(): PluginManagerInterface {
    $item_factory = $this->getFactory();
    return $item_factory->getItemPluginManager($this->type);
  }

  /**
   * Gets the plugin id used by the item.
   *
   * @return string
   *   The plugin id.
   */
  public function getPluginId(): string {
    return $this->pluginId;
  }

  /**
   * Gets an instance of the plugin used by the item.
   *
   * @return \Drupal\custom_forms\Plugin\CustomForms\FieldType\CustomFormsFieldTypeInterface|\Drupal\custom_forms\Plugin\CustomForms\GroupType\CustomFormsGroupTypeInterface
   *   The instance of the plugin.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   *   If the instance cannot be created, such as if the ID is invalid.
   */
  public function getPlugin() {
    $item_factory = $this->getFactory();
    return $item_factory->getItemPlugin($this->type, $this->pluginId, $this->settings);
  }

  /**
   * Gets the mapping plugin ID.
   *
   * @return string|null
   *   Returns NULL if item does not have or use mapping.
   */
  public function getMappingId(): ?string {
    return $this->mappingId;
  }

  /**
   * Gets the mapping plugin definition.
   *
   * @return array|null
   *   Returns NULL if item does not have or use mapping.
   */
  public function getMappingPluginDefinition(): ?array {
    // We need to load the proper plugin definition based on the specified item type.
    switch ($this->type) {
      case 'group':
        return NULL;
      case 'field':
      default:
        $item_factory = $this->getFactory();
        return $item_factory->getItemPluginDefinition('mapping', $this->mappingId);
        break;
    }
  }

  /**
   * Gets the mapping plugin manager.
   *
   * @return \Drupal\Component\Plugin\PluginManagerInterface
   */
  public function getMappingPluginManager(): PluginManagerInterface {
    $item_factory = $this->getFactory();
    return $item_factory->getItemPluginManager('mapping');
  }

  /**
   * Gets an instance of the mapping plugin.
   *
   * @return object|null
   *   Returns an instance of the mapping plugin, or NULL if the item does
   *   not have or use mapping.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   *   Throws an exception when the plugin is either missing or malformed.
   *   This indicates that something is very wrong with the custom form item.
   */
  public function getMappingPlugin() {
    if (!empty($this->mappingId)) {
      $item_factory = $this->getFactory();
      return $item_factory->getItemPlugin('mapping', $this->mappingId);
    }
    return NULL;
  }

  /**
   * Gets the machine name for the item
   *
   * @return string
   *   The generated machine name for the item.
   */
  public function getMachineName(): string {
    return $this->machineName;
  }

  /**
   * Gets the jQuery selector for the item.
   *
   * @return string
   *   Returns the jquery selector.
   */
  public function getJquerySelector(): string {
    try {
      $modified_selector = $this->getPlugin()
        ->modifyJquerySelector($this->machineName);
      return $modified_selector;
    } catch (PluginException $e) {
      $error_message = t('PluginException during when attempting to get jquery selector, falling back to machine name. Message = %message', [
        '%message' => $e->getMessage(),
      ]);
      \Drupal::logger('Custom Forms')->error($error_message);
      return $this->machineName;
    }
  }

  /**
   * Gets the settings associated with the item.
   *
   * @return array
   */
  public function getSettings(): array {
    return $this->settings;
  }

  /**
   * Gets a specific setting for the item.
   *
   * @param $key
   *   The key to get the setting for.
   *
   * @return bool|mixed
   *   Returns the value for the specified key if found, otherwise returns
   *   FALSE.
   */
  public function getSetting($key) {
    return $this->settings[$key] ?? FALSE;
  }

  /**
   * Gets the states array associated with the item.
   *
   * @return array
   */
  public function getStates(): array {
    return $this->states ?? [];
  }

  /**
   * Gets a specific state for the item.
   *
   * @param $key
   *   The key to get the state for.
   *
   * @return bool|mixed
   *   Returns the value of the specified key if found, otherwise FALSE.
   */
  public function getState($key) {
    return $this->states[$key] ?? FALSE;
  }

  /**
   * Gets the items that are children of this item.
   *
   * @param string $sort_by
   *   The column to sort the children by, default is weight.
   * @param string $sort_direction
   *   The direction to sort in, defaults to ASC.
   *
   * @return \Drupal\custom_forms\CustomFormItem[]
   */
  public function getChildren($sort_by = 'weight', $sort_direction = 'ASC'): array {
    if ($this->childItems === NULL) {
      $item_factory = $this->getFactory();
      $this->childItems = $item_factory->loadMultipleItems([
        'form' => $this->formId,
        'form_revision' => $this->formRevision,
        'pid' => $this->id,
        'langcode' => $this->langcode
      ], $sort_by, $sort_direction) ?? [];
    }
    return $this->childItems;
  }

  /**
   * Whether the plugin defines that it's machine name should be hidden.
   *
   * @return bool
   *   Returns TRUE if the machine name should be hidden, otherwise FALSE.
   */
  public function isMachineNameHidden(): bool {
    $definition = $this->getPluginDefinition();
    if (isset($definition['hide_machine_name'])) {
      return (bool) $definition['hide_machine_name'];
    }
    return FALSE;
  }

  /**
   * Sets the ID of the custom form item.
   *
   * @param integer $id
   *   The ID of the custom form item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setId($id): CustomFormItem {
    $this->id = $id;
    return $this;
  }

  /**
   * Sets the ID of the associated form.
   *
   * @param integer $formId
   *   The ID of the associated form.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setFormId($formId): CustomFormItem {
    $this->formId = $formId;
    return $this;
  }

  /**
   * Sets the ID of the revision of the associated form.
   *
   * @param integer $formRevision
   *   The ID of the revision of the associated form.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setFormRevisionId($formRevision): CustomFormItem  {
    $this->formRevision = $formRevision;
    return $this;
  }

  /**
   * Sets the ID of the revision of the custom form item.
   *
   * @param integer $revision
   *   The ID of the revision of the custom form item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setRevision($revision): CustomFormItem  {
    $this->revision = $revision;
    return $this;
  }

  /**
   * Sets the timestamp for when the item was created.
   *
   * @param integer $timestamp
   *   The timestamp for when the item was created.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setCreated($timestamp): CustomFormItem {
    $this->created = $timestamp;
    return $this;
  }

  /**
   * Sets the timestamp for when the item was last changed.
   *
   * @param integer $timestamp
   *   The timestamp for when the item was last changed.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setChanged($timestamp): CustomFormItem {
    $this->changed = $timestamp;
    return $this;
  }

  /**
   * Set the language code for the item.
   *
   * @param string $langcode
   *   The language code to set for the item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setLangcode($langcode) {
    $this->langcode = $langcode;
    return $this;
  }

  /**
   * Sets the weight of the item.
   *
   * @param $weight
   *   The weight of the item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setWeight($weight): CustomFormItem {
    $this->weight = $weight;
    return $this;
  }

  /**
   * Sets the ID of the parent item.
   *
   * @param $parentId
   *   The ID of the parent item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setParentId($parentId): CustomFormItem {
    $this->parentId = $parentId;
    return $this;
  }

  /**
   * Sets the depth of the item.
   *
   * @param $depth
   *   The depth to set on the item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setDepth($depth): CustomFormItem {
    $this->depth = $depth;
    return $this;
  }

  /**
   * Sets the type of the item.
   *
   * @param $type
   *   The type of the item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setType($type): CustomFormItem {
    $this->type = $type;
    return $this;
  }

  /**
   * Sets the plugin id used by the item.
   *
   * @param $pluginId
   *   The plugin id used by the item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setPluginId($pluginId): CustomFormItem {
    $this->pluginId = $pluginId;
    return $this;
  }

  /**
   * Sets the mapping plugin id.
   *
   * @param $mappingId
   *   The mapping plugin id.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setMappingId($mappingId): CustomFormItem {
    $this->mappingId = $mappingId;
    return $this;
  }

  /**
   * Sets the array of settings for the item.
   *
   * @param array $settings
   *   The array of settings for the item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setSettings(array $settings): CustomFormItem {
    $this->settings = $settings;
    return $this;
  }

  /**
   * Sets the setting with the specified key to the specified value.
   *
   * @param integer|string $key
   *   The key for the setting.
   * @param mixed $value
   *   The value for the setting.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setSetting($key, $value): CustomFormItem {
    $this->settings[$key] = $value;
    return $this;
  }

  /**
   * Sets the array of states for the item.
   *
   * @param array $states
   *   The array of states for the item.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setStates(array $states): CustomFormItem {
    $this->states = $states;
    return $this;
  }

  /**
   * Sets the state with the specified key to the specified value.
   *
   * @param integer|string $key
   *   The key for the state.
   * @param mixed $value
   *   The value for the state.
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setState($key, $value): CustomFormItem {
    $this->states[$key] = $value;
    return $this;
  }

  /**
   * Sets the child items of this item.
   *
   * @param \Drupal\custom_forms\CustomFormItem[] $children
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function setChildren(array $children): CustomFormItem {
    $this->childItems = $children;
    return $this;
  }

  /**
   * Adds a child to the item.
   *
   * @param \Drupal\custom_forms\CustomFormItem $child
   *
   * @return \Drupal\custom_forms\CustomFormItem
   */
  public function addChild(CustomFormItem $child): CustomFormItem {
    $this->childItems[$child->id()] = $child;
    return $this;
  }

  /**
   * Build the form for the item.
   *
   * @param array $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   * @param \Symfony\Component\HttpFoundation\Request $request
   *
   * @return array
   */
  public function buildForm(array $form, FormStateInterface $form_state, Request $request): array {
    $build = [];
    try {
      $build[$this->machineName] = $this->getPlugin()->buildForm($this, $form, $form_state, $request);
      $build[$this->machineName]['#weight'] = $this->getWeight();

      if (!empty($this->childItems)) {
        /** @var \Drupal\custom_forms\CustomFormItem $childItem */
        foreach ($this->childItems as $id => $childItem) {
          $build[$this->machineName] += $childItem->buildForm($form, $form_state, $request);
        }
      }

      // Invoke hook to allow modules to alter the render array for the item.
      \Drupal::moduleHandler()->invokeAll('preprocess_custom_forms__form_item', [&$build[$this->machineName], $this]);
    } catch (PluginException $e) {
      \Drupal::logger('Custom Forms')->error($e->getMessage() . '<p><pre>' . $e->getTraceAsString() . '</pre></p>');
    }

    return $build;
  }

  /**
   * Check if the submitted item is empty.
   *
   * @param array $values
   *   The array of submitted values
   *
   * @return bool
   *   Returns TRUE if the submitted item is empty, otherwise FALSE.
   */
  public function isEmpty(array $values) {
    try {
      return $this->getPlugin()->isEmpty($values, $this);
    } catch (PluginException $e) {
      \Drupal::logger('Custom Forms')->error($e->getMessage() . '<p><pre>' . $e->getTraceAsString() . '</pre></p>');
      return FALSE;
    }
  }

  /**
   * Serializes the class to a string representation of it.
   *
   * @return string the string representation of the object or null
   */
  public function __serialize(): array {
    // We only serialize the vital data to save on string length.
    return [
      'form_id' => $this->formId,
      'form_revision' => $this->formRevision,
      'created' => $this->created,
      'changed' => $this->changed,
      'langcode' => $this->langcode,
      'type' => $this->type,
      'plugin_id' => $this->pluginId,
      'machine_name' => $this->machineName,
      'settings' => $this->settings,
      'states' => $this->states,
      'mapping_id' => $this->mappingId,
      'weight' => $this->weight,
      'parent_id' => $this->parentId,
      'revision' => $this->revision,
      'id' => $this->id,
    ];
  }

  /**
   * Unserializes the string representation into an instance of CustomFormItem.
   *
   * @param string $serialized
   *   The string representation of the object.
   */
  public function __unserialize(array $data): void {
    // Move the unserialized data to their respective variables.
    $this->formId         = $data['form_id'];
    $this->formRevision   = $data['form_revision'];
    $this->created        = $data['created'];
    $this->changed        = $data['changed'];
    $this->langcode       = $data['langcode'];
    $this->type           = $data['type'];
    $this->pluginId       = $data['plugin_id'];
    $this->machineName    = $data['machine_name'];
    $this->settings       = $data['settings'];
    $this->states         = $data['states'];
    $this->mappingId      = $data['mapping_id'];
    $this->weight         = $data['weight'];
    $this->parentId       = $data['parent_id'];
    $this->revision       = $data['revision'];
    $this->id             = $data['id'];
  }

  /**
   * {@inheritdoc}
   */
  public function serialize() {
    return serialize($this->__serialize());
  }

  /**
   * {@inheritdoc}
   */
  public function unserialize($data) {
    $this->__unserialize(unserialize($data));
    return $this;
  }
}