diff --git a/config/install/language.content_settings.tpr_service.tpr_service.yml b/config/install/language.content_settings.tpr_service.tpr_service.yml new file mode 100644 index 00000000..5ce8174e --- /dev/null +++ b/config/install/language.content_settings.tpr_service.tpr_service.yml @@ -0,0 +1,16 @@ +langcode: en +status: true +dependencies: + module: + - content_translation + - helfi_tpr +third_party_settings: + content_translation: + enabled: true + bundle_settings: + untranslatable_fields_hide: '0' +id: tpr_service.tpr_service +target_entity_type_id: tpr_service +target_bundle: tpr_service +default_langcode: site_default +language_alterable: true diff --git a/helfi_tpr.install b/helfi_tpr.install new file mode 100644 index 00000000..6bf117e1 --- /dev/null +++ b/helfi_tpr.install @@ -0,0 +1,58 @@ +getDefinition('tpr_service'); + $manager->installEntityType($entity_type); +} + +/** + * Install TPR service description field. + */ +function helfi_tpr_update_8002() : void { + $manager = \Drupal::entityDefinitionUpdateManager(); + $fields = []; + $fields['description'] = BaseFieldDefinition::create('text_with_summary') + ->setTranslatable(TRUE) + ->setLabel(new TranslatableMarkup('Description')) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayConfigurable('view', TRUE); + + foreach ($fields as $name => $field) { + $manager->installFieldStorageDefinition($name, 'tpr_service', 'helfi_tpr', $field); + } +} + +/** + * Install TPR unit service reference field. + */ +function helfi_tpr_update_8003() : void { + $manager = \Drupal::entityDefinitionUpdateManager(); + $fields = []; + $fields['services'] = BaseFieldDefinition::create('entity_reference') + ->setLabel(new TranslatableMarkup('Services')) + ->setSettings([ + 'target_type' => 'tpr_service', + 'handler_settings' => [ + 'target_bundles' => ['tpr_service'], + ], + ]) + ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) + ->setDisplayConfigurable('view', TRUE) + ->setDisplayConfigurable('form', TRUE); + + foreach ($fields as $name => $field) { + $manager->installFieldStorageDefinition($name, 'tpr_unit', 'helfi_tpr', $field); + } +} diff --git a/helfi_tpr.links.menu.yml b/helfi_tpr.links.menu.yml index 3f41c9a7..c700b8d0 100644 --- a/helfi_tpr.links.menu.yml +++ b/helfi_tpr.links.menu.yml @@ -1,4 +1,4 @@ -entity.tpr_unit.settings: +tpr_unit.settings: title: TPR - Unit settings description: Configure TPR unit entity type route_name: tpr_unit.settings @@ -9,3 +9,15 @@ entity.tpr_unit.collection: description: List of TPR unit entities route_name: entity.tpr_unit.collection parent: system.admin_content + +tpr_service.settings: + title: TPR - Service settings + description: Configure TPR service entity type + route_name: tpr_service.settings + parent: system.admin_structure + +entity.tpr_service.collection: + title: TPR - Service entities + description: List of TPR service entities + route_name: entity.tpr_service.collection + parent: system.admin_content diff --git a/helfi_tpr.links.task.yml b/helfi_tpr.links.task.yml index 045eff01..40c44273 100644 --- a/helfi_tpr.links.task.yml +++ b/helfi_tpr.links.task.yml @@ -2,21 +2,52 @@ tpr_unit.settings: title: Settings route_name: tpr_unit.settings base_route: tpr_unit.settings + entity.tpr_unit.view: title: View route_name: entity.tpr_unit.canonical base_route: entity.tpr_unit.canonical + entity.tpr_unit.edit_form: title: Edit route_name: entity.tpr_unit.edit_form base_route: entity.tpr_unit.canonical + entity.tpr_unit.delete_form: title: Delete route_name: entity.tpr_unit.delete_form base_route: entity.tpr_unit.canonical weight: 10 -entity.tpr_unit.collection: + +tpr_unit.content_list: title: TPR - Unit route_name: entity.tpr_unit.collection base_route: system.admin_content weight: 10 + +tpr_service.settings: + title: Settings + route_name: tpr_service.settings + base_route: tpr_service.settings + +entity.tpr_service.view: + title: View + route_name: entity.tpr_service.canonical + base_route: entity.tpr_service.canonical + +entity.tpr_service.edit_form: + title: Edit + route_name: entity.tpr_service.edit_form + base_route: entity.tpr_service.canonical + +entity.tpr_service.delete_form: + title: Delete + route_name: entity.tpr_service.delete_form + base_route: entity.tpr_service.canonical + weight: 10 + +tpr_service.content_list: + title: TPR - Service + route_name: entity.tpr_service.collection + base_route: system.admin_content + weight: 10 diff --git a/migrations/tpr_service.yml b/migrations/tpr_service.yml new file mode 100644 index 00000000..bd53a096 --- /dev/null +++ b/migrations/tpr_service.yml @@ -0,0 +1,24 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - helfi_tpr +id: tpr_service +migration_tags: + - tpr +label: 'TPR service' +source: + plugin: tpr_service_register + track_changes: true + url: 'http://www.hel.fi/palvelukarttaws/rest/vpalvelurekisteri/description/' + ids: + id: + type: string +process: + id: id +destination: + plugin: tpr_service +migration_dependencies: + required: + - tpr_unit diff --git a/migrations/tpr_unit.yml b/migrations/tpr_unit.yml index 1cb4bc45..1e4a302a 100644 --- a/migrations/tpr_unit.yml +++ b/migrations/tpr_unit.yml @@ -5,14 +5,11 @@ dependencies: module: - helfi_tpr id: tpr_unit -field_plugin_method: null -cck_plugin_method: null migration_tags: - tpr -migration_group: tpr label: 'TPR unit' source: - plugin: tpr + plugin: tpr_service_map track_changes: true url: 'https://www.hel.fi/palvelukarttaws/rest/v4/unit/' ids: diff --git a/src/Entity/Listing/UnitListBuilder.php b/src/Entity/Listing/ListBuilder.php similarity index 96% rename from src/Entity/Listing/UnitListBuilder.php rename to src/Entity/Listing/ListBuilder.php index 58f7786a..9b272fe6 100644 --- a/src/Entity/Listing/UnitListBuilder.php +++ b/src/Entity/Listing/ListBuilder.php @@ -13,9 +13,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** - * Provides a list controller for the tpr_unit entity type. + * Provides a list controller for the tpr entity types. */ -class UnitListBuilder extends EntityListBuilder { +class ListBuilder extends EntityListBuilder { /** * The date formatter service. diff --git a/src/Entity/Service.php b/src/Entity/Service.php new file mode 100644 index 00000000..eaec30cb --- /dev/null +++ b/src/Entity/Service.php @@ -0,0 +1,83 @@ +setTranslatable(TRUE) + ->setLabel(new TranslatableMarkup('Description')) + ->setDisplayConfigurable('form', TRUE) + ->setDisplayConfigurable('view', TRUE); + + return $fields; + } + +} diff --git a/src/Entity/TprEntityBase.php b/src/Entity/TprEntityBase.php index 197779b9..a7d22d3a 100644 --- a/src/Entity/TprEntityBase.php +++ b/src/Entity/TprEntityBase.php @@ -74,6 +74,7 @@ protected static function createLinkField(string $label, int $cardinality = 1) : public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); $fields += static::revisionLogBaseFieldDefinitions($entity_type); + $fields['name'] = static::createStringField('Name'); return $fields; } diff --git a/src/Entity/Unit.php b/src/Entity/Unit.php index aaa02466..1dd1d595 100644 --- a/src/Entity/Unit.php +++ b/src/Entity/Unit.php @@ -19,7 +19,7 @@ * label_collection = @Translation("TPR - Unit"), * handlers = { * "view_builder" = "Drupal\Core\Entity\EntityViewBuilder", - * "list_builder" = "Drupal\helfi_tpr\Entity\Listing\UnitListBuilder", + * "list_builder" = "Drupal\helfi_tpr\Entity\Listing\ListBuilder", * "views_data" = "Drupal\views\EntityViewsData", * "access" = "Drupal\helfi_api_base\Entity\Access\RemoteEntityAccess", * "form" = { @@ -54,7 +54,7 @@ * "canonical" = "/tpr-unit/{tpr_unit}", * "edit-form" = "/admin/content/tpr-unit/{tpr_unit}/edit", * "delete-form" = "/admin/content/tpr-unit/{tpr_unit}/delete", - * "collection" = "/admin/content/tpr-unit" + * "collection" = "/admin/content/tpr-unit", * }, * field_ui_base_route = "tpr_unit.settings" * ) @@ -68,23 +68,76 @@ public static function getMigration(): ?string { return 'tpr_unit'; } + /** + * Adds the given service. + * + * @param \Drupal\helfi_tpr\Entity\Service $service + * The service. + * + * @return $this + * The self. + */ + public function addService(Service $service) : self { + if (!$this->hasService($service)) { + $this->get('services')->appendItem($service); + } + return $this; + } + + /** + * Removes the given service. + * + * @param \Drupal\helfi_tpr\Entity\Service $service + * The service. + * + * @return $this + * The self. + */ + public function removeService(Service $service) : self { + $index = $this->getServiceIndex($service); + if ($index !== FALSE) { + $this->get('services')->offsetUnset($index); + } + return $this; + } + + /** + * Checks whether the service exists or not. + * + * @param \Drupal\helfi_tpr\Entity\Service $service + * The service. + * + * @return bool + * Whether we have given service or not. + */ + public function hasService(Service $service) : bool { + return $this->getServiceIndex($service) !== FALSE; + } + + /** + * Gets the index of the given service. + * + * @param \Drupal\helfi_tpr\Entity\Service $service + * The service. + * + * @return int|bool + * The index of the given service, or FALSE if not found. + */ + protected function getServiceIndex(Service $service) { + $values = $this->get('services')->getValue(); + $order_item_ids = array_map(function ($value) { + return $value['target_id']; + }, $values); + + return array_search($service->id(), $order_item_ids); + } + /** * {@inheritdoc} */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); - $fields['name'] = static::createStringField('Name'); - $fields['service_map_embed'] = static::createStringField('Service map embed') - ->setDisplayOptions('view', [ - 'label' => 'hidden', - 'type' => 'service_map_embed', - 'weight' => 0, - ]); - $fields['latitude'] = static::createStringField('Latitude') - ->setTranslatable(FALSE); - $fields['longitude'] = static::createStringField('Longitude') - ->setTranslatable(FALSE); $fields['phone'] = static::createStringField('Phone', BaseFieldDefinition::CARDINALITY_UNLIMITED) ->setTranslatable(FALSE); $fields['call_charge_info'] = static::createStringField('Call charge info'); @@ -94,19 +147,14 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ->setTranslatable(FALSE); $fields['accessibility_email'] = static::createStringField('Accessibility email') ->setTranslatable(FALSE); - $fields['address_postal'] = static::createStringField('Address postal'); $fields['www'] = static::createLinkField('Website link'); - $fields['streetview_entrance_url'] = static::createLinkField('Streetview entrance') - ->setTranslatable(FALSE); $fields['accessibility_www'] = static::createLinkField('Accessibility website link') ->setTranslatable(FALSE); - $fields['description'] = BaseFieldDefinition::create('text_with_summary') ->setTranslatable(TRUE) ->setLabel(new TranslatableMarkup('Description')) ->setDisplayConfigurable('form', TRUE) ->setDisplayConfigurable('view', TRUE); - $fields['address'] = BaseFieldDefinition::create('address') ->setLabel(new TranslatableMarkup('Address')) ->setTranslatable(TRUE) @@ -119,6 +167,30 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { ]) ->setDisplayConfigurable('view', TRUE) ->setDisplayConfigurable('form', TRUE); + $fields['address_postal'] = static::createStringField('Address postal'); + $fields['service_map_embed'] = static::createStringField('Service map embed') + ->setDisplayOptions('view', [ + 'label' => 'hidden', + 'type' => 'service_map_embed', + 'weight' => 0, + ]); + $fields['latitude'] = static::createStringField('Latitude') + ->setTranslatable(FALSE); + $fields['longitude'] = static::createStringField('Longitude') + ->setTranslatable(FALSE); + $fields['streetview_entrance_url'] = static::createLinkField('Streetview entrance') + ->setTranslatable(FALSE); + $fields['services'] = BaseFieldDefinition::create('entity_reference') + ->setLabel(new TranslatableMarkup('Services')) + ->setSettings([ + 'target_type' => 'tpr_service', + 'handler_settings' => [ + 'target_bundles' => ['tpr_service'], + ], + ]) + ->setCardinality(BaseFieldDefinition::CARDINALITY_UNLIMITED) + ->setDisplayConfigurable('view', TRUE) + ->setDisplayConfigurable('form', TRUE); return $fields; } diff --git a/src/Plugin/migrate/destination/Service.php b/src/Plugin/migrate/destination/Service.php new file mode 100644 index 00000000..6645583c --- /dev/null +++ b/src/Plugin/migrate/destination/Service.php @@ -0,0 +1,55 @@ + 'name', + 'description_long' => 'description/value', + 'description_short' => 'description/summary', + ]; + } + + /** + * {@inheritdoc} + */ + public function getEntity(Row $row, array $old_destination_id_values) { + $entity = parent::getEntity($row, $old_destination_id_values); + + if ($unitIds = $row->getSourceProperty('unit_ids')) { + $units = Unit::loadMultiple($unitIds); + + array_map(function (Unit $unit) use ($entity) { + $unit->addService($entity) + ->save(); + }, $units); + } + + return $entity; + } + +} diff --git a/src/Plugin/migrate/destination/Tpr.php b/src/Plugin/migrate/destination/TranslatableEntityBase.php similarity index 98% rename from src/Plugin/migrate/destination/Tpr.php rename to src/Plugin/migrate/destination/TranslatableEntityBase.php index e1537903..586c6211 100644 --- a/src/Plugin/migrate/destination/Tpr.php +++ b/src/Plugin/migrate/destination/TranslatableEntityBase.php @@ -16,7 +16,7 @@ /** * Provides a destination plugin for Tpr entities. */ -abstract class Tpr extends EntityContentBase { +abstract class TranslatableEntityBase extends EntityContentBase { /** * The language manager service. @@ -41,6 +41,17 @@ public static function create( return $instance; } + /** + * {@inheritdoc} + */ + public function updateEntity(EntityInterface $entity, Row $row) { + $entity = parent::updateEntity($entity, $row); + // Always delete on rollback, even if it's "default" translation. + $this->setRollbackAction($row->getIdMap(), MigrateIdMapInterface::ROLLBACK_DELETE); + + return $entity; + } + /** * {@inheritdoc} */ @@ -73,17 +84,6 @@ protected function getEntity(Row $row, array $old_destination_id_values) { return $entity; } - /** - * {@inheritdoc} - */ - public function updateEntity(EntityInterface $entity, Row $row) { - $entity = parent::updateEntity($entity, $row); - // Always delete on rollback, even if it's "default" translation. - $this->setRollbackAction($row->getIdMap(), MigrateIdMapInterface::ROLLBACK_DELETE); - - return $entity; - } - /** * Gets the translatable source fields. * diff --git a/src/Plugin/migrate/destination/Unit.php b/src/Plugin/migrate/destination/Unit.php index 34a64ce3..088802f1 100644 --- a/src/Plugin/migrate/destination/Unit.php +++ b/src/Plugin/migrate/destination/Unit.php @@ -11,7 +11,7 @@ * id = "tpr_unit", * ) */ -final class Unit extends Tpr { +final class Unit extends TranslatableEntityBase { /** * {@inheritdoc} diff --git a/src/Plugin/migrate/source/Tpr.php b/src/Plugin/migrate/source/ServiceMap.php similarity index 92% rename from src/Plugin/migrate/source/Tpr.php rename to src/Plugin/migrate/source/ServiceMap.php index d0acb62f..ff0a6d91 100644 --- a/src/Plugin/migrate/source/Tpr.php +++ b/src/Plugin/migrate/source/ServiceMap.php @@ -12,10 +12,10 @@ * Source plugin for retrieving data from Tpr. * * @MigrateSource( - * id = "tpr" + * id = "tpr_service_map" * ) */ -class Tpr extends HttpSourcePluginBase implements ContainerFactoryPluginInterface { +class ServiceMap extends HttpSourcePluginBase implements ContainerFactoryPluginInterface { /** * Keep track of ignored rows to stop migrate after N ignored rows. @@ -35,7 +35,7 @@ class Tpr extends HttpSourcePluginBase implements ContainerFactoryPluginInterfac * {@inheritdoc} */ public function __toString() { - return 'Tpr'; + return 'TprServiceMap'; } /** @@ -97,7 +97,6 @@ protected function initializeListIterator() : \Iterator { if ($this->isPartialMigrate() && ($this->ignoredRows >= static::NUM_IGNORED_ROWS_BEFORE_STOPPING)) { break; } - $object += $this->getContent($this->buildCanonicalUrl((string) $object['id'])); $processed++; // Allow number of items to be limited by using an env variable. diff --git a/src/Plugin/migrate/source/ServiceRegister.php b/src/Plugin/migrate/source/ServiceRegister.php new file mode 100644 index 00000000..28dbb3df --- /dev/null +++ b/src/Plugin/migrate/source/ServiceRegister.php @@ -0,0 +1,91 @@ +count) { + $this->count = count($this->getContent($this->configuration['url'])); + } + return $this->count; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + return ['id' => ['type' => 'string']]; + } + + /** + * {@inheritdoc} + */ + public function fields() { + return []; + } + + /** + * {@inheritdoc} + */ + protected function initializeListIterator() : \Iterator { + $content = $this->getContent($this->configuration['url']); + + $fields = [ + 'title', + 'description_short', + 'description_long', + ]; + + foreach ($content as $item) { + $service = []; + + foreach (['fi', 'en', 'sv'] as $language) { + $url = $this->buildCanonicalUrl(sprintf('%s?language=%s', $item['id'], $language)); + $data = $this->getContent($url); + + list('id' => $id) = $data; + + if (!isset($service[$id])) { + $service[$id] = []; + } + + foreach ($fields as $field) { + $data[sprintf('%s_%s', $field, $language)] = $data[$field]; + } + $service[$id] += $data; + } + yield reset($service); + } + } + +} diff --git a/tests/fixtures/services.json b/tests/fixtures/services.json new file mode 100644 index 00000000..823f5bbd --- /dev/null +++ b/tests/fixtures/services.json @@ -0,0 +1,23 @@ +[ + { + "id": 1, + "main_description": true, + "service_id": 10004, + "title": "Service 1", + "description_short": "Description short 1" + }, + { + "id": 2, + "main_description": false, + "service_id": 10004, + "title": "Service 2", + "description_short": "Description short 2" + }, + { + "id": 3, + "main_description": false, + "service_id": 10004, + "title": "Service 3", + "description_short": "Description short 3" + } +] diff --git a/tests/src/Kernel/MigrationTest.php b/tests/src/Kernel/MigrationTest.php new file mode 100644 index 00000000..168a3b16 --- /dev/null +++ b/tests/src/Kernel/MigrationTest.php @@ -0,0 +1,115 @@ +installEntitySchema('tpr_unit'); + $this->installEntitySchema('tpr_service'); + $this->installConfig(['helfi_tpr']); + } + + /** + * Create the unit migration. + * + * @return array + * List of entities. + */ + protected function createUnitMigration() : array { + $units = $this->getFixture('helfi_tpr', 'unit.json'); + $responses = [ + new Response(200, [], $units), + ]; + + $this->container->set('http_client', $this->createMockHttpClient($responses)); + $this->executeMigration('tpr_unit'); + return Unit::loadMultiple(); + } + + /** + * Create the service migration. + * + * @return array + * List of entities. + */ + protected function createServiceMigration() : array { + $services = $this->getFixture('helfi_tpr', 'services.json'); + $responses = [ + new Response(200, [], NULL), + new Response(200, [], $services), + ]; + + foreach (json_decode($services, TRUE) as $id => $service) { + foreach (['fi', 'en', 'sv'] as $language) { + $service += [ + 'description_short' => $language . ' Description short ' . $id, + 'description_long' => $language . ' Description long ' . $id, + ]; + $responses[] = new Response(200, [], json_encode($service)); + } + } + + $this->container->set('http_client', $this->createMockHttpClient($responses)); + $this->executeMigration('tpr_service'); + return Service::loadMultiple(); + } + + /** + * Tests unit migration. + */ + public function testUnitMigration() : void { + $entities = $this->createUnitMigration(); + $this->assertCount(6, $entities); + + foreach (['en', 'sv'] as $langcode) { + foreach ($entities as $entity) { + $this->assertEquals($entity->getTranslation($langcode)->language()->getId(), $langcode); + } + } + } + + /** + * Tests service migration. + */ + public function testServiceMigration() : void { + // Services depend on unit migration. + $this->createUnitMigration(); + $entities = $this->createServiceMigration(); + $this->assertCount(3, $entities); + + foreach (['en', 'sv', 'fi'] as $langcode) { + foreach ($entities as $entity) { + $this->assertEquals($entity->getTranslation($langcode)->language()->getId(), $langcode); + } + } + } + +} diff --git a/tests/src/Kernel/UnitMigrationTest.php b/tests/src/Kernel/UnitMigrationTest.php deleted file mode 100644 index a1f8c512..00000000 --- a/tests/src/Kernel/UnitMigrationTest.php +++ /dev/null @@ -1,63 +0,0 @@ -installEntitySchema('tpr_unit'); - $this->installConfig(['helfi_tpr']); - } - - /** - * Test default migrations. - */ - public function testMigration() : void { - $units = $this->getFixture('helfi_tpr', 'unit.json'); - $responses = [ - new Response(200, [], $units), - ]; - - foreach (json_decode($units, TRUE) as $id => $unit) { - $responses[] = new Response(200, [], json_encode($unit)); - } - - $this->container->set('http_client', $this->createMockHttpClient($responses)); - $this->executeMigration('tpr_unit'); - $entities = Unit::loadMultiple(); - $this->assertCount(6, $entities); - - foreach (['en', 'sv'] as $langcode) { - foreach ($entities as $entity) { - $this->assertEquals($entity->getTranslation($langcode)->language()->getId(), $langcode); - } - } - } - -}