Repository URL to install this package:
|
Version:
2.0.2 ▾
|
<?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;
}
}