class ContentBuilderForm in Schema.org configuration tool (RDF UI) 8
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\rdf_builder\Form\ContentBuilderForm
Expanded class hierarchy of ContentBuilderForm
1 string reference to 'ContentBuilderForm'
- rdf_builder.routing.yml in rdf_builder/
rdf_builder.routing.yml - rdf_builder/rdf_builder.routing.yml
File
- rdf_builder/
src/ Form/ ContentBuilderForm.php, line 12
Namespace
Drupal\rdf_builder\FormView source
class ContentBuilderForm extends FormBase {
/**
* Easy_RDF Converter from rdfui.
*
* @var /Drupal/rdfui/EasyRdfConverter
*/
protected $converter;
/**
* The field type manager.
*
* @var \Drupal\node\Entity\NodeType
*/
protected $entity;
/**
* List of properties selected by user.
*
* @var array
*/
protected $properties;
/**
* Existing or created RDF Mapping.
*
* @var \Drupal\rdf\Entity\RdfMapping
*/
protected $rdfMapping;
/**
* Prefix for the content type.
*
* @var string
*/
private $prefix;
/**
* Array mapping schema.org data types to field types.
*
* @var array
*/
protected $datatype_field_mappings;
/**
* Constructs a new ContentBuilder.
*/
public function __construct() {
$this->converter = new SchemaOrgConverter();
$this->datatype_field_mappings = array(
'http://schema.org/Text' => 'string',
'http://schema.org/PostalAddress' => 'string_long',
'http://schema.org/Number' => 'integer',
'http://schema.org/MediaObject' => 'file',
'http://schema.org/AudioObject' => 'file',
'http://schema.org/DateTime' => 'datetime',
'http://schema.org/Date' => 'datetime',
'http://schema.org/Integer' => 'integer',
'http://schema.org/Time' => 'datetime',
'http://schema.org/ImageObject' => 'image',
'http://schema.org/Boolean' => 'boolean',
);
}
/**
* Submit handler for Content Builder next button.
* Capture the values from page one and store them away so they can be used
* at final submit time.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function nextSubmit(array &$form, FormStateInterface &$form_state) {
$form_state
->set([
'page_values',
1,
], $form_state
->getValues());
if ($form_state
->has([
'page_values',
2,
])) {
$form_state
->setValues($form_state
->get([
'page_values',
2,
]));
}
// When form rebuilds, build method would be chosen based on to page_num.
$form_state
->set('page_num', 2);
$form_state
->setRebuild();
}
/**
* @inheritdoc
*/
public function getFormId() {
return "rdf_builder_content_builder_form";
}
/**
* @inheritdoc
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// Display page 2 if $form_state->get('page_num') == 2.
if ($form_state
->has('page_num') && $form_state
->get('page_num') == 2) {
return $this
->buildFormPageTwo($form, $form_state);
}
// Otherwise build page 1.
$form_state
->set('page_num', 1);
$form['#title'] = $this
->t('Content types');
$form['description'] = array(
'#type' => 'item',
'#title' => $this
->t('Create a content type by importing Schema.Org entity type.'),
);
$form['rdf-type'] = array(
'#title' => $this
->t('Type'),
'#id' => 'rdf-predicate',
'#type' => 'select',
'#required' => TRUE,
'#options' => $this->converter
->getListTypes(),
'#empty_option' => '',
'#default_value' => $form_state
->getValue('rdf-type', ''),
'#attached' => array(
'library' => array(
'rdfui/drupal.rdfui.autocomplete',
),
),
'#description' => $this
->t('Specify the type you want to associated to this content type e.g. Article, Blog, etc.'),
);
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['next'] = array(
'#type' => 'submit',
'#value' => $this
->t('Next >>'),
'#button_type' => 'primary',
'#submit' => array(
array(
$this,
'nextSubmit',
),
),
'#validate' => array(
array(
$this,
'nextValidate',
),
),
);
return $form;
}
/**
* Returns the form for the second page.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return array
* The form structure.
*/
protected function buildFormPageTwo(array $form, FormStateInterface $form_state) {
$form['#title'] = $this
->t('Content types');
$form['description'] = array(
'#type' => 'item',
'#title' => $this
->t('Choose fields to start with.'),
);
$rdf_type = $form_state
->get([
'page_values',
1,
'rdf-type',
]);
$properties = $this->converter
->getTypeProperties($rdf_type);
$field_types = \Drupal::service('plugin.manager.field.field_type')
->getUiDefinitions();
$field_type_options = array();
foreach ($field_types as $name => $field_type) {
// Skip field types which should not be added via user interface.
if (empty($field_type['no_ui'])) {
$field_type_options[$name] = $field_type['label'];
}
}
asort($field_type_options);
$table = array(
'#type' => 'table',
'#tree' => TRUE,
'#header' => array(
$this
->t('Enable'),
$this
->t('Property'),
$this
->t('Data Type'),
),
'#regions' => array(),
'#attributes' => array(
'class' => array(
'rdfui-field-mappings',
),
'id' => Html::getId('rdf-builder'),
),
);
foreach ($properties as $key => $value) {
$table[$key] = array(
'#attributes' => array(
'id' => Html::getClass($key),
),
'enable' => array(
'#type' => 'checkbox',
'#title' => $this
->t('Enable'),
'#title_display' => 'invisible',
),
'property' => array(
'#markup' => Html::escape($value),
),
'type' => array(
'#type' => 'select',
'#title' => $this
->t('Data Type'),
'#title_display' => 'invisible',
'#options' => $field_type_options,
'#default_value' => $this
->getDefaultFieldType($key),
'#empty_option' => $this
->t('- Select a field type -'),
'#attributes' => array(
'class' => array(
'field-type-select',
),
),
'#cell_attributes' => array(
'colspan' => 2,
),
),
);
}
// Fields.
$table['#regions']['content']['rows_order'] = array();
foreach (Element::children($table) as $name) {
$table['#regions']['content']['rows_order'][] = $name;
}
$form['fields'] = $table;
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['submit'] = array(
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => $this
->t('Save'),
);
$form['actions']['previous'] = array(
'#type' => 'submit',
'#value' => $this
->t('< Back'),
'#submit' => array(
array(
$this,
'pageTwoBackSubmit',
),
),
'#limit_validation_errors' => array(),
'#validate' => array(
array(
$this,
'pageTwoBackValidate',
),
),
'#weight' => -1,
);
return $form;
}
/**
* Validate handler for the next button on first page.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function nextValidate(array $form, FormStateInterface $form_state) {
// @TODO validate if required.
}
/**
* Validate handler for the back button on second page.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function pageTwoBackValidate(array $form, FormStateInterface $form_state) {
// @TODO validate if required.
}
/**
* Back button handler submit handler.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function pageTwoBackSubmit(array &$form, FormStateInterface &$form_state) {
$form_state
->setValues($form_state
->get([
'page_values',
1,
]));
$form_state
->set('page_num', 1);
$form_state
->setRebuild();
}
/**
* @inheritdoc
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
foreach ($form_state
->getValue('fields') as $key => $property) {
if ($property['enable'] == 1) {
if (empty($property['type'])) {
$form_state
->setErrorByName('fields][$key][type', $this
->t('Create field: you need to provide a data type for %field.', array(
'%field' => explode(':', $key)[1],
)));
}
}
}
}
/**
* @inheritdoc
*
* Final submit handler- gather all data together and create new content type.
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->prefix = $this
->randomString(4);
$this->properties = array();
foreach ($form_state
->getValue('fields') as $key => $property) {
if ($property['enable'] == 1) {
$this->properties[$key] = $property;
}
}
$page_one_values = $form_state
->get([
'page_values',
1,
]);
$rdf_type = $page_one_values['rdf-type'];
$this
->createNodeType($rdf_type);
$this->rdfMapping = rdf_get_mapping('node', $this->entity
->id());
$this->rdfMapping
->setBundleMapping(array(
'types' => array(
$rdf_type,
),
));
$this
->createField();
$this->rdfMapping
->save();
$this
->messenger()
->addMessage($this
->t('Content Type %label created', [
'%label' => $this->entity
->label(),
]));
/*@TODO Revert all saved content type and fields in case of error*/
$form_state
->setRedirectUrl(new Url('entity.node.field_ui_fields', array(
'node_type' => $this->entity
->id(),
)));
}
/**
* Creates a new node_type.
*
* @param string $rdf_type
* URI of the resource.
*/
protected function createNodeType($rdf_type) {
$type = explode(':', $rdf_type);
$type = $this->prefix . $type[1];
// Truncate if machine_name is longer than 32 char.
if (strlen($type) > 32) {
$type = substr($type, 0, 32);
}
$values = array(
'name' => $this->converter
->label($rdf_type),
'type' => strtolower($type),
'description' => $this->converter
->description($rdf_type),
);
try {
$this->entity = \Drupal::entityTypeManager()
->getStorage('node_type')
->create($values);
$this->entity
->save();
} catch (\Exception $e) {
$this
->messenger()
->addMessage($this
->t('Error saving content type %invalid.', [
'%invalid' => $rdf_type,
]));
}
}
/**
* Create fields for the selected properties.
*/
protected function createField() {
$entity_type = 'node';
$bundle = $this->entity
->id();
foreach ($this->properties as $key => $value) {
$label = $this->converter
->label($key);
// Add the field prefix and truncate if longer than 32 char.
$field_name = $this->prefix . strtolower($label);
if (strlen($field_name) > 32) {
$field_name = substr($field_name, 0, 32);
}
$field_storage = array(
'field_name' => $field_name,
'entity_type' => $entity_type,
'type' => $value['type'],
'translatable' => TRUE,
);
$instance = array(
'field_name' => $field_name,
'entity_type' => $entity_type,
'bundle' => $bundle,
'label' => $label,
// Field translatability should be explicitly enabled by the users.
'translatable' => FALSE,
);
// Create the field and instance.
try {
\Drupal::entityTypeManager()
->getStorage('field_storage_config')
->create($field_storage)
->save();
\Drupal::entityTypeManager()
->getStorage('field_config')
->create($instance)
->save();
// Make sure the field is displayed in the 'default' form mode (using
// default widget and settings). It stays hidden for other form modes
// until it is explicitly configured.
\Drupal::service('entity_display.repository')
->getFormDisplay($entity_type, $bundle, 'default')
->setComponent($field_name)
->save();
// Make sure the field is displayed in the 'default' view mode (using
// default formatter and settings). It stays hidden for other view
// modes until it is explicitly configured.
\Drupal::service('entity_display.repository')
->getFormDisplay($entity_type, $bundle, 'default')
->setComponent($field_name)
->save();
// RDF Mapping.
$this->rdfMapping
->setFieldMapping($field_name, array(
'properties' => array(
$key,
),
));
} catch (\Exception $e) {
$this
->messenger()
->addError($this
->t('There was a problem creating field %label: !message', array(
'%label' => $instance['label'],
'!message' => $e
->getMessage(),
)));
}
}
}
/**
* Generates a random string of lower case letters of a given length.
*
* @param int $length
* Length of the random string.
*
* @return string
* Return a random string.
*/
private function randomString($length = 4) {
$result = '';
for ($i = 0; $i < $length; $i++) {
$num = rand(97, 122);
$result .= chr($num);
}
$result = $result . '_';
return $result;
}
/**
* Gets default datatype for a given URI.
*
* @param string $uri
* URI of Schema.org property.
*
* @return string
* Default field type or text if there is no better match.
*/
protected function getDefaultFieldType($uri) {
$range_datatypes = $this->converter
->getRangeDataTypes($uri);
foreach ($range_datatypes as $datatype) {
if (array_key_exists($datatype, $this->datatype_field_mappings)) {
return $this->datatype_field_mappings[$datatype];
}
}
return 'string';
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ContentBuilderForm:: |
protected | property | Easy_RDF Converter from rdfui. | |
ContentBuilderForm:: |
protected | property | Array mapping schema.org data types to field types. | |
ContentBuilderForm:: |
protected | property | The field type manager. | |
ContentBuilderForm:: |
private | property | Prefix for the content type. | |
ContentBuilderForm:: |
protected | property | List of properties selected by user. | |
ContentBuilderForm:: |
protected | property | Existing or created RDF Mapping. | |
ContentBuilderForm:: |
public | function |
@inheritdoc Overrides FormInterface:: |
|
ContentBuilderForm:: |
protected | function | Returns the form for the second page. | |
ContentBuilderForm:: |
protected | function | Create fields for the selected properties. | |
ContentBuilderForm:: |
protected | function | Creates a new node_type. | |
ContentBuilderForm:: |
protected | function | Gets default datatype for a given URI. | |
ContentBuilderForm:: |
public | function |
@inheritdoc Overrides FormInterface:: |
|
ContentBuilderForm:: |
public | function | Submit handler for Content Builder next button. Capture the values from page one and store them away so they can be used at final submit time. | |
ContentBuilderForm:: |
public | function | Validate handler for the next button on first page. | |
ContentBuilderForm:: |
public | function | Back button handler submit handler. | |
ContentBuilderForm:: |
public | function | Validate handler for the back button on second page. | |
ContentBuilderForm:: |
private | function | Generates a random string of lower case letters of a given length. | |
ContentBuilderForm:: |
public | function |
@inheritdoc Overrides FormInterface:: |
|
ContentBuilderForm:: |
public | function |
@inheritdoc Overrides FormBase:: |
|
ContentBuilderForm:: |
public | function | Constructs a new ContentBuilder. | |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FormBase:: |
protected | property | The config factory. | 1 |
FormBase:: |
protected | property | The request stack. | 1 |
FormBase:: |
protected | property | The route match. | |
FormBase:: |
protected | function | Retrieves a configuration object. | |
FormBase:: |
protected | function | Gets the config factory for this form. | 1 |
FormBase:: |
private | function | Returns the service container. | |
FormBase:: |
public static | function |
Instantiates a new instance of this class. Overrides ContainerInjectionInterface:: |
87 |
FormBase:: |
protected | function | Gets the current user. | |
FormBase:: |
protected | function | Gets the request object. | |
FormBase:: |
protected | function | Gets the route match. | |
FormBase:: |
protected | function | Gets the logger for a specific channel. | |
FormBase:: |
protected | function |
Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait:: |
|
FormBase:: |
public | function | Resets the configuration factory. | |
FormBase:: |
public | function | Sets the config factory for this form. | |
FormBase:: |
public | function | Sets the request stack object to use. | |
LinkGeneratorTrait:: |
protected | property | The link generator. | 1 |
LinkGeneratorTrait:: |
protected | function | Returns the link generator. | |
LinkGeneratorTrait:: |
protected | function | Renders a link to a route given a route name and its parameters. | |
LinkGeneratorTrait:: |
public | function | Sets the link generator service. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
UrlGeneratorTrait:: |
protected | property | The url generator. | |
UrlGeneratorTrait:: |
protected | function | Returns the URL generator service. | |
UrlGeneratorTrait:: |
public | function | Sets the URL generator service. | |
UrlGeneratorTrait:: |
protected | function | Generates a URL or path for a specific route based on the given parameters. |