diff --git a/.islandora.services.yml.swp b/.islandora.services.yml.swp new file mode 100644 index 00000000..7095e73a Binary files /dev/null and b/.islandora.services.yml.swp differ diff --git a/.travis.yml b/.travis.yml index a41e33f9..3e29ad8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,8 +22,8 @@ install: - $SCRIPT_DIR/travis_setup_drupal.sh - git -C "$TRAVIS_BUILD_DIR" checkout -b travis-testing - cd $DRUPAL_DIR; - - php -dmemory_limit=-1 $COMPOSER_PATH config repositories.local path "$TRAVIS_BUILD_DIR" - - php -dmemory_limit=-1 $COMPOSER_PATH require "islandora/islandora:dev-travis-testing as dev-8.x-1.x" --prefer-source --update-with-dependencies + - COMPOSER_MEMORY_LIMIT=-1 php -d memory_limit=-1 $COMPOSER_PATH config repositories.local path "$TRAVIS_BUILD_DIR" + - COMPOSER_MEMORY_LIMIT=-1 php -d memory_limit=-1 $COMPOSER_PATH require "islandora/islandora:dev-travis-testing as dev-8.x-1.x" --prefer-source --update-with-dependencies - cd web; drush --uri=127.0.0.1:8282 en -y islandora script: diff --git a/README.md b/README.md index 080b9e0d..bb38f386 100644 --- a/README.md +++ b/README.md @@ -5,51 +5,201 @@ ## Introduction -CLAW's core Islandora module for Drupal 8.x +Islandora is a module that turns a Drupal 8 site into a control panel for your digital repository. Through a user +interface, it allows repository administrators to +- Persist digital content in a Fedora repository +- Model digital content using core Drupal entities (nodes, media, files, and taxonomy terms). Currently, there is +support for + - collections + - images + - binary files (including PDfs) + - audio + - video +- Design forms for editing metadata +- Control the display and theming of digital content +- Perform full text searching of content and metadata +- Bulk ingest content (using Drupal's migrate framework) +- Administer fine grained access control +- Index RDF metadata in a triplestore +- Generate derivative files, such as web quality represenations. + - Currently, only image derivatives are supported (requires islandora_image), but more to come. +- Apply bulk operations to lists of content (re-index content, regenerate derivatives, etc...) +- And much, much more... + +Content in an Islandora repository is treated as ordinary Drupal content, so the entire Drupal ecosystem of contributed +modules is at your disposal. In fact, Islandora uses many contributed modules itself, including the extremely powerful +and flexible `context` module. The `context` module allows users to do many things through a UI that normally would +require programming custom modules or themes. Want to show certain users a simplified form for data entry? Want to +give each collection a different theme? Want to give anonymous users a restricted view? All of this can be done using +the `context` module. It is similar to the `rules` module, and it allows repository administrators to filter repository events (view, create, +update, delete, etc...) by the criteria of their choice and respond by executing configurable actions. + +## Requirements / Installation + +Setting up a full digital repsository is a daunting task involving many moving parts on one or more servers. To make things +easier to get started, you can fully bootstrap a complete repository solution using our Ansible installer, claw-playbook. +It can install both to a local Vagrant environment for development purposes, or it can install to one or more remote servers +by providing your own playbook. By default you'll get one server with everything on it (i.e. the kitchen sink install). But +we have broken down each component into its own Ansible role, so more advanced users can create customized builds containing +only what their needs require. See the README for more details. + +## Configuration + +If you want to get up and running as quickly as possible, import the `islanora_demo_feature` feature to install example configuration +and bootstrap your site. If you're starting from scratch, then _at a minimum_, you must: +1. Set the url to your message broker at `admin/config/islandora` +1. Enable the `islandora_core_feature` module, then visit `admin/config/development/features` and import its config. It contains +everything required for basic content modeling. You can also use drush to import the feature +`drush -y fim --bundle=islandora islandora_core_feature`. +1. Run the migration to load the taxonomy terms required by Islandora. This can be done by visiting `admin/structure/migrate`, or executed via drush +`drush -l http://localhost:8000 mim --group=islandora`. + +## Content Modeling + +Islandora uses core Drupal 8 functionality for modeling content. Most core content entities are utilized: + +1. Nodes + 1. Nodes hold descriptive and structural metadata about objects in your repository. Membership between nodes (e.g. members +of a collection, or pages of a book) is denoted with `field_member_of`, which is provided by `islandora_core_feature`. +Additional behavior can be controlled by tagging nodes with taxonomy terms using `field_tags`. +1. Media + 1. Media hold technical metadata for the files they represent. There are four core media types, used for audio, video, +images, and generic files. Media are associated with a node using `field_media_of`, which is provided by `islandora_core_feature`. +The role of the media is indicated by tagging it with a taxonomy term using `field_tags`. For example, +tagging a media as 'Preservation Master' indicates that it is the master archival copy of a file, while 'Service File' would +indicate that it is a lower quality derivative intended to be shown to the average user. +1. Files + 1. Files hold the binary conents that are described by Media. They often created along with a media to hold its technical metadata, +but can be created and then later associted with a Media in a separate process. +1. Taxonomy Terms + 1. Taxonomy terms are used to tag nodes and media so they can be classified, organized, and acted upon. They must contain a +`field_external_uri` field that holds an external URI for the term from a controlled vocabulary / ontology. The `islandora_core_feature` +provides a migration that can be executed to load all of the required terms for basic use into your repository. + +The `islandora_demo_feature` provides a complete example of content modeling in Islandora for audio, video, files, and images, including +tiff and JP2 support (e.g. large images). This includes some more advanced techniques, like switching display modes based on +taxonomy terms so 'images' and 'large images' can share a metadata profile but be displayed differently. It also includes +example actions for generating image derivatives (using the `islandora_image` module). You may not, however, want all of this functionality. +In fact, this feature is not meant to be the end-all-be-all of content modeling, but serves as an example of how it's done using +Islandora. You can take as much or as little of it as you'd like. If you're doing you're own thing, the gist is: + +- When making your own content type, it will require `field_member_of`, `field_tags`, and an rdf mapping. +- When making your own media type, it will require `field_media_of`, `field_tags`, `field_mimetype`, an rdf mapping, and a field to hold the file. +You can re-use `field_media_file`, `field_media_image`, `field_media_audio`, and `field_media_video` to do so. Media should +always be tagged (`field_tags`) with a term from the pcdmuse ontology (preservation master, service file, thumbnail image) to denote its usage. +- When making your own taxonomy vocabulary, its terms will require `field_external_uri` and an rdf mapping. +- All rdf mappings need to map the `changed` time to `schema:dateModified`. + +## Actions + +Islandora provides several useful actions for repository administrators that can be configured and executed through the user +interface. Any view can expose bulk operations by adding a `Bulk update` field to its display. + +Islandora also provides a thin wrapper around Actions so that they can be used in conjunction with the `context` module. +Repository events for indexing, deletion, and derivative generation are all handled by selecting one or more preconfigured +actions using the `context` user interface. + +### Delete Media + +You can use the `Delete media` action to bulk delete media, but not delete source files. + +### Delete Media and File(s) + +You can use the `Delete media and file(s)` action to bulk delete media and their source files. + +### Emit Node/Media/File/Term Event + +You can use `Emit a * event to a queue/topic` actions to produce messages so background processes can consume them and +perform work. The `islandora_core_feature` contains several preconfigured actions to perform indexing and removal +operations for Fedora and a triplestore. -## Installation +## REST API -For a fully automated install, see [claw-playbook](https://github.com/Islandora-Devops/claw-playbook). If you're installing -manually, then _at a minimum_, the REST configuration for Nodes, Media, and Files need to be enabled with `jwt_auth` for -authentication on all methods. The `json` and `jsonld` formats need to be enabled for for GET requests. Only the `json` fomat -is required for POST, PATCH, and DELETE requests. +Islandora has a light, mostly RESTful HTTP API that relies heavily on Drupal's core Rest module. The majority of what Islandora +provides is Link headers in GET and HEAD responses. These headers can be used to locate related resources and navigate your +repository. In addition to these link headers, there are additional endpoints exposed for uploading files, as well as a couple +of useful REST exports. -This can be done using the Rest UI module by setting granularity to 'Method'. If you want to use GET requests through a browser, -you'll want to enable `cookie` authentication. And if you want to use a username/password with cURL, you'll want to enable `basic -authentication`. +### Exposed Headers -![screenshot from 2018-03-09 10-09-57](https://user-images.githubusercontent.com/20773151/37212586-caf31dc8-2385-11e8-8122-1608dacbfb5f.png) +#### Referenced taxonomy terms (Nodes and Media) -If you want to import the configuration through Drupal's configuration synchronization tools, you can use these yaml files -from claw-playbook for [Nodes](https://github.com/Islandora-Devops/claw-playbook/blob/master/roles/internal/webserver-app/files/rest.resource.entity.node.yml), -[Media](https://github.com/Islandora-Devops/claw-playbook/blob/master/roles/internal/webserver-app/files/rest.resource.entity.media.yml), -and [Files](https://github.com/Islandora-Devops/claw-playbook/blob/master/roles/internal/webserver-app/files/rest.resource.entity.file.yml). +The taxonomy terms used to tag content are exposed as link headers with `rel="tag"` and a title equal to the taxonomy term's display +label. If the term has an external uri in a controlled vocabulary, then that uri is provided. Otherwise, the local Drupal uri is +provided. For example, if a piece of content is tagged with `taxonomy/term/1`, which has a display label of "Example Term", then the +link header returned in a GET or HEAD response would look like `Link: ; rel="tag"; title="Example Term"` -## REST API +If instead the term were to have the `field_external_uri` field with a value of `http://purl.org/dc/dcmitype/Collection` then the link +header would look like `Link: ; rel="tag"; title="Example Term"`. -Islandora has a light, mostly RESTful HTTP API that relies heavily on Drupal's core Rest module. +#### Referenced entities (Nodes and Media) -### /media/{media}/source +Entity reference fields are exposed as link headers with `rel="related"` and a title equal to the entity reference field's display label. +For example, if `http://example.org/node/1` has an entity reference field name "Associated Content" that references +`http://example.org/node/2`, then the link header returned in a GET or HEAD response would look like +`Link: ; rel="related"; title="Associated Content"`. -You can PUT content to the `/media/{media}/source` endpoint to update the File associated with a Media. The `Content-Type` -header is expected, as well as a `Content-Disposition` header of the form `attachment; filename="your_filename"` to indicate -the name to give the file. Requests with empty bodies or no `Content-Length` header will be rejected. +#### Associated media (Nodes only) + +Media entities that belong to nodes and are tagged with terms from the PCDM Use ontology are exposed as link headers with `rel="related"` +and a title equal to the display label of the taxonomy term. For example, if a Media is tagged as `Preservation Master` indicating +that it is the archival copy, the link header returned in a GET or HEAD response for a node would look like +`Link: ; rel="related"; title="Preservation Master"`. + +#### Source files (Media only) + +Files that are the source for Media entities are exposed as Link headers in the GET and HEAD responses with `rel="describes"`. The endpoint +to edit the contents of the source file is also exposed using `rel="edit-media"`. For example, if `http://example.org/media/1` has the source +file `http://example.org/file.txt`, then a GET or HEAD response would contain both +- `Link: ; rel="describes"` +- `Link: ; rel="edit-media"` + +### Exposed Endpoints + +#### /media/{media}/source + +You can PUT content to the `/media/{media}/source` endpoint to update the source file for a media. The `Content-Type` +header is required in addition to the PUT body. Requests with empty bodies or no `Content-Type` header will be rejected. Example usage: ``` -curl -u admin:islandora -v -X PUT -H 'Content-Type: image/png' -H 'Content-Disposition: attachment; filename="my_image.png"' --data-binary @my_image.png localhost:8000/media/1/source +curl -u admin:islandora -v -X PUT -H 'Content-Type: image/png' --data-binary @my_image.png localhost:8000/media/1/source ``` -### /node/{node}/media/{field}/add/{bundle} +#### /node/{node}/media/{media_type}/{taxonomy_term} -You can POST content to the `/node/{node}/media/{field}/add/{bundle}` endpoint to create a new Media of the specified bundle -using the POST body. It will be associated with the specified Node using the field from the route. The `Content-Type` +You can PUT content to the `/node/{node}/media/{media_type}/{taxonomy_term}` endpoint to create or update Media for Nodes. Media created +in this way will automatically be assigned to the node in the route and tagged with the term in the route. The `Content-Type` header is expected, as well as a `Content-Disposition` header of the form `attachment; filename="your_filename"` to indicate -the name to give the file. Requests with empty bodies or no `Content-Length` header will be rejected. +the name to give the file if it's new. Requests with empty bodies or that are without `Content-Type` and `Content-Disposition` +headers will be rejected. + +For example, to create a new Image media for node 1, and tag it with taxonomy term 1: +``` +curl -v -u admin:islandora -H "Content-Type: image/jpeg" -H "Content-Disposition: attachment; filename=\"test.jpeg\"" --data-binary @test.jpeg http://localhost:8000/node/1/media/image/1 +``` + +Or, to update an existing image media that is tagged with taxonomy term 2: +``` +curl -v -u admin:islandora -H "Content-Type: image/jpeg" -H "Content-Disposition: attachment; filename=\"test2.jpeg\"" --data-binary @test2.jpeg http://localhost:8000/node/1/media/image/2 +``` + +#### /node/{node}/members + +You can issue GET requests to this endpoint to get a list of members of a node. It is actually a REST export, and requires the `_format` query param. It can (read should) also be paged +like other REST export. For example, to get a paged list of members for a node, ten at a time: + +``` +curl -v -u admin:islandora http://localhost:8000/node/1/members?_format=json&items_per_page=10&offset=0 +``` + +#### /node/{node}/media + +You can issue GET requests to this endpoint to get a list of media of a node. It is actually a REST export, and requires the `_format` query param. Like the members endpoint, it can +be paged, but is less likely to be neccessary as most nodes don't have that many media. For example, to get the full list of media for a node: -Example usage: ``` -curl -v -u admin:islandora -H "Content-Type: image/jpeg" -H "Content-Disposition: attachment; filename=\"test.jpeg\"" --data-binary @test.jpeg http://localhost:8000/node/1/media/my_media_field/add/my_media_bundle +curl -v -u admin:islandora http://localhost:8000/node/1/media?_format=json ``` ## Maintainers @@ -58,6 +208,7 @@ Current maintainers: * [Diego Pino](https://github.com/diegopino) * [Jared Whiklo](https://github.com/whikloj) +* [Danny Lamb](https://github.com/dannylamb) ## Development diff --git a/composer.json b/composer.json index e3f76615..324d21c3 100644 --- a/composer.json +++ b/composer.json @@ -15,14 +15,19 @@ } ], "require": { - "drupal/inline_entity_form": "^1.0@beta", "drupal/context": "^4.0", - "drupal/search_api": "^1.0@beta", + "drupal/search_api": "1.x-dev", "islandora/jsonld": "dev-8.x-1.x", "stomp-php/stomp-php": "4.*", "drupal/jwt": "1.0.0-alpha6", - "drupal/media_entity_image": "^1.2", - "drupal/filehash": "^1.1" + "drupal/filehash": "^1.1", + "drupal/prepopulate" : "^2.0@alpha", + "drupal/eva" : "^1.3", + "drupal/features" : "^3.7", + "drupal/migrate_plus" : "4.0-beta3", + "drupal/migrate_tools" : "4.0-beta3", + "drupal/migrate_source_csv" : "^2.1", + "drupal/permissions_by_term" : "^1.51" }, "require-dev": { "phpunit/phpunit": "^4.8", diff --git a/config/install/core.entity_form_display.media.tn.default.yml b/config/install/core.entity_form_display.media.tn.default.yml deleted file mode 100644 index 4d4d5f98..00000000 --- a/config/install/core.entity_form_display.media.tn.default.yml +++ /dev/null @@ -1,41 +0,0 @@ -uuid: 9a8e59ea-6372-4dd8-8643-4afcaa583185 -langcode: en -status: true -dependencies: - config: - - field.field.media.tn.field_height - - field.field.media.tn.field_image - - field.field.media.tn.field_mimetype - - field.field.media.tn.field_width - - image.style.thumbnail - - media_entity.bundle.tn - enforced: - module: - - islandora - module: - - image -id: media.tn.default -targetEntityType: media -bundle: tn -mode: default -content: - field_image: - weight: 1 - settings: - progress_indicator: throbber - preview_image_style: thumbnail - third_party_settings: { } - type: image_image - name: - type: string_textfield - weight: 0 - settings: - size: 60 - placeholder: '' - third_party_settings: { } -hidden: - created: true - field_height: true - field_mimetype: true - field_width: true - uid: true diff --git a/config/install/core.entity_form_display.media.tn.inline.yml b/config/install/core.entity_form_display.media.tn.inline.yml deleted file mode 100644 index e00a3040..00000000 --- a/config/install/core.entity_form_display.media.tn.inline.yml +++ /dev/null @@ -1,36 +0,0 @@ -uuid: 7102e88a-f6ea-40db-9bbc-9ac31b1f99a3 -langcode: en -status: true -dependencies: - config: - - core.entity_form_mode.media.inline - - field.field.media.tn.field_height - - field.field.media.tn.field_image - - field.field.media.tn.field_mimetype - - field.field.media.tn.field_width - - image.style.thumbnail - - media_entity.bundle.tn - enforced: - module: - - islandora - module: - - image -id: media.tn.inline -targetEntityType: media -bundle: tn -mode: inline -content: - field_image: - weight: 0 - settings: - progress_indicator: throbber - preview_image_style: thumbnail - third_party_settings: { } - type: image_image -hidden: - created: true - field_height: true - field_mimetype: true - field_width: true - name: true - uid: true diff --git a/config/install/core.entity_form_mode.media.inline.yml b/config/install/core.entity_form_mode.media.inline.yml deleted file mode 100644 index 5196d198..00000000 --- a/config/install/core.entity_form_mode.media.inline.yml +++ /dev/null @@ -1,13 +0,0 @@ -uuid: 2cea66e8-8a46-4292-906c-24d85f6b8c04 -langcode: en -status: true -dependencies: - enforced: - module: - - islandora - module: - - media_entity -id: media.inline -label: Inline -targetEntityType: media -cache: true diff --git a/config/install/core.entity_view_display.media.tn.content.yml b/config/install/core.entity_view_display.media.tn.content.yml deleted file mode 100644 index 56d2844d..00000000 --- a/config/install/core.entity_view_display.media.tn.content.yml +++ /dev/null @@ -1,37 +0,0 @@ -uuid: cf7d61f8-9098-49c7-a46f-0f6d26692c0e -langcode: en -status: true -dependencies: - config: - - core.entity_view_mode.media.content - - field.field.media.tn.field_height - - field.field.media.tn.field_image - - field.field.media.tn.field_mimetype - - field.field.media.tn.field_width - - media_entity.bundle.tn - enforced: - module: - - islandora - module: - - image -id: media.tn.content -targetEntityType: media -bundle: tn -mode: content -content: - field_image: - weight: 0 - label: above - settings: - image_style: '' - image_link: '' - third_party_settings: { } - type: image -hidden: - created: true - field_height: true - field_mimetype: true - field_width: true - name: true - thumbnail: true - uid: true diff --git a/config/install/core.entity_view_display.media.tn.default.yml b/config/install/core.entity_view_display.media.tn.default.yml deleted file mode 100644 index b0fc89fa..00000000 --- a/config/install/core.entity_view_display.media.tn.default.yml +++ /dev/null @@ -1,76 +0,0 @@ -uuid: dae6d069-ea8a-48eb-9d7f-44f10b38dff8 -langcode: en -status: true -dependencies: - config: - - field.field.media.tn.field_height - - field.field.media.tn.field_image - - field.field.media.tn.field_mimetype - - field.field.media.tn.field_width - - media_entity.bundle.tn - enforced: - module: - - islandora - module: - - image - - user -id: media.tn.default -targetEntityType: media -bundle: tn -mode: default -content: - created: - label: hidden - type: timestamp - weight: 2 - settings: - date_format: medium - custom_date_format: '' - timezone: '' - third_party_settings: { } - field_height: - weight: 6 - label: above - settings: - thousand_separator: '' - prefix_suffix: true - third_party_settings: { } - type: number_integer - field_image: - weight: 3 - label: above - settings: - image_style: '' - image_link: '' - third_party_settings: { } - type: image - field_mimetype: - weight: 4 - label: above - settings: - link_to_entity: false - third_party_settings: { } - type: string - field_width: - weight: 5 - label: above - settings: - thousand_separator: '' - prefix_suffix: true - third_party_settings: { } - type: number_integer - name: - label: hidden - type: string - weight: 0 - settings: - link_to_entity: false - third_party_settings: { } - uid: - label: hidden - type: author - weight: 1 - settings: { } - third_party_settings: { } -hidden: - thumbnail: true diff --git a/config/install/core.entity_view_mode.media.content.yml b/config/install/core.entity_view_mode.media.content.yml deleted file mode 100644 index cbbcdf7f..00000000 --- a/config/install/core.entity_view_mode.media.content.yml +++ /dev/null @@ -1,14 +0,0 @@ -uuid: 72d426d5-5788-4a12-828b-31d7176e9e30 -langcode: en -status: true -dependencies: - module: - - media_entity - - islandora - enforced: - module: - - islandora -id: media.content -label: Content -targetEntityType: media -cache: true diff --git a/config/install/field.field.media.tn.field_mimetype.yml b/config/install/field.field.media.tn.field_mimetype.yml deleted file mode 100644 index 0fddade8..00000000 --- a/config/install/field.field.media.tn.field_mimetype.yml +++ /dev/null @@ -1,22 +0,0 @@ -uuid: dd6d11c2-912c-49c4-a88b-66263a800727 -langcode: en -status: true -dependencies: - config: - - field.storage.media.field_mimetype - - media_entity.bundle.tn - enforced: - module: - - islandora -id: media.tn.field_mimetype -field_name: field_mimetype -entity_type: media -bundle: tn -label: Mimetype -description: 'Thumbnail mimetype' -required: false -translatable: true -default_value: { } -default_value_callback: '' -settings: { } -field_type: string diff --git a/config/install/islandora.settings.yml b/config/install/islandora.settings.yml deleted file mode 100644 index 60a09ba9..00000000 --- a/config/install/islandora.settings.yml +++ /dev/null @@ -1,5 +0,0 @@ -broker_url: 'tcp://localhost:61613' -fedora_rest_endpoint: 'http://localhost:8080/fcrepo/rest' -_core: - default_config_hash: nDZDR2rrpXXQ-D_7BYrdDFAXYOsB5hgH6vCAMV5I3w8 -broadcast_queue: islandora-connector-broadcast diff --git a/config/install/media_entity.bundle.tn.yml b/config/install/media_entity.bundle.tn.yml deleted file mode 100644 index 3a78e2a8..00000000 --- a/config/install/media_entity.bundle.tn.yml +++ /dev/null @@ -1,22 +0,0 @@ -uuid: 76912590-fe79-472d-9025-3538a6dfb5cb -langcode: en -status: true -dependencies: - module: - - media_entity_image - enforced: - module: - - islandora -id: tn -label: TN -description: 'Thumbnail image file' -type: image -queue_thumbnail_downloads: false -new_revision: false -type_configuration: - source_field: field_image - gather_exif: false -field_map: - mime: field_mimetype - width: field_width - height: field_height diff --git a/config/install/system.action.delete_media.yml b/config/install/system.action.delete_media.yml new file mode 100644 index 00000000..c90edea0 --- /dev/null +++ b/config/install/system.action.delete_media.yml @@ -0,0 +1,13 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora + module: + - media +id: delete_media +label: 'Delete media' +type: media +plugin: delete_media +configuration: { } diff --git a/config/install/system.action.delete_media_and_file.yml b/config/install/system.action.delete_media_and_file.yml new file mode 100644 index 00000000..c0012c24 --- /dev/null +++ b/config/install/system.action.delete_media_and_file.yml @@ -0,0 +1,13 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora + module: + - media +id: delete_media_and_file +label: 'Delete media and file(s)' +type: media +plugin: delete_media_and_file +configuration: { } diff --git a/config/schema/islandora.schema.yml b/config/schema/islandora.schema.yml index b0bec045..350fc302 100644 --- a/config/schema/islandora.schema.yml +++ b/config/schema/islandora.schema.yml @@ -36,7 +36,7 @@ action.configuration.emit_media_event: action.configuration.emit_file_event: type: mapping - label: 'Emit a Flie event to a queue/topic' + label: 'Emit a File event to a queue/topic' mapping: queue: type: text @@ -45,6 +45,25 @@ action.configuration.emit_file_event: type: text label: 'Event Type' +action.configuration.emit_term_event: + type: mapping + label: 'Emit a Taxonomy Term event to a queue/topic' + mapping: + queue: + type: text + label: 'Queue' + event: + type: text + label: 'Event Type' + +action.configuration.delete_media: + type: action_configuration_default + label: 'Delete media' + +action.configuration.delete_media_and_file: + type: action_configuration_default + label: 'Delete media and file' + condition.plugin.is_node: type: condition.plugin mapping: @@ -53,13 +72,31 @@ condition.plugin.is_media: type: condition.plugin mapping: -condition.plugin.is_referenced_media: +condition.plugin.is_file: type: condition.plugin mapping: - field: - type: text - label: 'Reference Field' -condition.plugin.is_file: +condition.plugin.is_term: + type: condition.plugin + mapping: + +condition.plugin.node_has_term: + type: condition.plugin + mapping: + uri: + type: text + label: 'Taxonomy Term URI' + +condition.plugin.media_has_term: + type: condition.plugin + mapping: + uri: + type: text + label: 'Taxonomy Term URI' + +condition.plugin.parent_node_has_term: type: condition.plugin mapping: + uri: + type: text + label: 'Taxonomy Term URI' diff --git a/islandora.info.yml b/islandora.info.yml index fd0d81ac..563a711b 100644 --- a/islandora.info.yml +++ b/islandora.info.yml @@ -11,13 +11,20 @@ dependencies: - path - text - options - - inline_entity_form + - link - jsonld - search_api - jwt - - media_entity_image - - rest + - rest - filehash - basic_auth - - context + - context_ui - action + - eva + - taxonomy + - views_ui + - media + - prepopulate + - features_ui + - migrate_tools + - migrate_source_csv diff --git a/islandora.links.action.yml b/islandora.links.action.yml new file mode 100644 index 00000000..97b16e10 --- /dev/null +++ b/islandora.links.action.yml @@ -0,0 +1,11 @@ +islandora.add_media_to_node: + route_name: islandora.add_media_to_node_page + title: Add media + appears_on: + - view.media_of.page_1 + +islandora.add_member_to_node: + route_name: islandora.add_member_to_node_page + title: Add member + appears_on: + - view.manage_members.page_1 diff --git a/islandora.module b/islandora.module index dfe3c6fe..c1d6b17c 100644 --- a/islandora.module +++ b/islandora.module @@ -15,9 +15,10 @@ */ use Drupal\Core\Entity\EntityInterface; -use Drupal\islandora\ContextProvider\NodeContextProvider; -use Drupal\islandora\ContextProvider\MediaContextProvider; -use Drupal\islandora\ContextProvider\FileContextProvider; +use Drupal\node\NodeInterface; +use Drupal\media\MediaInterface; +use Drupal\file\FileInterface; +use Drupal\taxonomy\TermInterface; use Drupal\Core\Routing\RouteMatchInterface; /** @@ -58,104 +59,185 @@ function islandora_rdf_namespaces() { } /** - * Implements hook_entity_insert(). + * Implements hook_node_insert(). */ -function islandora_entity_insert(EntityInterface $entity) { - switch ($entity->getEntityType()->id()) { - case "node": - $provider = new NodeContextProvider($entity); - break; +function islandora_node_insert(NodeInterface $node) { + $utils = \Drupal::service('islandora.utils'); - case "media": - $provider = new MediaContextProvider($entity); - break; + // Execute index reactions. + $utils->executeNodeReactions('\Drupal\islandora\Plugin\ContextReaction\IndexReaction', $node); +} - case "file": - $provider = new FileContextProvider($entity); - break; +/** + * Implements hook_node_update(). + */ +function islandora_node_update(NodeInterface $node) { - default: - $provider = NULL; - break; - } + $utils = \Drupal::service('islandora.utils'); + if (!$utils->haveFieldsChanged($node, $node->original)) { + return; + }; - if ($provider) { - $context_manager = \Drupal::service('context.manager'); - $provided = $provider->getRuntimeContexts([]); - $context_manager->evaluateContexts($provided); + // Execute index reactions. + $utils->executeNodeReactions('\Drupal\islandora\Plugin\ContextReaction\IndexReaction', $node); +} - foreach ($context_manager->getActiveReactions('index') as $reaction) { - $reaction->execute($entity); - } +/** + * Implements hook_node_delete(). + */ +function islandora_node_delete(NodeInterface $node) { + $utils = \Drupal::service('islandora.utils'); + + // Execute delete reactions. + $utils->executeNodeReactions('\Drupal\islandora\Plugin\ContextReaction\DeleteReaction', $node); +} + +/** + * Implements hook_media_insert(). + */ +function islandora_media_insert(MediaInterface $media) { + $utils = \Drupal::service('islandora.utils'); + + // Execute index reactions. + $utils->executeMediaReactions('\Drupal\islandora\Plugin\ContextReaction\IndexReaction', $media); + + // If it has a parent node... + $node = $utils->getParentNode($media); + if ($node) { + // Fire off derivative reactions for the Media. + $utils->executeDerivativeReactions( + '\Drupal\islandora\Plugin\ContextReaction\DerivativeReaction', + $node, + $media + ); } } /** - * Implements hook_entity_update(). + * Implements hook_media_update(). */ -function islandora_entity_update(EntityInterface $entity) { - switch ($entity->getEntityType()->id()) { - case "node": - $provider = new NodeContextProvider($entity); - break; +function islandora_media_update(MediaInterface $media) { + $media_source_service = \Drupal::service('islandora.media_source_service'); - case "media": - $provider = new MediaContextProvider($entity); - break; + // Exit early if nothing's changed. + $utils = \Drupal::service('islandora.utils'); + if (!$utils->haveFieldsChanged($media, $media->original)) { + return; + }; - case "file": - $provider = new FileContextProvider($entity); - break; + // Execute index reactions. + $utils->executeMediaReactions('\Drupal\islandora\Plugin\ContextReaction\IndexReaction', $media); - default: - $provider = NULL; - break; + // Does it have a source field? + $source_field = $media_source_service->getSourceFieldName($media->bundle()); + if (empty($source_field)) { + return; } - if ($provider) { - $context_manager = \Drupal::service('context.manager'); - $provided = $provider->getRuntimeContexts([]); - $context_manager->evaluateContexts($provided); + // Exit early if the source file did not change. + if ($media->get($source_field)->equals($media->original->get($source_field))) { + return; + } - foreach ($context_manager->getActiveReactions('index') as $reaction) { - $reaction->execute($entity); - } + // If it has a parent node... + $node = $utils->getParentNode($media); + if ($node) { + // Fire off derivative reactions for the Media. + $utils->executeDerivativeReactions( + '\Drupal\islandora\Plugin\ContextReaction\DerivativeReaction', + $node, + $media + ); } } /** - * Implements hook_entity_delete(). + * Implements hook_media_delete(). */ -function islandora_entity_delete(EntityInterface $entity) { - switch ($entity->getEntityType()->id()) { - case "node": - $provider = new NodeContextProvider($entity); - break; +function islandora_media_delete(MediaInterface $media) { + $utils = \Drupal::service('islandora.utils'); - case "media": - $provider = new MediaContextProvider($entity); - break; + // Execute delete reactions. + $utils->executeMediaReactions('\Drupal\islandora\Plugin\ContextReaction\DeleteReaction', $media); +} - case "file": - $provider = new FileContextProvider($entity); - break; +/** + * Implements hook_file_insert(). + */ +function islandora_file_insert(FileInterface $file) { + $utils = \Drupal::service('islandora.utils'); - default: - $provider = NULL; - break; + // Execute index reactions. + $utils->executeFileReactions('\Drupal\islandora\Plugin\ContextReaction\IndexReaction', $file); +} + +/** + * Implements hook_file_update(). + */ +function islandora_file_update(FileInterface $file) { + // Exit early if unchanged. + if ($file->filehash['sha1'] == $file->original->filehash['sha1']) { + return; } - if ($provider) { - $context_manager = \Drupal::service('context.manager'); - $provided = $provider->getRuntimeContexts([]); - $context_manager->evaluateContexts($provided); + $utils = \Drupal::service('islandora.utils'); - foreach ($context_manager->getActiveReactions('delete') as $reaction) { - $reaction->execute($entity); + // Execute index reactions. + $utils->executeFileReactions('\Drupal\islandora\Plugin\ContextReaction\IndexReaction', $file); + + // Execute derivative reactions. + foreach ($utils->getReferencingMedia($file->id()) as $media) { + $node = $utils->getParentNode($media); + if ($node) { + $utils->executeDerivativeReactions( + '\Drupal\islandora\Plugin\ContextReaction\DerivativeReaction', + $node, + $media + ); } } } +/** + * Implements hook_file_delete(). + */ +function islandora_file_delete(FileInterface $file) { + $utils = \Drupal::service('islandora.utils'); + + // Execute delete reactions. + $utils->executeFileReactions('\Drupal\islandora\Plugin\ContextReaction\DeleteReaction', $file); +} + +/** + * Implements hook_taxonomy_term_insert(). + */ +function islandora_taxonomy_term_insert(TermInterface $term) { + $utils = \Drupal::service('islandora.utils'); + + // Execute delete reactions. + $utils->executeTermReactions('\Drupal\islandora\Plugin\ContextReaction\IndexReaction', $term); +} + +/** + * Implements hook_taxonomy_term_update(). + */ +function islandora_taxonomy_term_update(TermInterface $term) { + $utils = \Drupal::service('islandora.utils'); + + // Execute delete reactions. + $utils->executeTermReactions('\Drupal\islandora\Plugin\ContextReaction\IndexReaction', $term); +} + +/** + * Implements hook_taxonomy_term_delete(). + */ +function islandora_taxonomy_term_delete(TermInterface $term) { + $utils = \Drupal::service('islandora.utils'); + + // Execute delete reactions. + $utils->executeTermReactions('\Drupal\islandora\Plugin\ContextReaction\DeleteReaction', $term); +} + /** * Implements hook_jsonld_alter_normalized_array(). */ @@ -165,3 +247,78 @@ function islandora_jsonld_alter_normalized_array(EntityInterface $entity, array $reaction->execute($entity, $normalized, $context); } } + +/** + * Implements hook_entity_view_mode_alter(). + */ +function islandora_entity_view_mode_alter(&$view_mode, EntityInterface $entity) { + // Change the view mode based on user input from a 'view_mode_alter' + // ContextReaction. + $storage = \Drupal::service('entity_type.manager')->getStorage('entity_view_mode'); + $context_manager = \Drupal::service('context.manager'); + + foreach ($context_manager->getActiveReactions('\Drupal\islandora\Plugin\ContextReaction\ViewModeAlterReaction') as $reaction) { + // Construct the new view mode's machine name. + $entity_type = $entity->getEntityTypeId(); + $mode = $reaction->execute(); + $machine_name = "$entity_type.$mode"; + + // Try to load it. + $new_mode = $storage->load($machine_name); + + // If successful, alter the view mode. + if ($new_mode) { + $view_mode = $mode; + } + else { + // Otherwise, leave it be, but log a message. + \Drupal::logger('islandora')->info("EntityViewMode $machine_name does not exist. View mode cannot be altered."); + } + } +} + +/** + * Implements hook_preprocess_node(). + */ +function islandora_preprocess_node(&$variables) { + // Using alternate view modes causes on a node's canoncial page + // causes the title to get printed out twice. Once from the + // fields themselves and again as a block above the main content. + // Setting 'page' to TRUE gets rid of the title in the fields and + // leaves the block. This makes it look uniform with the 'default' + // view mode. + if (node_is_page($variables['elements']['#node'])) { + $variables['page'] = TRUE; + } +} + +/** + * Implements hook_entity_form_display_alter(). + */ +function islandora_entity_form_display_alter(&$form_display, $context) { + // Change the form display based on user input from a 'form_display_alter' + // ContextReaction. + $storage = \Drupal::service('entity_type.manager')->getStorage('entity_form_display'); + $context_manager = \Drupal::service('context.manager'); + + // Alter form display based on context. + foreach ($context_manager->getActiveReactions('\Drupal\islandora\Plugin\ContextReaction\FormDisplayAlterReaction') as $reaction) { + // Construct the new form display's machine name. + $entity_type = $context['entity_type']; + $bundle = $context['bundle']; + $mode = $reaction->execute(); + $machine_name = "$entity_type.$bundle.$mode"; + + // Try to load it. + $new_display = $storage->load($machine_name); + + // If successful, alter the form display. + if ($new_display) { + $form_display = $new_display; + } + else { + // Otherwise, leave it be, but log a message. + \Drupal::logger('islandora')->info("EntityFormDisplay $machine_name does not exist. Form display cannot be altered."); + } + } +} diff --git a/islandora.permissions.yml b/islandora.permissions.yml index f8cca135..3ea34595 100644 --- a/islandora.permissions.yml +++ b/islandora.permissions.yml @@ -2,3 +2,11 @@ view checksums: title: 'View Checksums' description: 'Allows access to viewing file checksums' + +manage members: + title: 'Manage Members' + description: 'Allows access to managing members for content' + +manage media: + title: 'Manage Media' + description: 'Allows access to managing media for content' diff --git a/islandora.routing.yml b/islandora.routing.yml index ef394fbd..58dea1a2 100644 --- a/islandora.routing.yml +++ b/islandora.routing.yml @@ -16,6 +16,28 @@ system.islandora_settings: requirements: _permission: 'administer site configuration' +islandora.add_member_to_node_page: + path: '/node/{node}/members/add' + defaults: + _controller: '\Drupal\islandora\Controller\ManageMembersController::addToNodePage' + _title_callback: '\Drupal\islandora\Controller\ManageMembersController::addTitle' + entity_type_id: node + options: + _admin_route: 'true' + requirements: + _entity_create_any_access: 'node' + +islandora.add_media_to_node_page: + path: '/node/{node}/media/add' + defaults: + _controller: '\Drupal\islandora\Controller\ManageMediaController::addToNodePage' + _title_callback: '\Drupal\islandora\Controller\ManageMediaController::addTitle' + entity_type_id: media + options: + _admin_route: 'true' + requirements: + _entity_create_any_access: 'media' + islandora.media_source_update: path: '/media/{media}/source' defaults: @@ -26,12 +48,12 @@ islandora.media_source_update: options: _auth: ['basic_auth', 'cookie', 'jwt_auth'] -islandora.media_source_add_to_node: - path: '/node/{node}/media/{field}/add/{bundle}' +islandora.media_source_put_to_node: + path: '/node/{node}/media/{media_type}/{taxonomy_term}' defaults: - _controller: '\Drupal\islandora\Controller\MediaSourceController::addToNode' - methods: [POST] + _controller: '\Drupal\islandora\Controller\MediaSourceController::putToNode' + methods: [PUT] requirements: - _custom_access: '\Drupal\islandora\Controller\MediaSourceController::addToNodeAccess' + _custom_access: '\Drupal\islandora\Controller\MediaSourceController::putToNodeAccess' options: _auth: ['basic_auth', 'cookie', 'jwt_auth'] diff --git a/islandora.services.yml b/islandora.services.yml index 133b9e01..1159f0a3 100644 --- a/islandora.services.yml +++ b/islandora.services.yml @@ -1,11 +1,6 @@ # Islandora Services # islandora.services.yml: services: - islandora.paramconverter.entity: - class: Drupal\islandora\ParamConverter\UuidEntityConverter - tags: - - { name: paramconverter } - arguments: ['@entity.manager'] islandora.eventgenerator: class: Drupal\islandora\EventGenerator\EventGenerator islandora.stomp: @@ -20,17 +15,18 @@ services: - { name: event_subscriber } islandora.media_link_header_subscriber: class: Drupal\islandora\EventSubscriber\MediaLinkHeaderSubscriber - arguments: ['@entity_type.manager', '@entity_field.manager', '@current_route_match', '@access_manager', '@current_user'] + arguments: ['@entity_type.manager', '@entity_field.manager', '@access_manager', '@current_user', '@current_route_match', '@request_stack'] tags: - { name: event_subscriber } islandora.node_link_header_subscriber: class: Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber - arguments: ['@entity_type.manager', '@entity_field.manager', '@current_route_match', '@access_manager', '@current_user'] + arguments: ['@entity_type.manager', '@entity_field.manager', '@access_manager', '@current_user', '@current_route_match', '@request_stack', '@islandora.utils'] + tags: + - { name: event_subscriber } + islandora.admin_view_route_subscriber: + class: Drupal\islandora\EventSubscriber\AdminViewsRouteSubscriber tags: - { name: event_subscriber } - islandora.versioncounter: - class: Drupal\islandora\VersionCounter\VersionCounter - arguments: ['@database'] logger.channel.islandora: parent: logger.channel_base arguments: ['islandora'] @@ -44,6 +40,14 @@ services: arguments: ['@current_route_match'] tags: - { name: 'context_provider' } + islandora.taxonomy_term_route_context_provider: + class: Drupal\islandora\ContextProvider\TermRouteContextProvider + arguments: ['@current_route_match'] + tags: + - { name: 'context_provider' } islandora.media_source_service: class: Drupal\islandora\MediaSource\MediaSourceService - arguments: ['@entity_type.manager', '@current_user', '@stream_wrapper_manager', '@token'] + arguments: ['@entity_type.manager', '@current_user', '@stream_wrapper_manager', '@language_manager', '@token', '@entity.query'] + islandora.utils: + class: Drupal\islandora\IslandoraUtils + arguments: ['@entity_type.manager', '@entity_field.manager', '@entity.query', '@context.manager', '@stream_wrapper_manager'] diff --git a/migrate/tags.csv b/migrate/tags.csv new file mode 100644 index 00000000..6f54f3db --- /dev/null +++ b/migrate/tags.csv @@ -0,0 +1,9 @@ +vid,name,description,external_uri +tags,"Preservation Master","Best quality representation of the Object appropriate for long-term preservation",http://pcdm.org/use#PreservationMasterFile +tags,"Service File","A medium quality representation of the Object appropriate for serving to users",http://pcdm.org/use#ServiceFile +tags,"Thumbnail","A low resolution image representation of the Object appropriate for using as an icon",http://pcdm.org/use#ThumbnailImage +tags,"Audio","A resource primarily intended to be heard. Examples include a music playback file format, an audio compact disc, and recorded speech or sounds",http://purl.org/coar/resource_type/c_18cc +tags,"Binary","A generic binary file for repository items that don't fall into any other category or cannot be shown in a browser",http://purl.org/coar/resource_type/c_1843 +tags,"Collection","A collection is an aggregation of items",http://purl.org/dc/dcmitype/Collection +tags,"Image","A visual representation other than text, including all types of moving image and still image",http://purl.org/coar/resource_type/c_c513 +tags,"Video","A recording of visual images, usually in motion and with sound accompaniment",http://purl.org/coar/resource_type/c_12ce diff --git a/modules/islandora_core_feature/config/install/core.entity_view_display.media.audio.source.yml b/modules/islandora_core_feature/config/install/core.entity_view_display.media.audio.source.yml new file mode 100644 index 00000000..4cb04d73 --- /dev/null +++ b/modules/islandora_core_feature/config/install/core.entity_view_display.media.audio.source.yml @@ -0,0 +1,41 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.source + - field.field.media.audio.field_file_size + - field.field.media.audio.field_media_audio_file + - field.field.media.audio.field_media_of + - field.field.media.audio.field_mime_type + - field.field.media.audio.field_tags + - media.type.audio + enforced: + module: + - islandora_core_feature + module: + - file +id: media.audio.source +targetEntityType: media +bundle: audio +mode: source +content: + field_media_audio_file: + type: file_audio + weight: 0 + label: visually_hidden + settings: + controls: true + multiple_file_display_type: tags + autoplay: false + loop: false + third_party_settings: { } + region: content +hidden: + created: true + field_file_size: true + field_media_of: true + field_mime_type: true + field_tags: true + name: true + thumbnail: true + uid: true diff --git a/modules/islandora_core_feature/config/install/core.entity_view_display.media.file.source.yml b/modules/islandora_core_feature/config/install/core.entity_view_display.media.file.source.yml new file mode 100644 index 00000000..a9466d15 --- /dev/null +++ b/modules/islandora_core_feature/config/install/core.entity_view_display.media.file.source.yml @@ -0,0 +1,38 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.source + - field.field.media.file.field_file_size + - field.field.media.file.field_media_file + - field.field.media.file.field_media_of + - field.field.media.file.field_mime_type + - field.field.media.file.field_tags + - media.type.file + enforced: + module: + - islandora_core_feature + module: + - file +id: media.file.source +targetEntityType: media +bundle: file +mode: source +content: + field_media_file: + label: hidden + settings: + use_description_as_link_text: true + third_party_settings: { } + type: file_default + weight: 0 + region: content +hidden: + created: true + field_file_size: true + field_media_of: true + field_mime_type: true + field_tags: true + name: true + thumbnail: true + uid: true diff --git a/modules/islandora_core_feature/config/install/core.entity_view_display.media.image.source.yml b/modules/islandora_core_feature/config/install/core.entity_view_display.media.image.source.yml new file mode 100644 index 00000000..e74fc872 --- /dev/null +++ b/modules/islandora_core_feature/config/install/core.entity_view_display.media.image.source.yml @@ -0,0 +1,43 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.source + - field.field.media.image.field_file_size + - field.field.media.image.field_height + - field.field.media.image.field_media_image + - field.field.media.image.field_media_of + - field.field.media.image.field_mime_type + - field.field.media.image.field_tags + - field.field.media.image.field_width + - media.type.image + enforced: + module: + - islandora_core_feature + module: + - image +id: media.image.source +targetEntityType: media +bundle: image +mode: source +content: + field_media_image: + label: visually_hidden + settings: + image_style: '' + image_link: content + third_party_settings: { } + type: image + weight: 0 + region: content +hidden: + created: true + field_file_size: true + field_height: true + field_media_of: true + field_mime_type: true + field_tags: true + field_width: true + name: true + thumbnail: true + uid: true diff --git a/modules/islandora_core_feature/config/install/core.entity_view_display.media.video.source.yml b/modules/islandora_core_feature/config/install/core.entity_view_display.media.video.source.yml new file mode 100644 index 00000000..1fe3e0fc --- /dev/null +++ b/modules/islandora_core_feature/config/install/core.entity_view_display.media.video.source.yml @@ -0,0 +1,44 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.source + - field.field.media.video.field_file_size + - field.field.media.video.field_media_of + - field.field.media.video.field_media_video_file + - field.field.media.video.field_mime_type + - field.field.media.video.field_tags + - media.type.video + enforced: + module: + - islandora_core_feature + module: + - file +id: media.video.source +targetEntityType: media +bundle: video +mode: source +content: + field_media_video_file: + type: file_video + weight: 0 + label: visually_hidden + settings: + muted: false + width: 640 + height: 480 + controls: true + autoplay: false + loop: false + multiple_file_display_type: tags + third_party_settings: { } + region: content +hidden: + created: true + field_file_size: true + field_media_of: true + field_mime_type: true + field_tags: true + name: true + thumbnail: true + uid: true diff --git a/modules/islandora_core_feature/config/install/core.entity_view_mode.media.source.yml b/modules/islandora_core_feature/config/install/core.entity_view_mode.media.source.yml new file mode 100644 index 00000000..df6df63c --- /dev/null +++ b/modules/islandora_core_feature/config/install/core.entity_view_mode.media.source.yml @@ -0,0 +1,12 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - media +id: media.source +label: Source +targetEntityType: media +cache: true diff --git a/modules/islandora_core_feature/config/install/features.bundle.islandora.yml b/modules/islandora_core_feature/config/install/features.bundle.islandora.yml new file mode 100644 index 00000000..9c358731 --- /dev/null +++ b/modules/islandora_core_feature/config/install/features.bundle.islandora.yml @@ -0,0 +1,100 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature +name: Islandora +machine_name: islandora +description: 'Features for islandora' +assignments: + alter: + core: true + uuid: true + user_permissions: true + enabled: true + weight: 0 + base: + types: + config: + comment_type: comment_type + node_type: node_type + content: + user: user + enabled: true + weight: -2 + core: + types: + config: + date_format: date_format + field_storage_config: field_storage_config + entity_form_mode: entity_form_mode + image_style: image_style + menu: menu + responsive_image_style: responsive_image_style + user_role: user_role + entity_view_mode: entity_view_mode + enabled: true + weight: 5 + dependency: + enabled: true + weight: 15 + exclude: + types: + config: + features_bundle: features_bundle + curated: true + module: + installed: true + profile: true + namespace: true + namespace_any: false + enabled: true + weight: -5 + existing: + enabled: true + weight: 12 + forward_dependency: + enabled: true + weight: 4 + namespace: + enabled: true + weight: 0 + optional: + types: + config: { } + enabled: true + weight: 0 + packages: + enabled: true + weight: -20 + profile: + curated: true + standard: + files: true + dependencies: true + types: + config: + block: block + language_content_settings: language_content_settings + configurable_language: configurable_language + migration: migration + shortcut_set: shortcut_set + tour: tour + enabled: true + weight: 10 + site: + types: + config: + action: action + contact_form: contact_form + block_content_type: block_content_type + rdf_mapping: rdf_mapping + search_page: search_page + taxonomy_vocabulary: taxonomy_vocabulary + editor: editor + filter_format: filter_format + enabled: true + weight: 7 +profile_name: '' +is_profile: false diff --git a/modules/islandora_core_feature/config/install/field.field.media.audio.field_file_size.yml b/modules/islandora_core_feature/config/install/field.field.media.audio.field_file_size.yml new file mode 100644 index 00000000..ce79179c --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.audio.field_file_size.yml @@ -0,0 +1,25 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_file_size + - media.type.audio + enforced: + module: + - islandora_core_feature +id: media.audio.field_file_size +field_name: field_file_size +entity_type: media +bundle: audio +label: 'File size' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + min: null + max: null + prefix: '' + suffix: '' +field_type: integer diff --git a/modules/islandora_core_feature/config/install/field.field.media.audio.field_media_audio_file.yml b/modules/islandora_core_feature/config/install/field.field.media.audio.field_media_audio_file.yml new file mode 100644 index 00000000..3835e009 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.audio.field_media_audio_file.yml @@ -0,0 +1,29 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_media_audio_file + - media.type.audio + enforced: + module: + - islandora_core_feature + module: + - file +id: media.audio.field_media_audio_file +field_name: field_media_audio_file +entity_type: media +bundle: audio +label: 'Audio file' +description: '' +required: true +translatable: true +default_value: { } +default_value_callback: '' +settings: + file_extensions: 'mp3 wav aac' + file_directory: '[date:custom:Y]-[date:custom:m]' + max_filesize: '' + description_field: false + handler: 'default:file' + handler_settings: { } +field_type: file diff --git a/modules/islandora_core_feature/config/install/field.field.media.audio.field_media_of.yml b/modules/islandora_core_feature/config/install/field.field.media.audio.field_media_of.yml new file mode 100644 index 00000000..a5f7d0f8 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.audio.field_media_of.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_media_of + - media.type.audio + enforced: + module: + - islandora_core_feature +id: media.audio.field_media_of +field_name: field_media_of +entity_type: media +bundle: audio +label: 'Media of' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:node' + handler_settings: { } +field_type: entity_reference diff --git a/modules/islandora_core_feature/config/install/field.field.media.audio.field_mime_type.yml b/modules/islandora_core_feature/config/install/field.field.media.audio.field_mime_type.yml new file mode 100644 index 00000000..aea97bd1 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.audio.field_mime_type.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_mime_type + - media.type.audio + enforced: + module: + - islandora_core_feature +id: media.audio.field_mime_type +field_name: field_mime_type +entity_type: media +bundle: audio +label: 'MIME type' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/islandora_core_feature/config/install/field.field.media.audio.field_tags.yml b/modules/islandora_core_feature/config/install/field.field.media.audio.field_tags.yml new file mode 100644 index 00000000..bd56c97d --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.audio.field_tags.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_tags + - media.type.audio + enforced: + module: + - islandora_core_feature +id: media.audio.field_tags +field_name: field_tags +entity_type: media +bundle: audio +label: Tags +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: { } +field_type: entity_reference diff --git a/modules/islandora_core_feature/config/install/field.field.media.file.field_file_size.yml b/modules/islandora_core_feature/config/install/field.field.media.file.field_file_size.yml new file mode 100644 index 00000000..a52a893f --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.file.field_file_size.yml @@ -0,0 +1,25 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_file_size + - media.type.file + enforced: + module: + - islandora_core_feature +id: media.file.field_file_size +field_name: field_file_size +entity_type: media +bundle: file +label: 'File size' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + min: null + max: null + prefix: '' + suffix: '' +field_type: integer diff --git a/modules/islandora_core_feature/config/install/field.field.media.file.field_media_file.yml b/modules/islandora_core_feature/config/install/field.field.media.file.field_media_file.yml new file mode 100644 index 00000000..fec6db7d --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.file.field_media_file.yml @@ -0,0 +1,30 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_media_file + - media.type.file + enforced: + module: + - media + - islandora_core_feature + module: + - file +id: media.file.field_media_file +field_name: field_media_file +entity_type: media +bundle: file +label: File +description: '' +required: true +translatable: true +default_value: { } +default_value_callback: '' +settings: + file_directory: '[date:custom:Y]-[date:custom:m]' + file_extensions: 'txt rtf doc docx ppt pptx xls xlsx pdf odf odg odp ods odt fodt fods fodp fodg key numbers pages tiff tif jp2' + max_filesize: '' + description_field: false + handler: 'default:file' + handler_settings: { } +field_type: file diff --git a/modules/islandora_core_feature/config/install/field.field.media.file.field_media_of.yml b/modules/islandora_core_feature/config/install/field.field.media.file.field_media_of.yml new file mode 100644 index 00000000..12c5cdfc --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.file.field_media_of.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_media_of + - media.type.file + enforced: + module: + - islandora_core_feature +id: media.file.field_media_of +field_name: field_media_of +entity_type: media +bundle: file +label: 'Media of' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + handler: 'default:node' + handler_settings: { } +field_type: entity_reference diff --git a/modules/islandora_core_feature/config/install/field.field.media.file.field_mime_type.yml b/modules/islandora_core_feature/config/install/field.field.media.file.field_mime_type.yml new file mode 100644 index 00000000..a93d6b8a --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.file.field_mime_type.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_mime_type + - media.type.file + enforced: + module: + - islandora_core_feature +id: media.file.field_mime_type +field_name: field_mime_type +entity_type: media +bundle: file +label: 'MIME type' +description: 'MIME type of the underlying file' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/islandora_core_feature/config/install/field.field.media.file.field_tags.yml b/modules/islandora_core_feature/config/install/field.field.media.file.field_tags.yml new file mode 100644 index 00000000..5ea4377a --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.file.field_tags.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_tags + - media.type.file + enforced: + module: + - islandora_core_feature +id: media.file.field_tags +field_name: field_tags +entity_type: media +bundle: file +label: Tags +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: { } +field_type: entity_reference diff --git a/modules/islandora_core_feature/config/install/field.field.media.image.field_file_size.yml b/modules/islandora_core_feature/config/install/field.field.media.image.field_file_size.yml new file mode 100644 index 00000000..b3c0a5b5 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.image.field_file_size.yml @@ -0,0 +1,25 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_file_size + - media.type.image + enforced: + module: + - islandora_core_feature +id: media.image.field_file_size +field_name: field_file_size +entity_type: media +bundle: image +label: 'File size' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + min: null + max: null + prefix: '' + suffix: '' +field_type: integer diff --git a/config/install/field.field.media.tn.field_height.yml b/modules/islandora_core_feature/config/install/field.field.media.image.field_height.yml similarity index 63% rename from config/install/field.field.media.tn.field_height.yml rename to modules/islandora_core_feature/config/install/field.field.media.image.field_height.yml index af401b7c..7ea6a093 100644 --- a/config/install/field.field.media.tn.field_height.yml +++ b/modules/islandora_core_feature/config/install/field.field.media.image.field_height.yml @@ -1,21 +1,20 @@ -uuid: 64ecf3f3-8aad-4794-a9cc-ea2320885fea langcode: en status: true dependencies: config: - field.storage.media.field_height - - media_entity.bundle.tn + - media.type.image enforced: module: - - islandora -id: media.tn.field_height + - islandora_core_feature +id: media.image.field_height field_name: field_height entity_type: media -bundle: tn +bundle: image label: Height -description: 'Thumbnail height' +description: '' required: false -translatable: true +translatable: false default_value: { } default_value_callback: '' settings: diff --git a/config/install/field.field.media.tn.field_image.yml b/modules/islandora_core_feature/config/install/field.field.media.image.field_media_image.yml similarity index 70% rename from config/install/field.field.media.tn.field_image.yml rename to modules/islandora_core_feature/config/install/field.field.media.image.field_media_image.yml index 5ed70de4..95e3ac00 100644 --- a/config/install/field.field.media.tn.field_image.yml +++ b/modules/islandora_core_feature/config/install/field.field.media.image.field_media_image.yml @@ -1,41 +1,41 @@ -uuid: 3e86756e-0782-4514-86f8-97d26ec6985d langcode: en status: true dependencies: config: - - field.storage.media.field_image - - media_entity.bundle.tn + - field.storage.media.field_media_image + - media.type.image enforced: module: - - islandora + - media + - islandora_core_feature module: - image -id: media.tn.field_image -field_name: field_image +id: media.image.field_media_image +field_name: field_media_image entity_type: media -bundle: tn +bundle: image label: Image -description: 'Thumbnail contents' -required: false +description: '' +required: true translatable: true default_value: { } default_value_callback: '' settings: - file_directory: '[date:custom:Y]-[date:custom:m]' - file_extensions: 'png gif jpg jpeg' - max_filesize: '' - max_resolution: '' - min_resolution: '' alt_field: true alt_field_required: true title_field: false title_field_required: false + max_resolution: '' + min_resolution: '' default_image: - uuid: '' + uuid: null alt: '' title: '' width: null height: null + file_directory: '[date:custom:Y]-[date:custom:m]' + file_extensions: 'png gif jpg jpeg' + max_filesize: '' handler: 'default:file' handler_settings: { } field_type: image diff --git a/modules/islandora_core_feature/config/install/field.field.media.image.field_media_of.yml b/modules/islandora_core_feature/config/install/field.field.media.image.field_media_of.yml new file mode 100644 index 00000000..ab7a6cce --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.image.field_media_of.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_media_of + - media.type.image + enforced: + module: + - islandora_core_feature +id: media.image.field_media_of +field_name: field_media_of +entity_type: media +bundle: image +label: 'Media of' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + handler: 'default:node' + handler_settings: { } +field_type: entity_reference diff --git a/modules/islandora_core_feature/config/install/field.field.media.image.field_mime_type.yml b/modules/islandora_core_feature/config/install/field.field.media.image.field_mime_type.yml new file mode 100644 index 00000000..39538c4c --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.image.field_mime_type.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_mime_type + - media.type.image + enforced: + module: + - islandora_core_feature +id: media.image.field_mime_type +field_name: field_mime_type +entity_type: media +bundle: image +label: 'MIME type' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/islandora_core_feature/config/install/field.field.media.image.field_tags.yml b/modules/islandora_core_feature/config/install/field.field.media.image.field_tags.yml new file mode 100644 index 00000000..26e013d6 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.image.field_tags.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_tags + - media.type.image + enforced: + module: + - islandora_core_feature +id: media.image.field_tags +field_name: field_tags +entity_type: media +bundle: image +label: Tags +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: { } +field_type: entity_reference diff --git a/config/install/field.field.media.tn.field_width.yml b/modules/islandora_core_feature/config/install/field.field.media.image.field_width.yml similarity index 63% rename from config/install/field.field.media.tn.field_width.yml rename to modules/islandora_core_feature/config/install/field.field.media.image.field_width.yml index d8856069..42aa19c1 100644 --- a/config/install/field.field.media.tn.field_width.yml +++ b/modules/islandora_core_feature/config/install/field.field.media.image.field_width.yml @@ -1,21 +1,20 @@ -uuid: 1f18aa08-5384-4880-892d-947eb1c3b457 langcode: en status: true dependencies: config: - field.storage.media.field_width - - media_entity.bundle.tn + - media.type.image enforced: module: - - islandora -id: media.tn.field_width + - islandora_core_feature +id: media.image.field_width field_name: field_width entity_type: media -bundle: tn +bundle: image label: Width -description: 'Thumbnail width' +description: '' required: false -translatable: true +translatable: false default_value: { } default_value_callback: '' settings: diff --git a/modules/islandora_core_feature/config/install/field.field.media.video.field_file_size.yml b/modules/islandora_core_feature/config/install/field.field.media.video.field_file_size.yml new file mode 100644 index 00000000..de036bc6 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.video.field_file_size.yml @@ -0,0 +1,25 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_file_size + - media.type.video + enforced: + module: + - islandora_core_feature +id: media.video.field_file_size +field_name: field_file_size +entity_type: media +bundle: video +label: 'File size' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + min: null + max: null + prefix: '' + suffix: '' +field_type: integer diff --git a/modules/islandora_core_feature/config/install/field.field.media.video.field_media_of.yml b/modules/islandora_core_feature/config/install/field.field.media.video.field_media_of.yml new file mode 100644 index 00000000..487ce951 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.video.field_media_of.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_media_of + - media.type.video + enforced: + module: + - islandora_core_feature +id: media.video.field_media_of +field_name: field_media_of +entity_type: media +bundle: video +label: 'Media of' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + handler: 'default:node' + handler_settings: { } +field_type: entity_reference diff --git a/modules/islandora_core_feature/config/install/field.field.media.video.field_media_video_file.yml b/modules/islandora_core_feature/config/install/field.field.media.video.field_media_video_file.yml new file mode 100644 index 00000000..25f002c7 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.video.field_media_video_file.yml @@ -0,0 +1,29 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_media_video_file + - media.type.video + enforced: + module: + - islandora_core_feature + module: + - file +id: media.video.field_media_video_file +field_name: field_media_video_file +entity_type: media +bundle: video +label: 'Video file' +description: '' +required: true +translatable: true +default_value: { } +default_value_callback: '' +settings: + file_extensions: mp4 + file_directory: '[date:custom:Y]-[date:custom:m]' + max_filesize: '' + description_field: false + handler: 'default:file' + handler_settings: { } +field_type: file diff --git a/modules/islandora_core_feature/config/install/field.field.media.video.field_mime_type.yml b/modules/islandora_core_feature/config/install/field.field.media.video.field_mime_type.yml new file mode 100644 index 00000000..bdec6319 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.video.field_mime_type.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_mime_type + - media.type.video + enforced: + module: + - islandora_core_feature +id: media.video.field_mime_type +field_name: field_mime_type +entity_type: media +bundle: video +label: 'MIME type' +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: { } +field_type: string diff --git a/modules/islandora_core_feature/config/install/field.field.media.video.field_tags.yml b/modules/islandora_core_feature/config/install/field.field.media.video.field_tags.yml new file mode 100644 index 00000000..308826fe --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.media.video.field_tags.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_tags + - media.type.video + enforced: + module: + - islandora_core_feature +id: media.video.field_tags +field_name: field_tags +entity_type: media +bundle: video +label: Tags +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: { } +field_type: entity_reference diff --git a/modules/islandora_core_feature/config/install/field.field.taxonomy_term.tags.field_external_uri.yml b/modules/islandora_core_feature/config/install/field.field.taxonomy_term.tags.field_external_uri.yml new file mode 100644 index 00000000..939e5a12 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.field.taxonomy_term.tags.field_external_uri.yml @@ -0,0 +1,25 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.taxonomy_term.field_external_uri + - taxonomy.vocabulary.tags + enforced: + module: + - islandora_core_feature + module: + - link +id: taxonomy_term.tags.field_external_uri +field_name: field_external_uri +entity_type: taxonomy_term +bundle: tags +label: 'External URI' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + link_type: 16 + title: 0 +field_type: link diff --git a/modules/islandora_core_feature/config/install/field.storage.media.field_file_size.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_file_size.yml new file mode 100644 index 00000000..5c3e67c4 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_file_size.yml @@ -0,0 +1,22 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - media +id: media.field_file_size +field_name: field_file_size +entity_type: media +type: integer +settings: + unsigned: false + size: normal +module: core +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/config/install/field.storage.media.field_height.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_height.yml similarity index 80% rename from config/install/field.storage.media.field_height.yml rename to modules/islandora_core_feature/config/install/field.storage.media.field_height.yml index 6f7c2185..73e569b3 100644 --- a/config/install/field.storage.media.field_height.yml +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_height.yml @@ -1,12 +1,11 @@ -uuid: 68e445be-834e-4a03-b5f3-46e4d3214660 langcode: en status: true dependencies: - module: - - media_entity enforced: module: - - islandora + - islandora_core_feature + module: + - media id: media.field_height field_name: field_height entity_type: media diff --git a/config/install/field.storage.media.field_file.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_media_audio_file.yml similarity index 68% rename from config/install/field.storage.media.field_file.yml rename to modules/islandora_core_feature/config/install/field.storage.media.field_media_audio_file.yml index d044dd2f..2421e500 100644 --- a/config/install/field.storage.media.field_file.yml +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_media_audio_file.yml @@ -1,22 +1,21 @@ -uuid: 3187338b-84ab-4ad4-9396-0600ed7cc6d6 langcode: en status: true dependencies: - module: - - file - - media_entity enforced: module: - - islandora -id: media.field_file -field_name: field_file + - islandora_core_feature + module: + - file + - media +id: media.field_media_audio_file +field_name: field_media_audio_file entity_type: media type: file settings: - display_field: true + target_type: file + display_field: false display_default: false uri_scheme: public - target_type: file module: file locked: false cardinality: 1 diff --git a/modules/islandora_core_feature/config/install/field.storage.media.field_media_file.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_media_file.yml new file mode 100644 index 00000000..b38a1ae0 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_media_file.yml @@ -0,0 +1,26 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - media + - islandora_core_feature + module: + - file + - media +id: media.field_media_file +field_name: field_media_file +entity_type: media +type: file +settings: + uri_scheme: public + target_type: file + display_field: false + display_default: false +module: file +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/config/install/field.storage.media.field_image.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_media_image.yml similarity index 66% rename from config/install/field.storage.media.field_image.yml rename to modules/islandora_core_feature/config/install/field.storage.media.field_media_image.yml index 81417f9f..22c3c4ee 100644 --- a/config/install/field.storage.media.field_image.yml +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_media_image.yml @@ -1,24 +1,21 @@ -uuid: 864f50f8-57b5-4a43-80f9-7548b1dc0196 langcode: en status: true dependencies: enforced: module: - - islandora + - media + - islandora_core_feature module: - file - image - - media_entity -_core: - default_config_hash: MX6T38DOi1q6LSZEP_PsH6mWEBZv-ncKCgfYVjQDvlY -id: media.field_image -field_name: field_image + - media +id: media.field_media_image +field_name: field_media_image entity_type: media type: image settings: - uri_scheme: public default_image: - uuid: '' + uuid: null alt: '' title: '' width: null @@ -26,6 +23,7 @@ settings: target_type: file display_field: false display_default: false + uri_scheme: public module: image locked: false cardinality: 1 diff --git a/config/install/field.storage.node.field_tn.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_media_of.yml similarity index 57% rename from config/install/field.storage.node.field_tn.yml rename to modules/islandora_core_feature/config/install/field.storage.media.field_media_of.yml index 35630fc5..305f9e53 100644 --- a/config/install/field.storage.node.field_tn.yml +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_media_of.yml @@ -1,19 +1,18 @@ -uuid: 70d43fa1-2c63-42a7-86ca-9ccaa1d0ac6d langcode: en status: true dependencies: - module: - - islandora - - media_entity enforced: module: - - islandora -id: node.field_tn -field_name: field_tn -entity_type: node + - islandora_core_feature + module: + - media + - node +id: media.field_media_of +field_name: field_media_of +entity_type: media type: entity_reference settings: - target_type: media + target_type: node module: core locked: false cardinality: 1 diff --git a/modules/islandora_core_feature/config/install/field.storage.media.field_media_video_file.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_media_video_file.yml new file mode 100644 index 00000000..0c02aef1 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_media_video_file.yml @@ -0,0 +1,25 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - file + - media +id: media.field_media_video_file +field_name: field_media_video_file +entity_type: media +type: file +settings: + target_type: file + display_field: false + display_default: false + uri_scheme: public +module: file +locked: false +cardinality: 1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/config/install/field.storage.media.field_mimetype.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_mime_type.yml similarity index 69% rename from config/install/field.storage.media.field_mimetype.yml rename to modules/islandora_core_feature/config/install/field.storage.media.field_mime_type.yml index fce41375..8f458941 100644 --- a/config/install/field.storage.media.field_mimetype.yml +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_mime_type.yml @@ -1,14 +1,13 @@ -uuid: ac5aa8aa-4672-498c-b814-2e4d477b8a75 langcode: en status: true dependencies: - module: - - media_entity enforced: module: - - islandora -id: media.field_mimetype -field_name: field_mimetype + - islandora_core_feature + module: + - media +id: media.field_mime_type +field_name: field_mime_type entity_type: media type: string settings: diff --git a/config/install/field.storage.node.field_obj.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_tags.yml similarity index 53% rename from config/install/field.storage.node.field_obj.yml rename to modules/islandora_core_feature/config/install/field.storage.media.field_tags.yml index a5cbcd38..b76af0b7 100644 --- a/config/install/field.storage.node.field_obj.yml +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_tags.yml @@ -1,22 +1,21 @@ -uuid: d31f7746-57f6-4081-973e-da400b1e51d1 langcode: en status: true dependencies: enforced: module: - - islandora + - islandora_core_feature module: - - islandora - - media_entity -id: node.field_obj -field_name: field_obj -entity_type: node + - media + - taxonomy +id: media.field_tags +field_name: field_tags +entity_type: media type: entity_reference settings: - target_type: media + target_type: taxonomy_term module: core locked: false -cardinality: 1 +cardinality: -1 translatable: true indexes: { } persist_with_no_fields: false diff --git a/config/install/field.storage.media.field_width.yml b/modules/islandora_core_feature/config/install/field.storage.media.field_width.yml similarity index 80% rename from config/install/field.storage.media.field_width.yml rename to modules/islandora_core_feature/config/install/field.storage.media.field_width.yml index a00cf391..aefac1ca 100644 --- a/config/install/field.storage.media.field_width.yml +++ b/modules/islandora_core_feature/config/install/field.storage.media.field_width.yml @@ -1,12 +1,11 @@ -uuid: 3d8f21ae-673c-4569-b7be-6352068e5fcb langcode: en status: true dependencies: - module: - - media_entity enforced: module: - - islandora + - islandora_core_feature + module: + - media id: media.field_width field_name: field_width entity_type: media diff --git a/config/install/field.storage.node.field_memberof.yml b/modules/islandora_core_feature/config/install/field.storage.node.field_member_of.yml similarity index 69% rename from config/install/field.storage.node.field_memberof.yml rename to modules/islandora_core_feature/config/install/field.storage.node.field_member_of.yml index 764b3cef..f7decd61 100644 --- a/config/install/field.storage.node.field_memberof.yml +++ b/modules/islandora_core_feature/config/install/field.storage.node.field_member_of.yml @@ -1,20 +1,20 @@ langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora -id: node.field_memberof -field_name: field_memberof + - islandora_core_feature + module: + - node +id: node.field_member_of +field_name: field_member_of entity_type: node type: entity_reference settings: target_type: node module: core locked: false -cardinality: 1 +cardinality: -1 translatable: true indexes: { } persist_with_no_fields: false diff --git a/modules/islandora_core_feature/config/install/field.storage.taxonomy_term.field_external_uri.yml b/modules/islandora_core_feature/config/install/field.storage.taxonomy_term.field_external_uri.yml new file mode 100644 index 00000000..b1d10e19 --- /dev/null +++ b/modules/islandora_core_feature/config/install/field.storage.taxonomy_term.field_external_uri.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - link + - taxonomy +id: taxonomy_term.field_external_uri +field_name: field_external_uri +entity_type: taxonomy_term +type: link +settings: { } +module: link +locked: false +cardinality: -1 +translatable: true +indexes: { } +persist_with_no_fields: false +custom_storage: false diff --git a/modules/islandora_core_feature/config/install/media.type.audio.yml b/modules/islandora_core_feature/config/install/media.type.audio.yml new file mode 100644 index 00000000..4ca59fd5 --- /dev/null +++ b/modules/islandora_core_feature/config/install/media.type.audio.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature +id: audio +label: Audio +description: 'A locally hosted audio file.' +source: audio_file +queue_thumbnail_downloads: false +new_revision: true +source_configuration: + source_field: field_media_audio_file +field_map: + mimetype: field_mime_type + filesize: field_file_size diff --git a/modules/islandora_core_feature/config/install/media.type.file.yml b/modules/islandora_core_feature/config/install/media.type.file.yml new file mode 100644 index 00000000..319485ca --- /dev/null +++ b/modules/islandora_core_feature/config/install/media.type.file.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature +id: file +label: File +description: 'Use local files for reusable media.' +source: file +queue_thumbnail_downloads: false +new_revision: true +source_configuration: + source_field: field_media_file +field_map: + mimetype: field_mime_type + filesize: field_file_size diff --git a/modules/islandora_core_feature/config/install/media.type.image.yml b/modules/islandora_core_feature/config/install/media.type.image.yml new file mode 100644 index 00000000..790835b6 --- /dev/null +++ b/modules/islandora_core_feature/config/install/media.type.image.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature +id: image +label: Image +description: 'Use local images for reusable media.' +source: image +queue_thumbnail_downloads: false +new_revision: true +source_configuration: + source_field: field_media_image +field_map: + mimetype: field_mime_type + filesize: field_file_size + width: field_width + height: field_height diff --git a/modules/islandora_core_feature/config/install/media.type.video.yml b/modules/islandora_core_feature/config/install/media.type.video.yml new file mode 100644 index 00000000..fd127305 --- /dev/null +++ b/modules/islandora_core_feature/config/install/media.type.video.yml @@ -0,0 +1,17 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature +id: video +label: Video +description: 'A locally hosted video file.' +source: video_file +queue_thumbnail_downloads: false +new_revision: true +source_configuration: + source_field: field_media_video_file +field_map: + mimetype: field_mime_type + filesize: field_file_size diff --git a/modules/islandora_core_feature/config/install/migrate_plus.migration.islandora_tags.yml b/modules/islandora_core_feature/config/install/migrate_plus.migration.islandora_tags.yml new file mode 100644 index 00000000..45267408 --- /dev/null +++ b/modules/islandora_core_feature/config/install/migrate_plus.migration.islandora_tags.yml @@ -0,0 +1,31 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature +id: islandora_tags +class: null +field_plugin_method: null +cck_plugin_method: null +migration_tags: islandora_tags +migration_group: islandora +label: 'Tags migration from CSV' +source: + plugin: csv + path: /var/www/html/drupal/web/modules/contrib/islandora/migrate/tags.csv + header_row_count: 1 + keys: + - external_uri +process: + name: name + vid: vid + description: description + field_external_uri: + plugin: urlencode + source: external_uri +destination: + plugin: 'entity:taxonomy_term' +migration_dependencies: + required: { } + optional: { } diff --git a/modules/islandora_core_feature/config/install/migrate_plus.migration_group.islandora.yml b/modules/islandora_core_feature/config/install/migrate_plus.migration_group.islandora.yml new file mode 100644 index 00000000..69b8503c --- /dev/null +++ b/modules/islandora_core_feature/config/install/migrate_plus.migration_group.islandora.yml @@ -0,0 +1,12 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature +id: islandora +label: Islandora +description: 'Migrations into Islandora' +source_type: Anything +module: null +shared_configuration: null diff --git a/modules/islandora_core_feature/config/install/rdf.mapping.media.audio.yml b/modules/islandora_core_feature/config/install/rdf.mapping.media.audio.yml new file mode 100644 index 00000000..6fb8df40 --- /dev/null +++ b/modules/islandora_core_feature/config/install/rdf.mapping.media.audio.yml @@ -0,0 +1,45 @@ +langcode: en +status: true +dependencies: + config: + - media.type.audio + enforced: + module: + - islandora_core_feature + module: + - media +id: media.audio +targetEntityType: media +bundle: audio +types: + - 'pcdm:File' +fieldMappings: + name: + properties: + - 'dc:title' + - 'rdf:label' + created: + properties: + - 'schema:dateCreated' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + changed: + properties: + - 'schema:dateModified' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + uid: + properties: + - 'schema:author' + mapping_type: rel + field_mime_type: + properties: + - 'ebucore:hasMimeType' + field_media_of: + properties: + - 'pcdm:fileOf' + mapping_type: rel + field_tags: + properties: + - 'schema:additionalType' + mapping_type: rel diff --git a/config/install/rdf.mapping.media.tn.yml b/modules/islandora_core_feature/config/install/rdf.mapping.media.file.yml similarity index 67% rename from config/install/rdf.mapping.media.tn.yml rename to modules/islandora_core_feature/config/install/rdf.mapping.media.file.yml index f65e03da..e298c2db 100644 --- a/config/install/rdf.mapping.media.tn.yml +++ b/modules/islandora_core_feature/config/install/rdf.mapping.media.file.yml @@ -1,21 +1,18 @@ -uuid: 77e9e71f-f67f-438f-80eb-bb5fa931a5ec langcode: en status: true dependencies: config: - - media_entity.bundle.tn + - media.type.file enforced: module: - - islandora + - islandora_core_feature module: - - media_entity -_core: - default_config_hash: 6L5MoXE-kIJb53NSl9cSQBFoyZNG1DWL8CFOSV60yMk -id: media.tn + - media +id: media.file targetEntityType: media -bundle: tn +bundle: file types: - - 'use:ThumbnailImage' + - 'pcdm:File' fieldMappings: name: properties: @@ -35,6 +32,14 @@ fieldMappings: properties: - 'schema:author' mapping_type: rel - field_mimetype: + field_mime_type: properties: - 'ebucore:hasMimeType' + field_media_of: + properties: + - 'pcdm:fileOf' + mapping_type: rel + field_tags: + properties: + - 'schema:additionalType' + mapping_type: rel diff --git a/modules/islandora_core_feature/config/install/rdf.mapping.media.image.yml b/modules/islandora_core_feature/config/install/rdf.mapping.media.image.yml new file mode 100644 index 00000000..3cc7a2ee --- /dev/null +++ b/modules/islandora_core_feature/config/install/rdf.mapping.media.image.yml @@ -0,0 +1,51 @@ +langcode: en +status: true +dependencies: + config: + - media.type.image + enforced: + module: + - islandora_core_feature + module: + - media +id: media.image +targetEntityType: media +bundle: image +types: + - 'pcdm:File' +fieldMappings: + name: + properties: + - 'dc:title' + - 'rdf:label' + created: + properties: + - 'schema:dateCreated' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + changed: + properties: + - 'schema:dateModified' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + uid: + properties: + - 'schema:author' + mapping_type: rel + field_mime_type: + properties: + - 'ebucore:hasMimeType' + field_media_of: + properties: + - 'pcdm:fileOf' + mapping_type: rel + field_tags: + properties: + - 'schema:additionalType' + mapping_type: rel + field_width: + properties: + - 'ebucore:width' + field_height: + properties: + - 'ebucore:height' diff --git a/modules/islandora_core_feature/config/install/rdf.mapping.media.video.yml b/modules/islandora_core_feature/config/install/rdf.mapping.media.video.yml new file mode 100644 index 00000000..c70bc50d --- /dev/null +++ b/modules/islandora_core_feature/config/install/rdf.mapping.media.video.yml @@ -0,0 +1,45 @@ +langcode: en +status: true +dependencies: + config: + - media.type.video + enforced: + module: + - islandora_core_feature + module: + - media +id: media.video +targetEntityType: media +bundle: video +types: + - 'pcdm:File' +fieldMappings: + name: + properties: + - 'dc:title' + - 'rdf:label' + created: + properties: + - 'schema:dateCreated' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + changed: + properties: + - 'schema:dateModified' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + uid: + properties: + - 'schema:author' + mapping_type: rel + field_mime_type: + properties: + - 'ebucore:hasMimeType' + field_media_of: + properties: + - 'pcdm:fileOf' + mapping_type: rel + field_tags: + properties: + - 'schema:additionalType' + mapping_type: rel diff --git a/modules/islandora_core_feature/config/install/rdf.mapping.taxonomy_term.tags.yml b/modules/islandora_core_feature/config/install/rdf.mapping.taxonomy_term.tags.yml new file mode 100644 index 00000000..0e07aad3 --- /dev/null +++ b/modules/islandora_core_feature/config/install/rdf.mapping.taxonomy_term.tags.yml @@ -0,0 +1,30 @@ +langcode: en +status: true +dependencies: + config: + - taxonomy.vocabulary.tags + enforced: + module: + - islandora_core_feature + module: + - taxonomy +id: taxonomy_term.tags +targetEntityType: taxonomy_term +bundle: tags +types: + - 'schema:Thing' +fieldMappings: + name: + properties: + - 'dc:title' + description: + properties: + - 'dc:description' + field_external_uri: + properties: + - 'owl:sameAs' + changed: + properties: + - 'schema:dateModified' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' diff --git a/modules/islandora_core_feature/config/install/rest.resource.entity.file.yml b/modules/islandora_core_feature/config/install/rest.resource.entity.file.yml new file mode 100644 index 00000000..d0a581ee --- /dev/null +++ b/modules/islandora_core_feature/config/install/rest.resource.entity.file.yml @@ -0,0 +1,46 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - basic_auth + - file + - jsonld + - jwt + - serialization + - user +id: entity.file +plugin_id: 'entity:file' +granularity: method +configuration: + GET: + supported_formats: + - jsonld + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + POST: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + DELETE: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + PATCH: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie diff --git a/modules/islandora_core_feature/config/install/rest.resource.entity.media.yml b/modules/islandora_core_feature/config/install/rest.resource.entity.media.yml new file mode 100644 index 00000000..3de126ac --- /dev/null +++ b/modules/islandora_core_feature/config/install/rest.resource.entity.media.yml @@ -0,0 +1,46 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - basic_auth + - jsonld + - jwt + - media + - serialization + - user +id: entity.media +plugin_id: 'entity:media' +granularity: method +configuration: + GET: + supported_formats: + - jsonld + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + POST: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + DELETE: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + PATCH: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie diff --git a/modules/islandora_core_feature/config/install/rest.resource.entity.node.yml b/modules/islandora_core_feature/config/install/rest.resource.entity.node.yml new file mode 100644 index 00000000..c3207255 --- /dev/null +++ b/modules/islandora_core_feature/config/install/rest.resource.entity.node.yml @@ -0,0 +1,46 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - basic_auth + - jsonld + - jwt + - node + - serialization + - user +id: entity.node +plugin_id: 'entity:node' +granularity: method +configuration: + GET: + supported_formats: + - jsonld + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + POST: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + DELETE: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + PATCH: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie diff --git a/modules/islandora_core_feature/config/install/rest.resource.entity.taxonomy_term.yml b/modules/islandora_core_feature/config/install/rest.resource.entity.taxonomy_term.yml new file mode 100644 index 00000000..871d2bab --- /dev/null +++ b/modules/islandora_core_feature/config/install/rest.resource.entity.taxonomy_term.yml @@ -0,0 +1,46 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - basic_auth + - jsonld + - jwt + - serialization + - taxonomy + - user +id: entity.taxonomy_term +plugin_id: 'entity:taxonomy_term' +granularity: method +configuration: + GET: + supported_formats: + - jsonld + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + POST: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + DELETE: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie + PATCH: + supported_formats: + - json + supported_auth: + - basic_auth + - jwt_auth + - cookie diff --git a/config/install/system.action.delete_file_from_fedora.yml b/modules/islandora_core_feature/config/install/system.action.delete_file_from_fedora.yml similarity index 67% rename from config/install/system.action.delete_file_from_fedora.yml rename to modules/islandora_core_feature/config/install/system.action.delete_file_from_fedora.yml index ee61cf04..6fba1ee0 100644 --- a/config/install/system.action.delete_file_from_fedora.yml +++ b/modules/islandora_core_feature/config/install/system.action.delete_file_from_fedora.yml @@ -1,16 +1,15 @@ -uuid: 76d619dd-54f1-4047-8e89-54d5f1a7c16a langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: delete_file_from_fedora label: 'Delete File from Fedora' type: file plugin: emit_file_event configuration: - queue: 'islandora-indexing-fcrepo-delete' + queue: islandora-indexing-fcrepo-delete event: delete diff --git a/config/install/system.action.delete_media_from_triplestore.yml b/modules/islandora_core_feature/config/install/system.action.delete_media_from_triplestore.yml similarity index 67% rename from config/install/system.action.delete_media_from_triplestore.yml rename to modules/islandora_core_feature/config/install/system.action.delete_media_from_triplestore.yml index 3a67fe15..20e1d7d5 100644 --- a/config/install/system.action.delete_media_from_triplestore.yml +++ b/modules/islandora_core_feature/config/install/system.action.delete_media_from_triplestore.yml @@ -1,16 +1,15 @@ -uuid: a5f0a427-9c30-41ec-92b8-04b47855aee1 langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: delete_media_from_triplestore label: 'Delete Media from Triplestore' type: media plugin: emit_media_event configuration: - queue: 'islandora-indexing-triplestore-delete' + queue: islandora-indexing-triplestore-delete event: delete diff --git a/config/install/system.action.delete_node_from_fedora.yml b/modules/islandora_core_feature/config/install/system.action.delete_node_from_fedora.yml similarity index 67% rename from config/install/system.action.delete_node_from_fedora.yml rename to modules/islandora_core_feature/config/install/system.action.delete_node_from_fedora.yml index ed1d891a..0c91ce4d 100644 --- a/config/install/system.action.delete_node_from_fedora.yml +++ b/modules/islandora_core_feature/config/install/system.action.delete_node_from_fedora.yml @@ -1,16 +1,15 @@ -uuid: 23ad55f4-301b-4ffb-b542-4cf2c0c291d8 langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: delete_node_from_fedora label: 'Delete Node from Fedora' type: node plugin: emit_node_event configuration: - queue: 'islandora-indexing-fcrepo-delete' + queue: islandora-indexing-fcrepo-delete event: delete diff --git a/config/install/system.action.delete_node_from_triplestore.yml b/modules/islandora_core_feature/config/install/system.action.delete_node_from_triplestore.yml similarity index 67% rename from config/install/system.action.delete_node_from_triplestore.yml rename to modules/islandora_core_feature/config/install/system.action.delete_node_from_triplestore.yml index 4fc9bae0..8b16cf3b 100644 --- a/config/install/system.action.delete_node_from_triplestore.yml +++ b/modules/islandora_core_feature/config/install/system.action.delete_node_from_triplestore.yml @@ -1,16 +1,15 @@ -uuid: 4340c20a-d314-4cbf-a26f-c36d7180ede5 langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: delete_node_from_triplestore label: 'Delete Node from Triplestore' type: node plugin: emit_node_event configuration: - queue: 'islandora-indexing-triplestore-delete' + queue: islandora-indexing-triplestore-delete event: delete diff --git a/modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_fedora.yml b/modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_fedora.yml new file mode 100644 index 00000000..951d7891 --- /dev/null +++ b/modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_fedora.yml @@ -0,0 +1,15 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - islandora +id: delete_taxonomy_term_in_fedora +label: 'Delete Taxonomy Term in Fedora' +type: taxonomy_term +plugin: emit_term_event +configuration: + queue: islandora-indexing-fcrepo-delete + event: Delete diff --git a/modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_triplestore.yml b/modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_triplestore.yml new file mode 100644 index 00000000..54261998 --- /dev/null +++ b/modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_triplestore.yml @@ -0,0 +1,15 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - islandora +id: delete_taxonomy_term_in_triplestore +label: 'Delete Taxonomy Term in Triplestore' +type: taxonomy_term +plugin: emit_term_event +configuration: + queue: islandora-indexing-triplestore-delete + event: Delete diff --git a/config/install/system.action.index_file_in_fedora.yml b/modules/islandora_core_feature/config/install/system.action.index_file_in_fedora.yml similarity index 67% rename from config/install/system.action.index_file_in_fedora.yml rename to modules/islandora_core_feature/config/install/system.action.index_file_in_fedora.yml index d1c98111..6dba92f5 100644 --- a/config/install/system.action.index_file_in_fedora.yml +++ b/modules/islandora_core_feature/config/install/system.action.index_file_in_fedora.yml @@ -1,16 +1,15 @@ -uuid: 526d2857-de6f-472d-87e2-d8726db72301 langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: index_file_in_fedora label: 'Index File in Fedora' type: file plugin: emit_file_event configuration: - queue: 'islandora-indexing-fcrepo-file' + queue: islandora-indexing-fcrepo-file event: update diff --git a/config/install/system.action.index_media_in_fedora.yml b/modules/islandora_core_feature/config/install/system.action.index_media_in_fedora.yml similarity index 68% rename from config/install/system.action.index_media_in_fedora.yml rename to modules/islandora_core_feature/config/install/system.action.index_media_in_fedora.yml index 7cd560d2..ff26adbd 100644 --- a/config/install/system.action.index_media_in_fedora.yml +++ b/modules/islandora_core_feature/config/install/system.action.index_media_in_fedora.yml @@ -1,16 +1,15 @@ -d: 27ce85fc-a9fe-46f5-b518-5af1126e2368 langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: index_media_in_fedora label: 'Index Media in Fedora' type: media plugin: emit_media_event configuration: - queue: 'islandora-indexing-fcrepo-media' + queue: islandora-indexing-fcrepo-media event: update diff --git a/config/install/system.action.index_media_in_triplestore.yml b/modules/islandora_core_feature/config/install/system.action.index_media_in_triplestore.yml similarity index 67% rename from config/install/system.action.index_media_in_triplestore.yml rename to modules/islandora_core_feature/config/install/system.action.index_media_in_triplestore.yml index 2c7737b4..6146a892 100644 --- a/config/install/system.action.index_media_in_triplestore.yml +++ b/modules/islandora_core_feature/config/install/system.action.index_media_in_triplestore.yml @@ -1,16 +1,15 @@ -uuid: f7c9169d-6556-4720-b225-11a09581272e langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: index_media_in_triplestore label: 'Index Media in Triplestore' type: media plugin: emit_media_event configuration: - queue: 'islandora-indexing-triplestore-index' + queue: islandora-indexing-triplestore-index event: update diff --git a/config/install/system.action.index_node_in_fedora.yml b/modules/islandora_core_feature/config/install/system.action.index_node_in_fedora.yml similarity index 66% rename from config/install/system.action.index_node_in_fedora.yml rename to modules/islandora_core_feature/config/install/system.action.index_node_in_fedora.yml index 9dbdf592..9b359035 100644 --- a/config/install/system.action.index_node_in_fedora.yml +++ b/modules/islandora_core_feature/config/install/system.action.index_node_in_fedora.yml @@ -1,16 +1,15 @@ -uuid: edb74080-7cf3-45e7-97e2-78cd7494ea92 langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: index_node_in_fedora label: 'Index Node in Fedora' type: node plugin: emit_node_event configuration: - queue: 'islandora-indexing-fcrepo-content' + queue: islandora-indexing-fcrepo-content event: update diff --git a/config/install/system.action.index_node_in_triplestore.yml b/modules/islandora_core_feature/config/install/system.action.index_node_in_triplestore.yml similarity index 66% rename from config/install/system.action.index_node_in_triplestore.yml rename to modules/islandora_core_feature/config/install/system.action.index_node_in_triplestore.yml index c604b3fe..ba194f51 100644 --- a/config/install/system.action.index_node_in_triplestore.yml +++ b/modules/islandora_core_feature/config/install/system.action.index_node_in_triplestore.yml @@ -1,16 +1,15 @@ -uuid: 5012a177-307c-4ee0-a986-cd35d76f2a58 langcode: en status: true dependencies: - module: - - islandora enforced: module: - - islandora + - islandora_core_feature + module: + - islandora id: index_node_in_triplestore label: 'Index Node in Triplestore' type: node plugin: emit_node_event configuration: - queue: 'islandora-indexing-triplestore-index' + queue: islandora-indexing-triplestore-index event: update diff --git a/modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_fedora.yml b/modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_fedora.yml new file mode 100644 index 00000000..2181bcd6 --- /dev/null +++ b/modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_fedora.yml @@ -0,0 +1,15 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - islandora +id: index_taxonomy_term_in_fedora +label: 'Index taxonomy term in Fedora' +type: taxonomy_term +plugin: emit_term_event +configuration: + queue: islandora-indexing-fcrepo-content + event: Update diff --git a/modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_the_triplestore.yml b/modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_the_triplestore.yml new file mode 100644 index 00000000..06593346 --- /dev/null +++ b/modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_the_triplestore.yml @@ -0,0 +1,15 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - islandora +id: index_taxonomy_term_in_the_triplestore +label: 'Index Taxonomy Term in the Triplestore' +type: taxonomy_term +plugin: emit_term_event +configuration: + queue: islandora-indexing-triplestore-index + event: Update diff --git a/modules/islandora_core_feature/config/install/taxonomy.vocabulary.tags.yml b/modules/islandora_core_feature/config/install/taxonomy.vocabulary.tags.yml new file mode 100644 index 00000000..92aa1809 --- /dev/null +++ b/modules/islandora_core_feature/config/install/taxonomy.vocabulary.tags.yml @@ -0,0 +1,11 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature +name: Tags +vid: tags +description: 'Use tags to group articles on similar topics into categories.' +hierarchy: 0 +weight: 0 diff --git a/modules/islandora_core_feature/config/install/views.view.display_media.yml b/modules/islandora_core_feature/config/install/views.view.display_media.yml new file mode 100644 index 00000000..defa1c45 --- /dev/null +++ b/modules/islandora_core_feature/config/install/views.view.display_media.yml @@ -0,0 +1,422 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.source + enforced: + module: + - islandora_core_feature + module: + - eva + - media + - taxonomy + - user +id: display_media +label: 'Media EVAs' +module: views +description: 'Displays media for content as EVA''s per model.' +tag: '' +base_table: media_field_data +base_field: mid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'view media' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: some + options: + items_per_page: 1 + offset: 0 + style: + type: default + options: + row_class: '' + default_row_class: true + uses_fields: false + row: + type: 'entity:media' + options: + relationship: none + view_mode: source + fields: + name: + id: name + table: media_field_data + field: name + entity_type: media + entity_field: media + label: '' + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + settings: + link_to_entity: true + plugin_id: field + relationship: none + group_type: group + admin_label: '' + exclude: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_alter_empty: true + click_sort_column: value + type: string + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + filters: + status: + value: '1' + table: media_field_data + field: status + plugin_id: boolean + entity_type: media + entity_field: status + id: status + expose: + operator: '' + group: 1 + sorts: { } + title: '' + header: { } + footer: { } + empty: { } + relationships: + field_tags: + id: field_tags + table: media__field_tags + field: field_tags + relationship: none + group_type: group + admin_label: 'field_tags: Taxonomy term' + required: false + plugin_id: standard + arguments: + field_media_of_target_id: + id: field_media_of_target_id + table: media__field_media_of + field: field_media_of_target_id + relationship: none + group_type: group + admin_label: '' + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: node + default_argument_options: { } + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: false + validate: + type: none + fail: 'not found' + validate_options: { } + break_phrase: false + not: false + plugin_id: numeric + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - user.permissions + tags: { } + entity_view_1: + display_plugin: entity_view + id: entity_view_1 + display_title: 'Preservation Master - Download' + position: 1 + display_options: + display_extenders: { } + display_description: 'Best quality representation of the Object appropriate for long-term preservation.' + filters: + status: + value: '1' + table: media_field_data + field: status + plugin_id: boolean + entity_type: media + entity_field: status + id: status + expose: + operator: '' + group: 1 + field_external_uri_uri: + id: field_external_uri_uri + table: taxonomy_term__field_external_uri + field: field_external_uri_uri + relationship: field_tags + group_type: group + admin_label: '' + operator: '=' + value: 'http://pcdm.org/use#PreservationMasterFile' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: string + defaults: + filters: false + filter_groups: false + filter_groups: + operator: AND + groups: + 1: AND + entity_type: node + bundles: + - islandora_object + argument_mode: id + default_argument: null + title: 'Preservation Master' + show_title: false + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - user.permissions + tags: { } + service_file: + display_plugin: entity_view + id: service_file + display_title: 'Service File' + position: 1 + display_options: + display_extenders: { } + display_description: 'A medium quality representation of the Object appropriate for serving to users.' + filters: + status: + value: '1' + table: media_field_data + field: status + plugin_id: boolean + entity_type: media + entity_field: status + id: status + expose: + operator: '' + group: 1 + field_external_uri_uri: + id: field_external_uri_uri + table: taxonomy_term__field_external_uri + field: field_external_uri_uri + relationship: field_tags + group_type: group + admin_label: '' + operator: '=' + value: 'http://pcdm.org/use#ServiceFile' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: string + defaults: + filters: false + filter_groups: false + title: false + filter_groups: + operator: AND + groups: + 1: AND + entity_type: node + bundles: + - islandora_object + title: 'Service File' + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - user.permissions + tags: { } + thumbnail: + display_plugin: entity_view + id: thumbnail + display_title: Thumbnail + position: 1 + display_options: + display_extenders: { } + display_description: 'A low resolution image representation of the Object appropriate for using as an icon.' + filters: + status: + value: '1' + table: media_field_data + field: status + plugin_id: boolean + entity_type: media + entity_field: status + id: status + expose: + operator: '' + group: 1 + field_external_uri_uri: + id: field_external_uri_uri + table: taxonomy_term__field_external_uri + field: field_external_uri_uri + relationship: field_tags + group_type: group + admin_label: '' + operator: '=' + value: 'http://pcdm.org/use#ThumbnailImage' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: string + defaults: + filters: false + filter_groups: false + title: false + filter_groups: + operator: AND + groups: + 1: AND + entity_type: node + bundles: + - islandora_object + title: Thumbnail + show_title: false + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - user.permissions + tags: { } diff --git a/config/install/views.view.file_checksum.yml b/modules/islandora_core_feature/config/install/views.view.file_checksum.yml similarity index 96% rename from config/install/views.view.file_checksum.yml rename to modules/islandora_core_feature/config/install/views.view.file_checksum.yml index a3091a17..53533b2d 100644 --- a/config/install/views.view.file_checksum.yml +++ b/modules/islandora_core_feature/config/install/views.view.file_checksum.yml @@ -1,19 +1,13 @@ -uuid: cd3f8b61-8032-4c3d-9de3-624b298c9bca langcode: en status: true dependencies: + enforced: + module: + - islandora_core_feature module: - - basic_auth - file - - jwt - rest - serialization - - user - enforced: - module: - - islandora -_core: - default_config_hash: e7XqQa-N16XDqeDTA7Ohgx6iLb6mIQ1RUs0krFFIbAw id: file_checksum label: 'File Checksum' module: views diff --git a/modules/islandora_core_feature/config/install/views.view.manage_members.yml b/modules/islandora_core_feature/config/install/views.view.manage_members.yml new file mode 100644 index 00000000..68208b04 --- /dev/null +++ b/modules/islandora_core_feature/config/install/views.view.manage_members.yml @@ -0,0 +1,342 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_core_feature + module: + - jsonld + - node + - rest + - serialization + - user +id: manage_members +label: 'Manage members' +module: views +description: 'Manage members belonging to a piece of content' +tag: '' +base_table: node_field_data +base_field: nid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'manage members' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: mini + options: + items_per_page: 10 + offset: 0 + id: 0 + total_pages: null + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + tags: + previous: ‹‹ + next: ›› + style: + type: table + row: + type: fields + fields: + node_bulk_form: + id: node_bulk_form + table: node + field: node_bulk_form + relationship: none + group_type: group + admin_label: '' + label: 'Node operations bulk form' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + action_title: Action + include_exclude: exclude + selected_actions: { } + entity_type: node + plugin_id: node_bulk_form + title: + id: title + table: node_field_data + field: title + entity_type: node + entity_field: title + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + settings: + link_to_entity: true + plugin_id: field + relationship: none + group_type: group + admin_label: '' + label: Title + exclude: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_alter_empty: true + click_sort_column: value + type: string + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + operations: + id: operations + table: node + field: operations + relationship: none + group_type: group + admin_label: '' + label: 'Operations links' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + destination: false + entity_type: node + plugin_id: entity_operations + filters: { } + sorts: { } + title: 'Manage members' + header: { } + footer: { } + empty: { } + relationships: { } + arguments: + field_member_of_target_id: + id: field_member_of_target_id + table: node__field_member_of + field: field_member_of_target_id + relationship: none + group_type: group + admin_label: '' + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: node + default_argument_options: { } + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: 'entity:node' + fail: 'not found' + validate_options: + operation: view + multiple: 0 + bundles: { } + access: false + break_phrase: false + not: false + plugin_id: numeric + display_extenders: { } + filter_groups: + operator: AND + groups: { } + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: 1 + display_options: + display_extenders: { } + path: node/%node/members + menu: + type: tab + title: Members + description: '' + expanded: false + parent: '' + weight: 0 + context: '0' + menu_name: main + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + rest_export_1: + display_plugin: rest_export + id: rest_export_1 + display_title: 'REST export' + position: 1 + display_options: + display_extenders: { } + path: node/%node/members + style: + type: serializer + options: + uses_fields: false + formats: + jsonld: jsonld + json: json + auth: + - basic_auth + - jwt_auth + - cookie + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - request_format + - url + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/modules/islandora_core_feature/config/install/views.view.media_of.yml b/modules/islandora_core_feature/config/install/views.view.media_of.yml new file mode 100644 index 00000000..8d92e16b --- /dev/null +++ b/modules/islandora_core_feature/config/install/views.view.media_of.yml @@ -0,0 +1,1235 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.media.field_mime_type + - field.storage.media.field_tags + enforced: + module: + - islandora_core_feature + module: + - jsonld + - media + - rest + - serialization + - user +id: media_of +label: 'Manage media' +module: views +description: 'Manage media belonging to a piece of content' +tag: '' +base_table: media_field_data +base_field: mid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'manage media' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: mini + options: + items_per_page: 10 + offset: 0 + id: 0 + total_pages: null + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + tags: + previous: ‹‹ + next: ›› + style: + type: table + options: + grouping: { } + row_class: '' + default_row_class: true + override: true + sticky: false + caption: '' + summary: '' + description: '' + columns: + media_bulk_form: media_bulk_form + name: name + bundle: bundle + field_media_model: field_media_model + field_mime_type: field_mime_type + changed: changed + operations: operations + info: + media_bulk_form: + align: '' + separator: '' + empty_column: false + responsive: '' + name: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + bundle: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + field_media_model: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + field_mime_type: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + changed: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + operations: + align: '' + separator: '' + empty_column: false + responsive: '' + default: field_media_model + empty_table: false + row: + type: fields + options: + default_field_elements: true + inline: { } + separator: '' + hide_empty: false + fields: + name: + id: name + table: media_field_data + field: name + relationship: none + group_type: group + admin_label: '' + label: Name + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: false + ellipsis: false + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: media + plugin_id: field + bundle: + id: bundle + table: media_field_data + field: bundle + relationship: none + group_type: group + admin_label: '' + label: 'Media type' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: target_id + type: entity_reference_label + settings: + link: true + group_column: target_id + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: bundle + plugin_id: field + field_mime_type: + id: field_mime_type + table: media__field_mime_type + field: field_mime_type + relationship: none + group_type: group + admin_label: '' + label: 'MIME type' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + plugin_id: field + changed: + id: changed + table: media_field_data + field: changed + relationship: none + group_type: group + admin_label: '' + label: Changed + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: timestamp + settings: + date_format: medium + custom_date_format: '' + timezone: '' + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: changed + plugin_id: field + media_bulk_form: + id: media_bulk_form + table: media + field: media_bulk_form + entity_type: media + plugin_id: bulk_form + operations: + id: operations + table: media + field: operations + entity_type: media + plugin_id: entity_operations + filters: { } + sorts: { } + title: 'Manage Media' + header: { } + footer: { } + empty: { } + relationships: { } + arguments: + field_media_of_target_id: + id: field_media_of_target_id + table: media__field_media_of + field: field_media_of_target_id + relationship: none + group_type: group + admin_label: '' + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: node + default_argument_options: { } + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: true + validate: + type: 'entity:node' + fail: 'not found' + validate_options: + operation: view + multiple: 0 + bundles: { } + access: false + break_phrase: false + not: false + plugin_id: numeric + display_extenders: { } + filter_groups: + operator: AND + groups: { } + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - user.permissions + tags: + - 'config:field.storage.media.field_mime_type' + - extensions + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: 1 + display_options: + display_extenders: { } + path: node/%node/media + menu: + type: tab + title: Media + description: 'Lists all media belonging to this content' + expanded: false + parent: '' + weight: 0 + context: '0' + menu_name: main + fields: + media_bulk_form: + id: media_bulk_form + table: media + field: media_bulk_form + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + action_title: Action + include_exclude: exclude + selected_actions: { } + entity_type: media + plugin_id: bulk_form + name: + id: name + table: media_field_data + field: name + relationship: none + group_type: group + admin_label: '' + label: Name + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: false + ellipsis: false + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: media + plugin_id: field + bundle: + id: bundle + table: media_field_data + field: bundle + relationship: none + group_type: group + admin_label: '' + label: 'Media type' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: target_id + type: entity_reference_label + settings: + link: true + group_column: target_id + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: bundle + plugin_id: field + field_mime_type: + id: field_mime_type + table: media__field_mime_type + field: field_mime_type + relationship: none + group_type: group + admin_label: '' + label: 'MIME type' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + plugin_id: field + field_tags: + id: field_tags + table: media__field_tags + field: field_tags + relationship: none + group_type: group + admin_label: '' + label: Tags + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: target_id + type: entity_reference_label + settings: + link: true + group_column: target_id + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + plugin_id: field + changed: + id: changed + table: media_field_data + field: changed + relationship: none + group_type: group + admin_label: '' + label: Changed + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: timestamp + settings: + date_format: medium + custom_date_format: '' + timezone: '' + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: changed + plugin_id: field + operations: + id: operations + table: media + field: operations + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + destination: false + entity_type: media + plugin_id: entity_operations + defaults: + fields: false + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - user.permissions + tags: + - 'config:field.storage.media.field_mime_type' + - 'config:field.storage.media.field_tags' + - extensions + rest_export_1: + display_plugin: rest_export + id: rest_export_1 + display_title: 'REST export' + position: 1 + display_options: + display_extenders: { } + path: node/%node/media + auth: + - basic_auth + - jwt_auth + - cookie + style: + type: serializer + options: + uses_fields: false + formats: + jsonld: jsonld + json: json + row: + type: data_entity + options: { } + fields: + name: + id: name + table: media_field_data + field: name + relationship: none + group_type: group + admin_label: '' + label: Name + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: false + ellipsis: false + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: media + plugin_id: field + bundle: + id: bundle + table: media_field_data + field: bundle + relationship: none + group_type: group + admin_label: '' + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: target_id + type: entity_reference_entity_id + settings: { } + group_column: target_id + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: bundle + plugin_id: field + field_mime_type: + id: field_mime_type + table: media__field_mime_type + field: field_mime_type + relationship: none + group_type: group + admin_label: '' + label: 'MIME type' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + plugin_id: field + changed: + id: changed + table: media_field_data + field: changed + relationship: none + group_type: group + admin_label: '' + label: Changed + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: timestamp + settings: + date_format: medium + custom_date_format: '' + timezone: '' + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: media + entity_field: changed + plugin_id: field + defaults: + fields: false + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - request_format + - url + - user.permissions + tags: + - 'config:field.storage.media.field_mime_type' + - extensions diff --git a/modules/islandora_core_feature/config/install/views.view.members.yml b/modules/islandora_core_feature/config/install/views.view.members.yml new file mode 100644 index 00000000..ae7a0d0a --- /dev/null +++ b/modules/islandora_core_feature/config/install/views.view.members.yml @@ -0,0 +1,255 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + enforced: + module: + - islandora_core_feature + module: + - node + - user +id: members +label: Members +module: views +description: 'Displays members for content.' +tag: '' +base_table: node_field_data +base_field: nid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: mini + options: + items_per_page: 10 + offset: 0 + id: 0 + total_pages: null + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + tags: + previous: ‹‹ + next: ›› + style: + type: default + options: + grouping: { } + row_class: '' + default_row_class: true + uses_fields: false + row: + type: 'entity:node' + options: + relationship: none + view_mode: teaser + fields: + title: + id: title + table: node_field_data + field: title + entity_type: node + entity_field: title + label: '' + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + settings: + link_to_entity: true + plugin_id: field + relationship: none + group_type: group + admin_label: '' + exclude: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_alter_empty: true + click_sort_column: value + type: string + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + filters: + status: + id: status + table: node_field_data + field: status + relationship: none + group_type: group + admin_label: '' + operator: '=' + value: '1' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + entity_type: node + entity_field: status + plugin_id: boolean + sorts: + created: + id: created + table: node_field_data + field: created + order: DESC + entity_type: node + entity_field: created + plugin_id: date + relationship: none + group_type: group + admin_label: '' + exposed: false + expose: + label: '' + granularity: second + header: { } + footer: { } + empty: { } + relationships: { } + arguments: + field_member_of_target_id: + id: field_member_of_target_id + table: node__field_member_of + field: field_member_of_target_id + relationship: none + group_type: group + admin_label: '' + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: node + default_argument_options: { } + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: false + validate: + type: none + fail: 'not found' + validate_options: { } + break_phrase: false + not: false + plugin_id: numeric + display_extenders: { } + filter_groups: + operator: AND + groups: { } + title: Members + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + block_1: + display_plugin: block + id: block_1 + display_title: Block + position: 2 + display_options: + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/modules/islandora_core_feature/islandora_core_feature.features.yml b/modules/islandora_core_feature/islandora_core_feature.features.yml new file mode 100644 index 00000000..9e48e9fd --- /dev/null +++ b/modules/islandora_core_feature/islandora_core_feature.features.yml @@ -0,0 +1,2 @@ +bundle: islandora +required: true diff --git a/modules/islandora_core_feature/islandora_core_feature.info.yml b/modules/islandora_core_feature/islandora_core_feature.info.yml new file mode 100644 index 00000000..74f34e34 --- /dev/null +++ b/modules/islandora_core_feature/islandora_core_feature.info.yml @@ -0,0 +1,26 @@ +name: 'Islandora Core Feature' +description: 'Minimum configuration required for Islandora.' +type: module +core: 8.x +dependencies: + - basic_auth + - eva + - features + - field + - file + - image + - islandora + - jsonld + - jwt + - link + - media + - migrate_plus + - node + - rdf + - rest + - serialization + - system + - taxonomy + - user + - views +package: Islandora diff --git a/modules/islandora_demo_feature/config/install/context.context.binary.yml b/modules/islandora_demo_feature/config/install/context.context.binary.yml new file mode 100644 index 00000000..df2d3f8a --- /dev/null +++ b/modules/islandora_demo_feature/config/install/context.context.binary.yml @@ -0,0 +1,31 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - islandora +name: binary +label: Binary +group: Islandora +description: 'Islandora binary objects' +requireAllConditions: false +disabled: false +conditions: + node_has_term: + id: node_has_term + negate: 0 + uuid: f84aa317-a681-4a1e-8a40-2fe2b6868ea8 + tids: + - + target_id: '5' + context_mapping: + node: '@node.node_route_context:node' + uri: 'http://purl.org/coar/resource_type/c_1843' +reactions: + view_mode_alter: + id: view_mode_alter + mode: node.binary + saved: false +weight: 0 diff --git a/modules/islandora_demo_feature/config/install/context.context.collection.yml b/modules/islandora_demo_feature/config/install/context.context.collection.yml new file mode 100644 index 00000000..2b4bf3d5 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/context.context.collection.yml @@ -0,0 +1,49 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - islandora +name: collection +label: Collection +group: Islandora +description: 'Islandora collections' +requireAllConditions: false +disabled: false +conditions: + node_has_term: + id: node_has_term + negate: 0 + uuid: 01ba2d2f-b966-4f40-bd9e-7cfc6e9f2522 + tid: '18' + context_mapping: + node: '@node.node_route_context:node' + tids: + - + target_id: '32' + uri: 'http://purl.org/dc/dcmitype/Collection' +reactions: + blocks: + blocks: + 83d50c24-adbb-4b7b-8b1c-6b9127bd084f: + id: 'views_block:members-block_1' + label: '' + provider: views + label_display: visible + views_label: '' + items_per_page: none + region: content_suffix + weight: '0' + context_mapping: { } + theme: carapace + css_class: '' + unique: 0 + context_id: collection + uuid: 83d50c24-adbb-4b7b-8b1c-6b9127bd084f + id: blocks + saved: false + uuid: 77301de1-1425-4da6-987d-8bedddf94f64 + include_default_blocks: 1 +weight: 0 diff --git a/config/install/context.context.file.yml b/modules/islandora_demo_feature/config/install/context.context.files.yml similarity index 75% rename from config/install/context.context.file.yml rename to modules/islandora_demo_feature/config/install/context.context.files.yml index 5cc17829..7b68870a 100644 --- a/config/install/context.context.file.yml +++ b/modules/islandora_demo_feature/config/install/context.context.files.yml @@ -1,23 +1,22 @@ -uuid: 6804c3b4-a33e-448c-97cc-cfcab3afe7c6 langcode: en status: true dependencies: enforced: module: - - islandora + - islandora_demo_feature module: - islandora -name: file -label: File +name: files +label: Files group: Islandora -description: 'Reactions for all Files' +description: 'All repository files' requireAllConditions: false disabled: false conditions: is_file: id: is_file negate: 0 - uuid: a98d439f-5512-4e60-965c-b215b8f78438 + uuid: 19b1b4e1-ea50-41f8-ab5b-8afb83eb5588 context_mapping: file: '@islandora.file_route_context_provider:file' reactions: diff --git a/modules/islandora_demo_feature/config/install/context.context.image_preservation_master.yml b/modules/islandora_demo_feature/config/install/context.context.image_preservation_master.yml new file mode 100644 index 00000000..ccc1cd98 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/context.context.image_preservation_master.yml @@ -0,0 +1,36 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - islandora +name: image_preservation_master +label: 'Image Preservation Master' +group: Islandora +description: 'Preservation masters for images' +requireAllConditions: true +disabled: false +conditions: + media_has_term: + id: media_has_term + negate: 0 + uuid: 56ad3452-fabe-40ed-a67a-345a00711730 + uri: 'http://pcdm.org/use#PreservationMasterFile' + context_mapping: + media: '@islandora.media_route_context_provider:media' + parent_node_has_term: + id: parent_node_has_term + negate: 0 + uuid: 28d21294-1622-4477-9983-749ac6286d99 + uri: 'http://purl.org/coar/resource_type/c_c513' + context_mapping: + media: '@islandora.media_route_context_provider:media' +reactions: + derivative: + id: derivative + actions: + generate_a_service_file_from_preservation_master: generate_a_service_file_from_preservation_master + saved: false +weight: 0 diff --git a/modules/islandora_demo_feature/config/install/context.context.image_service_file.yml b/modules/islandora_demo_feature/config/install/context.context.image_service_file.yml new file mode 100644 index 00000000..15a766c1 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/context.context.image_service_file.yml @@ -0,0 +1,36 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - islandora +name: image_service_file +label: 'Image Service File' +group: Islandora +description: 'Service files for images' +requireAllConditions: true +disabled: false +conditions: + media_has_term: + id: media_has_term + negate: 0 + uuid: 481cd239-1012-4767-8a28-caac7036c9cb + uri: 'http://pcdm.org/use#ServiceFile' + context_mapping: + media: '@islandora.media_route_context_provider:media' + parent_node_has_term: + id: parent_node_has_term + negate: 0 + uuid: 9f617394-6f70-4eec-8a9b-865bb2ab9fa1 + uri: 'http://purl.org/coar/resource_type/c_c513' + context_mapping: + media: '@islandora.media_route_context_provider:media' +reactions: + derivative: + id: derivative + actions: + generate_a_thumbnail_from_an_image_service_file: generate_a_thumbnail_from_an_image_service_file + saved: false +weight: 0 diff --git a/config/install/context.context.media.yml b/modules/islandora_demo_feature/config/install/context.context.media.yml similarity index 81% rename from config/install/context.context.media.yml rename to modules/islandora_demo_feature/config/install/context.context.media.yml index 3b0af476..bca5cf39 100644 --- a/config/install/context.context.media.yml +++ b/modules/islandora_demo_feature/config/install/context.context.media.yml @@ -1,23 +1,22 @@ -d: c14bfcb1-7e62-4a3c-98e9-0cdbadbe5c45 langcode: en status: true dependencies: enforced: module: - - islandora + - islandora_demo_feature module: - islandora name: media label: Media group: Islandora -description: 'Reactions for all Media' +description: 'All repository media' requireAllConditions: false disabled: false conditions: is_media: id: is_media negate: 0 - uuid: 2e291ec1-11ee-4c36-ba7e-cb05128bf27d + uuid: d43b2007-33d2-4503-b4a7-e3597f1e94de context_mapping: media: '@islandora.media_route_context_provider:media' reactions: diff --git a/modules/islandora_demo_feature/config/install/context.context.open_seadragon.yml b/modules/islandora_demo_feature/config/install/context.context.open_seadragon.yml new file mode 100644 index 00000000..e54803c3 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/context.context.open_seadragon.yml @@ -0,0 +1,28 @@ +langcode: en +status: true +dependencies: + module: + - islandora +name: open_seadragon +label: 'Open Seadragon' +group: Islandora +description: 'Displays media using the Open Seadragon viewer' +requireAllConditions: false +disabled: false +conditions: + node_has_term: + id: node_has_term + negate: 0 + uuid: dba449c3-4b9a-4428-8320-e6bd8f69eee2 + tids: + - + target_id: '35' + context_mapping: + node: '@node.node_route_context:node' + uri: 'http://openseadragon.github.io' +reactions: + view_mode_alter: + id: view_mode_alter + mode: node.open_seadragon + saved: false +weight: 0 diff --git a/config/install/context.context.node.yml b/modules/islandora_demo_feature/config/install/context.context.repository_content.yml similarity index 62% rename from config/install/context.context.node.yml rename to modules/islandora_demo_feature/config/install/context.context.repository_content.yml index 434d5b4e..4afeaea5 100644 --- a/config/install/context.context.node.yml +++ b/modules/islandora_demo_feature/config/install/context.context.repository_content.yml @@ -1,25 +1,31 @@ -d: 48525bb3-36a2-449a-92ed-1ab3e94b3da0 langcode: en status: true dependencies: enforced: module: - - islandora + - islandora_demo_feature module: - islandora -name: node -label: Node + - node +name: repository_content +label: Content group: Islandora -description: 'Reactions for all Nodes' +description: 'All repository content' requireAllConditions: false disabled: false conditions: - is_node: - id: is_node + node_type: + id: node_type + bundles: + islandora_object: islandora_object negate: 0 - uuid: f25d55aa-1664-4202-b846-afd20b527da2 + uuid: 640d52cd-7cd5-4d9e-837d-c93b2deb814e context_mapping: node: '@node.node_route_context:node' + node_has_term: + id: node_has_term + negate: false + uuid: 4852a60d-06ef-4c8c-b983-98218db82111 reactions: index: id: index diff --git a/modules/islandora_demo_feature/config/install/context.context.taxonomy_terms.yml b/modules/islandora_demo_feature/config/install/context.context.taxonomy_terms.yml new file mode 100644 index 00000000..0a5611e5 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/context.context.taxonomy_terms.yml @@ -0,0 +1,35 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - islandora +name: taxonomy_terms +label: 'Taxonomy Terms' +group: Islandora +description: 'All taxonomy terms' +requireAllConditions: false +disabled: false +conditions: + is_term: + id: is_term + negate: 0 + uuid: 71ad4847-3f48-4b16-b355-364672bdfc49 + context_mapping: + taxonomy_term: '@islandora.taxonomy_term_route_context_provider:taxonomy_term' +reactions: + index: + id: index + actions: + index_taxonomy_term_in_fedora: index_taxonomy_term_in_fedora + index_taxonomy_term_in_the_triplestore: index_taxonomy_term_in_the_triplestore + saved: false + delete: + id: delete + actions: + delete_taxonomy_term_in_fedora: delete_taxonomy_term_in_fedora + delete_taxonomy_term_in_triplestore: delete_taxonomy_term_in_triplestore + saved: false +weight: 0 diff --git a/modules/islandora_demo_feature/config/install/core.entity_form_display.media.audio.default.yml b/modules/islandora_demo_feature/config/install/core.entity_form_display.media.audio.default.yml new file mode 100644 index 00000000..fa3809d4 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_form_display.media.audio.default.yml @@ -0,0 +1,82 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.audio.field_file_size + - field.field.media.audio.field_media_audio_file + - field.field.media.audio.field_media_of + - field.field.media.audio.field_mime_type + - field.field.media.audio.field_tags + - media.type.audio + module: + - file + - path +id: media.audio.default +targetEntityType: media +bundle: audio +mode: default +content: + created: + type: datetime_timestamp + weight: 5 + region: content + settings: { } + third_party_settings: { } + field_media_audio_file: + weight: 1 + settings: + progress_indicator: throbber + third_party_settings: { } + type: file_generic + region: content + field_media_of: + type: entity_reference_autocomplete + weight: 2 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + field_tags: + type: entity_reference_autocomplete + weight: 3 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 6 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + settings: + display_label: true + weight: 7 + region: content + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 4 + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + region: content + third_party_settings: { } +hidden: + field_file_size: true + field_mime_type: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_form_display.media.file.default.yml b/modules/islandora_demo_feature/config/install/core.entity_form_display.media.file.default.yml new file mode 100644 index 00000000..73225991 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_form_display.media.file.default.yml @@ -0,0 +1,82 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.file.field_file_size + - field.field.media.file.field_media_file + - field.field.media.file.field_media_of + - field.field.media.file.field_mime_type + - field.field.media.file.field_tags + - media.type.file + module: + - file + - path +id: media.file.default +targetEntityType: media +bundle: file +mode: default +content: + created: + type: datetime_timestamp + weight: 5 + region: content + settings: { } + third_party_settings: { } + field_media_file: + settings: + progress_indicator: throbber + third_party_settings: { } + type: file_generic + weight: 1 + region: content + field_media_of: + type: entity_reference_autocomplete + weight: 2 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + field_tags: + type: entity_reference_autocomplete + weight: 3 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 6 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + settings: + display_label: true + weight: 7 + region: content + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 4 + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + region: content + third_party_settings: { } +hidden: + field_file_size: true + field_mime_type: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_form_display.media.image.default.yml b/modules/islandora_demo_feature/config/install/core.entity_form_display.media.image.default.yml new file mode 100644 index 00000000..d98700cb --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_form_display.media.image.default.yml @@ -0,0 +1,88 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.image.field_file_size + - field.field.media.image.field_height + - field.field.media.image.field_media_image + - field.field.media.image.field_media_of + - field.field.media.image.field_mime_type + - field.field.media.image.field_tags + - field.field.media.image.field_width + - image.style.thumbnail + - media.type.image + module: + - image + - path +id: media.image.default +targetEntityType: media +bundle: image +mode: default +content: + created: + type: datetime_timestamp + weight: 5 + region: content + settings: { } + third_party_settings: { } + field_media_image: + settings: + progress_indicator: throbber + preview_image_style: thumbnail + third_party_settings: { } + type: image_image + weight: 1 + region: content + field_media_of: + type: entity_reference_autocomplete + weight: 2 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + field_tags: + type: entity_reference_autocomplete + weight: 3 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 6 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + settings: + display_label: true + weight: 7 + region: content + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 4 + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + region: content + third_party_settings: { } +hidden: + field_file_size: true + field_height: true + field_mime_type: true + field_width: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_form_display.media.video.default.yml b/modules/islandora_demo_feature/config/install/core.entity_form_display.media.video.default.yml new file mode 100644 index 00000000..6fee55f5 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_form_display.media.video.default.yml @@ -0,0 +1,82 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.video.field_file_size + - field.field.media.video.field_media_of + - field.field.media.video.field_media_video_file + - field.field.media.video.field_mime_type + - field.field.media.video.field_tags + - media.type.video + module: + - file + - path +id: media.video.default +targetEntityType: media +bundle: video +mode: default +content: + created: + type: datetime_timestamp + weight: 5 + region: content + settings: { } + third_party_settings: { } + field_media_of: + type: entity_reference_autocomplete + weight: 2 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + field_media_video_file: + weight: 1 + settings: + progress_indicator: throbber + third_party_settings: { } + type: file_generic + region: content + field_tags: + type: entity_reference_autocomplete + weight: 3 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 6 + region: content + settings: { } + third_party_settings: { } + status: + type: boolean_checkbox + settings: + display_label: true + weight: 7 + region: content + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 4 + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + region: content + third_party_settings: { } +hidden: + field_file_size: true + field_mime_type: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_form_display.node.article.default.yml b/modules/islandora_demo_feature/config/install/core.entity_form_display.node.article.default.yml new file mode 100644 index 00000000..99d0f608 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_form_display.node.article.default.yml @@ -0,0 +1,103 @@ +langcode: en +status: true +dependencies: + config: + - field.field.node.article.body + - field.field.node.article.comment + - field.field.node.article.field_image + - field.field.node.article.field_tags + - image.style.thumbnail + - node.type.article + module: + - comment + - image + - path + - text +id: node.article.default +targetEntityType: node +bundle: article +mode: default +content: + body: + type: text_textarea_with_summary + weight: 1 + region: content + settings: + rows: 9 + summary_rows: 3 + placeholder: '' + third_party_settings: { } + comment: + type: comment_default + weight: 20 + region: content + settings: { } + third_party_settings: { } + created: + type: datetime_timestamp + weight: 10 + region: content + settings: { } + third_party_settings: { } + field_image: + type: image_image + weight: 4 + region: content + settings: + progress_indicator: throbber + preview_image_style: thumbnail + third_party_settings: { } + field_tags: + type: entity_reference_autocomplete_tags + weight: 3 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 30 + region: content + settings: { } + third_party_settings: { } + promote: + type: boolean_checkbox + settings: + display_label: true + weight: 15 + region: content + third_party_settings: { } + status: + type: boolean_checkbox + settings: + display_label: true + weight: 120 + region: content + third_party_settings: { } + sticky: + type: boolean_checkbox + settings: + display_label: true + weight: 16 + region: content + third_party_settings: { } + title: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 5 + region: content + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } +hidden: { } diff --git a/modules/islandora_demo_feature/config/install/core.entity_form_display.node.islandora_object.default.yml b/modules/islandora_demo_feature/config/install/core.entity_form_display.node.islandora_object.default.yml new file mode 100644 index 00000000..05908765 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_form_display.node.islandora_object.default.yml @@ -0,0 +1,100 @@ +langcode: en +status: true +dependencies: + config: + - field.field.node.islandora_object.field_description + - field.field.node.islandora_object.field_member_of + - field.field.node.islandora_object.field_tags + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature + module: + - path +id: node.islandora_object.default +targetEntityType: node +bundle: islandora_object +mode: default +content: + created: + type: datetime_timestamp + weight: 5 + region: content + settings: { } + third_party_settings: { } + field_description: + type: string_textarea + weight: 1 + region: content + settings: + rows: 5 + placeholder: '' + third_party_settings: { } + field_member_of: + weight: 2 + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + type: entity_reference_autocomplete + region: content + field_tags: + weight: 3 + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + third_party_settings: { } + type: entity_reference_autocomplete + region: content + path: + type: path + weight: 8 + region: content + settings: { } + third_party_settings: { } + promote: + type: boolean_checkbox + settings: + display_label: true + weight: 6 + region: content + third_party_settings: { } + status: + type: boolean_checkbox + settings: + display_label: true + weight: 9 + region: content + third_party_settings: { } + sticky: + type: boolean_checkbox + settings: + display_label: true + weight: 7 + region: content + third_party_settings: { } + title: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + uid: + type: entity_reference_autocomplete + weight: 4 + settings: + match_operator: CONTAINS + size: 60 + placeholder: '' + region: content + third_party_settings: { } + url_redirects: + weight: 9 + region: content + settings: { } + third_party_settings: { } +hidden: { } diff --git a/modules/islandora_demo_feature/config/install/core.entity_form_display.taxonomy_term.tags.default.yml b/modules/islandora_demo_feature/config/install/core.entity_form_display.taxonomy_term.tags.default.yml new file mode 100644 index 00000000..74a5b4a9 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_form_display.taxonomy_term.tags.default.yml @@ -0,0 +1,46 @@ +langcode: en +status: true +dependencies: + config: + - field.field.taxonomy_term.tags.field_external_uri + - taxonomy.vocabulary.tags + module: + - link + - path + - text +id: taxonomy_term.tags.default +targetEntityType: taxonomy_term +bundle: tags +mode: default +content: + description: + type: text_textarea + weight: 1 + region: content + settings: + placeholder: '' + rows: 5 + third_party_settings: { } + field_external_uri: + weight: 2 + settings: + placeholder_url: '' + placeholder_title: '' + third_party_settings: { } + type: link_default + region: content + name: + type: string_textfield + weight: 0 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: { } + path: + type: path + weight: 3 + region: content + settings: { } + third_party_settings: { } +hidden: { } diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.media.audio.default.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.audio.default.yml new file mode 100644 index 00000000..620a286d --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.audio.default.yml @@ -0,0 +1,73 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.audio.field_file_size + - field.field.media.audio.field_media_audio_file + - field.field.media.audio.field_media_of + - field.field.media.audio.field_mime_type + - field.field.media.audio.field_tags + - media.type.audio + module: + - file +id: media.audio.default +targetEntityType: media +bundle: audio +mode: default +content: + field_file_size: + type: number_integer + weight: 3 + region: content + label: above + settings: + thousand_separator: '' + prefix_suffix: true + third_party_settings: { } + field_media_audio_file: + type: file_audio + weight: 1 + label: visually_hidden + settings: + controls: true + autoplay: false + loop: false + multiple_file_display_type: tags + third_party_settings: { } + region: content + field_media_of: + type: entity_reference_label + weight: 4 + region: content + label: above + settings: + link: true + third_party_settings: { } + field_mime_type: + type: string + weight: 2 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } + field_tags: + type: entity_reference_label + weight: 5 + region: content + label: above + settings: + link: true + third_party_settings: { } + name: + type: string + weight: 0 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } +hidden: + created: true + thumbnail: true + uid: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.media.file.default.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.file.default.yml new file mode 100644 index 00000000..5b747f0a --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.file.default.yml @@ -0,0 +1,70 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.file.field_file_size + - field.field.media.file.field_media_file + - field.field.media.file.field_media_of + - field.field.media.file.field_mime_type + - field.field.media.file.field_tags + - media.type.file + module: + - file +id: media.file.default +targetEntityType: media +bundle: file +mode: default +content: + field_file_size: + type: number_integer + weight: 3 + region: content + label: above + settings: + thousand_separator: '' + prefix_suffix: true + third_party_settings: { } + field_media_file: + label: visually_hidden + settings: + use_description_as_link_text: true + third_party_settings: { } + type: file_default + weight: 1 + region: content + field_media_of: + type: entity_reference_label + weight: 4 + region: content + label: above + settings: + link: true + third_party_settings: { } + field_mime_type: + type: string + weight: 2 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } + field_tags: + type: entity_reference_label + weight: 5 + region: content + label: above + settings: + link: true + third_party_settings: { } + name: + type: string + weight: 0 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } +hidden: + created: true + thumbnail: true + uid: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.media.file.open_seadragon.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.file.open_seadragon.yml new file mode 100644 index 00000000..348585f1 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.file.open_seadragon.yml @@ -0,0 +1,37 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.open_seadragon + - field.field.media.file.field_file_size + - field.field.media.file.field_media_file + - field.field.media.file.field_media_of + - field.field.media.file.field_mime_type + - field.field.media.file.field_tags + - media.type.file + enforced: + module: + - islandora_demo_feature + module: + - openseadragon +id: media.file.open_seadragon +targetEntityType: media +bundle: file +mode: open_seadragon +content: + field_media_file: + label: hidden + settings: { } + third_party_settings: { } + type: openseadragon_image + weight: 0 + region: content +hidden: + created: true + field_file_size: true + field_media_of: true + field_mime_type: true + field_tags: true + name: true + thumbnail: true + uid: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.media.image.default.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.image.default.yml new file mode 100644 index 00000000..5b06cc11 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.image.default.yml @@ -0,0 +1,91 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.image.field_file_size + - field.field.media.image.field_height + - field.field.media.image.field_media_image + - field.field.media.image.field_media_of + - field.field.media.image.field_mime_type + - field.field.media.image.field_tags + - field.field.media.image.field_width + - media.type.image + module: + - image +id: media.image.default +targetEntityType: media +bundle: image +mode: default +content: + field_file_size: + type: number_integer + weight: 3 + region: content + label: above + settings: + thousand_separator: '' + prefix_suffix: true + third_party_settings: { } + field_height: + type: number_integer + weight: 5 + region: content + label: above + settings: + thousand_separator: '' + prefix_suffix: true + third_party_settings: { } + field_media_image: + label: visually_hidden + settings: + image_style: '' + image_link: file + third_party_settings: { } + type: image + weight: 1 + region: content + field_media_of: + type: entity_reference_label + weight: 6 + region: content + label: above + settings: + link: true + third_party_settings: { } + field_mime_type: + type: string + weight: 2 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } + field_tags: + type: entity_reference_label + weight: 7 + region: content + label: above + settings: + link: true + third_party_settings: { } + field_width: + type: number_integer + weight: 4 + region: content + label: above + settings: + thousand_separator: '' + prefix_suffix: true + third_party_settings: { } + name: + type: string + weight: 0 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } +hidden: + created: true + thumbnail: true + uid: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.media.image.open_seadragon.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.image.open_seadragon.yml new file mode 100644 index 00000000..021d8b85 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.image.open_seadragon.yml @@ -0,0 +1,41 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.open_seadragon + - field.field.media.image.field_file_size + - field.field.media.image.field_height + - field.field.media.image.field_media_image + - field.field.media.image.field_media_of + - field.field.media.image.field_mime_type + - field.field.media.image.field_tags + - field.field.media.image.field_width + - media.type.image + enforced: + module: + - islandora_demo_feature + module: + - openseadragon +id: media.image.open_seadragon +targetEntityType: media +bundle: image +mode: open_seadragon +content: + field_media_image: + label: visually_hidden + settings: { } + third_party_settings: { } + type: openseadragon_image + weight: 0 + region: content +hidden: + created: true + field_file_size: true + field_height: true + field_media_of: true + field_mime_type: true + field_tags: true + field_width: true + name: true + thumbnail: true + uid: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.media.video.default.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.video.default.yml new file mode 100644 index 00000000..f8f025fb --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.media.video.default.yml @@ -0,0 +1,76 @@ +langcode: en +status: true +dependencies: + config: + - field.field.media.video.field_file_size + - field.field.media.video.field_media_of + - field.field.media.video.field_media_video_file + - field.field.media.video.field_mime_type + - field.field.media.video.field_tags + - media.type.video + module: + - file +id: media.video.default +targetEntityType: media +bundle: video +mode: default +content: + field_file_size: + type: number_integer + weight: 3 + region: content + label: above + settings: + thousand_separator: '' + prefix_suffix: true + third_party_settings: { } + field_media_of: + type: entity_reference_label + weight: 4 + region: content + label: above + settings: + link: true + third_party_settings: { } + field_media_video_file: + type: file_video + weight: 1 + label: visually_hidden + settings: + muted: false + width: 640 + height: 480 + controls: true + autoplay: false + loop: false + multiple_file_display_type: tags + third_party_settings: { } + region: content + field_mime_type: + type: string + weight: 2 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } + field_tags: + type: entity_reference_label + weight: 5 + region: content + label: above + settings: + link: true + third_party_settings: { } + name: + type: string + weight: 0 + region: content + label: above + settings: + link_to_entity: false + third_party_settings: { } +hidden: + created: true + thumbnail: true + uid: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.binary.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.binary.yml new file mode 100644 index 00000000..4490938e --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.binary.yml @@ -0,0 +1,63 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.binary + - field.field.node.islandora_object.field_description + - field.field.node.islandora_object.field_member_of + - field.field.node.islandora_object.field_tags + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature + module: + - user +id: node.islandora_object.binary +targetEntityType: node +bundle: islandora_object +mode: binary +content: + display_media_entity_view_1: + weight: 0 + region: content + settings: { } + third_party_settings: { } + display_media_entity_view_3: + weight: 4 + region: content + settings: { } + third_party_settings: { } + field_description: + type: basic_string + weight: 1 + region: content + label: above + settings: { } + third_party_settings: { } + field_member_of: + weight: 2 + label: above + settings: + link: true + third_party_settings: { } + type: entity_reference_label + region: content + field_tags: + weight: 3 + label: above + settings: + link: true + third_party_settings: { } + type: entity_reference_label + region: content + links: + weight: 4 + region: content + settings: { } + third_party_settings: { } +hidden: + display_media_entity_view_2: true + display_media_service_file: true + display_media_thumbnail: true + openseadragon_media_evas_entity_view_2: true + openseadragon_media_evas_service_file: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.default.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.default.yml new file mode 100644 index 00000000..6917cd87 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.default.yml @@ -0,0 +1,62 @@ +langcode: en +status: true +dependencies: + config: + - field.field.node.islandora_object.field_description + - field.field.node.islandora_object.field_member_of + - field.field.node.islandora_object.field_tags + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature + module: + - user +id: node.islandora_object.default +targetEntityType: node +bundle: islandora_object +mode: default +content: + display_media_entity_view_3: + weight: 4 + region: content + settings: { } + third_party_settings: { } + display_media_service_file: + weight: 0 + region: content + settings: { } + third_party_settings: { } + field_description: + type: basic_string + weight: 1 + region: content + label: above + settings: { } + third_party_settings: { } + field_member_of: + weight: 2 + label: above + settings: + link: true + third_party_settings: { } + type: entity_reference_label + region: content + field_tags: + weight: 3 + label: above + settings: + link: true + third_party_settings: { } + type: entity_reference_label + region: content + links: + weight: 4 + region: content + settings: { } + third_party_settings: { } +hidden: + display_media_entity_view_1: true + display_media_entity_view_2: true + display_media_thumbnail: true + openseadragon_media_evas_entity_view_2: true + openseadragon_media_evas_service_file: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.open_seadragon.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.open_seadragon.yml new file mode 100644 index 00000000..491ed3a4 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.open_seadragon.yml @@ -0,0 +1,62 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.open_seadragon + - field.field.node.islandora_object.field_description + - field.field.node.islandora_object.field_member_of + - field.field.node.islandora_object.field_tags + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature + module: + - user +id: node.islandora_object.open_seadragon +targetEntityType: node +bundle: islandora_object +mode: open_seadragon +content: + display_media_entity_view_3: + weight: 4 + region: content + settings: { } + third_party_settings: { } + field_description: + type: basic_string + weight: 1 + region: content + label: above + settings: { } + third_party_settings: { } + field_member_of: + weight: 2 + label: above + settings: + link: true + third_party_settings: { } + type: entity_reference_label + region: content + field_tags: + weight: 3 + label: above + settings: + link: true + third_party_settings: { } + type: entity_reference_label + region: content + links: + weight: 4 + region: content + settings: { } + third_party_settings: { } + openseadragon_media_evas_entity_view_2: + weight: 0 + region: content + settings: { } + third_party_settings: { } +hidden: + display_media_entity_view_1: true + display_media_service_file: true + display_media_thumbnail: true + openseadragon_media_evas_service_file: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.teaser.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.teaser.yml new file mode 100644 index 00000000..d074b9da --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.node.islandora_object.teaser.yml @@ -0,0 +1,39 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + - field.field.node.islandora_object.field_description + - field.field.node.islandora_object.field_member_of + - field.field.node.islandora_object.field_tags + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature + module: + - user +id: node.islandora_object.teaser +targetEntityType: node +bundle: islandora_object +mode: teaser +content: + display_media_thumbnail: + weight: 0 + region: content + settings: { } + third_party_settings: { } + links: + weight: 2 + region: content + settings: { } + third_party_settings: { } +hidden: + display_media_entity_view_1: true + display_media_entity_view_2: true + display_media_service_file: true + field_description: true + field_member_of: true + field_tags: true + members_eva_entity_view_1: true + openseadragon_media_evas_entity_view_2: true + openseadragon_media_evas_service_file: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_display.taxonomy_term.tags.default.yml b/modules/islandora_demo_feature/config/install/core.entity_view_display.taxonomy_term.tags.default.yml new file mode 100644 index 00000000..f8710a0d --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_display.taxonomy_term.tags.default.yml @@ -0,0 +1,34 @@ +langcode: en +status: true +dependencies: + config: + - field.field.taxonomy_term.tags.field_external_uri + - taxonomy.vocabulary.tags + module: + - link + - text +id: taxonomy_term.tags.default +targetEntityType: taxonomy_term +bundle: tags +mode: default +content: + description: + label: hidden + type: text_default + weight: 0 + region: content + settings: { } + third_party_settings: { } + field_external_uri: + weight: 1 + label: above + settings: + trim_length: 80 + url_only: false + url_plain: false + rel: '' + target: '' + third_party_settings: { } + type: link + region: content +hidden: { } diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_mode.media.open_seadragon.yml b/modules/islandora_demo_feature/config/install/core.entity_view_mode.media.open_seadragon.yml new file mode 100644 index 00000000..fb07acd4 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_mode.media.open_seadragon.yml @@ -0,0 +1,12 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - media +id: media.open_seadragon +label: 'Open Seadragon' +targetEntityType: media +cache: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.binary.yml b/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.binary.yml new file mode 100644 index 00000000..366d35de --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.binary.yml @@ -0,0 +1,12 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - node +id: node.binary +label: Binary +targetEntityType: node +cache: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.open_seadragon.yml b/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.open_seadragon.yml new file mode 100644 index 00000000..6fefe5ca --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.open_seadragon.yml @@ -0,0 +1,12 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - node +id: node.open_seadragon +label: 'Open Seadragon' +targetEntityType: node +cache: true diff --git a/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.teaser.yml b/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.teaser.yml new file mode 100644 index 00000000..dcde72c4 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/core.entity_view_mode.node.teaser.yml @@ -0,0 +1,9 @@ +langcode: en +status: true +dependencies: + module: + - node +id: node.teaser +label: Teaser +targetEntityType: node +cache: true diff --git a/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_description.yml b/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_description.yml new file mode 100644 index 00000000..084d2dc6 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_description.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_description + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature +id: node.islandora_object.field_description +field_name: field_description +entity_type: node +bundle: islandora_object +label: Description +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: { } +field_type: string_long diff --git a/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_member_of.yml b/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_member_of.yml new file mode 100644 index 00000000..0770d342 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_member_of.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_member_of + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature +id: node.islandora_object.field_member_of +field_name: field_member_of +entity_type: node +bundle: islandora_object +label: 'Member of' +description: '' +required: false +translatable: false +default_value: { } +default_value_callback: '' +settings: + handler: 'default:node' + handler_settings: { } +field_type: entity_reference diff --git a/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_tags.yml b/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_tags.yml new file mode 100644 index 00000000..9b78801d --- /dev/null +++ b/modules/islandora_demo_feature/config/install/field.field.node.islandora_object.field_tags.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_tags + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature +id: node.islandora_object.field_tags +field_name: field_tags +entity_type: node +bundle: islandora_object +label: Tags +description: '' +required: false +translatable: true +default_value: { } +default_value_callback: '' +settings: + handler: 'default:taxonomy_term' + handler_settings: { } +field_type: entity_reference diff --git a/config/install/field.storage.node.field_description.yml b/modules/islandora_demo_feature/config/install/field.storage.node.field_description.yml similarity index 95% rename from config/install/field.storage.node.field_description.yml rename to modules/islandora_demo_feature/config/install/field.storage.node.field_description.yml index 22a1f37d..b695d63d 100644 --- a/config/install/field.storage.node.field_description.yml +++ b/modules/islandora_demo_feature/config/install/field.storage.node.field_description.yml @@ -1,11 +1,11 @@ langcode: en status: true dependencies: - module: - - islandora enforced: module: - islandora + module: + - node id: node.field_description field_name: field_description entity_type: node diff --git a/modules/islandora_demo_feature/config/install/migrate_plus.migration.islandora_demo_tags.yml b/modules/islandora_demo_feature/config/install/migrate_plus.migration.islandora_demo_tags.yml new file mode 100644 index 00000000..ceadab6e --- /dev/null +++ b/modules/islandora_demo_feature/config/install/migrate_plus.migration.islandora_demo_tags.yml @@ -0,0 +1,31 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature +id: islandora_demo_tags +class: null +field_plugin_method: null +cck_plugin_method: null +migration_tags: islandora_demo_tags +migration_group: islandora +label: 'Tags migration for islandora_demo feature' +source: + plugin: csv + path: /var/www/html/drupal/web/modules/contrib/islandora/modules/islandora_demo_feature/migrate/tags.csv + header_row_count: 1 + keys: + - external_uri +process: + name: name + vid: vid + description: description + field_external_uri: + plugin: urlencode + source: external_uri +destination: + plugin: 'entity:taxonomy_term' +migration_dependencies: + required: { } + optional: { } diff --git a/modules/islandora_demo_feature/config/install/node.type.islandora_object.yml b/modules/islandora_demo_feature/config/install/node.type.islandora_object.yml new file mode 100644 index 00000000..cde14d38 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/node.type.islandora_object.yml @@ -0,0 +1,20 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - menu_ui +third_party_settings: + menu_ui: + available_menus: + - main + parent: 'main:' +name: 'Repository Item' +type: islandora_object +description: 'An item in your Islandora repository.' +help: '' +new_revision: true +preview_mode: 1 +display_submitted: true diff --git a/modules/islandora_demo_feature/config/install/rdf.mapping.node.islandora_object.yml b/modules/islandora_demo_feature/config/install/rdf.mapping.node.islandora_object.yml new file mode 100644 index 00000000..84c3c8a0 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/rdf.mapping.node.islandora_object.yml @@ -0,0 +1,44 @@ +langcode: en +status: true +dependencies: + config: + - node.type.islandora_object + enforced: + module: + - islandora_demo_feature + module: + - node +id: node.islandora_object +targetEntityType: node +bundle: islandora_object +types: + - 'pcdm:Object' +fieldMappings: + field_description: + properties: + - 'dc:description' + field_member_of: + properties: + - 'pcdm:memberOf' + mapping_type: rel + title: + properties: + - 'dc:title' + created: + properties: + - 'schema:dateCreated' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + changed: + properties: + - 'schema:dateModified' + datatype_callback: + callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + uid: + properties: + - 'schema:author' + mapping_type: rel + field_tags: + properties: + - 'schema:additionalType' + mapping_type: rel diff --git a/modules/islandora_demo_feature/config/install/system.action.generate_a_service_file_from_preservation_master.yml b/modules/islandora_demo_feature/config/install/system.action.generate_a_service_file_from_preservation_master.yml new file mode 100644 index 00000000..3c380e1a --- /dev/null +++ b/modules/islandora_demo_feature/config/install/system.action.generate_a_service_file_from_preservation_master.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - islandora_image +id: generate_a_service_file_from_preservation_master +label: 'Generate a service file from image preservation master' +type: node +plugin: generate_image_derivative +configuration: + queue: islandora-connector-houdini + event: 'Generate Derivative' + source_term_uri: 'http://pcdm.org/use#PreservationMasterFile' + derivative_term_uri: 'http://pcdm.org/use#ServiceFile' + mimetype: image/jpeg + args: '' diff --git a/modules/islandora_demo_feature/config/install/system.action.generate_a_thumbnail_from_an_image_service_file.yml b/modules/islandora_demo_feature/config/install/system.action.generate_a_thumbnail_from_an_image_service_file.yml new file mode 100644 index 00000000..73d52560 --- /dev/null +++ b/modules/islandora_demo_feature/config/install/system.action.generate_a_thumbnail_from_an_image_service_file.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + enforced: + module: + - islandora_demo_feature + module: + - islandora_image +id: generate_a_thumbnail_from_an_image_service_file +label: 'Generate a thumbnail from an image service file' +type: node +plugin: generate_image_derivative +configuration: + queue: islandora-connector-houdini + event: 'Generate Derivative' + source_term_uri: 'http://pcdm.org/use#ServiceFile' + derivative_term_uri: 'http://pcdm.org/use#ThumbnailImage' + mimetype: image/jpeg + args: '-thumbnail 100x100' diff --git a/modules/islandora_demo_feature/config/install/views.view.openseadragon_media_evas.yml b/modules/islandora_demo_feature/config/install/views.view.openseadragon_media_evas.yml new file mode 100644 index 00000000..2eaf66ac --- /dev/null +++ b/modules/islandora_demo_feature/config/install/views.view.openseadragon_media_evas.yml @@ -0,0 +1,357 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.media.open_seadragon + enforced: + module: + - islandora_demo_feature + module: + - eva + - media + - taxonomy + - user +id: openseadragon_media_evas +label: 'OpenSeadragon Media EVAs' +module: views +description: 'Displays media for content as EVA''s per model.' +tag: '' +base_table: media_field_data +base_field: mid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'view media' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: some + options: + items_per_page: 1 + offset: 0 + style: + type: default + options: + row_class: '' + default_row_class: true + uses_fields: false + row: + type: 'entity:media' + options: + relationship: none + view_mode: open_seadragon + fields: + name: + id: name + table: media_field_data + field: name + entity_type: media + entity_field: media + label: '' + alter: + alter_text: false + make_link: false + absolute: false + trim: false + word_boundary: false + ellipsis: false + strip_tags: false + html: false + hide_empty: false + empty_zero: false + settings: + link_to_entity: true + plugin_id: field + relationship: none + group_type: group + admin_label: '' + exclude: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_alter_empty: true + click_sort_column: value + type: string + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + filters: + status: + value: '1' + table: media_field_data + field: status + plugin_id: boolean + entity_type: media + entity_field: status + id: status + expose: + operator: '' + group: 1 + sorts: { } + title: '' + header: { } + footer: { } + empty: { } + relationships: + field_tags: + id: field_tags + table: media__field_tags + field: field_tags + relationship: none + group_type: group + admin_label: 'field_tags: Taxonomy term' + required: false + plugin_id: standard + arguments: + field_media_of_target_id: + id: field_media_of_target_id + table: media__field_media_of + field: field_media_of_target_id + relationship: none + group_type: group + admin_label: '' + default_action: default + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: node + default_argument_options: { } + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: false + validate: + type: none + fail: 'not found' + validate_options: { } + break_phrase: false + not: false + plugin_id: numeric + display_extenders: { } + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - user.permissions + tags: { } + entity_view_2: + display_plugin: entity_view + id: entity_view_2 + display_title: 'Preservation Master' + position: 1 + display_options: + display_extenders: { } + display_description: 'Best quality representation of the Object appropriate for long-term preservation.' + filters: + status: + value: '1' + table: media_field_data + field: status + plugin_id: boolean + entity_type: media + entity_field: status + id: status + expose: + operator: '' + group: 1 + field_external_uri_uri: + id: field_external_uri_uri + table: taxonomy_term__field_external_uri + field: field_external_uri_uri + relationship: field_tags + group_type: group + admin_label: '' + operator: '=' + value: 'http://pcdm.org/use#PreservationMasterFile' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: string + defaults: + filters: false + filter_groups: false + style: false + row: false + filter_groups: + operator: AND + groups: + 1: AND + entity_type: node + bundles: + - islandora_object + argument_mode: id + default_argument: null + title: 'OpenSeadragon - Preservation Master' + show_title: false + style: + type: default + options: + row_class: '' + default_row_class: true + uses_fields: false + row: + type: 'entity:media' + options: + relationship: none + view_mode: open_seadragon + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - user.permissions + tags: { } + service_file: + display_plugin: entity_view + id: service_file + display_title: 'Service File' + position: 1 + display_options: + display_extenders: { } + display_description: 'A medium quality representation of the Object appropriate for serving to users.' + filters: + status: + value: '1' + table: media_field_data + field: status + plugin_id: boolean + entity_type: media + entity_field: status + id: status + expose: + operator: '' + group: 1 + field_external_uri_uri: + id: field_external_uri_uri + table: taxonomy_term__field_external_uri + field: field_external_uri_uri + relationship: field_tags + group_type: group + admin_label: '' + operator: '=' + value: 'http://pcdm.org/use#ServiceFile' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: string + defaults: + filters: false + filter_groups: false + title: false + filter_groups: + operator: AND + groups: + 1: AND + entity_type: node + bundles: + - islandora_object + title: 'OpenSeadragon - Service File' + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - user.permissions + tags: { } diff --git a/modules/islandora_demo_feature/islandora_demo_feature.features.yml b/modules/islandora_demo_feature/islandora_demo_feature.features.yml new file mode 100644 index 00000000..dcf04705 --- /dev/null +++ b/modules/islandora_demo_feature/islandora_demo_feature.features.yml @@ -0,0 +1,15 @@ +bundle: islandora +excluded: + - field.storage.node.field_image + - field.storage.node.field_tags + - field.field.node.article.field_image + - core.entity_view_display.node.article.default + - core.entity_view_display.node.article.rss + - core.entity_view_display.node.article.search_index + - core.entity_view_display.node.article.search_result + - core.entity_view_display.node.article.teaser + - core.entity_view_display.node.page.teaser + - views.view.archive + - views.view.frontpage + - views.view.taxonomy_term +required: true diff --git a/modules/islandora_demo_feature/islandora_demo_feature.info.yml b/modules/islandora_demo_feature/islandora_demo_feature.info.yml new file mode 100644 index 00000000..4c38d0ad --- /dev/null +++ b/modules/islandora_demo_feature/islandora_demo_feature.info.yml @@ -0,0 +1,28 @@ +name: 'Islandora Demo Feature' +description: 'A functional example that can be used to learn how content modeling works in CLAW.' +type: module +core: 8.x +dependencies: + - comment + - context + - eva + - field + - file + - image + - islandora + - islandora_core_feature + - islandora_image + - link + - media + - menu_ui + - migrate_plus + - node + - openseadragon + - path + - rdf + - system + - taxonomy + - text + - user + - views +package: Islandora diff --git a/modules/islandora_demo_feature/migrate/tags.csv b/modules/islandora_demo_feature/migrate/tags.csv new file mode 100644 index 00000000..28cfa951 --- /dev/null +++ b/modules/islandora_demo_feature/migrate/tags.csv @@ -0,0 +1,2 @@ +vid,name,description,external_uri +tags,"Open Seadragon","Display using the Open Seadragon viewer",http://openseadragon.github.io diff --git a/src/ContextProvider/MediaContextProvider.php b/src/ContextProvider/MediaContextProvider.php index 307f614e..33270357 100644 --- a/src/ContextProvider/MediaContextProvider.php +++ b/src/ContextProvider/MediaContextProvider.php @@ -2,7 +2,7 @@ namespace Drupal\islandora\ContextProvider; -use Drupal\media_entity\MediaInterface; +use Drupal\media\MediaInterface; use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Plugin\Context\ContextProviderInterface; @@ -18,14 +18,14 @@ class MediaContextProvider implements ContextProviderInterface { /** * Media to provide in a context. * - * @var \Drupal\media_entity\MediaInterface + * @var \Drupal\media\MediaInterface */ protected $media; /** * Constructs a new MediaRouteContext. * - * @var \Drupal\media_entity\MediaInterface $media + * @var \Drupal\media\MediaInterface $media * The media to provide in a context. */ public function __construct(MediaInterface $media) { diff --git a/src/ContextProvider/MediaRouteContextProvider.php b/src/ContextProvider/MediaRouteContextProvider.php index a921e563..3a731760 100644 --- a/src/ContextProvider/MediaRouteContextProvider.php +++ b/src/ContextProvider/MediaRouteContextProvider.php @@ -7,7 +7,7 @@ use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Plugin\Context\ContextProviderInterface; use Drupal\Core\Routing\RouteMatchInterface; -use Drupal\media_entity\Entity\Media; +use Drupal\media\Entity\Media; use Drupal\Core\StringTranslation\StringTranslationTrait; /** @@ -53,8 +53,8 @@ class MediaRouteContextProvider implements ContextProviderInterface { } } elseif ($this->routeMatch->getRouteName() == 'entity.media.add_form') { - $media_bundle = $this->routeMatch->getParameter('media_bundle'); - $value = Media::create(['bundle' => $media_bundle->id()]); + $media_type = $this->routeMatch->getParameter('media_type'); + $value = Media::create(['bundle' => $media_type->id()]); } } diff --git a/src/ContextProvider/TermContextProvider.php b/src/ContextProvider/TermContextProvider.php new file mode 100644 index 00000000..7a1e6b79 --- /dev/null +++ b/src/ContextProvider/TermContextProvider.php @@ -0,0 +1,52 @@ +term = $term; + } + + /** + * {@inheritdoc} + */ + public function getRuntimeContexts(array $unqualified_context_ids) { + $context_definition = new ContextDefinition('entity:taxonomy_term', NULL, FALSE); + $context = new Context($context_definition, $this->term); + return ['@islandora.taxonomy_term_route_context_provider:taxonomy_term' => $context]; + } + + /** + * {@inheritdoc} + */ + public function getAvailableContexts() { + $context = new Context(new ContextDefinition('entity:taxonomy_term', $this->t('Term from entity hook'))); + return ['@islandora.taxonomy_term_route_context_provider:taxonomy_term' => $context]; + } + +} diff --git a/src/ContextProvider/TermRouteContextProvider.php b/src/ContextProvider/TermRouteContextProvider.php new file mode 100644 index 00000000..59313523 --- /dev/null +++ b/src/ContextProvider/TermRouteContextProvider.php @@ -0,0 +1,71 @@ +routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public function getRuntimeContexts(array $unqualified_context_ids) { + $context_definition = new ContextDefinition('entity:taxonomy_term', NULL, FALSE); + $value = NULL; + + // Hack the file out of the route. + $route_object = $this->routeMatch->getRouteObject(); + if ($route_object) { + $route_contexts = $route_object->getOption('parameters'); + if ($route_contexts && isset($route_contexts['taxonomy_term'])) { + $term = $this->routeMatch->getParameter('taxonomy_term'); + if ($term) { + $value = $term; + } + } + } + + $cacheability = new CacheableMetadata(); + $cacheability->setCacheContexts(['route']); + + $context = new Context($context_definition, $value); + $context->addCacheableDependency($cacheability); + return ['taxonomy_term' => $context]; + } + + /** + * {@inheritdoc} + */ + public function getAvailableContexts() { + $context = new Context(new ContextDefinition('entity:taxonomy_term', $this->t('Term from URL'))); + return ['taxonomy_term' => $context]; + } + +} diff --git a/src/ContextReaction/DisplayAlterReaction.php b/src/ContextReaction/DisplayAlterReaction.php new file mode 100644 index 00000000..f214ccdc --- /dev/null +++ b/src/ContextReaction/DisplayAlterReaction.php @@ -0,0 +1,62 @@ +entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function execute() { + // Return the mode name by itself. + $config = $this->getConfiguration(); + $exploded = explode('.', $config[self::MODE]); + return $exploded[1]; + } + + /** + * {@inheritdoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + $this->setConfiguration([self::MODE => $form_state->getValue(self::MODE)]); + } + +} diff --git a/src/Controller/ManageMediaController.php b/src/Controller/ManageMediaController.php new file mode 100644 index 00000000..8ef77dff --- /dev/null +++ b/src/Controller/ManageMediaController.php @@ -0,0 +1,29 @@ +generateTypeList( + 'media', + 'media_type', + 'entity.media.add_form', + 'entity.media_type.add_form', + $node, + 'field_media_of' + ); + } + +} diff --git a/src/Controller/ManageMembersController.php b/src/Controller/ManageMembersController.php new file mode 100644 index 00000000..854e09cc --- /dev/null +++ b/src/Controller/ManageMembersController.php @@ -0,0 +1,143 @@ +entityTypeManager = $entity_type_manager; + $this->entityFieldManager = $entity_field_manager; + $this->renderer = $renderer; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity_type.manager'), + $container->get('entity_field.manager'), + $container->get('renderer') + ); + } + + /** + * Renders a list of types to add as members. + * + * @param \Drupal\node\NodeInterface $node + * Node you want to add a member to. + */ + public function addToNodePage(NodeInterface $node) { + return $this->generateTypeList( + 'node', + 'node_type', + 'node.add', + 'node.type_add', + $node, + 'field_member_of' + ); + } + + /** + * Renders a list of content types to add as members. + */ + protected function generateTypeList($entity_type, $bundle_type, $entity_add_form, $bundle_add_form, NodeInterface $node, $field) { + $type_definition = $this->entityTypeManager->getDefinition($bundle_type); + + $build = [ + '#theme' => 'entity_add_list', + '#bundles' => [], + '#cache' => ['tags' => $type_definition->getListCacheTags()], + ]; + + $bundles = $this->entityTypeManager->getStorage($bundle_type)->loadMultiple(); + $access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type); + + foreach (array_keys($bundles) as $bundle_id) { + $bundle = $bundles[$bundle_id]; + + // Skip bundles that don't have the specified field. + $fields = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle_id); + if (!isset($fields[$field])) { + continue; + } + + $build['#bundles'][$bundle_id] = [ + 'label' => $bundle->label(), + 'description' => $bundle->getDescription(), + 'add_link' => Link::createFromRoute( + $bundle->label(), + $entity_add_form, + [$bundle_type => $bundle->id()], + ['query' => ["edit[$field]" => $node->id()]] + ), + ]; + } + + // Filter out bundles the user can't create. + foreach (array_keys($bundles) as $bundle_id) { + $access = $access_control_handler->createAccess($bundle_id, NULL, [], TRUE); + if (!$access->isAllowed()) { + unset($build['#bundles'][$bundle_id]); + } + $this->renderer->addCacheableDependency($build, $access); + } + + // Build the message shown when there are no bundles. + $type_label = $type_definition->getLowercaseLabel(); + $link_text = $this->t('Add a new @entity_type.', ['@entity_type' => $type_label]); + $build['#add_bundle_message'] = $this->t('There is no @entity_type yet. @add_link', [ + '@entity_type' => $type_label, + '@add_link' => Link::createFromRoute($link_text, $bundle_add_form)->toString(), + ]); + + return $build; + } + +} diff --git a/src/Controller/MediaSourceController.php b/src/Controller/MediaSourceController.php index 83f6be01..5bb7f3ad 100644 --- a/src/Controller/MediaSourceController.php +++ b/src/Controller/MediaSourceController.php @@ -7,8 +7,10 @@ use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Database\Connection; use Drupal\Core\Routing\RouteMatch; use Drupal\Core\Session\AccountInterface; -use Drupal\media_entity\MediaInterface; +use Drupal\media\MediaInterface; +use Drupal\media\MediaTypeInterface; use Drupal\node\NodeInterface; +use Drupal\taxonomy\TermInterface; use Drupal\islandora\MediaSource\MediaSourceService; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -72,7 +74,7 @@ class MediaSourceController extends ControllerBase { /** * Updates a source file for a Media. * - * @param \Drupal\media_entity\MediaInterface $media + * @param \Drupal\media\MediaInterface $media * The media whose source file you want to update. * @param \Symfony\Component\HttpFoundation\Request $request * The request object. @@ -89,24 +91,6 @@ class MediaSourceController extends ControllerBase { throw new BadRequestHttpException("Missing Content-Type header"); } - $content_length = $request->headers->get('Content-Length', 0); - - if ($content_length <= 0) { - throw new BadRequestHttpException("Missing Content-Length"); - } - - $content_disposition = $request->headers->get('Content-Disposition', ""); - - if (empty($content_disposition)) { - throw new BadRequestHttpException("Missing Content-Disposition header"); - } - - $matches = []; - if (!preg_match('/attachment; filename="(.*)"/', $content_disposition, $matches)) { - throw new BadRequestHttpException("Malformed Content-Disposition header"); - } - $filename = $matches[1]; - // Since we update both the Media and its File, do this in a transaction. $transaction = $this->database->startTransaction(); @@ -115,9 +99,7 @@ class MediaSourceController extends ControllerBase { $this->service->updateSourceField( $media, $request->getContent(TRUE), - $content_type, - $content_length, - $filename + $content_type ); return new Response("", 204); @@ -137,10 +119,10 @@ class MediaSourceController extends ControllerBase { * * @param \Drupal\node\NodeInterface $node * The Node to which you want to add a Media. - * @param string $field - * Name of field on Node to reference Media. - * @param string $bundle - * Name of bundle for Media to create. + * @param \Drupal\media\MediaTypeInterface $media_type + * Media type for new media. + * @param \Drupal\taxonomy\TermInterface $taxonomy_term + * Term from the 'Behavior' vocabulary to give to new media. * @param \Symfony\Component\HttpFoundation\Request $request * The request object. * @@ -149,10 +131,10 @@ class MediaSourceController extends ControllerBase { * * @throws \Symfony\Component\HttpKernel\Exception\HttpException */ - public function addToNode( + public function putToNode( NodeInterface $node, - $field, - $bundle, + MediaTypeInterface $media_type, + TermInterface $taxonomy_term, Request $request ) { $content_type = $request->headers->get('Content-Type', ""); @@ -161,12 +143,6 @@ class MediaSourceController extends ControllerBase { throw new BadRequestHttpException("Missing Content-Type header"); } - $content_length = $request->headers->get('Content-Length', 0); - - if ($content_length <= 0) { - throw new BadRequestHttpException("Missing Content-Length"); - } - $content_disposition = $request->headers->get('Content-Disposition', ""); if (empty($content_disposition)) { @@ -179,23 +155,28 @@ class MediaSourceController extends ControllerBase { } $filename = $matches[1]; - // Since we create both a Media and its File, AND update a node, + // Since we create both a Media and its File, // start a transaction. $transaction = $this->database->startTransaction(); try { - $media = $this->service->addToNode( + $media = $this->service->putToNode( $node, - $field, - $bundle, + $media_type, + $taxonomy_term, $request->getContent(TRUE), $content_type, - $content_length, $filename ); - $response = new Response("", 201); - $response->headers->set("Location", $media->url('canonical', ['absolute' => TRUE])); + // We return the media if it was newly created. + if ($media) { + $response = new Response("", 201); + $response->headers->set("Location", $media->url('canonical', ['absolute' => TRUE])); + } + else { + $response = new Response("", 204); + } return $response; } catch (HttpException $e) { @@ -219,7 +200,7 @@ class MediaSourceController extends ControllerBase { * @return \Drupal\Core\Access\AccessResultInterface * Access result. */ - public function addToNodeAccess(AccountInterface $account, RouteMatch $route_match) { + public function putToNodeAccess(AccountInterface $account, RouteMatch $route_match) { // We'd have 404'd already if node didn't exist, so no need to check. // Just hack it out of the route match. $node = $route_match->getParameter('node'); diff --git a/src/EventGenerator/EmitEvent.php b/src/EventGenerator/EmitEvent.php index 22037c13..f76f97ba 100644 --- a/src/EventGenerator/EmitEvent.php +++ b/src/EventGenerator/EmitEvent.php @@ -4,7 +4,7 @@ namespace Drupal\islandora\EventGenerator; use Drupal\Core\Access\AccessResult; use Drupal\Core\Action\ConfigurableActionBase; -use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Session\AccountInterface; @@ -27,11 +27,11 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact protected $account; /** - * User storage. + * Entity type manager. * - * @var \Drupal\Core\Entity\EntityStorageInterface + * @var \Drupal\Core\Entity\EntityTypeManager */ - protected $userStorage; + protected $entityTypeManager; /** * Event generator service. @@ -65,8 +65,8 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact * The plugin implementation definition. * @param \Drupal\Core\Session\AccountInterface $account * Current user. - * @param \Drupal\Core\Entity\EntityStorageInterface $user_storage - * User storage. + * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager + * Entity type manager. * @param \Drupal\islandora\EventGenerator\EventGeneratorInterface $event_generator * EventGenerator service to serialize AS2 events. * @param \Stomp\StatefulStomp $stomp @@ -79,14 +79,14 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact $plugin_id, $plugin_definition, AccountInterface $account, - EntityStorageInterface $user_storage, + EntityTypeManager $entity_type_manager, EventGeneratorInterface $event_generator, StatefulStomp $stomp, JwtAuth $auth ) { parent::__construct($configuration, $plugin_id, $plugin_definition); $this->account = $account; - $this->userStorage = $user_storage; + $this->entityTypeManager = $entity_type_manager; $this->eventGenerator = $event_generator; $this->stomp = $stomp; $this->auth = $auth; @@ -101,7 +101,7 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact $plugin_id, $plugin_definition, $container->get('current_user'), - $container->get('entity_type.manager')->getStorage('user'), + $container->get('entity_type.manager'), $container->get('islandora.eventgenerator'), $container->get('islandora.stomp'), $container->get('jwt.authentication.jwt') @@ -126,21 +126,13 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact return; } - // Generate the event message. - $user = $this->userStorage->load($this->account->id()); - - if ($this->configuration['event'] == 'create') { - $message = $this->eventGenerator->generateCreateEvent($entity, $user); - } - elseif ($this->configuration['event'] == 'update') { - $message = $this->eventGenerator->generateUpdateEvent($entity, $user); - } - elseif ($this->configuration['event'] == 'delete') { - $message = $this->eventGenerator->generateDeleteEvent($entity, $user); - } - - // Transform message from string into a proper message object. - $message = new Message($message, ['Authorization' => "Bearer $token"]); + // Generate event as stomp message. + $user = $this->entityTypeManager->getStorage('user')->load($this->account->id()); + $data = $this->generateData($entity); + $message = new Message( + $this->eventGenerator->generateEvent($entity, $user, $data), + ['Authorization' => "Bearer $token"] + ); // Send the message. try { @@ -165,13 +157,20 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact } } + /** + * Override this function to control what gets encoded as a json note. + */ + protected function generateData($entity) { + return $this->configuration; + } + /** * {@inheritdoc} */ public function defaultConfiguration() { return [ 'queue' => '', - 'event' => 'create', + 'event' => 'Create', ]; } @@ -193,9 +192,10 @@ abstract class EmitEvent extends ConfigurableActionBase implements ContainerFact '#default_value' => $this->configuration['event'], '#description' => t('Type of event to emit'), '#options' => [ - 'create' => t('Create'), - 'update' => t('Update'), - 'delete' => t('Delete'), + 'Create' => t('Create'), + 'Update' => t('Update'), + 'Delete' => t('Delete'), + 'Generate Derivative' => t('Generate Derivative'), ], ]; return $form; diff --git a/src/EventGenerator/EventGenerator.php b/src/EventGenerator/EventGenerator.php index 551889ce..653e3b2c 100644 --- a/src/EventGenerator/EventGenerator.php +++ b/src/EventGenerator/EventGenerator.php @@ -6,8 +6,6 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Url; use Drupal\file\FileInterface; use Drupal\user\UserInterface; -use Drupal\media_entity\MediaInterface; -use Drupal\node\NodeInterface; /** * The default EventGenerator implementation. @@ -19,46 +17,11 @@ class EventGenerator implements EventGeneratorInterface { /** * {@inheritdoc} */ - public function generateCreateEvent(EntityInterface $entity, UserInterface $user) { - $event = $this->generateEvent($entity, $user); - $event["type"] = "Create"; - return json_encode($event); - } - - /** - * {@inheritdoc} - */ - public function generateUpdateEvent(EntityInterface $entity, UserInterface $user) { - $event = $this->generateEvent($entity, $user); - $event["type"] = "Update"; - return json_encode($event); - } - - /** - * {@inheritdoc} - */ - public function generateDeleteEvent(EntityInterface $entity, UserInterface $user) { - $event = $this->generateEvent($entity, $user); - $event["type"] = "Delete"; - return json_encode($event); - } - - /** - * Shared event generation function that does not impose a 'Type'. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity that was created. - * @param \Drupal\user\UserInterface $user - * The user who created the entity. - * - * @return array - * Event message as an array. - */ - protected function generateEvent(EntityInterface $entity, UserInterface $user) { + public function generateEvent(EntityInterface $entity, UserInterface $user, array $data) { $user_url = $user->toUrl()->setAbsolute()->toString(); - return [ + $event = [ "@context" => "https://www.w3.org/ns/activitystreams", "actor" => [ "type" => "Person", @@ -75,29 +38,33 @@ class EventGenerator implements EventGeneratorInterface { ], "object" => [ "id" => "urn:uuid:{$entity->uuid()}", - "url" => $this->generateEntityLinks($entity), + "url" => $entity instanceof FileInterface ? $this->generateFileLinks($entity) : $this->generateRestLinks($entity), ], ]; - } - /** - * Generates entity urls depending on entity type. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity. - * - * @return array - * AS2 Links. - */ - protected function generateEntityLinks(EntityInterface $entity) { - if ($entity instanceof FileInterface) { - return $this->generateFileLinks($entity); + $entity_type = $entity->getEntityTypeId(); + $event_type = $data["event"]; + if ($data["event"] == "Generate Derivative") { + $event["type"] = "Activity"; + $event["summary"] = $data["event"]; } - elseif ($entity instanceof MediaInterface) { - return $this->generateMediaLinks($entity); + else { + $event["type"] = ucfirst($data["event"]); + $event["summary"] = ucfirst($data["event"]) . " a " . ucfirst($entity_type); } - return $this->generateNodeLinks($entity); + unset($data["event"]); + unset($data["queue"]); + + if (!empty($data)) { + $event["attachment"] = [ + "type" => "Object", + "content" => $data, + "mediaType" => "application/json", + ]; + } + + return json_encode($event); } /** @@ -132,16 +99,16 @@ class EventGenerator implements EventGeneratorInterface { } /** - * Generates media urls. + * Generates REST urls. * - * @param \Drupal\media_entity\MediaInterface $media - * The media. + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity. * * @return array * AS2 Links. */ - protected function generateMediaLinks(MediaInterface $media) { - $url = $media->toUrl()->setAbsolute()->toString(); + protected function generateRestLinks(EntityInterface $entity) { + $url = $entity->toUrl()->setAbsolute()->toString(); return [ [ "name" => "Canoncial", @@ -165,32 +132,4 @@ class EventGenerator implements EventGeneratorInterface { ]; } - /** - * Generates node urls. - * - * @param \Drupal\node\NodeInterface $node - * The node. - * - * @return array - * AS2 Links. - */ - protected function generateNodeLinks(NodeInterface $node) { - $url = $node->toUrl()->setAbsolute()->toString(); - return [ - [ - "name" => "Canoncial", - "type" => "Link", - "href" => "$url", - "mediaType" => "text/html", - "rel" => "canonical", - ], - [ - "name" => "JSONLD", - "type" => "Link", - "href" => "$url?_format=jsonld", - "mediaType" => "application/ld+json", - ], - ]; - } - } diff --git a/src/EventGenerator/EventGeneratorInterface.php b/src/EventGenerator/EventGeneratorInterface.php index 766e1389..36dca131 100644 --- a/src/EventGenerator/EventGeneratorInterface.php +++ b/src/EventGenerator/EventGeneratorInterface.php @@ -6,47 +6,23 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\user\UserInterface; /** - * Inteface for a service that provides serialized event messages. + * Inteface for a service that provides serialized AS2 messages. */ interface EventGeneratorInterface { /** - * Generates a serialized 'Create' event. + * Generates an event as an associative array. * * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity that was created. + * The entity in the action. * @param \Drupal\user\UserInterface $user - * The user who created the entity. + * The user performing the action. + * @param array $data + * Arbitrary data to include as a json encoded note. * * @return string - * Serialized event message + * Serialized event message. */ - public function generateCreateEvent(EntityInterface $entity, UserInterface $user); - - /** - * Generates a serialized 'Create' event. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity that was updated. - * @param \Drupal\user\UserInterface $user - * The user who updated the entity. - * - * @return string - * Serialized event message - */ - public function generateUpdateEvent(EntityInterface $entity, UserInterface $user); - - /** - * Generates a serialized 'Create' event. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity that was deleted. - * @param \Drupal\user\UserInterface $user - * The user who deleted the entity. - * - * @return string - * Serialized event message - */ - public function generateDeleteEvent(EntityInterface $entity, UserInterface $user); + public function generateEvent(EntityInterface $entity, UserInterface $user, array $data); } diff --git a/src/EventSubscriber/AdminViewsRouteSubscriber.php b/src/EventSubscriber/AdminViewsRouteSubscriber.php new file mode 100644 index 00000000..2d7eb95b --- /dev/null +++ b/src/EventSubscriber/AdminViewsRouteSubscriber.php @@ -0,0 +1,25 @@ +get('view.media_of.page_1')) { + $route->setOption('_admin_route', 'TRUE'); + } + if ($route = $collection->get('view.manage_members.page_1')) { + $route->setOption('_admin_route', 'TRUE'); + } + } + +} diff --git a/src/EventSubscriber/LinkHeaderSubscriber.php b/src/EventSubscriber/LinkHeaderSubscriber.php index eb016ce7..6bec7f8c 100644 --- a/src/EventSubscriber/LinkHeaderSubscriber.php +++ b/src/EventSubscriber/LinkHeaderSubscriber.php @@ -10,6 +10,7 @@ use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; @@ -36,15 +37,6 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface { protected $entityFieldManager; /** - * The route match object. - * - * @var \Drupal\Core\Routing\RouteMatchInterface - */ - protected $routeMatch; - - /** - * Constructor. - * * The access manager. * * @var \Drupal\Core\Access\AccessManagerInterface @@ -58,6 +50,20 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface { */ protected $account; + /** + * The route match object. + * + * @var \Drupal\Core\Routing\RouteMatchInterface + */ + protected $routeMatch; + + /** + * Request stack (for current request). + * + * @var Symfony\Component\HttpFoundation\RequestStack + */ + protected $requestStack; + /** * Constructor. * @@ -65,25 +71,31 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface { * The entity type manager. * @param \Drupal\Core\Entity\EntityFieldManager $entity_field_manager * The entity field manager. - * @param \Drupal\Core\Routing\RouteMatchInterface $route_match - * The route match object. * @param \Drupal\Core\Access\AccessManagerInterface $access_manager * The access manager. * @param \Drupal\Core\Session\AccountInterface $account * The current user. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match object. + * @param Symfony\Component\HttpFoundation\RequestStack $request_stack + * Request stack (for current request). */ public function __construct( EntityTypeManager $entity_type_manager, EntityFieldManager $entity_field_manager, - RouteMatchInterface $route_match, AccessManagerInterface $access_manager, - AccountInterface $account + AccountInterface $account, + RouteMatchInterface $route_match, + RequestStack $request_stack ) { $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; + $this->accessManager = $access_manager; + $this->account = $account; $this->routeMatch = $route_match; $this->accessManager = $access_manager; $this->account = $account; + $this->requestStack = $request_stack; } /** @@ -181,9 +193,33 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface { foreach ($entity->get($field_name)->referencedEntities() as $referencedEntity) { // Headers are subject to an access check. if ($referencedEntity->access('view')) { - $entity_url = $referencedEntity->url('canonical', ['absolute' => TRUE]); - $field_label = $field_definition->label(); - $links[] = "<$entity_url>; rel=\"related\"; title=\"$field_label\""; + + // Taxonomy terms are written out as + // ; rel="tag"; title="Tag Name" + // where url is defined in field_same_as. + // If field_same_as doesn't exist or is empty, + // it becomes the taxonomy term's local uri. + if ($referencedEntity->getEntityTypeId() == 'taxonomy_term') { + $rel = "tag"; + $entity_url = $referencedEntity->url('canonical', ['absolute' => TRUE]); + if ($referencedEntity->hasField('field_external_uri')) { + $external_uri = $referencedEntity->get('field_external_uri')->first()->getValue()['uri']; + if (!empty($external_uri)) { + $entity_url = $external_uri; + } + } + $title = $referencedEntity->label(); + } + else { + // If it's not a taxonomy term, referenced entity link + // headers take the form + // ; rel="related"; title="Field Label" + // and the url is the local uri. + $rel = "related"; + $entity_url = $referencedEntity->url('canonical', ['absolute' => TRUE]); + $title = $field_definition->label(); + } + $links[] = "<$entity_url>; rel=\"$rel\"; title=\"$title\""; } } } @@ -205,13 +241,19 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface { $entity_type = $entity->getEntityType()->id(); $rest_resource_config = $rest_resource_config_storage->load("entity.$entity_type"); + $current_format = $this->requestStack->getCurrentRequest()->query->get('_format'); + $links = []; $route_name = $this->routeMatch->getRouteName(); if ($rest_resource_config) { - $configuration = $rest_resource_config->get('configuration'); + $formats = $rest_resource_config->getFormats("GET"); + + foreach ($formats as $format) { + if ($format == $current_format) { + continue; + } - foreach ($configuration['GET']['supported_formats'] as $format) { switch ($format) { case 'json': $mime = 'application/json'; @@ -233,11 +275,7 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface { continue; } - $meta_route_name = "rest.entity.$entity_type.GET.$format"; - - if ($route_name == $meta_route_name) { - continue; - } + $meta_route_name = "rest.entity.$entity_type.GET"; $route_params = [$entity_type => $entity->id()]; diff --git a/src/EventSubscriber/MediaLinkHeaderSubscriber.php b/src/EventSubscriber/MediaLinkHeaderSubscriber.php index e45d2c88..16e286e2 100644 --- a/src/EventSubscriber/MediaLinkHeaderSubscriber.php +++ b/src/EventSubscriber/MediaLinkHeaderSubscriber.php @@ -3,7 +3,7 @@ namespace Drupal\islandora\EventSubscriber; use Drupal\Core\Url; -use Drupal\media_entity\MediaInterface; +use Drupal\media\MediaInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; @@ -43,16 +43,16 @@ class MediaLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSub /** * Generates link headers for the described file and source update routes. * - * @param \Drupal\media_entity\MediaInterface $media + * @param \Drupal\media\MediaInterface $media * Media to generate link headers. * * @return string[] * Array of link headers */ protected function generateMediaLinks(MediaInterface $media) { - $media_bundle = $this->entityTypeManager->getStorage('media_bundle')->load($media->bundle()); + $media_type = $this->entityTypeManager->getStorage('media_type')->load($media->bundle()); - $type_configuration = $media_bundle->getTypeConfiguration(); + $type_configuration = $media_type->get('source_configuration'); $links = []; diff --git a/src/EventSubscriber/NodeLinkHeaderSubscriber.php b/src/EventSubscriber/NodeLinkHeaderSubscriber.php index e5bff9c6..6ce958b4 100644 --- a/src/EventSubscriber/NodeLinkHeaderSubscriber.php +++ b/src/EventSubscriber/NodeLinkHeaderSubscriber.php @@ -2,8 +2,16 @@ namespace Drupal\islandora\EventSubscriber; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Drupal\Core\Access\AccessManagerInterface; +use Drupal\Core\Entity\EntityFieldManager; +use Drupal\Core\Entity\EntityTypeManager; +use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\Core\Session\AccountInterface; +use Drupal\islandora\IslandoraUtils; +use Drupal\node\NodeInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Class NodeLinkHeaderSubscriber. @@ -12,6 +20,51 @@ use Symfony\Component\HttpKernel\Event\FilterResponseEvent; */ class NodeLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubscriberInterface { + /** + * Derivative utils. + * + * @var \Drupal\islandora\IslandoraUtils + */ + protected $utils; + + /** + * Constructor. + * + * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager + * The entity type manager. + * @param \Drupal\Core\Entity\EntityFieldManager $entity_field_manager + * The entity field manager. + * @param \Drupal\Core\Access\AccessManagerInterface $access_manager + * The access manager. + * @param \Drupal\Core\Session\AccountInterface $account + * The current user. + * @param \Drupal\Core\Routing\RouteMatchInterface $route_match + * The route match object. + * @param Symfony\Component\HttpFoundation\RequestStack $request_stack + * Request stack (for current request). + * @param \Drupal\islandora\IslandoraUtils $utils + * Derivative utils. + */ + public function __construct( + EntityTypeManager $entity_type_manager, + EntityFieldManager $entity_field_manager, + AccessManagerInterface $access_manager, + AccountInterface $account, + RouteMatchInterface $route_match, + RequestStack $request_stack, + IslandoraUtils $utils + ) { + $this->entityTypeManager = $entity_type_manager; + $this->entityFieldManager = $entity_field_manager; + $this->accessManager = $access_manager; + $this->account = $account; + $this->routeMatch = $route_match; + $this->accessManager = $access_manager; + $this->account = $account; + $this->requestStack = $request_stack; + $this->utils = $utils; + } + /** * Adds node-specific link headers to appropriate responses. * @@ -29,6 +82,7 @@ class NodeLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubs $links = array_merge( $this->generateEntityReferenceLinks($node), + $this->generateRelatedMediaLinks($node), $this->generateRestLinks($node) ); @@ -40,4 +94,28 @@ class NodeLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubs $response->headers->set('Link', $links, FALSE); } + /** + * Generates link headrs for media asssociated with a node. + */ + protected function generateRelatedMediaLinks(NodeInterface $node) { + $links = []; + foreach ($this->utils->getMedia($node) as $media) { + $url = $media->url('canonical', ['absolute' => TRUE]); + foreach ($media->referencedEntities() as $term) { + if ($term->getEntityTypeId() == 'taxonomy_term' && $term->hasField('field_external_uri')) { + $field = $term->get('field_external_uri'); + if (!$field->isEmpty()) { + $link = $field->first()->getValue(); + $uri = $link['uri']; + if (strpos($uri, 'http://pcdm.org/use#') === 0) { + $title = $term->label(); + $links[] = "<$url>; rel=\"related\"; title=\"$title\""; + } + } + } + } + } + return $links; + } + } diff --git a/src/Form/IslandoraSettingsForm.php b/src/Form/IslandoraSettingsForm.php index ebfad39b..60859782 100644 --- a/src/Form/IslandoraSettingsForm.php +++ b/src/Form/IslandoraSettingsForm.php @@ -41,7 +41,7 @@ class IslandoraSettingsForm extends ConfigFormBase { $form[self::BROKER_URL] = [ '#type' => 'textfield', '#title' => $this->t('Broker URL'), - '#default_value' => $config->get(self::BROKER_URL), + '#default_value' => $config->get(self::BROKER_URL) ? $config->get(self::BROKER_URL) : 'tcp://localhost:61613', ]; return parent::buildForm($form, $form_state); diff --git a/src/IslandoraUtils.php b/src/IslandoraUtils.php new file mode 100644 index 00000000..acac02b8 --- /dev/null +++ b/src/IslandoraUtils.php @@ -0,0 +1,370 @@ +entityTypeManager = $entity_type_manager; + $this->entityFieldManager = $entity_field_manager; + $this->entityQuery = $entity_query; + $this->contextManager = $context_manager; + $this->streamWrapperManager = $stream_wrapper_manager; + } + + /** + * Gets nodes that a media belongs to. + * + * @param \Drupal\media\MediaInterface $media + * The Media whose node you are searching for. + * + * @return \Drupal\node\NodeInterface + * Parent node. + */ + public function getParentNode(MediaInterface $media) { + if (!$media->hasField(self::MEDIA_OF_FIELD)) { + return NULL; + } + $field = $media->get(self::MEDIA_OF_FIELD); + if ($field->isEmpty()) { + return NULL; + } + return $field->first() + ->get('entity') + ->getTarget() + ->getValue(); + } + + /** + * Gets media that belong to a node. + * + * @param \Drupal\node\NodeInterface $node + * The parent node. + * + * @return \Drupal\media\MediaInterface[] + * The children Media. + */ + public function getMedia(NodeInterface $node) { + if (!$this->entityTypeManager->getStorage('field_storage_config')->load('media.' . self::MEDIA_OF_FIELD)) { + return []; + } + $mids = $this->entityQuery->get('media')->condition(self::MEDIA_OF_FIELD, $node->id())->execute(); + if (empty($mids)) { + return []; + } + return $this->entityTypeManager->getStorage('media')->loadMultiple($mids); + } + + /** + * Gets media that belong to a node with the specified term. + * + * @param \Drupal\node\NodeInterface $node + * The parent node. + * @param \Drupal\taxonomy\TermInterface $term + * Taxonomy term. + * + * @return \Drupal\media\MediaInterface + * The child Media. + */ + public function getMediaWithTerm(NodeInterface $node, TermInterface $term) { + $mids = $this->entityQuery->get('media') + ->condition(self::MEDIA_OF_FIELD, $node->id()) + ->condition(self::TAGS_FIELD, $term->id()) + ->execute(); + if (empty($mids)) { + return NULL; + } + return $this->entityTypeManager->getStorage('media')->load(reset($mids)); + } + + /** + * Gets Media that reference a File. + * + * @param int $fid + * File id. + * + * @return \Drupal\media\MediaInterface[] + * Array of media. + */ + public function getReferencingMedia($fid) { + // Get media fields that reference files. + $fields = $this->entityQuery->get('field_storage_config') + ->condition('entity_type', 'media') + ->condition('settings.target_type', 'file') + ->execute(); + + // Process field names, stripping off 'media.' and appending 'target_id'. + $conditions = array_map( + function ($field) { + return ltrim($field, 'media.') . '.target_id'; + }, + $fields + ); + + // Query for media that reference this file. + $query = $this->entityQuery->get('media', 'OR'); + foreach ($conditions as $condition) { + $query->condition($condition, $fid); + } + + return $this->entityTypeManager->getStorage('media')->loadMultiple($query->execute()); + } + + /** + * Gets the taxonomy term associated with an external uri. + * + * @param string $uri + * External uri. + * + * @return \Drupal\taxonomy\TermInterface|null + * Term or NULL if not found. + */ + public function getTermForUri($uri) { + $results = $this->entityQuery->get('taxonomy_term') + ->condition(self::EXTERNAL_URI_FIELD . '.uri', $uri) + ->execute(); + + if (empty($results)) { + return NULL; + } + return $this->entityTypeManager->getStorage('taxonomy_term')->load(reset($results)); + } + + /** + * Gets the taxonomy term associated with an external uri. + * + * @param \Drupal\taxonomy\TermInterface $term + * Taxonomy term. + * + * @return string|null + * URI or NULL if not found. + */ + public function getUriForTerm(TermInterface $term) { + if ($term && $term->hasField(self::EXTERNAL_URI_FIELD)) { + $field = $term->get(self::EXTERNAL_URI_FIELD); + if (!$field->isEmpty()) { + $link = $field->first()->getValue(); + return $link['uri']; + } + } + return NULL; + } + + /** + * Executes context reactions for a Node. + * + * @param string $reaction_type + * Reaction type. + * @param \Drupal\node\NodeInterface $node + * Node to evaluate contexts and pass to reaction. + */ + public function executeNodeReactions($reaction_type, NodeInterface $node) { + $provider = new NodeContextProvider($node); + $provided = $provider->getRuntimeContexts([]); + $this->contextManager->evaluateContexts($provided); + + // Fire off index reactions. + foreach ($this->contextManager->getActiveReactions($reaction_type) as $reaction) { + $reaction->execute($node); + } + } + + /** + * Executes context reactions for a Media. + * + * @param string $reaction_type + * Reaction type. + * @param \Drupal\media\MediaInterface $media + * Media to evaluate contexts and pass to reaction. + */ + public function executeMediaReactions($reaction_type, MediaInterface $media) { + $provider = new MediaContextProvider($media); + $provided = $provider->getRuntimeContexts([]); + $this->contextManager->evaluateContexts($provided); + + // Fire off index reactions. + foreach ($this->contextManager->getActiveReactions($reaction_type) as $reaction) { + $reaction->execute($media); + } + } + + /** + * Executes context reactions for a File. + * + * @param string $reaction_type + * Reaction type. + * @param \Drupal\file\FileInterface $file + * File to evaluate contexts and pass to reaction. + */ + public function executeFileReactions($reaction_type, FileInterface $file) { + $provider = new FileContextProvider($file); + $provided = $provider->getRuntimeContexts([]); + $this->contextManager->evaluateContexts($provided); + + // Fire off index reactions. + foreach ($this->contextManager->getActiveReactions($reaction_type) as $reaction) { + $reaction->execute($file); + } + } + + /** + * Executes context reactions for a File. + * + * @param string $reaction_type + * Reaction type. + * @param \Drupal\taxonomy\TermInterface $term + * Term to evaluate contexts and pass to reaction. + */ + public function executeTermReactions($reaction_type, TermInterface $term) { + $provider = new TermContextProvider($term); + $provided = $provider->getRuntimeContexts([]); + $this->contextManager->evaluateContexts($provided); + + // Fire off index reactions. + foreach ($this->contextManager->getActiveReactions($reaction_type) as $reaction) { + $reaction->execute($term); + } + } + + /** + * Executes derivative reactions for a Media and Node. + * + * @param string $reaction_type + * Reaction type. + * @param \Drupal\node\NodeInterface $node + * Node to pass to reaction. + * @param \Drupal\media\MediaInterface $media + * Media to evaluate contexts. + */ + public function executeDerivativeReactions($reaction_type, NodeInterface $node, MediaInterface $media) { + $provider = new MediaContextProvider($media); + $provided = $provider->getRuntimeContexts([]); + $this->contextManager->evaluateContexts($provided); + + // Fire off index reactions. + foreach ($this->contextManager->getActiveReactions($reaction_type) as $reaction) { + $reaction->execute($node); + } + } + + /** + * Evaluates if fields have changed between two instances of a ContentEntity. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The updated entity. + * @param \Drupal\Core\Entity\ContentEntityInterface $original + * The original entity. + */ + public function haveFieldsChanged(ContentEntityInterface $entity, ContentEntityInterface $original) { + + $field_definitions = $this->entityFieldManager->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()); + + $ignore_list = ['vid' => 1, 'changed' => 1, 'path' => 1]; + $field_definitions = array_diff_key($field_definitions, $ignore_list); + + foreach ($field_definitions as $field_name => $field_definition) { + $langcodes = array_keys($entity->getTranslationLanguages()); + + if ($langcodes !== array_keys($original->getTranslationLanguages())) { + // If the list of langcodes has changed, we need to save. + return TRUE; + } + + foreach ($langcodes as $langcode) { + $items = $entity + ->getTranslation($langcode) + ->get($field_name) + ->filterEmptyItems(); + $original_items = $original + ->getTranslation($langcode) + ->get($field_name) + ->filterEmptyItems(); + + // If the field items are not equal, we need to save. + if (!$items->equals($original_items)) { + return TRUE; + } + } + } + + return FALSE; + } + +} diff --git a/src/MediaSource/MediaSourceService.php b/src/MediaSource/MediaSourceService.php index 885e6bea..7e836d96 100644 --- a/src/MediaSource/MediaSourceService.php +++ b/src/MediaSource/MediaSourceService.php @@ -4,13 +4,17 @@ namespace Drupal\islandora\MediaSource; use Drupal\Component\Render\PlainTextOutput; use Drupal\Core\Entity\EntityTypeManager; +use Drupal\Core\Entity\Query\QueryFactory; +use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\StreamWrapper\StreamWrapperManager; use Drupal\Core\Utility\Token; -use Drupal\media_entity\MediaInterface; +use Drupal\file\FileInterface; +use Drupal\media\MediaInterface; +use Drupal\media\MediaTypeInterface; use Drupal\node\NodeInterface; +use Drupal\taxonomy\TermInterface; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\ConflictHttpException; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -40,6 +44,13 @@ class MediaSourceService { */ protected $streamWrapperManager; + /** + * Language manager. + * + * @var \Drupal\Core\Language\LanguageManagerInterface + */ + protected $languageManager; + /** * Token service. * @@ -47,6 +58,13 @@ class MediaSourceService { */ protected $token; + /** + * Entity query. + * + * @var \Drupal\Core\Entity\Query\QueryFactory + */ + protected $entityQuery; + /** * Constructor. * @@ -56,37 +74,45 @@ class MediaSourceService { * The current user. * @param \Drupal\Core\StreamWrapper\StreamWrapperManager $stream_wrapper_manager * Stream wrapper manager. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * Language manager. * @param \Drupal\Core\Utility\Token $token * Token service. + * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query + * Entity query. */ public function __construct( EntityTypeManager $entity_type_manager, AccountInterface $account, StreamWrapperManager $stream_wrapper_manager, - Token $token + LanguageManagerInterface $language_manager, + Token $token, + QueryFactory $entity_query ) { $this->entityTypeManager = $entity_type_manager; $this->account = $account; $this->streamWrapperManager = $stream_wrapper_manager; + $this->languageManager = $language_manager; $this->token = $token; + $this->entityQuery = $entity_query; } /** * Gets the name of a source field for a Media. * - * @param string $media_bundle + * @param string $media_type * Media bundle whose source field you are searching for. * * @return string|null * Field name if it exists in configuration, else NULL. */ - public function getSourceFieldName($media_bundle) { - $bundle = $this->entityTypeManager->getStorage('media_bundle')->load($media_bundle); + public function getSourceFieldName($media_type) { + $bundle = $this->entityTypeManager->getStorage('media_type')->load($media_type); if (!$bundle) { - throw new NotFoundHttpException("Bundle $media_bundle does not exist"); + throw new NotFoundHttpException("Bundle $media_type does not exist"); } - $type_configuration = $bundle->getTypeConfiguration(); + $type_configuration = $bundle->get('source_configuration'); if (!isset($type_configuration['source_field'])) { return NULL; } @@ -97,25 +123,19 @@ class MediaSourceService { /** * Updates a media's source field with the supplied resource. * - * @param \Drupal\media_entity\MediaInterface $media + * @param \Drupal\media\MediaInterface $media * The media to update. * @param resource $resource * New file contents as a resource. * @param string $mimetype * New mimetype of contents. - * @param string $content_length - * New size of contents. - * @param string $filename - * New filename for contents. * * @throws HttpException */ public function updateSourceField( MediaInterface $media, $resource, - $mimetype, - $content_length, - $filename + $mimetype ) { // Get the source field for the media type. $source_field = $this->getSourceFieldName($media->bundle()); @@ -128,44 +148,60 @@ class MediaSourceService { $files = $media->get($source_field)->referencedEntities(); $file = reset($files); - // Set relevant fields on file. - $file->setMimeType($mimetype); - $file->setFilename($filename); - $file->setSize($content_length); + // Update it. + $this->updateFile($file, $resource, $mimetype); - // Validate file extension. - $bundle = $media->bundle(); - $source_field_config = $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$source_field"); - $valid_extensions = $source_field_config->getSetting('file_extensions'); - $errors = file_validate_extensions($file, $valid_extensions); - - if (!empty($errors)) { - throw new BadRequestHttpException("Invalid file extension. Valid types are :$valid_extensions"); + // Set fields provided by type plugin and mapped in bundle configuration + // for the media. + foreach ($media->bundle->entity->getFieldMap() as $source => $destination) { + if ($media->hasField($destination) && $value = $media->getSource()->getMetadata($media, $source)) { + $media->set($destination, $value); + // Ensure width and height are updated on File reference when it's an + // image. Otherwise you run into scaling problems when updating images + // with different sizes. + if ($source == 'width' || $source == 'height') { + $media->get($source_field)->first()->set($source, $value); + } + } } - // Copy the contents over using streams. + $media->save(); + } + + /** + * Updates a File's binary contents on disk. + * + * @param \Drupal\file\FileInterface $file + * File to update. + * @param resource $resource + * Stream holding the new contents. + * @param string $mimetype + * Mimetype of new contents. + */ + protected function updateFile(FileInterface $file, $resource, $mimetype = NULL) { $uri = $file->getFileUri(); $file_stream_wrapper = $this->streamWrapperManager->getViaUri($uri); $path = ""; $file_stream_wrapper->stream_open($uri, 'w', STREAM_REPORT_ERRORS, $path); $file_stream = $file_stream_wrapper->stream_cast(STREAM_CAST_AS_STREAM); - if (stream_copy_to_stream($resource, $file_stream) === FALSE) { - throw new HttpException(500, "The file could not be copied into $uri"); + $content_length = stream_copy_to_stream($resource, $file_stream); + + if ($content_length === FALSE) { + throw new HttpException(500, "Request body could not be copied to $uri"); } - $file->save(); - // Set fields provided by type plugin and mapped in bundle configuration - // for the media. - foreach ($media->bundle->entity->field_map as $source => $destination) { - if ($media->hasField($destination) && $value = $media->getType()->getField($media, $source)) { - $media->set($destination, $value); - } + if ($content_length === 0) { + // Clean up the newly created, empty file. + $file_stream_wrapper->unlink($uri); + throw new BadRequestHttpException("The request contents are empty."); + } + + if (!empty($mimetype)) { + $file->setMimeType($mimetype); } // Flush the image cache for the image so thumbnails get regenerated. image_path_flush($uri); - - $media->save(); } /** @@ -173,123 +209,117 @@ class MediaSourceService { * * @param \Drupal\node\NodeInterface $node * The node to reference the newly created Media. - * @param string $field - * Name of field on the Node to reference the Media. - * @param string $bundle - * Bundle of Media to create. + * @param \Drupal\media\MediaTypeInterface $media_type + * Media type for new media. + * @param \Drupal\taxonomy\TermInterface $taxonomy_term + * Term from the 'Behavior' vocabulary to give to new media. * @param resource $resource * New file contents as a resource. * @param string $mimetype * New mimetype of contents. - * @param string $content_length - * New size of contents. * @param string $filename * New filename for contents. * * @throws HttpException */ - public function addToNode( + public function putToNode( NodeInterface $node, - $field, - $bundle, + MediaTypeInterface $media_type, + TermInterface $taxonomy_term, $resource, $mimetype, - $content_length, $filename ) { - if (!$node->hasField($field)) { - throw new NotFoundHttpException(); - } - - if (!$node->get($field)->isEmpty()) { - throw new ConflictHttpException(); - } - - // Get the source field for the media type. - $source_field = $this->getSourceFieldName($bundle); - if (empty($source_field)) { - throw new NotFoundHttpException("Source field not set for {$media->bundle()} media"); - } - - // Load its config to get file extensions and upload path. - $source_field_config = $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$source_field"); - - // Construct the destination uri. - $directory = $source_field_config->getSetting('file_directory'); - $directory = trim($directory, '/'); - $directory = PlainTextOutput::renderFromHtml($this->token->replace($directory, ['node' => $node])); - $scheme = file_default_scheme(); - $destination_directory = "$scheme://$directory"; - $destination = "$destination_directory/$filename"; - - // Construct the File. - $file = $this->entityTypeManager->getStorage('file')->create([ - 'uid' => $this->account->id(), - 'uri' => $destination, - 'filename' => $filename, - 'filemime' => $mimetype, - 'filesize' => $content_length, - 'status' => FILE_STATUS_PERMANENT, - ]); - - // Validate file extension. - $source_field_config = $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$source_field"); - $valid_extensions = $source_field_config->getSetting('file_extensions'); - $errors = file_validate_extensions($file, $valid_extensions); - - if (!empty($errors)) { - throw new BadRequestHttpException("Invalid file extension. Valid types are $valid_extensions"); - } - - if (!file_prepare_directory($destination_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { - throw new HttpException(500, "The destination directory does not exist, could not be created, or is not writable"); - } - - // Copy the contents over using streams. - $uri = $file->getFileUri(); - $file_stream_wrapper = $this->streamWrapperManager->getViaUri($uri); - $path = ""; - $file_stream_wrapper->stream_open($uri, 'w', STREAM_REPORT_ERRORS, $path); - $file_stream = $file_stream_wrapper->stream_cast(STREAM_CAST_AS_STREAM); - if (stream_copy_to_stream($resource, $file_stream) === FALSE) { - throw new HttpException(500, "The file could not be copied into $uri"); - } - $file->save(); - - // Construct the Media. - $media_struct = [ - 'bundle' => $bundle, - 'uid' => $this->account->id(), - 'name' => $filename, - "$source_field" => [ - 'target_id' => $file->id(), - ], - ]; - if ($source_field_config->getSetting('alt_field') && $source_field_config->getSetting('alt_field_required')) { - $media_struct[$source_field]['alt'] = $filename; + $existing = $this->entityQuery->get('media') + ->condition('field_media_of', $node->id()) + ->condition('field_tags', $taxonomy_term->id()) + ->execute(); + + if (!empty($existing)) { + // Just update already existing media. + $media = $this->entityTypeManager->getStorage('media')->load(reset($existing)); + $this->updateSourceField( + $media, + $resource, + $mimetype + ); + return FALSE; } - $media = $this->entityTypeManager->getStorage('media')->create($media_struct); + else { + // Otherwise, the media doesn't exist yet. + // So make everything by hand. + // Get the source field for the media type. + $bundle = $media_type->id(); + $source_field = $this->getSourceFieldName($bundle); + if (empty($source_field)) { + throw new NotFoundHttpException("Source field not set for $bundle media"); + } - // Set fields provided by type plugin and mapped in bundle configuration - // for the media. - foreach ($media->bundle->entity->field_map as $source => $destination) { - if ($media->hasField($destination) && $value = $media->getType()->getField($media, $source)) { - $media->set($destination, $value); + // Load its config to get file extensions and upload path. + $source_field_config = $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$source_field"); + + // Construct the destination uri. + $directory = $source_field_config->getSetting('file_directory'); + $directory = trim($directory, '/'); + $directory = PlainTextOutput::renderFromHtml($this->token->replace($directory, ['node' => $node])); + $scheme = file_default_scheme(); + $destination_directory = "$scheme://$directory"; + $destination = "$destination_directory/$filename"; + + // Construct the File. + $file = $this->entityTypeManager->getStorage('file')->create([ + 'uid' => $this->account->id(), + 'uri' => $destination, + 'filename' => $filename, + 'filemime' => $mimetype, + 'status' => FILE_STATUS_PERMANENT, + ]); + + // Validate file extension. + $source_field_config = $this->entityTypeManager->getStorage('field_config')->load("media.$bundle.$source_field"); + $valid_extensions = $source_field_config->getSetting('file_extensions'); + $errors = file_validate_extensions($file, $valid_extensions); + + if (!empty($errors)) { + throw new BadRequestHttpException("Invalid file extension. Valid types are $valid_extensions"); } - } - // Flush the image cache for the image so thumbnails get regenerated. - image_path_flush($uri); + if (!file_prepare_directory($destination_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) { + throw new HttpException(500, "The destination directory does not exist, could not be created, or is not writable"); + } - $media->save(); + // Copy over the file content. + $this->updateFile($file, $resource, $mimetype); + $file->save(); + + // Construct the Media. + $media_struct = [ + 'bundle' => $bundle, + 'uid' => $this->account->id(), + 'name' => $filename, + 'langcode' => $this->languageManager->getDefaultLanguage()->getId(), + "$source_field" => [ + 'target_id' => $file->id(), + ], + 'field_tags' => [ + 'target_id' => $taxonomy_term->id(), + ], + 'field_media_of' => [ + 'target_id' => $node->id(), + ], + ]; + + // Set alt text. + if ($source_field_config->getSetting('alt_field') && $source_field_config->getSetting('alt_field_required')) { + $media_struct[$source_field]['alt'] = $filename; + } - // Update the Node. - $node->get($field)->appendItem($media); - $node->save(); + $media = $this->entityTypeManager->getStorage('media')->create($media_struct); + $media->save(); + return $media; + } - // Return the created media. - return $media; } } diff --git a/src/ParamConverter/UuidEntityConverter.php b/src/ParamConverter/UuidEntityConverter.php deleted file mode 100644 index 4ac1fbd7..00000000 --- a/src/ParamConverter/UuidEntityConverter.php +++ /dev/null @@ -1,29 +0,0 @@ -entityManager->loadEntityByUuid($name, $value); - } - - /** - * {@inheritdoc} - */ - public function applies($definition, $name, Route $route) { - return (!empty($definition['type']) && $definition['type'] == 'uuid'); - } - -} diff --git a/src/Plugin/Action/DeleteMedia.php b/src/Plugin/Action/DeleteMedia.php new file mode 100644 index 00000000..82c4d842 --- /dev/null +++ b/src/Plugin/Action/DeleteMedia.php @@ -0,0 +1,35 @@ +delete(); + } + } + + /** + * {@inheritdoc} + */ + public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { + return $object->access('delete', $account, $return_as_object); + } + +} diff --git a/src/Plugin/Action/DeleteMediaAndFile.php b/src/Plugin/Action/DeleteMediaAndFile.php new file mode 100644 index 00000000..2e9d1df1 --- /dev/null +++ b/src/Plugin/Action/DeleteMediaAndFile.php @@ -0,0 +1,120 @@ +mediaSourceService = $media_source_service; + $this->connection = $connection; + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('islandora.media_source_service'), + $container->get('database'), + $container->get('logger.channel.islandora') + ); + } + + /** + * {@inheritdoc} + */ + public function execute($entity = NULL) { + if (!$entity) { + return; + } + + $transaction = $this->connection->startTransaction(); + + try { + // Delete all the source files and then the media. + $source_field = $this->mediaSourceService->getSourceFieldName($entity->bundle()); + foreach ($entity->get($source_field)->referencedEntities() as $file) { + $file->delete(); + } + $entity->delete(); + } + catch (\Exception $e) { + $transaction->rollBack(); + $this->logger->error("Cannot delete media and its files. Rolling back transaction: @msg", ["@msg" => $e->getMessage()]); + } + } + + /** + * {@inheritdoc} + */ + public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { + return $object->access('delete', $account, $return_as_object); + } + +} diff --git a/src/Plugin/Action/EmitTermEvent.php b/src/Plugin/Action/EmitTermEvent.php new file mode 100644 index 00000000..409fd1d3 --- /dev/null +++ b/src/Plugin/Action/EmitTermEvent.php @@ -0,0 +1,16 @@ +contentTypeStorage = $content_type_storage; - $this->entityFieldManager = $entity_field_manager; - $this->entityQuery = $entity_query; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $container->get('entity_type.manager')->getStorage('node_type'), - $container->get('entity_field.manager'), - $container->get('entity.query'), - $configuration, - $plugin_id, - $plugin_definition - ); - } - - /** - * {@inheritdoc} - */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - // Get all entity reference fields that target Media. - $media_reference_fields = $this->entityQuery->get('field_storage_config') - ->condition('entity_type', 'node') - ->condition('type', 'entity_reference') - ->condition('settings.target_type', 'media') - ->execute(); - - // Trim off the preceding 'node.'. - $media_reference_fields = array_map( - function ($field) { - return ltrim($field, 'node.'); - }, - $media_reference_fields - ); - - // Flip the results so it can be used in an array_intersect_key later on. - $media_reference_fields = array_flip($media_reference_fields); - - // Get all content types. - $content_types = $this->contentTypeStorage->loadMultiple(); - - // Build up the 2D options array. - $options = []; - foreach ($content_types as $content_type) { - // Filter fields to those we know are media references. - $all_fields = $this->entityFieldManager->getFieldDefinitions('node', $content_type->id()); - $reference_fields = array_intersect_key($all_fields, $media_reference_fields); - - // First dimension is keyed by the content type label. - // Second dimension is keyed by the content_type machine name concatenated - // with the field name. The content type machine name is needed for - // disambiguation, otherwise fields attached to multiple content types - // have unexpected behaviour when submitting the form. - foreach ($reference_fields as $field_name => $field_definition) { - $content_type_label = $content_type->label(); - $field_key = $content_type->id() . '|' . $field_name; - $field_label = $field_definition->getLabel(); - $options[$content_type_label][$field_key] = $field_label; - } - } - - // Create the 2D select. - $form['field'] = [ - '#title' => $this->t('Referenced As'), - '#description' => $this->t('The field that references the Media.'), - '#type' => 'select', - '#options' => $options, - '#default_value' => isset($this->configuration['field']) ? $this->configuration['field'] : '', - '#size' => 10, - ]; - - return parent::buildConfigurationForm($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - $this->configuration['field'] = $form_state->getValue('field'); - parent::submitConfigurationForm($form, $form_state); - } - - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return ['field' => ''] + parent::defaultConfiguration(); - } - - /** - * {@inheritdoc} - */ - public function summary() { - return $this->t('The Media is referenced by a Node using the specified field.'); - } - - /** - * {@inheritdoc} - */ - public function evaluate() { - // Check to see that the media is referenced by a node of the specified - // type using the specified field. - $media = $this->getContextValue('media'); - $field_key = $this->configuration['field']; - list($content_type, $field) = explode('|', $field_key); - return $this->entityQuery->get('node') - ->condition('type', $content_type) - ->condition("$field.target_id", $media->id()) - ->execute(); - } - -} diff --git a/src/Plugin/Condition/IsTerm.php b/src/Plugin/Condition/IsTerm.php new file mode 100644 index 00000000..e6ca5c17 --- /dev/null +++ b/src/Plugin/Condition/IsTerm.php @@ -0,0 +1,43 @@ +t('The entity is a Taxonomy Term'); + } + + /** + * {@inheritdoc} + */ + public function getContextMapping() { + $this->configuration['context_mapping'] = ['taxonomy_term' => '@islandora.taxonomy_term_route_context_provider:taxonomy_term']; + return parent::getContextMapping(); + } + + /** + * {@inheritdoc} + */ + public function evaluate() { + return $this->getContextValue('taxonomy_term') instanceof TermInterface; + } + +} diff --git a/src/Plugin/Condition/MediaHasTerm.php b/src/Plugin/Condition/MediaHasTerm.php new file mode 100644 index 00000000..1af6f752 --- /dev/null +++ b/src/Plugin/Condition/MediaHasTerm.php @@ -0,0 +1,41 @@ +getContextValue('media'); + if (!$media) { + return FALSE; + } + return $this->evaluateEntity($media); + } + + /** + * {@inheritdoc} + */ + public function summary() { + if (!empty($this->configuration['negate'])) { + return $this->t('The media is not associated with taxonomy term with uri @uri.', ['@uri' => $this->configuration['uri']]); + } + else { + return $this->t('The media is associated with taxonomy term with uri @uri.', ['@uri' => $this->configuration['uri']]); + } + } + +} diff --git a/src/Plugin/Condition/NodeHasTerm.php b/src/Plugin/Condition/NodeHasTerm.php new file mode 100644 index 00000000..9b96098c --- /dev/null +++ b/src/Plugin/Condition/NodeHasTerm.php @@ -0,0 +1,172 @@ +utils = $utils; + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('islandora.utils'), + $container->get('entity_type.manager') + ); + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + if (isset($this->configuration['uri']) && !empty($this->configuration['uri'])) { + $default = $this->utils->getTermForUri($this->configuration['uri']); + } + else { + $default = NULL; + } + + $form['term'] = [ + '#type' => 'entity_autocomplete', + '#title' => $this->t('Term'), + '#tags' => TRUE, + '#required' => TRUE, + '#default_value' => $default, + '#target_type' => 'taxonomy_term', + ]; + + return parent::buildConfigurationForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + // Set URI for term if possible. + $this->configuration['uri'] = NULL; + $value = $form_state->getValue('term'); + if (!empty($value)) { + $tid = $value[0]['target_id']; + $term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid); + $uri = $this->utils->getUriForTerm($term); + if ($uri) { + $this->configuration['uri'] = $uri; + } + } + parent::submitConfigurationForm($form, $form_state); + } + + /** + * {@inheritdoc} + */ + public function evaluate() { + $node = $this->getContextValue('node'); + if (!$node) { + return FALSE; + } + return $this->evaluateEntity($node); + } + + /** + * Evaluates if an entity has the specified term(s). + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity to evalute. + * + * @return bool + * TRUE if entity has all the specified term(s), otherwise FALSE. + */ + protected function evaluateEntity(EntityInterface $entity) { + foreach ($entity->referencedEntities() as $referenced_entity) { + if ($referenced_entity->getEntityTypeId() == 'taxonomy_term' + && $referenced_entity->hasField(IslandoraUtils::EXTERNAL_URI_FIELD)) { + $field = $referenced_entity->get(IslandoraUtils::EXTERNAL_URI_FIELD); + if (!$field->isEmpty()) { + $link = $field->first()->getValue(); + if ($link['uri'] == $this->configuration['uri']) { + return $this->isNegated() ? FALSE : TRUE; + } + } + } + } + + return $this->isNegated() ? TRUE : FALSE; + } + + /** + * {@inheritdoc} + */ + public function summary() { + if (!empty($this->configuration['negate'])) { + return $this->t('The node is not associated with taxonomy term with uri @uri.', ['@uri' => $this->configuration['uri']]); + } + else { + return $this->t('The node is associated with taxonomy term with uri @uri.', ['@uri' => $this->configuration['uri']]); + } + } + +} diff --git a/src/Plugin/Condition/ParentNodeHasTerm.php b/src/Plugin/Condition/ParentNodeHasTerm.php new file mode 100644 index 00000000..371c373e --- /dev/null +++ b/src/Plugin/Condition/ParentNodeHasTerm.php @@ -0,0 +1,45 @@ +getContextValue('media'); + if (!$media) { + return FALSE; + } + $node = $this->utils->getParentNode($media); + if (!$node) { + return FALSE; + } + return $this->evaluateEntity($node); + } + + /** + * {@inheritdoc} + */ + public function summary() { + if (!empty($this->configuration['negate'])) { + return $this->t('The parent node is not associated with taxonomy term with uri @uri.', ['@uri' => $this->configuration['uri']]); + } + else { + return $this->t('The parent node is associated with taxonomy term with uri @uri.', ['@uri' => $this->configuration['uri']]); + } + } + +} diff --git a/src/Plugin/ContextReaction/DerivativeReaction.php b/src/Plugin/ContextReaction/DerivativeReaction.php new file mode 100644 index 00000000..7ddaed4f --- /dev/null +++ b/src/Plugin/ContextReaction/DerivativeReaction.php @@ -0,0 +1,15 @@ +t('Change the form display for an entity'); + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + // Build up options array. + $entity_types = $this->entityTypeManager->getDefinitions(); + $form_displays = $this->entityTypeManager->getStorage('entity_form_display')->loadMultiple(); + + $options = []; + + foreach ($form_displays as $form_display) { + $entity_type = $form_display->getTargetEntityTypeId(); + $entity_type_label = $entity_types[$entity_type]->getLabel()->render(); + $mode = $form_display->getMode(); + $options[$entity_type_label]["$entity_type.$mode"] = ucfirst($mode); + } + + // Provide a select to choose display mode. + $config = $this->getConfiguration(); + $form[self::MODE] = [ + '#title' => $this->t('Form Mode'), + '#description' => $this->t("The selected form mode will be used if conditions are met."), + '#type' => 'select', + '#options' => $options, + '#default_value' => isset($config[self::MODE]) ? $config[self::MODE] : '', + ]; + return $form; + } + +} diff --git a/src/Plugin/ContextReaction/ViewModeAlterReaction.php b/src/Plugin/ContextReaction/ViewModeAlterReaction.php new file mode 100644 index 00000000..2508cea2 --- /dev/null +++ b/src/Plugin/ContextReaction/ViewModeAlterReaction.php @@ -0,0 +1,53 @@ +t('Change the view mode for an entity'); + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + // Build up options array. + $entity_types = $this->entityTypeManager->getDefinitions(); + $view_modes = $this->entityTypeManager->getStorage('entity_view_mode')->loadMultiple(); + + $options = []; + + foreach ($view_modes as $view_mode) { + $exploded = explode('.', $view_mode->id()); + $entity_type_label = $entity_types[$exploded[0]]->getLabel()->render(); + $options[$entity_type_label][$view_mode->id()] = $view_mode->label(); + } + + // Provide a select to choose display mode. + $config = $this->getConfiguration(); + $form[self::MODE] = [ + '#title' => $this->t('View Mode'), + '#description' => $this->t("The selected view mode will be used if conditions are met."), + '#type' => 'select', + '#options' => $options, + '#default_value' => isset($config[self::MODE]) ? $config[self::MODE] : '', + ]; + return $form; + } + +} diff --git a/src/StompFactory.php b/src/StompFactory.php index 3f170182..0e3528c1 100644 --- a/src/StompFactory.php +++ b/src/StompFactory.php @@ -26,6 +26,11 @@ class StompFactory { $settings = $config->get(IslandoraSettingsForm::CONFIG_NAME); $brokerUrl = $settings->get(IslandoraSettingsForm::BROKER_URL); + // Try a sensible default if one hasn't been configured. + if (empty($brokerUrl)) { + $brokerUrl = "tcp://localhost:61613"; + } + $client = new Client($brokerUrl); return new StatefulStomp($client); } diff --git a/src/VersionCounter/VersionCounter.php b/src/VersionCounter/VersionCounter.php deleted file mode 100644 index b3df5884..00000000 --- a/src/VersionCounter/VersionCounter.php +++ /dev/null @@ -1,80 +0,0 @@ -database = $database; - } - - /** - * {@inheritdoc} - */ - public function create($uuid) { - $this->database->insert('islandora_version_count') - ->fields( - [ - 'uuid' => $uuid, - ] - ) - ->execute(); - } - - /** - * {@inheritdoc} - */ - public function get($uuid) { - $query = $this->database->select('islandora_version_count', 'ivc') - ->condition('ivc.uuid', $uuid) - ->fields('ivc', ['count']); - - $results = $query->execute(); - - foreach ($results as $result) { - return $result->count; - } - - return -1; - } - - /** - * {@inheritdoc} - */ - public function increment($uuid) { - return $this->database->update('islandora_version_count') - ->expression('count', 'count + 1') - ->condition('uuid', $uuid) - ->execute(); - } - - /** - * {@inheritdoc} - */ - public function delete($uuid) { - return $this->database->delete('islandora_version_count') - ->condition('uuid', $uuid) - ->execute(); - } - -} diff --git a/src/VersionCounter/VersionCounterInterface.php b/src/VersionCounter/VersionCounterInterface.php deleted file mode 100644 index 5ee83849..00000000 --- a/src/VersionCounter/VersionCounterInterface.php +++ /dev/null @@ -1,59 +0,0 @@ -container->get('entity_type.manager')->getStorage('node_type')->create([ - 'type' => 'test_type_with_reference', - 'label' => 'Test Type With Reference', + $this->node = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'Referencer', ]); - $test_type_with_reference->save(); - - // Add two entity reference fields. - // One for nodes and one for media. - $this->createEntityReferenceField('node', 'test_type_with_reference', 'field_media', 'Media Entity', 'media', 'default', [], 2); + $this->node->save(); - $this->referencer = $this->container->get('entity_type.manager')->getStorage('node')->create([ - 'type' => 'test_type_with_reference', - 'title' => 'Referencer', + $this->preservationMasterTerm = $this->container->get('entity_type.manager')->getStorage('taxonomy_term')->create([ + 'name' => 'Preservation Master', + 'vid' => $this->testVocabulary->id(), + 'field_external_uri' => [['uri' => "http://pcdm.org/use#PreservationMasterFile"]], ]); - $this->referencer->save(); + $this->preservationMasterTerm->save(); } /** - * @covers \Drupal\islandora\Controller\MediaSourceController::addToNode + * @covers \Drupal\islandora\Controller\MediaSourceController::putToNode */ public function testAddMediaToNode() { // Hack out the guzzle client. $client = $this->getSession()->getDriver()->getClient()->getClient(); $add_to_node_url = Url::fromRoute( - 'islandora.media_source_add_to_node', + 'islandora.media_source_put_to_node', [ - 'node' => $this->referencer->id(), - 'field' => 'field_media', - 'bundle' => 'tn', + 'node' => $this->node->id(), + 'media_type' => $this->testMediaType->id(), + 'taxonomy_term' => $this->preservationMasterTerm->id(), ] ) ->setAbsolute() ->toString(); $bad_node_url = Url::fromRoute( - 'islandora.media_source_add_to_node', + 'islandora.media_source_put_to_node', [ 'node' => 123456, - 'field' => 'field_media', - 'bundle' => 'tn', + 'media_type' => $this->testMediaType->id(), + 'taxonomy_term' => $this->preservationMasterTerm->id(), ] ) ->setAbsolute() ->toString(); - $image = file_get_contents(__DIR__ . '/../../static/test.jpeg'); + $file_contents = file_get_contents(__DIR__ . '/../../fixtures/test_file.txt'); // Test different permissions scenarios. $options = [ 'http_errors' => FALSE, 'headers' => [ - 'Content-Type' => 'image/jpeg', - 'Content-Disposition' => 'attachment; filename="test.jpeg"', + 'Content-Type' => 'text/plain', + 'Content-Disposition' => 'attachment; filename="test_file.txt"', ], - 'body' => $image, + 'body' => $file_contents, ]; // 403 if you don't have permissions to update the node. $account = $this->drupalCreateUser([ 'access content', - 'create media', ]); $this->drupalLogin($account); $options['auth'] = [$account->getUsername(), $account->pass_raw]; - $response = $client->request('POST', $add_to_node_url, $options); + $response = $client->request('PUT', $add_to_node_url, $options); $this->assertTrue($response->getStatusCode() == 403, "Expected 403, received {$response->getStatusCode()}"); // Bad node URL should return 404, regardless of permissions. // Just making sure our custom access function doesn't obfuscate responses. - $response = $client->request('POST', $bad_node_url, $options); + $response = $client->request('PUT', $bad_node_url, $options); $this->assertTrue($response->getStatusCode() == 404, "Expected 404, received {$response->getStatusCode()}"); // 403 if you don't have permissions to create Media. @@ -107,7 +109,7 @@ class AddMediaToNodeTest extends IslandoraFunctionalTestBase { ]); $this->drupalLogin($account); $options['auth'] = [$account->getUsername(), $account->pass_raw]; - $response = $client->request('POST', $add_to_node_url, $options); + $response = $client->request('PUT', $add_to_node_url, $options); $this->assertTrue($response->getStatusCode() == 403, "Expected 403, received {$response->getStatusCode()}"); // Now with proper credentials, test responses given to malformed requests. @@ -122,11 +124,11 @@ class AddMediaToNodeTest extends IslandoraFunctionalTestBase { 'auth' => [$account->getUsername(), $account->pass_raw], 'http_errors' => FALSE, 'headers' => [ - 'Content-Disposition' => 'attachment; filename="test.jpeg"', + 'Content-Disposition' => 'attachment; filename="test_file.txt"', ], - 'body' => $image, + 'body' => $file_contents, ]; - $response = $client->request('POST', $add_to_node_url, $options); + $response = $client->request('PUT', $add_to_node_url, $options); $this->assertTrue($response->getStatusCode() == 400, "Expected 400, received {$response->getStatusCode()}"); // Request without Content-Disposition header should fail with 400. @@ -134,11 +136,11 @@ class AddMediaToNodeTest extends IslandoraFunctionalTestBase { 'auth' => [$account->getUsername(), $account->pass_raw], 'http_errors' => FALSE, 'headers' => [ - 'Content-Type' => 'image/jpeg', + 'Content-Type' => 'text/plain', ], - 'body' => $image, + 'body' => $file_contents, ]; - $response = $client->request('POST', $add_to_node_url, $options); + $response = $client->request('PUT', $add_to_node_url, $options); $this->assertTrue($response->getStatusCode() == 400, "Expected 400, received {$response->getStatusCode()}"); // Request with malformed Content-Disposition header should fail with 400. @@ -146,12 +148,12 @@ class AddMediaToNodeTest extends IslandoraFunctionalTestBase { 'auth' => [$account->getUsername(), $account->pass_raw], 'http_errors' => FALSE, 'headers' => [ - 'Content-Type' => 'image/jpeg', - 'Content-Disposition' => 'garbage; filename="test.jpeg"', + 'Content-Type' => 'text/plain', + 'Content-Disposition' => 'garbage; filename="test_file.txt"', ], - 'body' => $image, + 'body' => $file_contents, ]; - $response = $client->request('POST', $add_to_node_url, $options); + $response = $client->request('PUT', $add_to_node_url, $options); $this->assertTrue($response->getStatusCode() == 400, "Expected 400, received {$response->getStatusCode()}"); // Request without body should fail with 400. @@ -159,11 +161,11 @@ class AddMediaToNodeTest extends IslandoraFunctionalTestBase { 'auth' => [$account->getUsername(), $account->pass_raw], 'http_errors' => FALSE, 'headers' => [ - 'Content-Type' => 'image/jpeg', - 'Content-Disposition' => 'attachment; filename="test.jpeg"', + 'Content-Type' => 'text/plain', + 'Content-Disposition' => 'attachment; filename="test_file.txt"', ], ]; - $response = $client->request('POST', $add_to_node_url, $options); + $response = $client->request('PUT', $add_to_node_url, $options); $this->assertTrue($response->getStatusCode() == 400, "Expected 400, received {$response->getStatusCode()}"); // Test properly formed requests with bad parameters in the route. @@ -171,53 +173,57 @@ class AddMediaToNodeTest extends IslandoraFunctionalTestBase { 'auth' => [$account->getUsername(), $account->pass_raw], 'http_errors' => FALSE, 'headers' => [ - 'Content-Type' => 'image/jpeg', - 'Content-Disposition' => 'attachment; filename="test.jpeg"', + 'Content-Type' => 'text/plain', + 'Content-Disposition' => 'attachment; filename="test_file.txt"', ], - 'body' => $image, + 'body' => $file_contents, ]; // Bad node id should return 404 even with proper permissions. - $response = $client->request('POST', $bad_node_url, $options); + $response = $client->request('PUT', $bad_node_url, $options); $this->assertTrue($response->getStatusCode() == 404, "Expected 404, received {$response->getStatusCode()}"); - // Bad field name in url should return 404. - $bad_field_url = Url::fromRoute( - 'islandora.media_source_add_to_node', + // Bad media type in url should return 404. + $bad_media_type_url = Url::fromRoute( + 'islandora.media_source_put_to_node', [ - 'node' => $this->referencer->id(), - 'field' => 'field_garbage', - 'bundle' => 'tn', + 'node' => $this->node->id(), + 'media_type' => 'derp', + 'taxonomy_term' => $this->preservationMasterTerm->id(), ] ) ->setAbsolute() ->toString(); - $response = $client->request('POST', $bad_field_url, $options); + $response = $client->request('PUT', $bad_media_type_url, $options); $this->assertTrue($response->getStatusCode() == 404, "Expected 404, received {$response->getStatusCode()}"); - // Bad bundle name in url should return 404. - $bad_bundle_url = Url::fromRoute( - 'islandora.media_source_add_to_node', + // Bad taxonomy term in url should return 404. + $bad_term_url = Url::fromRoute( + 'islandora.media_source_put_to_node', [ - 'node' => $this->referencer->id(), - 'field' => 'field_media', - 'bundle' => 'garbage', + 'node' => $this->node->id(), + 'media_type' => $this->testMediaType->id(), + 'taxonomy_term' => 123456, ] ) ->setAbsolute() ->toString(); - $response = $client->request('POST', $bad_bundle_url, $options); + $response = $client->request('PUT', $bad_term_url, $options); $this->assertTrue($response->getStatusCode() == 404, "Expected 404, received {$response->getStatusCode()}"); // Should be successful with proper url, options, and permissions. - $response = $client->request('POST', $add_to_node_url, $options); + $options = [ + 'auth' => [$account->getUsername(), $account->pass_raw], + 'http_errors' => FALSE, + 'headers' => [ + 'Content-Type' => 'text/plain', + 'Content-Disposition' => 'attachment; filename="test_file.txt"', + ], + 'body' => $file_contents, + ]; + $response = $client->request('PUT', $add_to_node_url, $options); $this->assertTrue($response->getStatusCode() == 201, "Expected 201, received {$response->getStatusCode()}"); $this->assertTrue(!empty($response->getHeader("Location")), "Response must include Location header"); - - // Should fail with 409 if Node already references a media using the field - // (i.e. the previous call was successful). - $response = $client->request('POST', $add_to_node_url, $options); - $this->assertTrue($response->getStatusCode() == 409, "Expected 409, received {$response->getStatusCode()}"); } } diff --git a/tests/src/Functional/DeleteMediaTest.php b/tests/src/Functional/DeleteMediaTest.php new file mode 100644 index 00000000..1a3673aa --- /dev/null +++ b/tests/src/Functional/DeleteMediaTest.php @@ -0,0 +1,88 @@ +createUser(['create media']); + + list($this->file, $this->media) = $this->makeMediaAndFile($account); + } + + /** + * Tests the delete_media action. + * + * @covers \Drupal\islandora\Plugin\Action\DeleteMedia::execute + */ + public function testDeleteMedia() { + $action = $this->container->get('entity_type.manager')->getStorage('action')->load('delete_media'); + + $mid = $this->media->id(); + $fid = $this->file->id(); + + $action->execute([$this->media]); + + // Attempt to reload the entities. + // Media should be gone but file should remain. + $this->assertTrue( + !$this->container->get('entity_type.manager')->getStorage('media')->load($mid), + "Media must be deleted after running action" + ); + $this->assertTrue( + $this->container->get('entity_type.manager')->getStorage('file')->load($fid), + "File must remain after running action" + ); + } + + /** + * Tests the delete_media_and_file action. + * + * @covers \Drupal\islandora\Plugin\Action\DeleteMediaAndFile::execute + */ + public function testDeleteMediaAndFile() { + $action = $this->container->get('entity_type.manager')->getStorage('action')->load('delete_media_and_file'); + + $mid = $this->media->id(); + $fid = $this->file->id(); + + $action->execute([$this->media]); + + // Attempt to reload the entities. + // Both media and file should be gone. + $this->assertTrue( + !$this->container->get('entity_type.manager')->getStorage('media')->load($mid), + "Media must be deleted after running action" + ); + $this->assertTrue( + !$this->container->get('entity_type.manager')->getStorage('file')->load($fid), + "File must be deleted after running action" + ); + } + +} diff --git a/tests/src/Functional/DerivativeReactionTest.php b/tests/src/Functional/DerivativeReactionTest.php new file mode 100644 index 00000000..38ec6ffa --- /dev/null +++ b/tests/src/Functional/DerivativeReactionTest.php @@ -0,0 +1,79 @@ +node = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'Test Node', + ]); + $this->node->save(); + } + + /** + * @covers \Drupal\islandora\IslandoraUtils::executeDerivativeReactions + */ + public function testExecuteDerivativeReaction() { + // Create a test user. + $account = $this->drupalCreateUser([ + 'bypass node access', + 'administer contexts', + 'administer actions', + 'create media', + 'update media', + ]); + $this->drupalLogin($account); + + $this->createContext('Test', 'test'); + $this->addPresetReaction('test', 'derivative', 'hello_world'); + + // Create a new media. + $values = [ + 'name[0][value]' => 'Test Media', + 'files[field_media_file_0]' => __DIR__ . '/../../fixtures/test_file.txt', + 'field_media_of[0][target_id]' => 'Test Node', + ]; + $this->drupalPostForm('media/add/' . $this->testMediaType->id(), $values, t('Save')); + + // field_media_of is set and there's a file, so derivatives should fire. + $this->assertSession()->pageTextContains("Hello World!"); + + // Change media but not file, so derivatives should not fire. + $values = [ + 'name[0][value]' => 'Test Media Changed', + ]; + $this->postEntityEditForm($this->getUrl(), $values, 'Save'); + $media_url = $this->getUrl(); + $this->assertSession()->pageTextNotContains("Hello World!"); + + // Change the file, so derivatives should fire again. + $values = [ + 'files[field_media_file_0]' => __DIR__ . '/../../fixtures/test_file2.txt', + ]; + $this->drupalGet($media_url . '/edit'); + $this->getSession()->getPage()->pressButton(t('Remove')); + $this->getSession()->getPage()->fillField('files[field_media_file_0]', __DIR__ . '/../../fixtures/test_file2.txt'); + $this->getSession()->getPage()->pressButton(t('Save')); + $this->assertSession()->pageTextContains("Hello World!"); + } + +} diff --git a/tests/src/Functional/EmitNodeEventTest.php b/tests/src/Functional/EmitNodeEventTest.php index 06aef6c6..083c1ead 100644 --- a/tests/src/Functional/EmitNodeEventTest.php +++ b/tests/src/Functional/EmitNodeEventTest.php @@ -9,70 +9,13 @@ namespace Drupal\Tests\islandora\Functional; */ class EmitNodeEventTest extends IslandoraFunctionalTestBase { - /** - * {@inheritdoc} - */ - public function setUp() { - parent::setUp(); - - // Set up JWT stuff. - $key_value = <<container->get('entity_type.manager')->getStorage('key')->create([ - 'id' => 'test', - 'label' => 'Test', - 'key_type' => 'jwt_rs', - 'key_type_settings' => [ - 'algorithm' => 'RS256', - ], - 'key_provider' => 'config', - 'key_provider_settings' => [ - 'key_value' => $key_value, - ], - ]); - $key->save(); - - $jwt_config = $this->container->get('config.factory')->getEditable('jwt.config'); - $jwt_config->set('algorithm', 'RS256'); - $jwt_config->set('key_id', 'test'); - $jwt_config->save(TRUE); - } - /** * @covers \Drupal\islandora\ContextProvider\NodeContextProvider::__construct * @covers \Drupal\islandora\ContextProvider\NodeContextProvider::getRuntimeContexts * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateCreateEvent + * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateEvent * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts * @covers \Drupal\islandora\IslandoraContextManager::applyContexts * @covers \Drupal\islandora\Plugin\Condition\IsNode::evaluate @@ -81,7 +24,7 @@ EOD; * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute * @covers \Drupal\islandora\IslandoraServiceProvider::alter */ - public function testNodeCreateEvent() { + public function testEmitEvent() { // Create a test user. $account = $this->drupalCreateUser([ 'bypass node access', @@ -91,7 +34,7 @@ EOD; $this->drupalLogin($account); // Create an action to emit a node event. - $action_id = $this->createEmitAction('node', 'create'); + $action_id = $this->createEmitAction('node', 'Create'); // Create a context and add the action as an index reaction. $this->createContext('Test', 'test'); @@ -107,338 +50,6 @@ EOD; $this->verifyMessageIsSent($queue, 'Create'); } - /** - * @covers \Drupal\islandora\ContextProvider\MediaContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\MediaContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateCreateEvent - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsMedia::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testMediaCreateEvent() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'administer contexts', - 'administer actions', - 'view media', - 'create media', - ]); - $this->drupalLogin($account); - - // Create an action to emit a media event. - $action_id = $this->createEmitAction('media', 'create'); - - // Create a context and add the action as an index reaction. - $this->createContext('Test', 'test'); - $this->addCondition('test', 'is_media'); - $this->addPresetReaction('test', 'index', $action_id); - $this->assertSession()->statusCodeEquals(200); - - // Create a new media, which publishes the create event. - $this->createThumbnailWithFile(); - - // Validate the message actually gets sent. - $queue = str_replace('_', '-', $action_id); - $this->verifyMessageIsSent($queue, 'Create'); - } - - /** - * @covers \Drupal\islandora\ContextProvider\FileContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\FileContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateCreateEvent - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsFile::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testFileCreateEvent() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'administer contexts', - 'administer actions', - 'view media', - 'create media', - ]); - $this->drupalLogin($account); - - // Create an action to emit a media event. - $action_id = $this->createEmitAction('file', 'create'); - - // Create a context and add the action as an index reaction. - $this->createContext('Test', 'test'); - $this->addCondition('test', 'is_file'); - $this->addPresetReaction('test', 'index', $action_id); - $this->assertSession()->statusCodeEquals(200); - - // Create a new file, which publishes the create event. - $this->createThumbnailWithFile(); - - // Validate the message actually gets sent. - $queue = str_replace('_', '-', $action_id); - $this->verifyMessageIsSent($queue, 'Create'); - } - - /** - * @covers \Drupal\islandora\ContextProvider\NodeContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\NodeContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateUpdateEvent - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsNode::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testNodeUpdateEvent() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'bypass node access', - 'administer contexts', - 'administer actions', - ]); - $this->drupalLogin($account); - - // Create an action to emit a node event. - $action_id = $this->createEmitAction('node', 'update'); - - // Create a context and add the action as an index reaction. - $this->createContext('Test', 'test'); - $this->addCondition('test', 'is_node'); - $this->addPresetReaction('test', 'index', $action_id); - $this->assertSession()->statusCodeEquals(200); - - // Create a new node, which publishes the update event. - $this->postNodeAddForm('test_type', ['title[0][value]' => 'Test Node'], 'Save'); - - $queue = str_replace('_', '-', $action_id); - $this->verifyMessageIsSent($queue, 'Update'); - } - - /** - * @covers \Drupal\islandora\ContextProvider\MediaContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\MediaContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateUpdateEvent - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsMedia::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testMediaUpdateEvent() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'administer contexts', - 'administer actions', - 'view media', - 'create media', - ]); - $this->drupalLogin($account); - - // Create an action to emit a media event. - $action_id = $this->createEmitAction('media', 'update'); - - // Create a context and add the action as an index reaction. - $this->createContext('Test', 'test'); - $this->addCondition('test', 'is_media'); - $this->addPresetReaction('test', 'index', $action_id); - $this->assertSession()->statusCodeEquals(200); - - // Create a new media, which publishes the update event. - $this->createThumbnailWithFile(); - - // Validate the message actually gets sent. - $queue = str_replace('_', '-', $action_id); - $this->verifyMessageIsSent($queue, 'Update'); - } - - /** - * @covers \Drupal\islandora\ContextProvider\FileContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\FileContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateUpdateEvent - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsFile::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testFileUpdateEvent() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'administer contexts', - 'administer actions', - 'view media', - 'create media', - ]); - $this->drupalLogin($account); - - // Create an action to emit a media event. - $action_id = $this->createEmitAction('file', 'update'); - - // Create a context and add the action as an index reaction. - $this->createContext('Test', 'test'); - $this->addCondition('test', 'is_file'); - $this->addPresetReaction('test', 'index', $action_id); - $this->assertSession()->statusCodeEquals(200); - - // Create a new file, which publishes the update event. - $this->createThumbnailWithFile(); - - // Validate the message actually gets sent. - $queue = str_replace('_', '-', $action_id); - $this->verifyMessageIsSent($queue, 'Update'); - } - - /** - * @covers \Drupal\islandora\ContextProvider\NodeContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\NodeContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateDeleteEvent - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsNode::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testNodeDeleteEvent() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'bypass node access', - 'administer contexts', - 'administer actions', - ]); - $this->drupalLogin($account); - - // Create an action to emit a node event. - $action_id = $this->createEmitAction('node', 'delete'); - - // Create a context and add the action as an index reaction. - $this->createContext('Test', 'test'); - $this->addCondition('test', 'is_node'); - $this->addPresetReaction('test', 'index', $action_id); - $this->assertSession()->statusCodeEquals(200); - - // Create a new node, which publishes the delete event (lol). - $this->postNodeAddForm('test_type', ['title[0][value]' => 'Test Node'], 'Save'); - - $queue = str_replace('_', '-', $action_id); - $this->verifyMessageIsSent($queue, 'Delete'); - } - - /** - * @covers \Drupal\islandora\ContextProvider\MediaContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\MediaContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateDeleteEvent - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsMedia::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testMediaDeleteEvent() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'administer contexts', - 'administer actions', - 'view media', - 'create media', - ]); - $this->drupalLogin($account); - - // Create an action to emit a media event. - $action_id = $this->createEmitAction('media', 'delete'); - - // Create a context and add the action as an index reaction. - $this->createContext('Test', 'test'); - $this->addCondition('test', 'is_media'); - $this->addPresetReaction('test', 'index', $action_id); - $this->assertSession()->statusCodeEquals(200); - - // Create a new media, which publishes the delete event. - $this->createThumbnailWithFile(); - - // Validate the message actually gets sent. - $queue = str_replace('_', '-', $action_id); - $this->verifyMessageIsSent($queue, 'Delete'); - } - - /** - * @covers \Drupal\islandora\ContextProvider\FileContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\FileContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\EventGenerator\EmitEvent::buildConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::submitConfigurationForm - * @covers \Drupal\islandora\EventGenerator\EmitEvent::execute - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateDeleteEvent - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsFile::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testFileDeleteEvent() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'administer contexts', - 'administer actions', - 'view media', - 'create media', - ]); - $this->drupalLogin($account); - - // Create an action to emit a media event. - $action_id = $this->createEmitAction('file', 'delete'); - - // Create a context and add the action as an index reaction. - $this->createContext('Test', 'test'); - $this->addCondition('test', 'is_file'); - $this->addPresetReaction('test', 'index', $action_id); - $this->assertSession()->statusCodeEquals(200); - - // Create a new file, which publishes the delete event. - $this->createThumbnailWithFile(); - - // Validate the message actually gets sent. - $queue = str_replace('_', '-', $action_id); - $this->verifyMessageIsSent($queue, 'Delete'); - } - /** * Utility function to create an emit action. * @@ -449,14 +60,14 @@ EOD; */ protected function createEmitAction($entity_type, $event_type) { $this->drupalGet('admin/config/system/actions'); - $this->getSession()->getPage()->findById("edit-action")->selectOption("Emit a $entity_type event to a queue/topic..."); + $this->getSession()->getPage()->findById("edit-action")->selectOption("Emit a $entity_type event to a queue/topic"); $this->getSession()->getPage()->pressButton(t('Create')); $this->assertSession()->statusCodeEquals(200); - $action_id = "emit_" . $entity_type . "_" . $event_type; - $this->getSession()->getPage()->fillField('edit-label', "Emit $entity_type $event_type"); + $action_id = "emit_" . $entity_type . "_" . lcfirst($event_type); + $this->getSession()->getPage()->fillField('edit-label', "Emit $entity_type " . lcfirst($event_type)); $this->getSession()->getPage()->fillField('edit-id', $action_id); - $this->getSession()->getPage()->fillField('edit-queue', "emit-$entity_type-$event_type"); + $this->getSession()->getPage()->fillField('edit-queue', "emit-$entity_type-" . lcfirst($event_type)); $this->getSession()->getPage()->findById("edit-event")->selectOption($event_type); $this->getSession()->getPage()->pressButton(t('Save')); $this->assertSession()->statusCodeEquals(200); diff --git a/tests/src/Functional/FormDisplayAlterReactionTest.php b/tests/src/Functional/FormDisplayAlterReactionTest.php new file mode 100644 index 00000000..d5d41dea --- /dev/null +++ b/tests/src/Functional/FormDisplayAlterReactionTest.php @@ -0,0 +1,65 @@ +drupalCreateUser([ + 'bypass node access', + 'administer contexts', + 'administer actions', + 'view media', + 'create media', + 'update media', + ]); + $this->drupalLogin($account); + + // Create a new node referencing the media. + $this->postNodeAddForm( + 'test_type', + [ + 'title[0][value]' => 'Test Node', + ], + 'Save' + ); + + // Stash the node's url. + $url = $this->getUrl(); + + // Visit the edit url and make sure we're on the default form display + // (e.g. there's an autocomplete for the member of field); + $this->drupalGet($url . "/edit"); + $this->assertSession()->pageTextContains("Member Of"); + + // Create a context and set the form mode to alter to "secondary". + $this->createContext('Test', 'test'); + + $this->drupalGet("admin/structure/context/test/reaction/add/form_display_alter"); + $this->getSession()->getPage()->findById("edit-reactions-form-display-alter-mode")->selectOption('node.secondary'); + $this->getSession()->getPage()->pressButton(t('Save and continue')); + $this->assertSession()->statusCodeEquals(200); + + drupal_flush_all_caches(); + + // Re-visit the node and make sure we're in secondar mode (e.g. the media + // field is not displayed). + $this->drupalGet($url . "/edit"); + $this->assertSession()->pageTextNotContains("Member Of"); + + } + +} + diff --git a/tests/src/Functional/IsFileTest.php b/tests/src/Functional/IsFileTest.php index df8997e3..b5e7277c 100644 --- a/tests/src/Functional/IsFileTest.php +++ b/tests/src/Functional/IsFileTest.php @@ -37,9 +37,14 @@ class IsFileTest extends IslandoraFunctionalTestBase { $this->addCondition('test', 'is_file'); $this->addPresetReaction('test', 'index', 'hello_world'); - // Add a new Thumbnail media and confirm Hello World! is printed to the + // Add a new media and confirm Hello World! is printed to the // screen for the file upload. - $this->createThumbnailWithFile(); + $file = current($this->getTestFiles('file')); + $values = [ + 'name[0][value]' => 'Test Media', + 'files[field_media_file_0]' => __DIR__ . '/../../fixtures/test_file.txt', + ]; + $this->drupalPostForm('media/add/' . $this->testMediaType->id(), $values, t('Save')); $this->assertSession()->pageTextContains("Hello World!"); // Stash the media's url. @@ -49,7 +54,7 @@ class IsFileTest extends IslandoraFunctionalTestBase { $values = [ 'name[0][value]' => 'Test Media Changed', ]; - $this->postEntityEditForm($url, $values, 'Save and keep published'); + $this->postEntityEditForm($url, $values, 'Save'); // Confirm Hello World! is not printed to the screen. $this->assertSession()->pageTextNotContains("Hello World!"); diff --git a/tests/src/Functional/IsMediaTest.php b/tests/src/Functional/IsMediaTest.php index 967b9460..1e6929e9 100644 --- a/tests/src/Functional/IsMediaTest.php +++ b/tests/src/Functional/IsMediaTest.php @@ -37,9 +37,13 @@ class IsMediaTest extends IslandoraFunctionalTestBase { $this->addCondition('test', 'is_media'); $this->addPresetReaction('test', 'index', 'hello_world'); - // Add a new Thumbnail media and confirm Hello World! is printed to the + // Add a new media and confirm Hello World! is printed to the // screen. - $this->createThumbnailWithFile(); + $values = [ + 'name[0][value]' => 'Test Media', + 'files[field_media_file_0]' => __DIR__ . '/../../fixtures/test_file.txt', + ]; + $this->drupalPostForm('media/add/' . $this->testMediaType->id(), $values, t('Save')); $this->assertSession()->pageTextContains("Hello World!"); // Create a new node. diff --git a/tests/src/Functional/IsNodeTest.php b/tests/src/Functional/IsNodeTest.php index 1c4b7c14..198db1db 100644 --- a/tests/src/Functional/IsNodeTest.php +++ b/tests/src/Functional/IsNodeTest.php @@ -41,9 +41,14 @@ class IsNodeTest extends IslandoraFunctionalTestBase { $this->postNodeAddForm('test_type', ['title[0][value]' => 'Test Node'], 'Save'); $this->assertSession()->pageTextContains("Hello World!"); - // Add a new Thumbnail media and confirm Hello World! is not printed to the + // Add a new media and confirm Hello World! is not printed to the // screen. - $this->createThumbnailWithFile(); + $file = current($this->getTestFiles('file')); + $values = [ + 'name[0][value]' => 'Test Media', + 'files[field_media_file_0]' => __DIR__ . '/../../fixtures/test_file.txt', + ]; + $this->drupalPostForm('media/add/' . $this->testMediaType->id(), $values, t('Save')); $this->assertSession()->pageTextNotContains("Hello World!"); } diff --git a/tests/src/Functional/IsReferencedMediaTest.php b/tests/src/Functional/IsReferencedMediaTest.php deleted file mode 100644 index 84fbfc30..00000000 --- a/tests/src/Functional/IsReferencedMediaTest.php +++ /dev/null @@ -1,144 +0,0 @@ -container->get('entity_type.manager')->getStorage('node_type')->create([ - 'type' => 'test_type_with_reference', - 'label' => 'Test Type With Reference', - ]); - $test_type_with_reference->save(); - $this->createEntityReferenceField('node', 'test_type_with_reference', 'field_media', 'Media Entity', 'media', 'default', [], 2); - - $another_test_type_with_reference = $this->container->get('entity_type.manager')->getStorage('node_type')->create([ - 'type' => 'another_test_type_with_reference', - 'label' => 'Another Test Type With Reference', - ]); - $another_test_type_with_reference->save(); - $this->createEntityReferenceField('node', 'another_test_type_with_reference', 'field_media', 'Media Entity', 'media', 'default', [], 2); - - // Create the media. - $media_bundle = $this->drupalCreateMediaBundle(); - $this->referenced = $this->container->get('entity_type.manager')->getStorage('media')->create([ - 'bundle' => $media_bundle->id(), - 'name' => 'Referenced Media', - ]); - $this->referenced->save(); - - $this->notReferenced = $this->container->get('entity_type.manager')->getStorage('media')->create([ - 'bundle' => $media_bundle->id(), - 'name' => 'Unreferenced Media', - ]); - $this->notReferenced->save(); - - $this->referencedByAnother = $this->container->get('entity_type.manager')->getStorage('media')->create([ - 'bundle' => $media_bundle->id(), - 'name' => 'Referenced By Another', - ]); - $this->referencedByAnother->save(); - - // Reference one by a node of the type we're expecting. - $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ - 'type' => 'test_type_with_reference', - 'title' => 'Referencer', - 'field_media' => [$this->referenced->id()], - ]); - $node->save(); - - // Reference one by a node of the type we're not expecting. - $another_node = $this->container->get('entity_type.manager')->getStorage('node')->create([ - 'type' => 'another_test_type_with_reference', - 'title' => 'Another Referencer', - 'field_media' => [$this->referencedByAnother->id()], - ]); - $node->save(); - } - - /** - * @covers \Drupal\islandora\ContextProvider\MediaContextProvider::__construct - * @covers \Drupal\islandora\ContextProvider\MediaContextProvider::getRuntimeContexts - * @covers \Drupal\islandora\IslandoraContextManager::evaluateContexts - * @covers \Drupal\islandora\IslandoraContextManager::applyContexts - * @covers \Drupal\islandora\Plugin\Condition\IsReferencedMedia::buildConfigurationForm - * @covers \Drupal\islandora\Plugin\Condition\IsReferencedMedia::submitConfigurationForm - * @covers \Drupal\islandora\Plugin\Condition\IsReferencedMedia::evaluate - * @covers \Drupal\islandora\PresetReaction\PresetReaction::buildConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::submitConfigurationForm - * @covers \Drupal\islandora\PresetReaction\PresetReaction::execute - * @covers \Drupal\islandora\IslandoraServiceProvider::alter - */ - public function testIsReferencedMedia() { - // Create a test user. - $account = $this->drupalCreateUser([ - 'administer contexts', - 'view media', - 'update any media', - ]); - $this->drupalLogin($account); - - $this->createContext('Test', 'test'); - - // Add the condition. - $this->drupalGet("admin/structure/context/test/condition/add/is_referenced_media"); - $this->getSession()->getPage()->findById("edit-conditions-is-referenced-media-field")->selectOption('test_type_with_reference|field_media'); - $this->getSession()->getPage()->pressButton('Save and continue'); - - // Add the reaction to say "Hello World!". - $this->addPresetReaction('test', 'index', 'hello_world'); - - // Edit the referenced node. "Hello World!" should be output to the screen. - $this->postEntityEditForm("media/{$this->referenced->id()}", ['name[0][value]' => 'Referenced Media Changed'], 'Save and keep published'); - $this->assertSession()->pageTextContains("Hello World!"); - - // Edit the unreferenced node. "Hello World!" should not be output to the - // screen. - $this->postEntityEditForm("media/{$this->notReferenced->id()}", ['name[0][value]' => 'Unreferenced Media Changed'], 'Save and keep published'); - $this->assertSession()->pageTextNotContains("Hello World!"); - - // Edit the node referenced by a different type. "Hello World!" should not - // be output to the screen. - $this->postEntityEditForm("media/{$this->referencedByAnother->id()}", ['name[0][value]' => 'Referenced By Another Changed'], 'Save and keep published'); - $this->assertSession()->pageTextNotContains("Hello World!"); - } - -} diff --git a/tests/src/Functional/IsTermTest.php b/tests/src/Functional/IsTermTest.php new file mode 100644 index 00000000..bb328ba7 --- /dev/null +++ b/tests/src/Functional/IsTermTest.php @@ -0,0 +1,51 @@ +drupalCreateUser([ + 'bypass node access', + 'administer contexts', + 'administer taxonomy', + ]); + $this->drupalLogin($account); + + $this->createContext('Test', 'test'); + $this->addCondition('test', 'is_term'); + $this->addPresetReaction('test', 'index', 'hello_world'); + + // Create a new term and confirm Hello World! is printed to the screen. + $this->drupalPostForm( + 'admin/structure/taxonomy/manage/' . $this->testVocabulary->id() . '/add', + ['name[0][value]' => 'Test Term'], + t('Save') + ); + $this->assertSession()->pageTextContains("Hello World!"); + + // Create a new node and confirm Hello World! is not printed to the screen. + $this->postNodeAddForm('test_type', ['title[0][value]' => 'Test Node'], 'Save'); + $this->assertSession()->pageTextNotContains("Hello World!"); + } + +} diff --git a/tests/src/Functional/IslandoraFunctionalTestBase.php b/tests/src/Functional/IslandoraFunctionalTestBase.php index f347287a..b9f99dd0 100644 --- a/tests/src/Functional/IslandoraFunctionalTestBase.php +++ b/tests/src/Functional/IslandoraFunctionalTestBase.php @@ -2,19 +2,23 @@ namespace Drupal\Tests\islandora\Functional; +use Drupal\Core\Config\FileStorage; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Url; -use Drupal\rest\Entity\RestResourceConfig; -use Drupal\rest\RestResourceConfigInterface; +use Drupal\Core\Session\AccountInterface; +use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; +use Drupal\link\LinkItemInterface; use Drupal\Tests\BrowserTestBase; use Drupal\Tests\TestFileCreationTrait; +use Drupal\Tests\media\Functional\MediaFunctionalTestCreateMediaTypeTrait; /** * Base class for Functional tests. */ class IslandoraFunctionalTestBase extends BrowserTestBase { + use EntityReferenceTestTrait; use TestFileCreationTrait; + use MediaFunctionalTestCreateMediaTypeTrait; protected static $modules = ['context_ui', 'islandora']; @@ -27,164 +31,72 @@ class IslandoraFunctionalTestBase extends BrowserTestBase { 'key.key.test', ]; + protected $testType; + + protected $testMediaType; + + protected $testVocabulary; + /** * {@inheritdoc} */ public function setUp() { parent::setUp(); - // Delete the context entities provided by the module. - // This will get removed as we split apart contexts into different - // solution packs. - $this->container->get('entity_type.manager')->getStorage('context')->load('node')->delete(); - $this->container->get('entity_type.manager')->getStorage('context')->load('media')->delete(); - $this->container->get('entity_type.manager')->getStorage('context')->load('file')->delete(); - - // Set up basic REST config. // Delete the node rest config that's bootstrapped with Drupal. $this->container->get('entity_type.manager')->getStorage('rest_resource_config')->load('entity.node')->delete(); - // Create our own for Nodes, Media, and Files. - $this->container->get('entity_type.manager')->getStorage('rest_resource_config')->create([ - 'id' => 'entity.node', - 'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY, - 'configuration' => [ - 'GET' => [ - 'supported_auth' => [ - 'cookie', - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - 'jsonld', - ], - ], - 'POST' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], - 'DELETE' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], - 'PATCH' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], - ], - ])->save(); - $this->container->get('entity_type.manager')->getStorage('rest_resource_config')->create([ - 'id' => 'entity.media', - 'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY, - 'configuration' => [ - 'GET' => [ - 'supported_auth' => [ - 'cookie', - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - 'jsonld', - ], - ], - 'POST' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], - 'DELETE' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], - 'PATCH' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], + // Set up JWT stuff. + $key_value = <<container->get('entity_type.manager')->getStorage('key')->create([ + 'id' => 'test', + 'label' => 'Test', + 'key_type' => 'jwt_rs', + 'key_type_settings' => [ + 'algorithm' => 'RS256', ], - ])->save(); - RestResourceConfig::create([ - 'id' => 'entity.file', - 'granularity' => RestResourceConfigInterface::METHOD_GRANULARITY, - 'configuration' => [ - 'GET' => [ - 'supported_auth' => [ - 'cookie', - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - 'jsonld', - ], - ], - 'POST' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], - 'DELETE' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], - 'PATCH' => [ - 'supported_auth' => [ - 'basic_auth', - 'jwt_auth', - ], - 'supported_formats' => [ - 'json', - ], - ], + 'key_provider' => 'config', + 'key_provider_settings' => [ + 'key_value' => $key_value, ], - ])->save(); - - // Create a test content type. - $test_type = $this->container->get('entity_type.manager')->getStorage('node_type')->create([ - 'type' => 'test_type', - 'label' => 'Test Type', ]); - $test_type->save(); + $key->save(); + $jwt_config = $this->container->get('config.factory')->getEditable('jwt.config'); + $jwt_config->set('algorithm', 'RS256'); + $jwt_config->set('key_id', 'test'); + $jwt_config->save(TRUE); + + // Make some bundles and field by hand so hooks fire. // Create an action that dsm's "Hello World!". $hello_world = $this->container->get('entity_type.manager')->getStorage('action')->create([ 'id' => 'hello_world', @@ -197,6 +109,55 @@ class IslandoraFunctionalTestBase extends BrowserTestBase { ]); $hello_world->save(); + // Create a vocabulary. + $this->testVocabulary = $this->container->get('entity_type.manager')->getStorage('taxonomy_vocabulary')->create([ + 'name' => 'Test Vocabulary', + 'vid' => 'test_vocabulary', + ]); + $this->testVocabulary->save(); + + // Create an external_uri field for taxonomy terms. + $fieldStorage = $this->container->get('entity_type.manager')->getStorage('field_storage_config')->create([ + 'field_name' => 'field_external_uri', + 'entity_type' => 'taxonomy_term', + 'type' => 'link', + ]); + $fieldStorage->save(); + $field = $this->container->get('entity_type.manager')->getStorage('field_config')->create([ + 'field_storage' => $fieldStorage, + 'bundle' => $this->testVocabulary->id(), + 'settings' => [ + 'title' => 'External URI', + 'link_type' => LinkItemInterface::LINK_EXTERNAL, + ], + ]); + $field->save(); + + // Create a test content type. + $this->testType = $this->container->get('entity_type.manager')->getStorage('node_type')->create([ + 'type' => 'test_type', + 'name' => 'Test Type', + ]); + $this->testType->save(); + $this->createEntityReferenceField('node', 'test_type', 'field_member_of', 'Member Of', 'node', 'default', [], 2); + $this->createEntityReferenceField('node', 'test_type', 'field_tags', 'Tags', 'taxonomy_term', 'default', [], 2); + + // Create a media type. + $this->testMediaType = $this->createMediaType(['bundle' => 'test_media_type'], 'file'); + $this->testMediaType->save(); + $this->createEntityReferenceField('media', $this->testMediaType->id(), 'field_media_of', 'Media Of', 'node', 'default', [], 2); + $this->createEntityReferenceField('media', $this->testMediaType->id(), 'field_tags', 'Tags', 'taxonomy_term', 'default', [], 2); + + // Copy over the rest of the config from yml files. + $source = new FileStorage(__DIR__ . '/../../fixtures/config'); + $destination = $this->container->get('config.storage'); + + foreach ($source->listAll() as $name) { + $destination->write($name, $source->read($name)); + } + + // Cache clear / rebuild. + drupal_flush_all_caches(); $this->container->get('router.builder')->rebuild(); } @@ -227,39 +188,6 @@ class IslandoraFunctionalTestBase extends BrowserTestBase { $this->assertSession()->statusCodeEquals(200); } - /** - * Creates a new TN media with a file. - */ - protected function createThumbnailWithFile() { - // Have to do this in two steps since there's no ajax for the alt text. - // It's as annoying as in real life. - $file = current($this->getTestFiles('image')); - $values = [ - 'name[0][value]' => 'Test Media', - 'files[field_image_0]' => \Drupal::service('file_system')->realpath($file->uri), - ]; - $this->drupalPostForm('media/add/tn', $values, t('Save and publish')); - $values = [ - 'field_image[0][alt]' => 'Alternate text', - ]; - $this->getSession()->getPage()->fillField('edit-field-image-0-alt', 'alt text'); - $this->getSession()->getPage()->pressButton(t('Save and publish')); - $this->assertSession()->statusCodeEquals(200); - $results = $this->container->get('entity_type.manager')->getStorage('file')->loadByProperties(['filename' => $file->filename]); - $file_entity = reset($results); - $file_url = $file_entity->url('canonical', ['absolute' => TRUE]); - $rest_url = Url::fromRoute('islandora.media_source_update', ['media' => $file_entity->id()]) - ->setAbsolute() - ->toString(); - return [ - 'media' => $this->getUrl(), - 'file' => [ - 'file' => $file_url, - 'rest' => $rest_url, - ], - ]; - } - /** * Create a new node by posting its add form. */ @@ -288,6 +216,10 @@ class IslandoraFunctionalTestBase extends BrowserTestBase { protected function doesNotHaveLinkHeader($rel) { $headers = $this->getSession()->getResponseHeaders(); + if (!isset($headers['Link'])) { + return TRUE; + } + foreach ($headers['Link'] as $link_header) { if (strpos($link_header, "rel=\"$rel\"") !== FALSE) { return FALSE; @@ -361,4 +293,33 @@ class IslandoraFunctionalTestBase extends BrowserTestBase { return $count; } + /** + * Utility function to make a media and an associated file. + */ + protected function makeMediaAndFile(AccountInterface $account) { + // Make a file for the Media. + $file = $this->container->get('entity_type.manager')->getStorage('file')->create([ + 'uid' => $account->id(), + 'uri' => "public://test_file.txt", + 'filename' => "test_file.txt", + 'filemime' => "text/plain", + 'status' => FILE_STATUS_PERMANENT, + ]); + $file->save(); + + // Get the source field for the media. + $type_configuration = $this->testMediaType->get('source_configuration'); + $source_field = $type_configuration['source_field']; + + // Make the media for the referencer. + $media = $this->container->get('entity_type.manager')->getStorage('media')->create([ + 'bundle' => $this->testMediaType->id(), + 'name' => 'Media', + "$source_field" => [$file->id()], + ]); + $media->save(); + + return [$file, $media]; + } + } diff --git a/tests/src/Functional/LinkHeaderTest.php b/tests/src/Functional/LinkHeaderTest.php new file mode 100644 index 00000000..9f7f8328 --- /dev/null +++ b/tests/src/Functional/LinkHeaderTest.php @@ -0,0 +1,237 @@ +drupalCreateUser(); + $this->drupalLogin($account); + + // 'Image' tag. + $this->imageTerm = $this->container->get('entity_type.manager')->getStorage('taxonomy_term')->create([ + 'name' => 'Image', + 'vid' => $this->testVocabulary->id(), + 'field_external_uri' => [['uri' => "http://purl.org/coar/resource_type/c_c513"]], + ]); + $this->imageTerm->save(); + + // 'Preservation Master' tag. + $this->preservationMasterTerm = $this->container->get('entity_type.manager')->getStorage('taxonomy_term')->create([ + 'name' => 'Preservation Master', + 'vid' => $this->testVocabulary->id(), + 'field_external_uri' => [['uri' => "http://pcdm.org/use#PreservationMasterFile"]], + ]); + $this->preservationMasterTerm->save(); + + // Node to be referenced via member of. + $this->referenced = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => $this->testType->id(), + 'title' => 'Referenced', + ]); + $this->referenced->save(); + + // Node that is member of something, with an Image tag. + $this->referencer = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => $this->testType->id(), + 'title' => 'Referencer', + 'field_member_of' => [$this->referenced->id()], + 'field_tags' => [$this->imageTerm->id()], + ]); + $this->referencer->save(); + + list($this->file, $this->media) = $this->makeMediaAndFile($account); + $this->media->set('field_media_of', $this->referencer); + $this->media->set('field_tags', $this->preservationMasterTerm); + $this->media->save(); + } + + /** + * @covers \Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber::onResponse + */ + public function testNodeLinkHeaders() { + // Visit the referenced node, there should not be a related header since + // its entity reference field is empty. + $this->drupalGet('node/' . $this->referenced->id()); + $this->assertTrue( + $this->doesNotHaveLinkHeader('related'), + "Node that has empty entity reference field must not return link header." + ); + + // Visit the referencer. It should return a rel="related" link header + // for referenced node and the referencing media, plus one for the tag. + $this->drupalGet('node/' . $this->referencer->id()); + $this->assertTrue( + $this->validateLinkHeaderWithEntity('related', $this->referenced, 'Member Of') == 1, + "Malformed related node link header" + ); + $this->assertTrue( + $this->validateLinkHeaderWithEntity('related', $this->media, $this->preservationMasterTerm->label()) == 1, + "Malformed related media link header" + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('tag', $this->imageTerm->get('field_external_uri')->first()->getValue()['uri'], $this->imageTerm->label()) == 1, + "Malformed tag link header" + ); + + // Check for links to REST endpoints for metadata. + $entity_url = $this->referencer->toUrl('canonical', ['absolute' => TRUE]) + ->toString(); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=json", NULL, 'application/json') == 1, + "Node must have link header pointing to json REST endpoint." + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=jsonld", NULL, 'application/ld+json') == 1, + "Node must have link header pointing to jsonld REST endpoint." + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=xml", NULL, 'application/xml') == 0, + "Node must not have link header pointing to disabled xml REST endpoint." + ); + + // Check that the current representation is not advertised when visitng + // a REST endpoint (e.g. the json link header doesn't appear when you're + // visiting the ?_format=json endpoint). + $this->drupalGet('node/' . $this->referencer->id(), ['query' => ['_format' => 'json']]); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=json", NULL, 'application/json') == 0, + "Node must not have link header pointing to json REST endpoint when vising the json REST endpoint." + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=jsonld", NULL, 'application/ld+json') == 1, + "Node must have link header pointing to jsonld REST endpoint when visiting the json REST endpoint." + ); + } + + /** + * @covers \Drupal\islandora\EventSubscriber\MediaLinkHeaderSubscriber + */ + public function testMediaLinkHeaders() { + + // Get the file to check its url in the response headers. + $file_url = $this->file->url('canonical', ['absolute' => TRUE]); + $rest_url = Url::fromRoute('islandora.media_source_update', ['media' => $this->media->id()]) + ->setAbsolute() + ->toString(); + $media_url = $this->media->url('canonical', ['absolute' => TRUE]); + + // Perform a GET request as anonymous. + $this->drupalGet($media_url, [], ['Cache-Control: no-cache']); + + // Check link headers. + $this->assertTrue( + $this->validateLinkHeaderWithUrl('describes', $file_url, '', 'text/plain') == 1, + "Malformed 'describes' link header, expecting $file_url" + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('edit-media', $rest_url, '', '') == 0, + "Anonymous should not be able to see the edit-media link" + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('tag', $this->preservationMasterTerm->get('field_external_uri')->first()->getValue()['uri'], $this->preservationMasterTerm->label()) == 1, + "Malformed tag link header" + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', $media_url . "?_format=json", NULL, 'application/json') == 1, + "Media must have link header pointing to json REST endpoint." + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', $media_url . "?_format=jsonld", NULL, 'application/ld+json') == 1, + "Media must have link header pointing to jsonld REST endpoint." + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', $media_url . "?_format=xml", NULL, 'application/xml') == 0, + "Media must not have link header pointing to disabled xml REST endpoint." + ); + + // Create a test user with edit media permissions. + $account = $this->drupalCreateUser(['update media']); + $this->drupalLogin($account); + + // Perform a GET request with update media permissions. + $this->drupalGet($media_url, [], ['Cache-Control: no-cache']); + + // Check link headers again, the edit-media link header should be present. + $this->assertTrue( + $this->validateLinkHeaderWithUrl('describes', $file_url, '', 'text/plain') == 1, + "Malformed 'describes' link header, expecting $file_url" + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('edit-media', $rest_url, '', '') == 1, + "Malformed 'edit-media' link, expecting $rest_url" + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('tag', $this->preservationMasterTerm->get('field_external_uri')->first()->getValue()['uri'], $this->preservationMasterTerm->label()) == 1, + "Malformed tag link header" + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', $media_url . "?_format=json", NULL, 'application/json') == 1, + "Media must have link header pointing to json REST endpoint." + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', $media_url . "?_format=jsonld", NULL, 'application/ld+json') == 1, + "Media must have link header pointing to jsonld REST endpoint." + ); + $this->assertTrue( + $this->validateLinkHeaderWithUrl('alternate', $media_url . "?_format=xml", NULL, 'application/xml') == 0, + "Media must not have link header pointing to disabled xml REST endpoint." + ); + } + +} diff --git a/tests/src/Functional/MediaLinkHeaderTest.php b/tests/src/Functional/MediaLinkHeaderTest.php deleted file mode 100644 index 232dc117..00000000 --- a/tests/src/Functional/MediaLinkHeaderTest.php +++ /dev/null @@ -1,53 +0,0 @@ -drupalCreateUser([ - 'view media', - 'create media', - 'update media', - ]); - $this->drupalLogin($account); - - $urls = $this->createThumbnailWithFile(); - - $this->drupalGet($urls['media'], [], ['Cache-Control: no-cache']); - - $this->assertTrue( - $this->validateLinkHeaderWithUrl('describes', $urls['file']['file'], '', 'image/png') == 1, - "Malformed 'describes' link header" - ); - $this->assertTrue( - $this->validateLinkHeaderWithUrl('edit-media', $urls['file']['rest'], '', '') == 1, - "Malformed 'edit-media' link header" - ); - - // Check for links to REST endpoints for metadata. - $this->assertTrue( - $this->validateLinkHeaderWithUrl('alternate', $urls['media'] . "?_format=json", NULL, 'application/json') == 1, - "Media must have link header pointing to json REST endpoint." - ); - $this->assertTrue( - $this->validateLinkHeaderWithUrl('alternate', $urls['media'] . "?_format=jsonld", NULL, 'application/ld+json') == 1, - "Media must have link header pointing to jsonld REST endpoint." - ); - $this->assertTrue( - $this->validateLinkHeaderWithUrl('alternate', $urls['media'] . "?_format=xml", NULL, 'application/xml') == 0, - "Media must not have link header pointing to disabled xml REST endpoint." - ); - - } - -} diff --git a/tests/src/Functional/MediaSourceUpdateTest.php b/tests/src/Functional/MediaSourceUpdateTest.php index 80c45f24..6994f2ab 100644 --- a/tests/src/Functional/MediaSourceUpdateTest.php +++ b/tests/src/Functional/MediaSourceUpdateTest.php @@ -12,87 +12,91 @@ use Drupal\Core\Url; class MediaSourceUpdateTest extends IslandoraFunctionalTestBase { /** - * @covers \Drupal\islandora\Controller\MediaSourceController::put + * Media to belong to the referencer. + * + * @var \Drupal\media\MediaInterface */ - public function testMediaSourceUpdate() { - $account = $this->drupalCreateUser([ + protected $media; + + /** + * File to belong to the media. + * + * @var \Drupal\file\FileInterface + */ + protected $file; + + /** + * User. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $account; + + /** + * {@inheritdoc} + */ + public function setUp() { + parent::setUp(); + + // Make a user with appropriate permissions. + $this->account = $this->drupalCreateUser([ 'view media', 'create media', 'update media', ]); - $this->drupalLogin($account); + $this->drupalLogin($this->account); + + // Make a file for the Media. + $this->file = $this->container->get('entity_type.manager')->getStorage('file')->create([ + 'uid' => $this->account->id(), + 'uri' => "public://test_file.txt", + 'filename' => "test_file.txt", + 'filemime' => "text/plain", + 'status' => FILE_STATUS_PERMANENT, + ]); + $this->file->save(); + + // Get the source field for the media. + $type_configuration = $this->testMediaType->get('source_configuration'); + $source_field = $type_configuration['source_field']; - // Make a media and give it a png. - $urls = $this->createThumbnailWithFile(); - $url = $urls['media']; + // Make the media. + $this->media = $this->container->get('entity_type.manager')->getStorage('media')->create([ + 'bundle' => $this->testMediaType->id(), + 'name' => 'Media', + "$source_field" => [$this->file->id()], + ]); + $this->media->save(); + } + /** + * @covers \Drupal\islandora\Controller\MediaSourceController::put + */ + public function testMediaSourceUpdate() { // Hack out the guzzle client. $client = $this->getSession()->getDriver()->getClient()->getClient(); - // GET the media to stash its original values for comparison later. - $options = [ - 'auth' => [$account->getUsername(), $account->pass_raw], - 'http_errors' => FALSE, - ]; - $response = $client->request('GET', $url . '?_format=json', $options); - $media = json_decode($response->getBody(), TRUE); - - $mid = $media['mid'][0]['value']; - $original_mimetype = $media['field_mimetype'][0]['value']; - $original_width = $media['field_width'][0]['value']; - $original_height = $media['field_height'][0]['value']; - $original_image = file_get_contents($media['field_image'][0]['url']); - - $media_update_url = Url::fromRoute('islandora.media_source_update', ['media' => $mid]) + $media_update_url = Url::fromRoute('islandora.media_source_update', ['media' => $this->media->id()]) ->setAbsolute() ->toString(); - $image = file_get_contents(__DIR__ . '/../../static/test.jpeg'); + $file_contents = file_get_contents(__DIR__ . '/../../fixtures/test_file2.txt'); // Update without Content-Type header should fail with 400. $options = [ - 'auth' => [$account->getUsername(), $account->pass_raw], - 'http_errors' => FALSE, - 'headers' => [ - 'Content-Disposition' => 'attachment; filename="test.jpeg"', - ], - 'body' => $image, - ]; - $response = $client->request('PUT', $media_update_url, $options); - $this->assertTrue($response->getStatusCode() == 400, "Expected 400, received {$response->getStatusCode()}"); - - // Update without Content-Disposition header should fail with 400. - $options = [ - 'auth' => [$account->getUsername(), $account->pass_raw], + 'auth' => [$this->account->getUsername(), $this->account->pass_raw], 'http_errors' => FALSE, - 'headers' => [ - 'Content-Type' => 'image/jpeg', - ], - 'body' => $image, - ]; - $response = $client->request('PUT', $media_update_url, $options); - $this->assertTrue($response->getStatusCode() == 400, "Expected 400, received {$response->getStatusCode()}"); - - // Update with malformed Content-Disposition header should fail with 400. - $options = [ - 'auth' => [$account->getUsername(), $account->pass_raw], - 'http_errors' => FALSE, - 'headers' => [ - 'Content-Type' => 'image/jpeg', - 'Content-Disposition' => 'garbage; filename="test.jpeg"', - ], - 'body' => $image, + 'body' => $file_contents, ]; $response = $client->request('PUT', $media_update_url, $options); $this->assertTrue($response->getStatusCode() == 400, "Expected 400, received {$response->getStatusCode()}"); // Update without body should fail with 400. $options = [ - 'auth' => [$account->getUsername(), $account->pass_raw], + 'auth' => [$this->account->getUsername(), $this->account->pass_raw], 'http_errors' => FALSE, 'headers' => [ - 'Content-Type' => 'image/jpeg', - 'Content-Disposition' => 'attachment; filename="test.jpeg"', + 'Content-Type' => 'text/plain', ], ]; $response = $client->request('PUT', $media_update_url, $options); @@ -100,39 +104,32 @@ class MediaSourceUpdateTest extends IslandoraFunctionalTestBase { // Should be successful. $options = [ - 'auth' => [$account->getUsername(), $account->pass_raw], + 'auth' => [$this->account->getUsername(), $this->account->pass_raw], 'http_errors' => FALSE, 'headers' => [ - 'Content-Type' => 'image/jpeg', - 'Content-Disposition' => 'attachment; filename="test.jpeg"', + 'Content-Type' => 'text/plain', ], - 'body' => $image, + 'body' => $file_contents, ]; $response = $client->request('PUT', $media_update_url, $options); $this->assertTrue($response->getStatusCode() == 204, "Expected 204, received {$response->getStatusCode()}"); - // GET the media again and compare image and metadata. + // GET the media and compare file and metadata. $options = [ - 'auth' => [$account->getUsername(), $account->pass_raw], + 'auth' => [$this->account->getUsername(), $this->account->pass_raw], 'http_errors' => FALSE, ]; + $url = $this->media->url('canonical', ['absolute' => TRUE]); $response = $client->request('GET', $url . '?_format=json', $options); $updated = json_decode($response->getBody(), TRUE); - $updated_mimetype = $updated['field_mimetype'][0]['value']; - $updated_width = $updated['field_width'][0]['value']; - $updated_height = $updated['field_height'][0]['value']; - $updated_image = file_get_contents($updated['field_image'][0]['url']); + // Get the source field for the media. + $type_configuration = $this->testMediaType->get('source_configuration'); + $source_field = $type_configuration['source_field']; - $this->assertTrue($original_mimetype != $updated_mimetype, "Mimetypes should be updated with media source update"); - $this->assertTrue($original_width != $updated_width, "Width should be updated with media source update"); - $this->assertTrue($original_height != $updated_height, "Height should be updated with media source update"); - $this->assertTrue($original_image != $updated_image, "Image should be updated with media source update"); + $updated_file_contents = file_get_contents($updated[$source_field][0]['url']); - $this->assertTrue($updated_mimetype == "image/jpeg", "Invalid mimetype. Expected image/jpeg, received $updated_mimetype"); - $this->assertTrue($updated_width == 295, "Invalid width. Expected 295, received $updated_width"); - $this->assertTrue($updated_height == 70, "Invalid height. Expected 70, received $updated_height"); - $this->assertTrue($updated_image == file_get_contents(__DIR__ . '/../../static/test.jpeg'), "Updated image not the same as PUT body."); + $this->assertTrue($updated_file_contents == file_get_contents(__DIR__ . '/../../fixtures/test_file2.txt'), "Updated file not the same as PUT body."); } } diff --git a/tests/src/Functional/NodeLinkHeaderTest.php b/tests/src/Functional/NodeLinkHeaderTest.php deleted file mode 100644 index f80367d7..00000000 --- a/tests/src/Functional/NodeLinkHeaderTest.php +++ /dev/null @@ -1,176 +0,0 @@ -container->get('entity_type.manager')->getStorage('node_type')->create([ - 'type' => 'test_type_with_reference', - 'label' => 'Test Type With Reference', - ]); - $test_type_with_reference->save(); - - // Add two entity reference fields. - // One for nodes and one for media. - $this->createEntityReferenceField('node', 'test_type_with_reference', 'field_reference', 'Referenced Entity', 'node', 'default', [], 2); - $this->createEntityReferenceField('node', 'test_type_with_reference', 'field_media', 'Media Entity', 'media', 'default', [], 2); - - $this->other = $this->container->get('entity_type.manager')->getStorage('node')->create([ - 'type' => 'test_type', - 'title' => 'Test object w/o entity reference field', - ]); - $this->other->save(); - - $this->referenced = $this->container->get('entity_type.manager')->getStorage('node')->create([ - 'type' => 'test_type_with_reference', - 'title' => 'Referenced', - ]); - $this->referenced->save(); - - $media_bundle = $this->drupalCreateMediaBundle(); - $this->media = $this->container->get('entity_type.manager')->getStorage('media')->create([ - 'bundle' => $media_bundle->id(), - 'name' => 'Media', - ]); - $this->media->save(); - - $this->referencer = $this->container->get('entity_type.manager')->getStorage('node')->create([ - 'type' => 'test_type_with_reference', - 'title' => 'Referencer', - 'field_reference' => [$this->referenced->id()], - 'field_media' => [$this->media->id()], - ]); - $this->referencer->save(); - } - - /** - * @covers \Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber::onResponse - */ - public function testNodeLinkHeaders() { - // Create a test user that can see media. - $account = $this->drupalCreateUser([ - 'view media', - ]); - $this->drupalLogin($account); - - // Visit the other, there should not be a related header since it does not - // even have the field. - $this->drupalGet('node/' . $this->other->id()); - $this->assertTrue( - $this->doesNotHaveLinkHeader('related'), - "Node that does not have entity reference field must not return related link header." - ); - - // Visit the referenced node, there should not be a related header since - // its entity reference field is empty. - $this->drupalGet('node/' . $this->referenced->id()); - $this->assertTrue( - $this->doesNotHaveLinkHeader('related'), - "Node that has empty entity reference field must not return link header." - ); - - // Visit the referencer. It should return a rel="related" link header - // for both the referenced node and media entity. - $this->drupalGet('node/' . $this->referencer->id()); - $this->assertTrue( - $this->validateLinkHeaderWithEntity('related', $this->referenced, 'Referenced Entity') == 1, - "Malformed related link header" - ); - $this->assertTrue( - $this->validateLinkHeaderWithEntity('related', $this->media, 'Media Entity') == 1, - "Malformed related link header" - ); - - // Check for links to REST endpoints for metadata. - $entity_url = $this->referencer->toUrl('canonical', ['absolute' => TRUE]) - ->toString(); - $this->assertTrue( - $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=json", NULL, 'application/json') == 1, - "Node must have link header pointing to json REST endpoint." - ); - $this->assertTrue( - $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=jsonld", NULL, 'application/ld+json') == 1, - "Node must have link header pointing to jsonld REST endpoint." - ); - $this->assertTrue( - $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=xml", NULL, 'application/xml') == 0, - "Node must not have link header pointing to disabled xml REST endpoint." - ); - - // Check that the current representation is not advertised when visitng - // a REST endpoint (e.g. the json link header doesn't appear when you're - // visiting the ?_format=json endpoint). - $this->drupalGet('node/' . $this->referencer->id(), ['query' => ['_format' => 'json']]); - $this->assertTrue( - $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=json", NULL, 'application/json') == 0, - "Node must not have link header pointing to json REST endpoint when vising the json REST endpoint." - ); - $this->assertTrue( - $this->validateLinkHeaderWithUrl('alternate', "$entity_url?_format=jsonld", NULL, 'application/ld+json') == 1, - "Node must have link header pointing to jsonld REST endpoint when visiting the json REST endpoint." - ); - - // Log in as anonymous. - $account = $this->drupalCreateUser(); - $this->drupalLogin($account); - - // Visit the referencer. It should return a rel="related" link header - // for both the referenced node bun not the media entity b/c permissions. - $this->drupalGet('node/' . $this->referencer->id()); - $this->assertTrue( - $this->validateLinkHeaderWithEntity('related', $this->referenced, 'Referenced Entity') == 1, - "Malformed related link header" - ); - $this->assertTrue( - $this->validateLinkHeaderWithEntity('related', $this->media, 'Media Entity') == 0, - "Anonymous should not be able to see media link header" - ); - } - -} diff --git a/tests/src/Functional/ViewModeAlterReactionTest.php b/tests/src/Functional/ViewModeAlterReactionTest.php new file mode 100644 index 00000000..04f07e00 --- /dev/null +++ b/tests/src/Functional/ViewModeAlterReactionTest.php @@ -0,0 +1,89 @@ +referenced = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => $this->testType->id(), + 'title' => 'Referenced', + ]); + $this->referenced->save(); + + // Node that is member of something. + $this->referencer = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => $this->testType->id(), + 'title' => 'Referencer', + 'field_member_of' => [$this->referenced->id()], + ]); + $this->referencer->save(); + } + + /** + * @covers \Drupal\islandora\Plugin\ContextReaction\ViewModeAlterReaction::execute + * @covers \Drupal\islandora\Plugin\ContextReaction\ViewModeAlterReaction::buildConfigurationForm + * @covers \Drupal\islandora\Plugin\ContextReaction\ViewModeAlterReaction::submitConfigurationForm + */ + public function testViewModeAlter() { + + // Create a test user. + $account = $this->drupalCreateUser([ + 'bypass node access', + 'administer contexts', + 'administer actions', + 'view media', + 'create media', + 'update media', + ]); + $this->drupalLogin($account); + + // Stash the node's url. + $url = $this->referencer->url('canonical', ['absolute' => TRUE]); + $this->drupalGet($url); + + // Make sure we're viewing the default (e.g. the media field is displayed). + $this->assertSession()->pageTextContains("Member Of"); + + // Create a context and set the view mode to alter to "teaser". + $this->createContext('Test', 'test'); + + $this->drupalGet("admin/structure/context/test/reaction/add/view_mode_alter"); + $this->getSession()->getPage()->findById("edit-reactions-view-mode-alter-mode")->selectOption('node.teaser'); + $this->getSession()->getPage()->pressButton(t('Save and continue')); + $this->assertSession()->statusCodeEquals(200); + + drupal_flush_all_caches(); + + // Re-visit the node and make sure we're in teaser mode (e.g. the media + // field is not displayed). + $this->drupalGet($url); + $this->assertSession()->pageTextNotContains("Member Of"); + } + +} diff --git a/tests/src/Kernel/EventGeneratorTest.php b/tests/src/Kernel/EventGeneratorTest.php index 46a6cb8c..b33d4cd5 100644 --- a/tests/src/Kernel/EventGeneratorTest.php +++ b/tests/src/Kernel/EventGeneratorTest.php @@ -70,10 +70,14 @@ class EventGeneratorTest extends IslandoraKernelTestBase { /** * Tests the generateCreateEvent() method. * - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateCreateEvent + * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateEvent */ public function testGenerateCreateEvent() { - $json = $this->eventGenerator->generateCreateEvent($this->entity, $this->user); + $json = $this->eventGenerator->generateEvent( + $this->entity, + $this->user, + ['event' => 'create', 'queue' => 'islandora-indexing-fcrepo-content'] + ); $msg = json_decode($json, TRUE); $this->assertBasicStructure($msg); @@ -83,10 +87,14 @@ class EventGeneratorTest extends IslandoraKernelTestBase { /** * Tests the generateUpdateEvent() method. * - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateUpdateEvent + * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateEvent */ public function testGenerateUpdateEvent() { - $json = $this->eventGenerator->generateUpdateEvent($this->entity, $this->user); + $json = $this->eventGenerator->generateEvent( + $this->entity, + $this->user, + ['event' => 'update', 'queue' => 'islandora-indexing-fcrepo-content'] + ); $msg = json_decode($json, TRUE); $this->assertBasicStructure($msg); @@ -96,10 +104,15 @@ class EventGeneratorTest extends IslandoraKernelTestBase { /** * Tests the generateDeleteEvent() method. * - * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateDeleteEvent + * @covers \Drupal\islandora\EventGenerator\EventGenerator::generateEvent */ public function testGenerateDeleteEvent() { - $json = $this->eventGenerator->generateDeleteEvent($this->entity, $this->user); + $json = $this->eventGenerator->generateEvent( + $this->entity, + $this->user, + ['event' => 'delete', 'queue' => 'islandora-indexing-fcrepo-delete'] + ); + $msg = json_decode($json, TRUE); $msg = json_decode($json, TRUE); $this->assertBasicStructure($msg); diff --git a/tests/src/Kernel/IslandoraKernelTestBase.php b/tests/src/Kernel/IslandoraKernelTestBase.php index 892b0a5a..a24afa69 100644 --- a/tests/src/Kernel/IslandoraKernelTestBase.php +++ b/tests/src/Kernel/IslandoraKernelTestBase.php @@ -22,7 +22,6 @@ abstract class IslandoraKernelTestBase extends KernelTestBase { 'path', 'text', 'options', - 'inline_entity_form', 'serialization', 'rest', 'basic_auth', @@ -35,10 +34,8 @@ abstract class IslandoraKernelTestBase extends KernelTestBase { 'key', 'jwt', 'file', - 'entity', 'image', - 'media_entity', - 'media_entity_image', + 'media', 'islandora', ]; @@ -54,6 +51,7 @@ abstract class IslandoraKernelTestBase extends KernelTestBase { $this->installEntitySchema('user'); $this->installEntitySchema('node'); $this->installEntitySchema('context'); + $this->installEntitySchema('file'); $this->installConfig('filter'); }