Browse Source

Merge branch 'master' into versioning

pull/733/head
Eli Zoller 6 years ago
parent
commit
3a5382813a
  1. 7
      .travis.yml
  2. 16
      CONTRIBUTING.md
  3. 13
      config/install/system.action.delete_media.yml
  4. 31
      config/schema/islandora.schema.yml
  5. 12
      islandora.install
  6. 3
      islandora.module
  7. 8
      islandora.services.yml
  8. 3
      modules/islandora_audio/tests/src/Functional/GenerateAudioDerivativeTest.php
  9. 3
      modules/islandora_breadcrumbs/config/install/islandora.breadcrumbs.yml
  10. 12
      modules/islandora_breadcrumbs/config/schema/islandora_breadcrumbs.schema.yml
  11. 7
      modules/islandora_breadcrumbs/islandora_breadcrumbs.info.yml
  12. 6
      modules/islandora_breadcrumbs/islandora_breadcrumbs.services.yml
  13. 96
      modules/islandora_breadcrumbs/src/IslandoraBreadcrumbBuilder.php
  14. 109
      modules/islandora_breadcrumbs/tests/src/Functional/BreadcrumbsTest.php
  15. 2
      modules/islandora_core_feature/config/install/field.field.media.audio.field_media_use.yml
  16. 2
      modules/islandora_core_feature/config/install/field.field.media.file.field_media_use.yml
  17. 2
      modules/islandora_core_feature/config/install/field.field.media.image.field_media_use.yml
  18. 2
      modules/islandora_core_feature/config/install/field.field.media.video.field_media_use.yml
  19. 2
      modules/islandora_core_feature/config/install/field.storage.media.field_media_use.yml
  20. 2
      modules/islandora_core_feature/config/install/field.storage.node.field_display_hints.yml
  21. 3
      modules/islandora_image/tests/src/Functional/GenerateImageDerivativeTest.php
  22. 3
      modules/islandora_video/tests/src/Functional/GenerateVideoDerivativeTest.php
  23. 21
      src/ContextReaction/NormalizerAlterReaction.php
  24. 19
      src/Controller/MediaSourceController.php
  25. 36
      src/EventGenerator/EventGenerator.php
  26. 30
      src/EventSubscriber/LinkHeaderSubscriber.php
  27. 3
      src/EventSubscriber/MediaLinkHeaderSubscriber.php
  28. 65
      src/EventSubscriber/NodeLinkHeaderSubscriber.php
  29. 12
      src/Flysystem/Adapter/FedoraAdapter.php
  30. 10
      src/Flysystem/Fedora.php
  31. 74
      src/IslandoraUtils.php
  32. 2
      src/Plugin/Action/AbstractGenerateDerivative.php
  33. 35
      src/Plugin/Action/DeleteMedia.php
  34. 174
      src/Plugin/Condition/MediaHasMimetype.php
  35. 187
      src/Plugin/Condition/NodeHadNamespace.php
  36. 168
      src/Plugin/Condition/NodeHasParent.php
  37. 94
      src/Plugin/Condition/NodeIsPublished.php
  38. 13
      src/Plugin/ContextReaction/MappingUriPredicateReaction.php
  39. 5
      src/PresetReaction/PresetReaction.php
  40. 25
      tests/src/Functional/DeleteMediaTest.php
  41. 3
      tests/src/Functional/GenerateDerivativeTestBase.php
  42. 26
      tests/src/Functional/IslandoraFunctionalTestBase.php
  43. 2
      tests/src/Kernel/EventGeneratorTest.php
  44. 5
      tests/src/Kernel/GeminiClientFactoryTest.php
  45. 35
      tests/src/Kernel/GeminiLookupTest.php

7
.travis.yml

@ -26,10 +26,9 @@ install:
- cd web; drush --uri=127.0.0.1:8282 en -y islandora - cd web; drush --uri=127.0.0.1:8282 en -y islandora
script: script:
- $SCRIPT_DIR/line_endings.sh $TRAVIS_BUILD_DIR - $SCRIPT_DIR/travis_scripts.sh
- phpcs --standard=Drupal --ignore=*.md --extensions=php,module,inc,install,test,profile,theme,css,info $TRAVIS_BUILD_DIR - $SCRIPT_DIR/run-tests.sh "islandora"
- phpcpd --names *.module,*.inc,*.test,*.php $TRAVIS_BUILD_DIR - $SCRIPT_DIR/run-tests.sh "islandora_breadcrumbs"
- php core/scripts/run-tests.sh --suppress-deprecations --url http://127.0.0.1:8282 --verbose --php `which php` --module "islandora"
notifications: notifications:
irc: irc:

16
CONTRIBUTING.md

