ww_publish-8.x-1.x-dev/src/ParagraphField.php
src/ParagraphField.php
<?php
namespace Drupal\ww_publish;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\paragraphs\Entity\Paragraph;
use Drupal\ww_publish\Events\ParagraphFieldEvent;
class ParagraphField {
use MediaFieldTrait;
use FieldTrait;
/**
* Paragraph field configuration.
*
* @var \Drupal\Core\Field\FieldDefinitionInterface
*/
private $fieldConfig;
/**
* The SNS message.
*
* @var \Drupal\ww_publish\Message
*/
protected $message;
/**
* Metadata of the article received from WoodWing Studio.
*
* @var \Drupal\ww_publish\Metadata
*/
private $articleMetadata;
/**
* Article Components.
*
* @var array
*/
private $articleComponents;
/**
* Configuration of the ww_publish module.
*
* @var \Drupal\Core\Config\Config
*/
private $config;
/**
* A logger instance.
*
* @var \Psr\Log\LoggerInterface
*/
private $logger;
/**
* Constructor.
*
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_config
* Field config.
* @param \Drupal\ww_publish\Metadata $article_metadata
* Article components.
* @param array $article_components
* Article data.
* @param array $prepared_files
* Prepared files.
* @param \Drupal\Core\Config\Config $config
* Configuration of the ww_publish module.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
*/
public function __construct(FieldDefinitionInterface $field_config, Message $message, $article_components, $config, $logger) {
$this->message = $message;
$this->fieldConfig = $field_config;
$this->articleComponents = $article_components;
$this->config = $config;
$this->logger = $logger;
}
/**
* Get article data.
*
* @param \Drupal\Core\Field\FieldItemList $messagesField
* Error messages field.
*
* @return array
* @throws \Drupal\Core\TypedData\Exception\MissingDataException
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function getArticleData(&$messagesField = NULL): array {
$identifiers = $this->getIdentifiers();
$articleData = [];
foreach ($this->articleComponents as $wwComponent) {
$identifierKeys = array_keys(
array_column($identifiers, 'first_identifier'),
$wwComponent->identifier
);
$paragraph = NULL;
if (!empty($identifierKeys)) {
$identifierData = [];
foreach ($identifierKeys as $identifierKey) {
$identifierData[] = $identifiers[$identifierKey];
}
$paragraph = $this->createParagraph($wwComponent, $identifierData, $messagesField);
}
$event = new ParagraphFieldEvent($this->message, $wwComponent, $paragraph);
\Drupal::service('event_dispatcher')->dispatch($event);
if ($event->getParagraph()) {
$paragraph = $event->getParagraph();
$paragraph->save();
$articleData[] = [
'target_id' => $paragraph->id(),
'target_revision_id' => $paragraph->getRevisionId(),
];
}
}
if ($this->config->get('debug_mode'))
$this->logger->debug('Paragraph article data: <pre><code>@article_data</code></pre>', ['@article_data' => print_r($articleData, TRUE)]);
return $articleData;
}
/**
* Get content of the component.
*
* @param object $wwComponent
* WoodWing Studio component.
* @param array $identifiers
* The array items are arrays with the following keys: 'identifier',
* 'first_identifier', 'last_identifier', 'paragraph_type', 'field_name',
* 'field_type', 'field_config'.
* @param \Drupal\Core\Field\FieldItemList $messagesField
* Error messages field.
*
* @return \Drupal\Core\Entity\EntityInterface
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Drupal\Core\TypedData\Exception\MissingDataException
*/
private function createParagraph(object $wwComponent, array $identifiers, &$messagesField = NULL): ?EntityInterface {
$paragraphData = [
'type' => $identifiers[0]['paragraph_type'],
];
$createParagraph = FALSE;
foreach ($identifiers as $identifier) {
$wwIdentifiers = explode('|', $identifier['identifier']);
switch ($identifier['field_type']) {
case 'entity_reference':
$media_bundle = $this->getMediaTargetBundle($identifier['field_config']);
if (!empty($wwComponent->content->image)) {
$referenceId = $this->createMediaImage($media_bundle, $wwComponent->content);
if ($referenceId) {
$paragraphData[$identifier['field_name']] = [
'target_id' => $referenceId,
];
$createParagraph = TRUE;
}
}
break;
case 'entity_reference_revisions':
if ($this->config->get('debug_mode')) {
$this->logger->debug('WoodWing Studio component containers for @identifier: <pre><code>@containers</code></pre>', ['@identifier' => $wwComponent->identifier, '@containers' => print_r($wwComponent->containers, TRUE)]);
$this->logger->debug('Last identifier: @last_identifier', ['@last_identifier' => $identifier['last_identifier']]);
}
$paragraphField = new ParagraphField($identifier['field_config'], $this->message, $wwComponent->containers->{$identifier['last_identifier']}, $this->config, $this->logger);
$articleData = $paragraphField->getArticleData($messagesField);
if ($articleData) {
$paragraphData[$identifier['field_name']] = $articleData;
$createParagraph = TRUE;
}
break;
case 'link':
$child_identifiers = \array_slice($wwIdentifiers, 1);
$uri = $this->getComponentContent($wwComponent, ...$child_identifiers);
if (!is_string($uri) && $identifier['field_config']->isRequired()) {
$message = 'The component with identifier @station_identifier can not be saved as a link in the field @field_name.';
$this->logger->error($message, ['@station_identifier' => $identifier['identifier'], '@field_name' => $this->fieldConfig->getName()]);
$messagesField[]['value'] = t($message, ['@station_identifier' => $identifier['identifier'], '@field_name' => $this->fieldConfig->getName()]);
break;
}
if ($uri) {
$paragraphData[$identifier['field_name']] = [
'uri' => $uri,
];
$createParagraph = TRUE;
}
break;
default:
// Get content from the text property.
$content = [];
if (property_exists($wwComponent, 'content')) {
foreach ($wwComponent->content as $content_key => $component_content) {
$content[$content_key] = '';
if (\is_array($component_content)) {
foreach ($component_content as $text) {
$content[$content_key] .= $this->getAtributeContent($text, (bool) $identifier['field_config']->getFieldStorageDefinition()->getPropertyDefinition('format'));
}
}
else {
$content[$content_key] = $component_content;
}
}
}
$content = \array_filter($content);
if (!empty($content)) {
// Apply a template on the content.
$template = \Drupal::service('ww_publish.template');
if ($template->exist($identifier['identifier'], 'component')) {
$content = $template->apply($identifier['identifier'], 'component', $content);
}
else {
// No template, pick either the specified or first content
// component.
if (count($wwIdentifiers) === 2) {
$content = $content[$wwIdentifiers[1]] ?? '';
}
else {
$content = reset($content);
}
}
$content = $this->shortenValueToFieldMaxLength($content, $identifier['field_config'], $messagesField);
// Create a new paragraph.
if (\in_array($identifier['field_type'], ['string', 'string_long'])) {
$paragraphData[$identifier['field_name']] = [
'value' => strip_tags($content)
];
}
else {
$paragraphData[$identifier['field_name']] = [
'value' => $content,
'format' => $this->getTextFormat($this->fieldConfig),
];
}
$createParagraph = TRUE;
}
elseif ($identifier['field_config']->isRequired()) {
$message = 'The component with identifier @station_identifier can not be saved as a string in the field @field_name.';
$this->logger->error($message, ['@station_identifier' => $identifier['identifier'], '@field_name' => $this->fieldConfig->getName()]);
$messagesField[]['value'] = t($message, ['@station_identifier' => $identifier['identifier'], '@field_name' => $this->fieldConfig->getName()]);
}
}
}
if ($createParagraph) {
if ($this->config->get('debug_mode'))
$this->logger->debug('Paragraph data: <pre><code>@paragraph_data</code></pre>', ['@paragraph_data' => print_r($paragraphData, TRUE)]);
return Paragraph::create($paragraphData);
} else {
return NULL;
}
}
/**
* Get the component content.
*
* @param object $wwComponent
* WoodWing Studio component, from which the content should be extracted.
* @param string $contentProperty
* Property in the content object.
* @param string $textProperty
* Property in the object in the text array.
*
* @return string|bool
*/
private function getComponentContent(object $wwComponent, $contentProperty = 'text', $textProperty = NULL) {
$componentContent = [];
if (property_exists($wwComponent, 'content') && property_exists($wwComponent->content, $contentProperty)) {
if ($textProperty) {
if (\property_exists($wwComponent->content->$contentProperty, $textProperty)) {
return $this->getAtributeContent($wwComponent->content->$contentProperty->$textProperty);
}
}
else {
foreach ($wwComponent->content->{$contentProperty} as $text) {
$componentContent[] = $this->getAtributeContent($text);
}
return implode('', $componentContent);
}
}
return FALSE;
}
/**
* Get all defined WoodWing Studio identifiers.
*
* All identifiers from fields in all enabled paragraph types is returned as
* an array, of arrays with the following keys: identifier, paragraph_type,
* field_name.
*
* @return array
* @throws \Drupal\Core\TypedData\Exception\MissingDataException
*/
private function getIdentifiers(): array {
$identifiers = [];
// Get all enabled paragraph types.
$enabledParagraphTypes = $this->fieldConfig->get('settings')['handler_settings']['target_bundles'];
foreach ($enabledParagraphTypes as $type) {
$fields = \Drupal::service('entity_field.manager')->getFieldDefinitions('paragraph', $type);
foreach ($fields as $field_name => $fieldConfig) {
if ($fieldConfig instanceof FieldConfig && $fieldConfig->get('entity_type') === 'paragraph') {
$wwIdentifiers = $fieldConfig->getThirdPartySetting('ww_publish', 'content_station_identifier');
if ($wwIdentifiers) {
foreach (\explode(',', $wwIdentifiers) as $identifier) {
$paragraph_type = $fieldConfig->get("bundle");
$explodedIdentifier = explode('|', $identifier);
$lastIdentifier = end($explodedIdentifier);
$identifiers[] = [
'identifier' => $identifier,
'first_identifier' => strtok($identifier, '|'),
'last_identifier' => $lastIdentifier,
'paragraph_type' => $paragraph_type,
'field_name' => $field_name,
'field_type' => $fieldConfig->getType(),
'field_config' => $fieldConfig,
];
}
}
}
}
}
return $identifiers;
}
}
