View source
<?php
namespace Drupal\rdf_builder\Form;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
use Drupal\rdfui\SchemaOrgConverter;
class ContentBuilderForm extends FormBase {
protected $converter;
protected $entity;
protected $properties;
protected $rdfMapping;
private $prefix;
protected $datatype_field_mappings;
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',
);
}
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,
]));
}
$form_state
->set('page_num', 2);
$form_state
->setRebuild();
}
public function getFormId() {
return "rdf_builder_content_builder_form";
}
public function buildForm(array $form, FormStateInterface $form_state) {
if ($form_state
->has('page_num') && $form_state
->get('page_num') == 2) {
return $this
->buildFormPageTwo($form, $form_state);
}
$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;
}
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) {
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,
),
),
);
}
$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;
}
public function nextValidate(array $form, FormStateInterface $form_state) {
}
public function pageTwoBackValidate(array $form, FormStateInterface $form_state) {
}
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();
}
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],
)));
}
}
}
}
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(),
]));
$form_state
->setRedirectUrl(new Url('entity.node.field_ui_fields', array(
'node_type' => $this->entity
->id(),
)));
}
protected function createNodeType($rdf_type) {
$type = explode(':', $rdf_type);
$type = $this->prefix . $type[1];
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,
]));
}
}
protected function createField() {
$entity_type = 'node';
$bundle = $this->entity
->id();
foreach ($this->properties as $key => $value) {
$label = $this->converter
->label($key);
$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,
'translatable' => FALSE,
);
try {
\Drupal::entityTypeManager()
->getStorage('field_storage_config')
->create($field_storage)
->save();
\Drupal::entityTypeManager()
->getStorage('field_config')
->create($instance)
->save();
\Drupal::service('entity_display.repository')
->getFormDisplay($entity_type, $bundle, 'default')
->setComponent($field_name)
->save();
\Drupal::service('entity_display.repository')
->getFormDisplay($entity_type, $bundle, 'default')
->setComponent($field_name)
->save();
$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(),
)));
}
}
}
private function randomString($length = 4) {
$result = '';
for ($i = 0; $i < $length; $i++) {
$num = rand(97, 122);
$result .= chr($num);
}
$result = $result . '_';
return $result;
}
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';
}
}