@ -1,6 +1,10 @@
# Welcome! # Welcome!
If you are reading this document then you are interested in contributing to the Islandora CLAW. All contributions are welcome: use-cases, documentation, code, patches, bug reports, feature requests, etc. You do not need to be a programmer to speak up! If you are reading this document then you are interested in contributing to Islandora 8. All contributions are welcome: use-cases, documentation, code, patches, bug reports, feature requests, etc. You do not need to be a programmer to speak up!
We also have an irc channel -- #islandora -- on freenode.net. Feel free to hang out there, ask questions, and help others out if you can.
Please note that this project operates under the [Islandora Community Code of Conduct](http://islandora.ca/codeofconduct). By participating in this project you agree to abide by its terms.
## Workflows ## Workflows
@ -8,7 +12,7 @@ The group meets each Wednesday at 1:00 PM Eastern. Meeting notes and announcemen
### Use cases ### Use cases
If you would like to submit a use case to the Islandora CLAW project, please submit an issue [here](https://github.com/Islandora-CLAW/CLAW/issues/new) using the [Use Case template](https://github.com/Islandora-CLAW/CLAW/wiki/Use-Case-template), prepending "Use Case:" to the title of the issue. If you would like to submit a use case to the Islandora 8 project, please submit an issue [here](https://github.com/Islandora-CLAW/CLAW/issues/new) using the [Use Case template](https://github.com/Islandora-CLAW/CLAW/wiki/Use-Case-template), prepending "Use Case:" to the title of the issue.
### Documentation ### Documentation
@ -16,11 +20,11 @@ You can contribute documentation in two different ways. One way is to create an
### Request a new feature ### Request a new feature
To request a new feature you should [open an issue in the CLAW repository](https://github.com/Islandora-CLAW/CLAW/issues/new) or create a use case (see the _Use cases_ section above), and summarize the desired functionality. Prepend "Enhancement:" if creating an issue on the project repo, and "Use Case:" if creating a use case. To request a new feature you should [open an issue in the Islandora 8 repository](https://github.com/Islandora-CLAW/CLAW/issues/new) or create a use case (see the _Use cases_ section above), and summarize the desired functionality. Prepend "Enhancement:" if creating an issue on the project repo, and "Use Case:" if creating a use case.
### Report a bug ### Report a bug
To report a bug you should [open an issue in the CLAW repository](https://github.com/Islandora-CLAW/CLAW/issues/new) that summarizes the bug. Prepend the label "Bug:" to the title of the issue. To report a bug you should [open an issue in the Islandora 8 repository](https://github.com/Islandora-CLAW/CLAW/issues/new) that summarizes the bug. Prepend the label "Bug:" to the title of the issue.
In order to help us understand and fix the bug it would be great if you could provide us with: In order to help us understand and fix the bug it would be great if you could provide us with:
@ -36,7 +40,7 @@ That is great! In this case please send us a pull request as described in the se
### Contribute code ### Contribute code
Before you set out to contribute code you will need to have completed a [Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_cla.pdf) or be covered by a [Corporate Contributor Licencse Agreement](http://islandora.ca/sites/default/files/islandora_ccla.pdf). The signed copy of the license agreement should be sent to <mailto:community@islandora.ca> Before you set out to contribute code you will need to have completed a [Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_cla.pdf) or be covered by a [Corporate Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_ccla.pdf). The signed copy of the license agreement should be sent to <mailto:community@islandora.ca>
_If you are interested in contributing code to Islandora but do not know where to begin:_ _If you are interested in contributing code to Islandora but do not know where to begin:_
@ -66,4 +70,4 @@ You may want to read [Syncing a fork](https://help.github.com/articles/syncing-a
## License Agreements ## License Agreements
The Islandora Foundation requires that contributors complete a [Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_cla.pdf) or be covered by a [Corporate Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_ccla.pdf). The signed copy of the license agreement should be sent to <a href="mailto:community@islandora.ca?Subject=Contributor%20License%20Agreement" target="_top">community@islandora.ca</a>. This license is for your protection as a contributor as well as the protection of the Foundation and its users; it does not change your rights to use your own contributions for any other purpose. The Islandora Foundation requires that contributors complete a [Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_cla.pdf) or be covered by a [Corporate Contributor License Agreement](http://islandora.ca/sites/default/files/islandora_ccla.pdf). The signed copy of the license agreement should be sent to <a href="mailto:community@islandora.ca?Subject=Contributor%20License%20Agreement" target="_top">community@islandora.ca</a>. This license is for your protection as a contributor as well as the protection of the Foundation and its users; it does not change your rights to use your own contributions for any other purpose. A list of current CLAs is kept [here](https://github.com/Islandora/islandora/wiki/Contributor-License-Agreements).

13
config/install/system.action.delete_media.yml

@ -1,13 +0,0 @@
langcode: en
status: true
dependencies:
enforced:
module:
- islandora
module:
- islandora
id: delete_media
label: 'Delete media'
type: media
plugin: delete_media
configuration: { }

31
config/schema/islandora.schema.yml

@ -68,10 +68,6 @@ action.configuration.emit_term_event:
type: text type: text
label: 'Event Type' label: 'Event Type'
action.configuration.delete_media:
type: action_configuration_default
label: 'Delete media'
action.configuration.delete_media_and_file: action.configuration.delete_media_and_file:
type: action_configuration_default type: action_configuration_default
label: 'Delete media and file' label: 'Delete media and file'
@ -83,6 +79,16 @@ condition.plugin.node_has_term:
type: text type: text
label: 'Taxonomy Term URI' label: 'Taxonomy Term URI'
condition.plugin.node_has_parent:
type: condition.plugin
mapping:
parent_nid:
type: integer
label: 'Parent node'
parent_reference_field:
type: string
label: 'Parent reference field'
condition.plugin.media_has_term: condition.plugin.media_has_term:
type: condition.plugin type: condition.plugin
mapping: mapping:
@ -113,6 +119,13 @@ condition.plugin.media_uses_filesystem:
sequence: sequence:
type: string type: string
condition.plugin.media_has_mimetype:
type: condition.plugin
mapping:
mimetypes:
type: text
label: 'Mime types'
condition.plugin.content_entity_type: condition.plugin.content_entity_type:
type: condition.plugin type: condition.plugin
mapping: mapping:
@ -121,6 +134,16 @@ condition.plugin.content_entity_type:
sequence: sequence:
type: string type: string
condition.plugin.node_had_namespace:
type: condition.plugin
mapping:
namespace:
type: text
label: 'Namespace'
pid_field:
type: ignore
label: 'PID field'
field.formatter.settings.islandora_image: field.formatter.settings.islandora_image:
type: mapping type: mapping
label: 'Image field display format settings' label: 'Image field display format settings'

12
islandora.install

@ -40,3 +40,15 @@ function islandora_schema() {
]; ];
return $schema; return $schema;
} }
/**
* Delete the 'delete_media' action we used to provide, if it exists.
*
* Use the core 'media_delete_action' instead.
*/
function islandora_update_8001(&$sandbox) {
$action = \Drupal::service('entity_type.manager')->getStorage('action')->load('delete_media');
if ($action) {
$action->delete();
}
}

3
islandora.module

@ -343,10 +343,13 @@ function islandora_form_block_form_alter(&$form, FormStateInterface $form_state,
// to alter block layout. // to alter block layout.
unset($form['visibility']['content_entity_type']); unset($form['visibility']['content_entity_type']);
unset($form['visibility']['parent_node_has_term']); unset($form['visibility']['parent_node_has_term']);
unset($form['visibility']['node_had_namespace']);
unset($form['visibility']['media_has_term']); unset($form['visibility']['media_has_term']);
unset($form['visibility']['file_uses_filesystem']); unset($form['visibility']['file_uses_filesystem']);
unset($form['visibility']['node_has_term']); unset($form['visibility']['node_has_term']);
unset($form['visibility']['node_has_parent']);
unset($form['visibility']['media_uses_filesystem']); unset($form['visibility']['media_uses_filesystem']);
unset($form['visibility']['media_has_mimetype']);
} }
/** /**

8
islandora.services.yml

@ -3,7 +3,7 @@
services: services:
islandora.eventgenerator: islandora.eventgenerator:
class: Drupal\islandora\EventGenerator\EventGenerator class: Drupal\islandora\EventGenerator\EventGenerator
arguments: ['@language_manager', '@islandora.media_source_service'] arguments: ['@islandora.utils', '@islandora.media_source_service']
islandora.stomp: islandora.stomp:
class: Stomp\StatefulStomp class: Stomp\StatefulStomp
factory: ['Drupal\islandora\StompFactory', create] factory: ['Drupal\islandora\StompFactory', create]
@ -16,12 +16,12 @@ services:
- { name: event_subscriber } - { name: event_subscriber }
islandora.media_link_header_subscriber: islandora.media_link_header_subscriber:
class: Drupal\islandora\EventSubscriber\MediaLinkHeaderSubscriber class: Drupal\islandora\EventSubscriber\MediaLinkHeaderSubscriber
arguments: ['@entity_type.manager', '@entity_field.manager', '@access_manager', '@current_user', '@current_route_match', '@request_stack', '@language_manager'] arguments: ['@entity_type.manager', '@entity_field.manager', '@access_manager', '@current_user', '@current_route_match', '@request_stack', '@islandora.utils']
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
islandora.node_link_header_subscriber: islandora.node_link_header_subscriber:
class: Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber class: Drupal\islandora\EventSubscriber\NodeLinkHeaderSubscriber
arguments: ['@entity_type.manager', '@entity_field.manager', '@access_manager', '@current_user', '@current_route_match', '@request_stack', '@language_manager', '@islandora.utils'] arguments: ['@entity_type.manager', '@entity_field.manager', '@access_manager', '@current_user', '@current_route_match', '@request_stack', '@islandora.utils']
tags: tags:
- { name: event_subscriber } - { name: event_subscriber }
islandora.admin_view_route_subscriber: islandora.admin_view_route_subscriber:
@ -51,7 +51,7 @@ services:
arguments: ['@entity_type.manager', '@current_user', '@language_manager', '@entity.query', '@file_system', '@islandora.utils'] arguments: ['@entity_type.manager', '@current_user', '@language_manager', '@entity.query', '@file_system', '@islandora.utils']
islandora.utils: islandora.utils:
class: Drupal\islandora\IslandoraUtils class: Drupal\islandora\IslandoraUtils
arguments: ['@entity_type.manager', '@entity_field.manager', '@entity.query', '@context.manager', '@flysystem_factory'] arguments: ['@entity_type.manager', '@entity_field.manager', '@entity.query', '@context.manager', '@flysystem_factory', '@language_manager']
islandora.gemini.client: islandora.gemini.client:
class: Islandora\Crayfish\Commons\Client\GeminiClient class: Islandora\Crayfish\Commons\Client\GeminiClient
factory: ['Drupal\islandora\GeminiClientFactory', create] factory: ['Drupal\islandora\GeminiClientFactory', create]

3
modules/islandora_audio/tests/src/Functional/GenerateAudioDerivativeTest.php

@ -11,6 +11,9 @@ use Drupal\Tests\islandora\Functional\GenerateDerivativeTestBase;
*/ */
class GenerateAudioDerivativeTest extends GenerateDerivativeTestBase { class GenerateAudioDerivativeTest extends GenerateDerivativeTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['context_ui', 'islandora_audio']; protected static $modules = ['context_ui', 'islandora_audio'];
/** /**

3
modules/islandora_breadcrumbs/config/install/islandora.breadcrumbs.yml

@ -0,0 +1,3 @@
maxDepth: -1
includeSelf: FALSE
referenceField: field_member_of

12
modules/islandora_breadcrumbs/config/schema/islandora_breadcrumbs.schema.yml

@ -0,0 +1,12 @@
islandora.breadcrumbs:
type: config_object
mapping:
maxDepth:
type: integer
label: 'Max Depth'
includeSelf:
type: boolean
label: 'Include Self'
referenceField:
type: string
label: 'Reference Field'

7
modules/islandora_breadcrumbs/islandora_breadcrumbs.info.yml

@ -0,0 +1,7 @@
name: 'Islandora Breadcrumbs'
type: module
description: 'Builds breadcrumbs based on field_member_of relationships.'
core: 8.x
package: Islandora
dependencies:
- islandora

6
modules/islandora_breadcrumbs/islandora_breadcrumbs.services.yml

@ -0,0 +1,6 @@
services:
islandora_breadcrumbs.breadcrumb:
class: Drupal\islandora_breadcrumbs\IslandoraBreadcrumbBuilder
arguments: ['@config.factory']
tags:
- { name: breadcrumb_builder, priority: 100 }

96
modules/islandora_breadcrumbs/src/IslandoraBreadcrumbBuilder.php

@ -0,0 +1,96 @@
<?php
namespace Drupal\islandora_breadcrumbs;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Provides breadcrumbs for nodes using a configured entity reference field.
*/
class IslandoraBreadcrumbBuilder implements BreadcrumbBuilderInterface {
/**
* The configuration.
*
* @var \Drupal\Core\Config\ImmutableConfig
*/
protected $config;
/**
* Constructs a breadcrumb builder.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory.
*/
public function __construct(ConfigFactoryInterface $config_factory) {
$this->config = $config_factory->get('islandora.breadcrumbs');
}
/**
* {@inheritdoc}
*/
public function applies(RouteMatchInterface $attributes) {
$parameters = $attributes->getParameters()->all();
if (!empty($parameters['node'])) {
return ($parameters['node']->hasField($this->config->get('referenceField')) &&
!$parameters['node']->get($this->config->get('referenceField'))->isEmpty());
}
}
/**
* {@inheritdoc}
*/
public function build(RouteMatchInterface $route_match) {
$node = $route_match->getParameter('node');
$breadcrumb = new Breadcrumb();
$chain = [];
$this->walkMembership($node, $chain);
if (!$this->config->get('includeSelf')) {
array_pop($chain);
}
$breadcrumb->addCacheableDependency($node);
// Add membership chain to the breadcrumb.
foreach ($chain as $chainlink) {
$breadcrumb->addCacheableDependency($chainlink);
$breadcrumb->addLink($chainlink->toLink());
}
$breadcrumb->addCacheContexts(['route']);
return $breadcrumb;
}
/**
* Follows chain of field_member_of links.
*
* We pass crumbs by reference to enable checking for looped chains.
*/
protected function walkMembership(EntityInterface $entity, &$crumbs) {
// Avoid infinate loops, return if we've seen this before.
foreach ($crumbs as $crumb) {
if ($crumb->uuid == $entity->uuid) {
return;
}
}
// Add this item onto the pile.
array_unshift($crumbs, $entity);
if ($this->config->get('maxDepth') > 0 && count($crumbs) >= $this->config->get('maxDepth')) {
return;
}
// Find the next in the chain, if there are any.
if ($entity->hasField($this->config->get('referenceField')) &&
!$entity->get($this->config->get('referenceField'))->isEmpty()) {
$this->walkMembership($entity->get($this->config->get('referenceField'))->entity, $crumbs);
}
}
}

109
modules/islandora_breadcrumbs/tests/src/Functional/BreadcrumbsTest.php

@ -0,0 +1,109 @@
<?php
namespace Drupal\Tests\islandora_breadcrumbs\Functional;
use Drupal\Tests\islandora\Functional\IslandoraFunctionalTestBase;
use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait;
/**
* Tests the Islandora Breadcrumbs Builder.
*
* @group islandora_breadcrumbs
*/
class BreadcrumbsTest extends IslandoraFunctionalTestBase {
use AssertBreadcrumbTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'islandora_breadcrumbs',
];
/**
* A node.
*
* @var \Drupal\node\NodeInterface
*/
protected $nodeA;
/**
* Another node.
*
* @var \Drupal\node\NodeInterface
*/
protected $nodeB;
/**
* Yet another node.
*
* @var \Drupal\node\NodeInterface
*/
protected $nodeC;
/**
* Another one.
*
* @var \Drupal\node\NodeInterface
*/
protected $nodeD;
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
// Create some nodes.
$this->nodeA = $this->container->get('entity_type.manager')->getStorage('node')->create([
'type' => $this->testType->id(),
'title' => 'Node A',
]);
$this->nodeA->save();
$this->nodeB = $this->container->get('entity_type.manager')->getStorage('node')->create([
'type' => $this->testType->id(),
'title' => 'Node B',
]);
$this->nodeB->set('field_member_of', [$this->nodeA->id()]);
$this->nodeB->save();
$this->nodeC = $this->container->get('entity_type.manager')->getStorage('node')->create([
'type' => $this->testType->id(),
'title' => 'Node C',
]);
$this->nodeC->set('field_member_of', [$this->nodeB->id()]);
$this->nodeC->save();
$this->nodeD = $this->container->get('entity_type.manager')->getStorage('node')->create([
'type' => $this->testType->id(),
'title' => 'Node D',
]);
$this->nodeD->set('field_member_of', [$this->nodeC->id()]);
$this->nodeD->save();
}
/**
* @covers \Drupal\islandora_breadcrumbs\IslandoraBreadcrumbBuilder::applies
*/
public function testDefaults() {
$breadcrumbs = [
$this->nodeC->toUrl()->toString() => $this->nodeC->label(),
$this->nodeB->toUrl()->toString() => $this->nodeB->label(),
$this->nodeA->toUrl()->toString() => $this->nodeA->label(),
];
$this->assertBreadcrumb($this->nodeD->toUrl()->toString(), $breadcrumbs);
// Create a reference loop.
$this->nodeA->set('field_member_of', [$this->nodeD->id()]);
$this->nodeA->save();
// We should still escape it and have the same trail as before.
$this->assertBreadcrumb($this->nodeD->toUrl()->toString(), $breadcrumbs);
}
}

2
modules/islandora_core_feature/config/install/field.field.media.audio.field_media_use.yml

@ -10,7 +10,7 @@ field_name: field_media_use
entity_type: media entity_type: media
bundle: audio bundle: audio
label: 'Media Use' label: 'Media Use'
description: '' description: 'Defined by Portland Common Data Model: Use Extension https://pcdm.org/2015/05/12/use. ''Original File'' will trigger creation of derivatives.'
required: false required: false
translatable: false translatable: false
default_value: { } default_value: { }

2
modules/islandora_core_feature/config/install/field.field.media.file.field_media_use.yml

@ -10,7 +10,7 @@ field_name: field_media_use
entity_type: media entity_type: media
bundle: file bundle: file
label: 'Media Use' label: 'Media Use'
description: '' description: 'Defined by Portland Common Data Model: Use Extension https://pcdm.org/2015/05/12/use. ''Original File'' will trigger creation of derivatives.'
required: false required: false
translatable: true translatable: true
default_value: { } default_value: { }

2
modules/islandora_core_feature/config/install/field.field.media.image.field_media_use.yml

@ -10,7 +10,7 @@ field_name: field_media_use
entity_type: media entity_type: media
bundle: image bundle: image
label: 'Media Use' label: 'Media Use'
description: '' description: 'Defined by Portland Common Data Model: Use Extension https://pcdm.org/2015/05/12/use. ''Original File'' will trigger creation of derivatives.'
required: false required: false
translatable: true translatable: true
default_value: { } default_value: { }

2
modules/islandora_core_feature/config/install/field.field.media.video.field_media_use.yml

@ -10,7 +10,7 @@ field_name: field_media_use
entity_type: media entity_type: media
bundle: video bundle: video
label: 'Media Use' label: 'Media Use'
description: '' description: 'Defined by Portland Common Data Model: Use Extension https://pcdm.org/2015/05/12/use. ''Original File'' will trigger creation of derivatives.'
required: false required: false
translatable: true translatable: true
default_value: { } default_value: { }

2
modules/islandora_core_feature/config/install/field.storage.media.field_media_use.yml

@ -12,7 +12,7 @@ settings:
target_type: taxonomy_term target_type: taxonomy_term
module: core module: core
locked: false locked: false
cardinality: 1 cardinality: -1
translatable: true translatable: true
indexes: { } indexes: { }
persist_with_no_fields: false persist_with_no_fields: false

2
modules/islandora_core_feature/config/install/field.storage.node.field_display_hints.yml

@ -12,7 +12,7 @@ settings:
target_type: taxonomy_term target_type: taxonomy_term
module: core module: core
locked: false locked: false
cardinality: -1 cardinality: 1
translatable: true translatable: true
indexes: { } indexes: { }
persist_with_no_fields: false persist_with_no_fields: false

3
modules/islandora_image/tests/src/Functional/GenerateImageDerivativeTest.php

@ -11,6 +11,9 @@ use Drupal\Tests\islandora\Functional\GenerateDerivativeTestBase;
*/ */
class GenerateImageDerivativeTest extends GenerateDerivativeTestBase { class GenerateImageDerivativeTest extends GenerateDerivativeTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['context_ui', 'islandora_image']; protected static $modules = ['context_ui', 'islandora_image'];
/** /**

3
modules/islandora_video/tests/src/Functional/GenerateVideoDerivativeTest.php

@ -11,6 +11,9 @@ use Drupal\Tests\islandora\Functional\GenerateDerivativeTestBase;
*/ */
class GenerateVideoDerivativeTest extends GenerateDerivativeTestBase { class GenerateVideoDerivativeTest extends GenerateDerivativeTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['context_ui', 'islandora_video']; protected static $modules = ['context_ui', 'islandora_video'];
/** /**

21
src/ContextReaction/NormalizerAlterReaction.php

@ -7,6 +7,7 @@ use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\jsonld\Form\JsonLdSettingsForm; use Drupal\jsonld\Form\JsonLdSettingsForm;
use Drupal\islandora\IslandoraUtils;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
@ -25,16 +26,25 @@ abstract class NormalizerAlterReaction extends ContextReactionPluginBase impleme
*/ */
protected $jsonldConfig; protected $jsonldConfig;
/**
* Islandora utils.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function __construct(array $configuration, public function __construct(array $configuration,
$plugin_id, $plugin_id,
$plugin_definition, $plugin_definition,
ConfigFactoryInterface $config_factory) { ConfigFactoryInterface $config_factory,
IslandoraUtils $utils) {
parent::__construct($configuration, $plugin_id, $plugin_definition); parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->jsonldConfig = $config_factory->get(JsonLdSettingsForm::CONFIG_NAME); $this->jsonldConfig = $config_factory->get(JsonLdSettingsForm::CONFIG_NAME);
$this->utils = $utils;
} }
/** /**
@ -45,7 +55,8 @@ abstract class NormalizerAlterReaction extends ContextReactionPluginBase impleme
$configuration, $configuration,
$plugin_id, $plugin_id,
$plugin_definition, $plugin_definition,
$container->get('config.factory') $container->get('config.factory'),
$container->get('islandora.utils')
); );
} }
@ -71,11 +82,11 @@ abstract class NormalizerAlterReaction extends ContextReactionPluginBase impleme
* The url. * The url.
*/ */
protected function getSubjectUrl(EntityInterface $entity) { protected function getSubjectUrl(EntityInterface $entity) {
$url = $entity->toUrl('canonical', ['absolute' => TRUE]); $format = '';
if (!$this->jsonldConfig->get(JsonLdSettingsForm::REMOVE_JSONLD_FORMAT)) { if (!$this->jsonldConfig->get(JsonLdSettingsForm::REMOVE_JSONLD_FORMAT)) {
$url->setRouteParameter('_format', 'jsonld'); $format = 'jsonld';
} }
return $url->toString(); return $this->utils->getRestUrl($entity, $format);
} }
} }

19
src/Controller/MediaSourceController.php

@ -11,6 +11,7 @@ use Drupal\media\MediaInterface;
use Drupal\media\MediaTypeInterface; use Drupal\media\MediaTypeInterface;
use Drupal\node\NodeInterface; use Drupal\node\NodeInterface;
use Drupal\taxonomy\TermInterface; use Drupal\taxonomy\TermInterface;
use Drupal\islandora\IslandoraUtils;
use Drupal\islandora\MediaSource\MediaSourceService; use Drupal\islandora\MediaSource\MediaSourceService;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@ -39,6 +40,13 @@ class MediaSourceController extends ControllerBase {
*/ */
protected $database; protected $database;
/**
* Islandora utils.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;
/** /**
* MediaSourceController constructor. * MediaSourceController constructor.
* *
@ -46,13 +54,17 @@ class MediaSourceController extends ControllerBase {
* Service for business logic. * Service for business logic.
* @param \Drupal\Core\Database\Connection $database * @param \Drupal\Core\Database\Connection $database
* Database connection. * Database connection.
* @param \Drupal\islandora\IslandoraUtils $utils
* Islandora utils.
*/ */
public function __construct( public function __construct(
MediaSourceService $service, MediaSourceService $service,
Connection $database Connection $database,
IslandoraUtils $utils
) { ) {
$this->service = $service; $this->service = $service;
$this->database = $database; $this->database = $database;
$this->utils = $utils;
} }
/** /**
@ -67,7 +79,8 @@ class MediaSourceController extends ControllerBase {
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static( return new static(
$container->get('islandora.media_source_service'), $container->get('islandora.media_source_service'),
$container->get('database') $container->get('database'),
$container->get('islandora.utils')
); );
} }
@ -162,7 +175,7 @@ class MediaSourceController extends ControllerBase {
// We return the media if it was newly created. // We return the media if it was newly created.
if ($media) { if ($media) {
$response = new Response("", 201); $response = new Response("", 201);
$response->headers->set("Location", $media->url('canonical', ['absolute' => TRUE])); $response->headers->set("Location", $this->utils->getEntityUrl($media));
} }
else { else {
$response = new Response("", 204); $response = new Response("", 204);

36
src/EventGenerator/EventGenerator.php

@ -3,8 +3,7 @@
namespace Drupal\islandora\EventGenerator; namespace Drupal\islandora\EventGenerator;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\LanguageManagerInterface; use Drupal\islandora\IslandoraUtils;
use Drupal\Core\Url;
use Drupal\islandora\MediaSource\MediaSourceService; use Drupal\islandora\MediaSource\MediaSourceService;
use Drupal\user\UserInterface; use Drupal\user\UserInterface;
@ -16,11 +15,11 @@ use Drupal\user\UserInterface;
class EventGenerator implements EventGeneratorInterface { class EventGenerator implements EventGeneratorInterface {
/** /**
* Language manager. * Islandora utils.
* *
* @var \Drupal\Core\Language\LanguageManagerInterface * @var \Drupal\islandora\IslandoraUtils
*/ */
protected $languageManager; protected $utils;
/** /**
* Media source service. * Media source service.
@ -32,13 +31,13 @@ class EventGenerator implements EventGeneratorInterface {
/** /**
* Constructor. * Constructor.
* *
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * @param \Drupal\islandora\IslandoraUtils $utils
* Language manager. * Islandora utils.
* @param \Drupal\islandora\MediaSource\MediaSourceService $media_source * @param \Drupal\islandora\MediaSource\MediaSourceService $media_source
* Media source service. * Media source service.
*/ */
public function __construct(LanguageManagerInterface $language_manager, MediaSourceService $media_source) { public function __construct(IslandoraUtils $utils, MediaSourceService $media_source) {
$this->languageManager = $language_manager; $this->utils = $utils;
$this->mediaSource = $media_source; $this->mediaSource = $media_source;
} }
@ -47,21 +46,16 @@ class EventGenerator implements EventGeneratorInterface {
*/ */
public function generateEvent(EntityInterface $entity, UserInterface $user, array $data) { public function generateEvent(EntityInterface $entity, UserInterface $user, array $data) {
$user_url = $user->toUrl()->setAbsolute()->toString(); $user_url = $this->utils->getEntityUrl($user);
$entity_type = $entity->getEntityTypeId();
$undefined = $this->languageManager->getLanguage('und'); $entity_type = $entity->getEntityTypeId();
if ($entity_type == 'file') { if ($entity_type == 'file') {
$entity_url = $entity->url('canonical', ['absolute' => TRUE, 'language' => $undefined]); $entity_url = $this->utils->getDownloadUrl($entity);
$mimetype = $entity->getMimeType(); $mimetype = $entity->getMimeType();
} }
else { else {
$entity_url = Url::fromRoute( $entity_url = $this->utils->getEntityUrl($entity);
"rest.entity.$entity_type.GET",
[$entity_type => $entity->id()],
['absolute' => TRUE, 'language' => $undefined]
)->toString();
$mimetype = 'text/html'; $mimetype = 'text/html';
} }
@ -112,14 +106,14 @@ class EventGenerator implements EventGeneratorInterface {
$event['object']['url'][] = [ $event['object']['url'][] = [
"name" => "JSON", "name" => "JSON",
"type" => "Link", "type" => "Link",
"href" => "$entity_url?_format=json", "href" => $this->utils->getRestUrl($entity, 'json'),
"mediaType" => "application/json", "mediaType" => "application/json",
"rel" => "alternate", "rel" => "alternate",
]; ];
$event['object']['url'][] = [ $event['object']['url'][] = [
"name" => "JSONLD", "name" => "JSONLD",
"type" => "Link", "type" => "Link",
"href" => "$entity_url?_format=jsonld", "href" => $this->utils->getRestUrl($entity, 'jsonld'),
"mediaType" => "application/ld+json", "mediaType" => "application/ld+json",
"rel" => "alternate", "rel" => "alternate",
]; ];
@ -132,7 +126,7 @@ class EventGenerator implements EventGeneratorInterface {
$event['object']['url'][] = [ $event['object']['url'][] = [
"name" => "Describes", "name" => "Describes",
"type" => "Link", "type" => "Link",
"href" => $file->url('canonical', ['absolute' => TRUE, 'language' => $undefined]), "href" => $this->utils->getDownloadUrl($file),
"mediaType" => $file->getMimeType(), "mediaType" => $file->getMimeType(),
"rel" => "describes", "rel" => "describes",
]; ];

30
src/EventSubscriber/LinkHeaderSubscriber.php

@ -6,10 +6,9 @@ use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Entity\EntityFieldManager; use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface; use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url; use Drupal\islandora\IslandoraUtils;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@ -66,11 +65,11 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
protected $requestStack; protected $requestStack;
/** /**
* Language manager. * Islandora utils.
* *
* @var \Drupal\Core\Language\LanguageManagerInterface * @var \Drupal\islandora\IslandoraUtils
*/ */
protected $languageManager; protected $utils;
/** /**
* Constructor. * Constructor.
@ -87,8 +86,8 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
* The route match object. * The route match object.
* @param Symfony\Component\HttpFoundation\RequestStack $request_stack * @param Symfony\Component\HttpFoundation\RequestStack $request_stack
* Request stack (for current request). * Request stack (for current request).
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * @param \Drupal\islandora\IslandoraUtils $utils
* Language manager. * Islandora utils.
*/ */
public function __construct( public function __construct(
EntityTypeManager $entity_type_manager, EntityTypeManager $entity_type_manager,
@ -97,7 +96,7 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
AccountInterface $account, AccountInterface $account,
RouteMatchInterface $route_match, RouteMatchInterface $route_match,
RequestStack $request_stack, RequestStack $request_stack,
LanguageManagerInterface $language_manager IslandoraUtils $utils
) { ) {
$this->entityTypeManager = $entity_type_manager; $this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager; $this->entityFieldManager = $entity_field_manager;
@ -107,7 +106,7 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
$this->accessManager = $access_manager; $this->accessManager = $access_manager;
$this->account = $account; $this->account = $account;
$this->requestStack = $request_stack; $this->requestStack = $request_stack;
$this->languageManager = $language_manager; $this->utils = $utils;
} }
/** /**
@ -206,6 +205,8 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
// Headers are subject to an access check. // Headers are subject to an access check.
if ($referencedEntity->access('view')) { if ($referencedEntity->access('view')) {
$entity_url = $this->utils->getEntityUrl($referencedEntity);
// Taxonomy terms are written out as // Taxonomy terms are written out as
// <url>; rel="tag"; title="Tag Name" // <url>; rel="tag"; title="Tag Name"
// where url is defined in field_same_as. // where url is defined in field_same_as.
@ -213,7 +214,6 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
// it becomes the taxonomy term's local uri. // it becomes the taxonomy term's local uri.
if ($referencedEntity->getEntityTypeId() == 'taxonomy_term') { if ($referencedEntity->getEntityTypeId() == 'taxonomy_term') {
$rel = "tag"; $rel = "tag";
$entity_url = $referencedEntity->url('canonical', ['absolute' => TRUE]);
if ($referencedEntity->hasField('field_external_uri')) { if ($referencedEntity->hasField('field_external_uri')) {
$external_uri = $referencedEntity->get('field_external_uri')->getValue(); $external_uri = $referencedEntity->get('field_external_uri')->getValue();
if (!empty($external_uri) && isset($external_uri[0]['uri'])) { if (!empty($external_uri) && isset($external_uri[0]['uri'])) {
@ -228,7 +228,6 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
// <url>; rel="related"; title="Field Label" // <url>; rel="related"; title="Field Label"
// and the url is the local uri. // and the url is the local uri.
$rel = "related"; $rel = "related";
$entity_url = $referencedEntity->url('canonical', ['absolute' => TRUE]);
$title = $field_definition->label(); $title = $field_definition->label();
} }
$links[] = "<$entity_url>; rel=\"$rel\"; title=\"$title\""; $links[] = "<$entity_url>; rel=\"$rel\"; title=\"$title\"";
@ -287,19 +286,16 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
continue; continue;
} }
// Skip route if the user doesn't have access.
$meta_route_name = "rest.entity.$entity_type.GET"; $meta_route_name = "rest.entity.$entity_type.GET";
$route_params = [$entity_type => $entity->id()]; $route_params = [$entity_type => $entity->id()];
if (!$this->accessManager->checkNamedRoute($meta_route_name, $route_params, $this->account)) { if (!$this->accessManager->checkNamedRoute($meta_route_name, $route_params, $this->account)) {
continue; continue;
} }
$meta_url = Url::fromRoute($meta_route_name, $route_params) $meta_url = $this->utils->getRestUrl($entity, $format);
->setAbsolute()
->toString();
$links[] = "<$meta_url?_format=$format>; rel=\"alternate\"; type=\"$mime\""; $links[] = "<$meta_url>; rel=\"alternate\"; type=\"$mime\"";
} }
} }

3
src/EventSubscriber/MediaLinkHeaderSubscriber.php

@ -77,10 +77,9 @@ class MediaLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSub
} }
// Collect file links for the media. // Collect file links for the media.
$undefined = $this->languageManager->getLanguage('und');
foreach ($media->get($source_field)->referencedEntities() as $referencedEntity) { foreach ($media->get($source_field)->referencedEntities() as $referencedEntity) {
if ($referencedEntity->access('view')) { if ($referencedEntity->access('view')) {
$file_url = $referencedEntity->url('canonical', ['absolute' => TRUE, 'language' => $undefined]); $file_url = $this->utils->getDownloadUrl($referencedEntity);
$links[] = "<$file_url>; rel=\"describes\"; type=\"{$referencedEntity->getMimeType()}\""; $links[] = "<$file_url>; rel=\"describes\"; type=\"{$referencedEntity->getMimeType()}\"";
} }
} }

65
src/EventSubscriber/NodeLinkHeaderSubscriber.php

@ -2,17 +2,8 @@
namespace Drupal\islandora\EventSubscriber; namespace Drupal\islandora\EventSubscriber;
use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\islandora\IslandoraUtils;
use Drupal\node\NodeInterface; use Drupal\node\NodeInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/** /**
@ -22,55 +13,6 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
*/ */
class NodeLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubscriberInterface { 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\Core\Language\LanguageManagerInterface $language_manager
* Language manager.
* @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,
LanguageManagerInterface $language_manager,
IslandoraUtils $utils
) {
parent::__construct(
$entity_type_manager,
$entity_field_manager,
$access_manager,
$account,
$route_match,
$request_stack,
$language_manager
);
$this->utils = $utils;
}
/** /**
* Adds node-specific link headers to appropriate responses. * Adds node-specific link headers to appropriate responses.
* *
@ -105,13 +47,8 @@ class NodeLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubs
*/ */
protected function generateRelatedMediaLinks(NodeInterface $node) { protected function generateRelatedMediaLinks(NodeInterface $node) {
$links = []; $links = [];
$undefined = $this->languageManager->getLanguage('und');
foreach ($this->utils->getMedia($node) as $media) { foreach ($this->utils->getMedia($node) as $media) {
$url = Url::fromRoute( $url = $this->utils->getEntityUrl($media);
"rest.entity.media.GET",
['media' => $media->id()],
['absolute' => TRUE, 'language' => $undefined]
)->toString();
foreach ($media->referencedEntities() as $term) { foreach ($media->referencedEntities() as $term) {
if ($term->getEntityTypeId() == 'taxonomy_term' && $term->hasField('field_external_uri')) { if ($term->getEntityTypeId() == 'taxonomy_term' && $term->hasField('field_external_uri')) {
$field = $term->get('field_external_uri'); $field = $term->get('field_external_uri');

12
src/Flysystem/Adapter/FedoraAdapter.php

@ -20,7 +20,18 @@ class FedoraAdapter implements AdapterInterface {
use StreamedCopyTrait; use StreamedCopyTrait;
use NotSupportingVisibilityTrait; use NotSupportingVisibilityTrait;
/**
* Fedora client.
*
* @var \Islandora\Chullo\IFedoraApi
*/
protected $fedora; protected $fedora;
/**
* Mimetype guesser.
*
* @var \Symfony\Component\HttpFoundation\File\Mimetype\MimeTypeGuesserInterface
*/
protected $mimeTypeGuesser; protected $mimeTypeGuesser;
/** /**
@ -75,7 +86,6 @@ class FedoraAdapter implements AdapterInterface {
$meta = $this->getMetadataFromHeaders($response); $meta = $this->getMetadataFromHeaders($response);
$meta['path'] = $path; $meta['path'] = $path;
if ($meta['type'] == 'file') { if ($meta['type'] == 'file') {
$meta['stream'] = StreamWrapper::getResource($response->getBody()); $meta['stream'] = StreamWrapper::getResource($response->getBody());
} }

10
src/Flysystem/Fedora.php

@ -27,8 +27,18 @@ class Fedora implements FlysystemPluginInterface, ContainerFactoryPluginInterfac
use FlysystemUrlTrait; use FlysystemUrlTrait;
/**
* Fedora client.
*
* @var \Islandora\Chullo\IFedoraApi
*/
protected $fedora; protected $fedora;
/**
* Mimetype guesser.
*
* @var \Symfony\Component\HttpFoundation\File\Mimetype\MimeTypeGuesserInterface
*/
protected $mimeTypeGuesser; protected $mimeTypeGuesser;
/** /**

74
src/IslandoraUtils.php

@ -4,12 +4,15 @@ namespace Drupal\islandora;
use Drupal\context\ContextManager; use Drupal\context\ContextManager;
use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityFieldManager; use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Entity\Query\QueryException; use Drupal\Core\Entity\Query\QueryException;
use Drupal\Core\Entity\Query\QueryFactory; use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Site\Settings; use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\file\FileInterface; use Drupal\file\FileInterface;
use Drupal\flysystem\FlysystemFactory; use Drupal\flysystem\FlysystemFactory;
use Drupal\islandora\ContextProvider\NodeContextProvider; use Drupal\islandora\ContextProvider\NodeContextProvider;
@ -64,6 +67,13 @@ class IslandoraUtils {
*/ */
protected $flysystemFactory; protected $flysystemFactory;
/**
* Language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/** /**
* Constructor. * Constructor.
* *
@ -77,19 +87,23 @@ class IslandoraUtils {
* Context manager. * Context manager.
* @param \Drupal\flysystem\FlysystemFactory $flysystem_factory * @param \Drupal\flysystem\FlysystemFactory $flysystem_factory
* Flysystem factory. * Flysystem factory.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* Language manager.
*/ */
public function __construct( public function __construct(
EntityTypeManager $entity_type_manager, EntityTypeManager $entity_type_manager,
EntityFieldManager $entity_field_manager, EntityFieldManager $entity_field_manager,
QueryFactory $entity_query, QueryFactory $entity_query,
ContextManager $context_manager, ContextManager $context_manager,
FlysystemFactory $flysystem_factory FlysystemFactory $flysystem_factory,
LanguageManagerInterface $language_manager
) { ) {
$this->entityTypeManager = $entity_type_manager; $this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager; $this->entityFieldManager = $entity_field_manager;
$this->entityQuery = $entity_query; $this->entityQuery = $entity_query;
$this->contextManager = $context_manager; $this->contextManager = $context_manager;
$this->flysystemFactory = $flysystem_factory; $this->flysystemFactory = $flysystem_factory;
$this->languageManager = $language_manager;
} }
/** /**
@ -498,4 +512,62 @@ class IslandoraUtils {
return $condition; return $condition;
} }
/**
* Gets the id URL of an entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity whose URL you want.
*
* @return string
* The entity URL.
*/
public function getEntityUrl(EntityInterface $entity) {
$undefined = $this->languageManager->getLanguage('und');
$entity_type = $entity->getEntityTypeId();
return Url::fromRoute(
"entity.$entity_type.canonical",
[$entity_type => $entity->id()],
['absolute' => TRUE, 'language' => $undefined]
)->toString();
}
/**
* Gets the downloadable URL for a file.
*
* @param \Drupal\file\FileInterface $file
* The file whose URL you want.
*
* @return string
* The file URL.
*/
public function getDownloadUrl(FileInterface $file) {
$undefined = $this->languageManager->getLanguage('und');
return $file->url('canonical', ['absolute' => TRUE, 'language' => $undefined]);
}
/**
* Gets the URL for an entity's REST endpoint.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity whose REST endpoint you want.
* @param string $format
* REST serialization format.
*
* @return string
* The REST URL.
*/
public function getRestUrl(EntityInterface $entity, $format = '') {
$undefined = $this->languageManager->getLanguage('und');
$entity_type = $entity->getEntityTypeId();
$rest_url = Url::fromRoute(
"rest.entity.$entity_type.GET",
[$entity_type => $entity->id()],
['absolute' => TRUE, 'language' => $undefined]
)->toString();
if (!empty($format)) {
$rest_url .= "?_format=$format";
}
return $rest_url;
}
} }

2
src/Plugin/Action/AbstractGenerateDerivative.php

@ -155,7 +155,7 @@ class AbstractGenerateDerivative extends EmitEvent {
throw new \RuntimeException("Could not locate source file for media {$source_media->id()}", 500); throw new \RuntimeException("Could not locate source file for media {$source_media->id()}", 500);
} }
$data['source_uri'] = $source_file->url('canonical', ['absolute' => TRUE]); $data['source_uri'] = $this->utils->getDownloadUrl($source_file);
// Find the term for the derivative and use it to set the destination url // Find the term for the derivative and use it to set the destination url
// in the data array. // in the data array.

35
src/Plugin/Action/DeleteMedia.php

@ -1,35 +0,0 @@
<?php
namespace Drupal\islandora\Plugin\Action;
use Drupal\Core\Action\ActionBase;
use Drupal\Core\Session\AccountInterface;
/**
* Deletes a media.
*
* @Action(
* id = "delete_media",
* label = @Translation("Delete media"),
* type = "media"
* )
*/
class DeleteMedia extends ActionBase {
/**
* {@inheritdoc}
*/
public function execute($entity = NULL) {
if ($entity) {
$entity->delete();
}
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
return $object->access('delete', $account, $return_as_object);
}
}

174
src/Plugin/Condition/MediaHasMimetype.php

@ -0,0 +1,174 @@
<?php
namespace Drupal\islandora\Plugin\Condition;
use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\islandora\IslandoraUtils;
use Drupal\islandora\MediaSource\MediaSourceService;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a condition based on a node's media's MimeType.
*
* Note that this condition applies when the parent node is viewed.
* It is not fired during ingest (i.e., it doesn't apply to
* derivative generation).
*
* @Condition(
* id = "media_has_mimetype",
* label = @Translation("Media has Mime type"),
* context_definitions = {
* "node" = @ContextDefinition("entity:node", label = @Translation("node"))
* }
* )
*/
class MediaHasMimetype extends ConditionPluginBase implements ContainerFactoryPluginInterface {
/**
* Islandora utils.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;
/**
* Term storage.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* A MediaSourceService.
*
* @var \Drupal\islandora\MediaSource\MediaSourceService
*/
private $mediaSource;
/**
* Constructor.
*
* @param array $configuration
* The plugin configuration, i.e. an array with configuration values keyed
* by configuration option name. The special key 'context' may be used to
* initialize the defined contexts by setting it to an array of context
* values keyed by context names.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\islandora\IslandoraUtils $utils
* Islandora utility functions.
* @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
* Entity type manager.
* @param \Drupal\islandora\MediaSource\MediaSourceService $media_source
* Media source service.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
IslandoraUtils $utils,
EntityTypeManager $entity_type_manager,
MediaSourceService $media_source
) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $utils);
$this->utils = $utils;
$this->entityTypeManager = $entity_type_manager;
$this->mediaSource = $media_source;
}
/**
* {@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'),
$container->get('islandora.media_source_service')
);
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['mimetypes'] = [
'#type' => 'textfield',
'#title' => t('Mime types'),
'#default_value' => $this->configuration['mimetypes'],
'#required' => TRUE,
'#maxlength' => 256,
'#description' => t('Comma-delimited list of Mime types (e.g. image/jpeg, video/mp4, etc...) that trigger the condition.'),
];
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['mimetypes'] = $form_state->getValue('mimetypes');
parent::submitConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function summary() {
$mimetypes = $this->configuration['mimetypes'];
return $this->t(
'The media has one of the Mime types @mimetypes',
[
'@mimetypes' => $mimetypes,
]
);
}
/**
* {@inheritdoc}
*/
public function evaluate() {
if (empty($this->configuration['mimetypes']) && !$this->isNegated()) {
return TRUE;
}
$node = \Drupal::routeMatch()->getParameter('node');
if (is_null($node) || is_string($node)) {
return FALSE;
}
$media = $this->utils->getMedia($node);
if (count($media) > 0) {
$mimetypes = explode(',', str_replace(' ', '', $this->configuration['mimetypes']));
foreach ($media as $medium) {
$file = $this->mediaSource->getSourceFile($medium);
if (in_array($file->getMimeType(), $mimetypes)) {
return $this->isNegated() ? FALSE : TRUE;
}
}
}
else {
return FALSE;
}
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array_merge(
['mimetypes' => ''],
parent::defaultConfiguration()
);
}
}

187
src/Plugin/Condition/NodeHadNamespace.php

@ -0,0 +1,187 @@
<?php
namespace Drupal\islandora\Plugin\Condition;
use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\islandora\IslandoraUtils;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a Islandora 7.x namespace condition for nodes.
*
* @Condition(
* id = "node_had_namespace",
* label = @Translation("Node had 7.x namespace"),
* context = {
* "node" = @ContextDefinition("entity:node", required = TRUE , label = @Translation("node"))
* }
* )
*/
class NodeHadNamespace extends ConditionPluginBase implements ContainerFactoryPluginInterface {
/**
* Islandora utils.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;
/**
* Term storage.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* Constructor.
*
* @param array $configuration
* The plugin configuration, i.e. an array with configuration values keyed
* by configuration option name. The special key 'context' may be used to
* initialize the defined contexts by setting it to an array of context
* values keyed by context names.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\islandora\IslandoraUtils $utils
* Islandora utils.
* @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
* Entity type manager.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
IslandoraUtils $utils,
EntityTypeManager $entity_type_manager
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->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) {
$form['namespace'] = [
'#type' => 'textfield',
'#title' => $this->t('Islandora 7.x Namespaces'),
'#description' => $this->t('Comma-delimited list of 7.x PID namespaces, including the trailing colon (e.g., "islandora:,ir:").'),
'#default_value' => $this->configuration['namespace'],
'#maxlength' => 256,
];
$field_map = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('string');
$node_fields = array_keys($field_map['node']);
$options = array_combine($node_fields, $node_fields);
$form['pid_field'] = [
'#type' => 'select',
'#title' => t('Field that contains the PID'),
'#options' => $options,
'#default_value' => $this->configuration['pid_field'],
'#required' => TRUE,
'#description' => t("Machine name of the field that contains the PID."),
];
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['namespace'] = NULL;
$namespace = $form_state->getValue('namespace');
if (!empty($namespace)) {
if ($namespace) {
$this->configuration['namespace'] = $namespace;
}
}
$this->configuration['pid_field'] = $form_state->getValue('pid_field');
parent::submitConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function evaluate() {
if (empty($this->configuration['namespace']) && !$this->isNegated()) {
return TRUE;
}
$node = $this->getContextValue('node');
if (!$node) {
return FALSE;
}
return $this->evaluateEntity($node);
}
/**
* Evaluates if the value of field_pid with a registered 7.x namespace.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to evalute.
*
* @return bool
* TRUE if entity has the specified namespace, otherwise FALSE.
*/
protected function evaluateEntity(EntityInterface $entity) {
$pid_field = $this->configuration['pid_field'];
if ($entity->hasField($pid_field)) {
$pid_value = $entity->get($pid_field)->getValue();
$pid = $pid_value[0]['value'];
$namespace = strtok($pid, ':') . ':';
$registered_namespaces = explode(',', $this->configuration['namespace']);
foreach ($registered_namespaces as &$registered_namespace) {
$registered_namespace = trim($registered_namespace);
if (in_array($namespace, $registered_namespaces)) {
return $this->isNegated() ? FALSE : TRUE;
}
}
}
return $this->isNegated() ? TRUE : FALSE;
}
/**
* {@inheritdoc}
*/
public function summary() {
if (!empty($this->configuration['negate'])) {
return $this->t('The node does not have a value in its PID field with the namespace @namespace.', ['@namespace' => $this->configuration['namespace']]);
}
else {
return $this->t('The node has a value in its PID field with the namespace @namespace.', ['@namespace' => $this->configuration['namespace']]);
}
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return array_merge(
['namespace' => '', 'pid_field' => 'field_pid'],
parent::defaultConfiguration()
);
}
}

168
src/Plugin/Condition/NodeHasParent.php

@ -0,0 +1,168 @@
<?php
namespace Drupal\islandora\Plugin\Condition;
use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a condition to detect node's parent.
*
* @Condition(
* id = "node_has_parent",
* label = @Translation("Node has parent"),
* context = {
* "node" = @ContextDefinition("entity:node", required = TRUE , label = @Translation("node"))
* }
* )
*/
class NodeHasParent extends ConditionPluginBase implements ContainerFactoryPluginInterface {
/**
* Node storage.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* Constructor.
*
* @param array $configuration
* The plugin configuration, i.e. an array with configuration values keyed
* by configuration option name. The special key 'context' may be used to
* initialize the defined contexts by setting it to an array of context
* values keyed by context names.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
* Entity type manager.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
EntityTypeManager $entity_type_manager
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return parent::defaultConfiguration() + [
'parent_reference_field' => 'field_member_of',
'parent_nid' => '',
];
}
/**
* {@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 buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form['parent_nid'] = [
'#type' => 'entity_autocomplete',
'#title' => t('Parent node'),
'#default_value' => $this->entityTypeManager->getStorage('node')->load($this->configuration['parent_nid']),
'#required' => TRUE,
'#description' => t("Can be a collection node or a compound object."),
'#target_type' => 'node',
];
$field_map = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('entity_reference');
$node_fields = array_keys($field_map['node']);
$options = array_combine($node_fields, $node_fields);
$form['parent_reference_field'] = [
'#type' => 'select',
'#title' => t('Field that contains reference to parents'),
'#options' => $options,
'#default_value' => $this->configuration['parent_reference_field'],
'#required' => TRUE,
'#description' => t("Machine name of field that contains references to parent node."),
];
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this->configuration['parent_nid'] = $form_state->getValue('parent_nid');
$this->configuration['parent_reference_field'] = $form_state->getValue('parent_reference_field');
parent::submitConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function evaluate() {
if (empty($this->configuration['parent_nid']) && !$this->isNegated()) {
return TRUE;
}
$node = $this->getContextValue('node');
if (!$node) {
return FALSE;
}
return $this->evaluateEntity($node);
}
/**
* Evaluates if an entity has the specified node as its parent.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity to evalute.
*
* @return bool
* TRUE if entity references the specified parent.
*/
protected function evaluateEntity(EntityInterface $entity) {
foreach ($entity->referencedEntities() as $referenced_entity) {
if ($entity->getEntityTypeID() == 'node' && $referenced_entity->getEntityTypeId() == 'node') {
$parent_reference_field = $this->configuration['parent_reference_field'];
$field = $entity->get($parent_reference_field);
if (!$field->isEmpty()) {
$nids = $field->getValue();
foreach ($nids as $nid) {
if ($nid['target_id'] == $this->configuration['parent_nid']) {
return $this->isNegated() ? FALSE : TRUE;
}
}
}
}
}
}
/**
* {@inheritdoc}
*/
public function summary() {
if (!empty($this->configuration['negate'])) {
return $this->t('The node does not have node @nid as its parent.', ['@nid' => $this->configuration['parent_nid']]);
}
else {
return $this->t('The node has node @nid as its parent.', ['@nid' => $this->configuration['parent_nid']]);
}
}
}

94
src/Plugin/Condition/NodeIsPublished.php

@ -0,0 +1,94 @@
<?php
namespace Drupal\islandora\Plugin\Condition;
use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides an 'Is Published' condition for nodes.
*
* @Condition(
* id = "node_is_published",
* label = @Translation("Node is published"),
* context = {
* "node" = @ContextDefinition("entity:node", required = TRUE , label = @Translation("node"))
* }
* )
*/
class NodeIsPublished extends ConditionPluginBase implements ContainerFactoryPluginInterface {
/**
* Term storage.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityTypeManager;
/**
* Constructor.
*
* @param array $configuration
* The plugin configuration, i.e. an array with configuration values keyed
* by configuration option name. The special key 'context' may be used to
* initialize the defined contexts by setting it to an array of context
* values keyed by context names.
* @param string $plugin_id
* The plugin_id for the plugin instance.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager
* Entity type manager.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
EntityTypeManager $entity_type_manager
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$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('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function evaluate() {
$node = $this->getContextValue('node');
if (!$node && !$this->isNegated()) {
return FALSE;
}
if ($node->isPublished() && !$this->isNegated()) {
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function summary() {
if (!empty($this->configuration['negate'])) {
return $this->t('The node is not published.');
}
else {
return $this->t('The node is published.');
}
}
}

13
src/Plugin/ContextReaction/MappingUriPredicateReaction.php

@ -9,6 +9,7 @@ use Drupal\islandora\ContextReaction\NormalizerAlterReaction;
use Drupal\islandora\MediaSource\MediaSourceService; use Drupal\islandora\MediaSource\MediaSourceService;
use Drupal\jsonld\Normalizer\NormalizerBase; use Drupal\jsonld\Normalizer\NormalizerBase;
use Drupal\media\MediaInterface; use Drupal\media\MediaInterface;
use Drupal\islandora\IslandoraUtils;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
@ -23,6 +24,11 @@ class MappingUriPredicateReaction extends NormalizerAlterReaction {
const URI_PREDICATE = 'drupal_uri_predicate'; const URI_PREDICATE = 'drupal_uri_predicate';
/**
* Media source service.
*
* @var \Drupal\islandora\MediaSource\MediaSourceService
*/
protected $mediaSource; protected $mediaSource;
/** /**
@ -32,13 +38,15 @@ class MappingUriPredicateReaction extends NormalizerAlterReaction {
$plugin_id, $plugin_id,
$plugin_definition, $plugin_definition,
ConfigFactoryInterface $config_factory, ConfigFactoryInterface $config_factory,
IslandoraUtils $utils,
MediaSourceService $media_source) { MediaSourceService $media_source) {
parent::__construct( parent::__construct(
$configuration, $configuration,
$plugin_id, $plugin_id,
$plugin_definition, $plugin_definition,
$config_factory $config_factory,
$utils
); );
$this->mediaSource = $media_source; $this->mediaSource = $media_source;
} }
@ -52,6 +60,7 @@ class MappingUriPredicateReaction extends NormalizerAlterReaction {
$plugin_id, $plugin_id,
$plugin_definition, $plugin_definition,
$container->get('config.factory'), $container->get('config.factory'),
$container->get('islandora.utils'),
$container->get('islandora.media_source_service') $container->get('islandora.media_source_service')
); );
} }
@ -80,7 +89,7 @@ class MappingUriPredicateReaction extends NormalizerAlterReaction {
// Swap media and file urls. // Swap media and file urls.
if ($entity instanceof MediaInterface) { if ($entity instanceof MediaInterface) {
$file = $this->mediaSource->getSourceFile($entity); $file = $this->mediaSource->getSourceFile($entity);
$graph['@id'] = $file->url('canonical', ['absolute' => TRUE]); $graph['@id'] = $this->utils->getDownloadUrl($file);
} }
if (isset($graph[$drupal_predicate])) { if (isset($graph[$drupal_predicate])) {
if (!is_array($graph[$drupal_predicate])) { if (!is_array($graph[$drupal_predicate])) {

5
src/PresetReaction/PresetReaction.php

@ -14,6 +14,11 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
*/ */
class PresetReaction extends ContextReactionPluginBase implements ContainerFactoryPluginInterface { class PresetReaction extends ContextReactionPluginBase implements ContainerFactoryPluginInterface {
/**
* Action storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $actionStorage; protected $actionStorage;
/** /**

25
tests/src/Functional/DeleteMediaTest.php

@ -35,31 +35,6 @@ class DeleteMediaTest extends IslandoraFunctionalTestBase {
list($this->file, $this->media) = $this->makeMediaAndFile($account); 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. * Tests the delete_media_and_file action.
* *

3
tests/src/Functional/GenerateDerivativeTestBase.php

@ -7,6 +7,9 @@ namespace Drupal\Tests\islandora\Functional;
*/ */
abstract class GenerateDerivativeTestBase extends IslandoraFunctionalTestBase { abstract class GenerateDerivativeTestBase extends IslandoraFunctionalTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['context_ui']; protected static $modules = ['context_ui'];
/** /**

26
tests/src/Functional/IslandoraFunctionalTestBase.php

@ -20,8 +20,14 @@ class IslandoraFunctionalTestBase extends BrowserTestBase {
use TestFileCreationTrait; use TestFileCreationTrait;
use MediaTypeCreationTrait; use MediaTypeCreationTrait;
/**
* {@inheritdoc}
*/
protected static $modules = ['context_ui', 'field_ui', 'islandora']; protected static $modules = ['context_ui', 'field_ui', 'islandora'];
/**
* {@inheritdoc}
*/
protected static $configSchemaCheckerExclusions = [ protected static $configSchemaCheckerExclusions = [
'jwt.config', 'jwt.config',
'context.context.test', 'context.context.test',
@ -29,12 +35,28 @@ class IslandoraFunctionalTestBase extends BrowserTestBase {
'context.context.media', 'context.context.media',
'context.context.file', 'context.context.file',
'key.key.test', 'key.key.test',
'media.settings',
]; ];
/**
* Test node type.
*
* @var \Drupal\node\Entity\NodeType
*/
protected $testType; protected $testType;
/**
* Test media type.
*
* @var \Drupal\media\Entity\MediaType
*/
protected $testMediaType; protected $testMediaType;
/**
* Test vocabulary.
*
* @var \Drupal\taxonomy\Entity\Vocabulary
*/
protected $testVocabulary; protected $testVocabulary;
/** /**
@ -170,6 +192,10 @@ EOD;
$destination->write($name, $source->read($name)); $destination->write($name, $source->read($name));
} }
$media_settings = $this->container->get('config.factory')->getEditable('media.settings');
$media_settings->set('standalone_url', TRUE);
$media_settings->save(TRUE);
// Cache clear / rebuild. // Cache clear / rebuild.
drupal_flush_all_caches(); drupal_flush_all_caches();
$this->container->get('router.builder')->rebuild(); $this->container->get('router.builder')->rebuild();

2
tests/src/Kernel/EventGeneratorTest.php

@ -65,7 +65,7 @@ class EventGeneratorTest extends IslandoraKernelTestBase {
// Create the event generator so we can test it. // Create the event generator so we can test it.
$this->eventGenerator = new EventGenerator( $this->eventGenerator = new EventGenerator(
$this->container->get('language_manager'), $this->container->get('islandora.utils'),
$this->container->get('islandora.media_source_service') $this->container->get('islandora.media_source_service')
); );
} }

5
tests/src/Kernel/GeminiClientFactoryTest.php

@ -18,6 +18,11 @@ use Psr\Log\LoggerInterface;
*/ */
class GeminiClientFactoryTest extends IslandoraKernelTestBase { class GeminiClientFactoryTest extends IslandoraKernelTestBase {
/**
* Logger.
*
* @var \Psr\Log\LoggerInterface
*/
private $logger; private $logger;
/** /**

35
tests/src/Kernel/GeminiLookupTest.php

@ -23,18 +23,53 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
*/ */
class GeminiLookupTest extends IslandoraKernelTestBase { class GeminiLookupTest extends IslandoraKernelTestBase {
/**
* JWT Auth.
*
* @var \Drupal\jwt\Authentication\Provider\JwtAuth
*/
private $jwtAuth; private $jwtAuth;
/**
* Logger.
*
* @var \Psr\Log\LoggerInterface
*/
private $logger; private $logger;
/**
* Guzzle.
*
* @var \GuzzleHttp\Client
*/
private $guzzle; private $guzzle;
/**
* Gemini client.
*
* @var \Islandora\Crayfish\Commons\Client\GeminiClient
*/
private $geminiClient; private $geminiClient;
/**
* Media source service.
*
* @var \Drupal\islandora\MediaSource\MediaSourceService
*/
private $mediaSource; private $mediaSource;
/**
* An entity.
*
* @var \Drupal\Core\Entity\EntityInterface
*/
private $entity; private $entity;
/**
* A media.
*
* @var \Drupal\media\MediaInterface
*/
private $media; private $media;
/** /**

Loading…
Cancel
Save