content_workflow_bynder-1.0.0/src/Plugin/migrate/source/ContentWorkflowBynderMigrateSource.php
src/Plugin/migrate/source/ContentWorkflowBynderMigrateSource.php
<?php namespace Drupal\content_workflow_bynder\Plugin\migrate\source; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\content_workflow_bynder\DrupalContentWorkflowBynderClient; use Drupal\migrate\MigrateException; use Drupal\migrate\Plugin\migrate\source\SourcePluginBase; use Drupal\migrate\Plugin\MigrateIdMapInterface; use Drupal\migrate\Plugin\MigrationInterface; use Drupal\migrate\Row; use GatherContent\DataTypes\Element; use GatherContent\DataTypes\ElementSimpleChoice; use GatherContent\DataTypes\ElementSimpleFile; use GatherContent\DataTypes\ElementSimpleText; use Symfony\Component\DependencyInjection\ContainerInterface; /** * A source class for Content Workflow API. * * @\Drupal\migrate\Annotation\MigrateSource( * id = "content_workflow_bynder_migration" * ) */ class ContentWorkflowBynderMigrateSource extends SourcePluginBase implements ContainerFactoryPluginInterface { /** * Project ID. * * @var int */ protected $projectId; /** * Template ID. * * @var int */ protected $templateId; /** * An array of source fields. * * @var array */ protected $fields = []; /** * An array of metatag source fields. * * @var array */ protected $metatagFields = []; /** * Drupal Content Workflow Client. * * @var \Drupal\content_workflow_bynder\DrupalContentWorkflowBynderClient */ protected $client; /** * {@inheritdoc} */ protected $trackChanges = TRUE; /** * List of Content Workflow IDs to import. * * If set, the collection lookups will be skipped and only those items will * be loaded. * * @var array */ protected array $ids; /** * {@inheritdoc} */ public function __construct( array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, DrupalContentWorkflowBynderClient $client ) { parent::__construct($configuration, $plugin_id, $plugin_definition, $migration); $configFields = [ 'projectId', 'templateId', 'fields', 'metatagFields', ]; foreach ($configFields as $configField) { if (isset($configuration[$configField])) { $this->{$configField} = $configuration[$configField]; } else { throw new MigrateException("The source configuration must include '$configField'."); } } $this->client = $client; } /** * {@inheritdoc} */ public static function create( ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL ) { return new static( $configuration, $plugin_id, $plugin_definition, $migration, $container->get('content_workflow_bynder.client') ); } /** * {@inheritdoc} */ public function count($refresh = FALSE): int { return count($this->getItems()); } /** * {@inheritdoc} */ public function getIds() { return [ 'id' => ['type' => 'string'], ]; } /** * Items to import. * * @var array */ protected $items = NULL; /** * {@inheritdoc} */ public function __toString() { return 'Content Workflow migration'; } /** * {@inheritdoc} */ public function fields() { return $this->fields; } /** * Get protected values. * * @param string $property * Property name. * * @return mixed * Value of the property. */ public function get(string $property) { return $this->{$property}; } /** * Get all items for given project and template. * * @return array * All items. */ public function getItems() { if ($this->items !== NULL) { return $this->items; } $ids = $this->getItemIds(); foreach ($ids as $id) { $collectedMetaTags = []; $cwbItem = $this->client->itemGet($id); if (empty($cwbItem)) { continue; } $item = get_object_vars($cwbItem); $item['item_title'] = $cwbItem->name; foreach ($cwbItem->content as $fieldId => $field) { $value = $this->getFieldValue($field); // Check if the field is for meta tags. if (array_key_exists($fieldId, $this->metatagFields)) { $collectedMetaTags[$this->metatagFields[$fieldId]] = $value; continue; } $item[$fieldId] = $value; } if (!empty($collectedMetaTags)) { $value = $this->prepareMetatags($collectedMetaTags); $item['meta_tags'] = $value; } // In single component mode, define an item for each entry in the // specified component. if (!empty($this->configuration['singleComponent'])) { if (!empty($item[$this->configuration['singleComponent']][0])) { foreach ($item[$this->configuration['singleComponent']] as $component_delta => $component_value) { $component_item = $item; $component_item[$this->configuration['singleComponent']] = $component_value; $component_item['id'] = $id . ':' . $component_delta; $this->items[$component_item['id']] = $component_item; } // Do not add the item again. continue; } } $this->items[$id] = $item; } return $this->items; } /** * Limit the source to the given IDs. * * @param array $ids */ public function setItemIds(array $ids): void { $this->ids = $ids; } /** * Either returns the set item ids or returns all for this project/template. * * @return array * List of IDS. */ public function getItemIds(): array { if (isset($this->ids)) { return $this->ids; } $current_page = 0; $this->ids = []; do { $response = $this->client->itemsGet($this->projectId, [ 'template_id' => $this->templateId, 'page' => ($current_page + 1), ]); // The first response will reveal the total number of pages. If there // is more than one page, continue until total pages has been reached. if (empty($response['data'])) { break; } /** @var \GatherContent\DataTypes\Pagination $pagination */ $pagination = $response['pagination']; $total_pages = $pagination->totalPages; $current_page = $pagination->currentPage; foreach ($response['data'] as $key => $item) { $this->ids[] = $item->id; } } while ($current_page < $total_pages); return $this->ids; } /** * Convert items to array. * * @param array $items * Items to covert. * * @return array * The converted array. */ protected function convertItemsToArray(array $items) { $converted = []; if ($items !== NULL) { foreach ($items as $key => $item) { $converted[$key] = get_object_vars($item); } } return $converted; } /** * Returns the correct files for the gathecontent content. * * @param array $cwbFiles * Content Workflow file array. * @param \GatherContent\DataTypes\Element $field * Content Workflow field. * * @return array * File list. */ protected function getFiles(array $cwbFiles, Element $field) { $value = []; foreach ($cwbFiles as $file) { if ($file->field == $field->id) { $value[] = $file; } } return $value; } /** * {@inheritdoc} */ protected function initializeIterator() { return new \ArrayIterator($this->getItems()); } /** * {@inheritdoc} */ public function prepareRow(Row $row) { $ret = parent::prepareRow($row); if ($ret) { foreach ($row->getSource() as $fieldid => $field) { if (in_array($fieldid, $this->fields) && is_array($field)) { foreach ($field as $subObject) { if ($subObject instanceof ElementSimpleFile) { // Entity with image needs to update as the alt_text property of // the image may have been updated/changed in Content Workflow. $idMap = $row->getIdMap(); $idMap['source_row_status'] = MigrateIdMapInterface::STATUS_NEEDS_UPDATE; $row->setIdMap($idMap); break 2; } } } } } return $ret; } /** * Returns the collected metatags values serialized. * * @param array $collectedMetaTags * The collected metatags. * * @return string * Serialized string. */ protected function prepareMetatags(array $collectedMetaTags) { return serialize($collectedMetaTags); } /** * Get field's value. * * @param mixed $field * Field object/objects. * * @return array * Returns value. */ protected function getFieldValue($field) { if (!is_array($field)) { return $field->getValue(); } $value = []; foreach ($field as $key => $item) { if ($item instanceof ElementSimpleChoice) { $value[$key] = [ 'cwb_id' => $item->id, ]; } elseif ($item instanceof ElementSimpleFile) { $value[$key] = $item; } elseif ($item instanceof ElementSimpleText) { // Lists of texts are keyed in an extra value, other texts // for example in a component) are not. if (is_int($key)) { $value[$key] = ['value' => $item->getValue()]; } else { $value[$key] = $item->getValue(); } } elseif (!is_array($item)) { $value[$key] = $item->getValue(); } else { $value[$key] = $this->getFieldValue($item); } } return $value; } }