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
script:
- $SCRIPT_DIR/line_endings.sh $TRAVIS_BUILD_DIR
- phpcs --standard=Drupal --ignore=*.md --extensions=php,module,inc,install,test,profile,theme,css,info $TRAVIS_BUILD_DIR
- phpcpd --names *.module,*.inc,*.test,*.php $TRAVIS_BUILD_DIR
- php core/scripts/run-tests.sh --suppress-deprecations --url http://127.0.0.1:8282 --verbose --php `which php` --module "islandora"
- $SCRIPT_DIR/travis_scripts.sh
- $SCRIPT_DIR/run-tests.sh "islandora"
- $SCRIPT_DIR/run-tests.sh "islandora_breadcrumbs"
notifications:
irc:

16
CONTRIBUTING.md

@ -1,6 +1,10 @@
# 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
@ -8,7 +12,7 @@ The group meets each Wednesday at 1:00 PM Eastern. Meeting notes and announcemen
### 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
@ -16,11 +20,11 @@ You can contribute documentation in two different ways. One way is to create an
### 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
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:
@ -36,7 +40,7 @@ That is great! In this case please send us a pull request as described in the se
### 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:_
@ -66,4 +70,4 @@ You may want to read [Syncing a fork](https://help.github.com/articles/syncing-a
## 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
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'
@ -83,6 +79,16 @@ condition.plugin.node_has_term:
type: text
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:
type: condition.plugin
mapping:
@ -113,6 +119,13 @@ condition.plugin.media_uses_filesystem:
sequence:
type: string
condition.plugin.media_has_mimetype:
type: condition.plugin
mapping:
mimetypes:
type: text
label: 'Mime types'
condition.plugin.content_entity_type:
type: condition.plugin
mapping:
@ -121,6 +134,16 @@ condition.plugin.content_entity_type:
sequence:
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:
type: mapping
label: 'Image field display format settings'

12
islandora.install

@ -40,3 +40,15 @@ function islandora_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.
unset($form['visibility']['content_entity_type']);
unset($form['visibility']['parent_node_has_term']);
unset($form['visibility']['node_had_namespace']);
unset($form['visibility']['media_has_term']);
unset($form['visibility']['file_uses_filesystem']);
unset($form['visibility']['node_has_term']);
unset($form['visibility']['node_has_parent']);
unset($form['visibility']['media_uses_filesystem']);
unset($form['visibility']['media_has_mimetype']);
}
/**

8
islandora.services.yml

@ -3,7 +3,7 @@
services:
islandora.eventgenerator:
class: Drupal\islandora\EventGenerator\EventGenerator
arguments: ['@language_manager', '@islandora.media_source_service']
arguments: ['@islandora.utils', '@islandora.media_source_service']
islandora.stomp:
class: Stomp\StatefulStomp
factory: ['Drupal\islandora\StompFactory', create]
@ -16,12 +16,12 @@ services:
- { name: event_subscriber }
islandora.media_link_header_subscriber:
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:
- { name: event_subscriber }
islandora.node_link_header_subscriber:
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:
- { name: event_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']
islandora.utils:
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:
class: Islandora\Crayfish\Commons\Client\GeminiClient
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 {
/**
* {@inheritdoc}
*/
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
bundle: audio
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
translatable: false
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
bundle: file
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
translatable: true
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
bundle: image
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
translatable: true
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
bundle: video
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
translatable: true
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
module: core
locked: false
cardinality: 1
cardinality: -1
translatable: true
indexes: { }
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
module: core
locked: false
cardinality: -1
cardinality: 1
translatable: true
indexes: { }
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 {
/**
* {@inheritdoc}
*/
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 {
/**
* {@inheritdoc}
*/
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\Plugin\ContainerFactoryPluginInterface;
use Drupal\jsonld\Form\JsonLdSettingsForm;
use Drupal\islandora\IslandoraUtils;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@ -25,16 +26,25 @@ abstract class NormalizerAlterReaction extends ContextReactionPluginBase impleme
*/
protected $jsonldConfig;
/**
* Islandora utils.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration,
$plugin_id,
$plugin_definition,
ConfigFactoryInterface $config_factory) {
ConfigFactoryInterface $config_factory,
IslandoraUtils $utils) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->jsonldConfig = $config_factory->get(JsonLdSettingsForm::CONFIG_NAME);
$this->utils = $utils;
}
/**
@ -45,7 +55,8 @@ abstract class NormalizerAlterReaction extends ContextReactionPluginBase impleme
$configuration,
$plugin_id,
$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.
*/
protected function getSubjectUrl(EntityInterface $entity) {
$url = $entity->toUrl('canonical', ['absolute' => TRUE]);
$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\node\NodeInterface;
use Drupal\taxonomy\TermInterface;
use Drupal\islandora\IslandoraUtils;
use Drupal\islandora\MediaSource\MediaSourceService;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
@ -39,6 +40,13 @@ class MediaSourceController extends ControllerBase {
*/
protected $database;
/**
* Islandora utils.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;
/**
* MediaSourceController constructor.
*
@ -46,13 +54,17 @@ class MediaSourceController extends ControllerBase {
* Service for business logic.
* @param \Drupal\Core\Database\Connection $database
* Database connection.
* @param \Drupal\islandora\IslandoraUtils $utils
* Islandora utils.
*/
public function __construct(
MediaSourceService $service,
Connection $database
Connection $database,
IslandoraUtils $utils
) {
$this->service = $service;
$this->database = $database;
$this->utils = $utils;
}
/**
@ -67,7 +79,8 @@ class MediaSourceController extends ControllerBase {
public static function create(ContainerInterface $container) {
return new static(
$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.
if ($media) {
$response = new Response("", 201);
$response->headers->set("Location", $media->url('canonical', ['absolute' => TRUE]));
$response->headers->set("Location", $this->utils->getEntityUrl($media));
}
else {
$response = new Response("", 204);

36
src/EventGenerator/EventGenerator.php

@ -3,8 +3,7 @@
namespace Drupal\islandora\EventGenerator;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Url;
use Drupal\islandora\IslandoraUtils;
use Drupal\islandora\MediaSource\MediaSourceService;
use Drupal\user\UserInterface;
@ -16,11 +15,11 @@ use Drupal\user\UserInterface;
class EventGenerator implements EventGeneratorInterface {
/**
* Language manager.
* Islandora utils.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
* @var \Drupal\islandora\IslandoraUtils
*/
protected $languageManager;
protected $utils;
/**
* Media source service.
@ -32,13 +31,13 @@ class EventGenerator implements EventGeneratorInterface {
/**
* Constructor.
*
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* Language manager.
* @param \Drupal\islandora\IslandoraUtils $utils
* Islandora utils.
* @param \Drupal\islandora\MediaSource\MediaSourceService $media_source
* Media source service.
*/
public function __construct(LanguageManagerInterface $language_manager, MediaSourceService $media_source) {
$this->languageManager = $language_manager;
public function __construct(IslandoraUtils $utils, MediaSourceService $media_source) {
$this->utils = $utils;
$this->mediaSource = $media_source;
}
@ -47,21 +46,16 @@ class EventGenerator implements EventGeneratorInterface {
*/
public function generateEvent(EntityInterface $entity, UserInterface $user, array $data) {
$user_url = $user->toUrl()->setAbsolute()->toString();
$entity_type = $entity->getEntityTypeId();
$user_url = $this->utils->getEntityUrl($user);
$undefined = $this->languageManager->getLanguage('und');
$entity_type = $entity->getEntityTypeId();
if ($entity_type == 'file') {
$entity_url = $entity->url('canonical', ['absolute' => TRUE, 'language' => $undefined]);
$entity_url = $this->utils->getDownloadUrl($entity);
$mimetype = $entity->getMimeType();
}
else {
$entity_url = Url::fromRoute(
"rest.entity.$entity_type.GET",
[$entity_type => $entity->id()],
['absolute' => TRUE, 'language' => $undefined]
)->toString();
$entity_url = $this->utils->getEntityUrl($entity);
$mimetype = 'text/html';
}
@ -112,14 +106,14 @@ class EventGenerator implements EventGeneratorInterface {
$event['object']['url'][] = [
"name" => "JSON",
"type" => "Link",
"href" => "$entity_url?_format=json",
"href" => $this->utils->getRestUrl($entity, 'json'),
"mediaType" => "application/json",
"rel" => "alternate",
];
$event['object']['url'][] = [
"name" => "JSONLD",
"type" => "Link",
"href" => "$entity_url?_format=jsonld",
"href" => $this->utils->getRestUrl($entity, 'jsonld'),
"mediaType" => "application/ld+json",
"rel" => "alternate",
];
@ -132,7 +126,7 @@ class EventGenerator implements EventGeneratorInterface {
$event['object']['url'][] = [
"name" => "Describes",
"type" => "Link",
"href" => $file->url('canonical', ['absolute' => TRUE, 'language' => $undefined]),
"href" => $this->utils->getDownloadUrl($file),
"mediaType" => $file->getMimeType(),
"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\EntityInterface;
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 Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
@ -66,11 +65,11 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
protected $requestStack;
/**
* Language manager.
* Islandora utils.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
* @var \Drupal\islandora\IslandoraUtils
*/
protected $languageManager;
protected $utils;
/**
* Constructor.
@ -87,8 +86,8 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
* 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
* Islandora utils.
*/
public function __construct(
EntityTypeManager $entity_type_manager,
@ -97,7 +96,7 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
AccountInterface $account,
RouteMatchInterface $route_match,
RequestStack $request_stack,
LanguageManagerInterface $language_manager
IslandoraUtils $utils
) {
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
@ -107,7 +106,7 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
$this->accessManager = $access_manager;
$this->account = $account;
$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.
if ($referencedEntity->access('view')) {
$entity_url = $this->utils->getEntityUrl($referencedEntity);
// Taxonomy terms are written out as
// <url>; rel="tag"; title="Tag Name"
// 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.
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')->getValue();
if (!empty($external_uri) && isset($external_uri[0]['uri'])) {
@ -228,7 +228,6 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
// <url>; 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\"";
@ -287,19 +286,16 @@ abstract class LinkHeaderSubscriber implements EventSubscriberInterface {
continue;
}
// Skip route if the user doesn't have access.
$meta_route_name = "rest.entity.$entity_type.GET";
$route_params = [$entity_type => $entity->id()];
if (!$this->accessManager->checkNamedRoute($meta_route_name, $route_params, $this->account)) {
continue;
}
$meta_url = Url::fromRoute($meta_route_name, $route_params)
->setAbsolute()
->toString();
$meta_url = $this->utils->getRestUrl($entity, $format);
$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.
$undefined = $this->languageManager->getLanguage('und');
foreach ($media->get($source_field)->referencedEntities() as $referencedEntity) {
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()}\"";
}
}

65
src/EventSubscriber/NodeLinkHeaderSubscriber.php

@ -2,17 +2,8 @@
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 Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
@ -22,55 +13,6 @@ use Symfony\Component\EventDispatcher\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.
*
@ -105,13 +47,8 @@ class NodeLinkHeaderSubscriber extends LinkHeaderSubscriber implements EventSubs
*/
protected function generateRelatedMediaLinks(NodeInterface $node) {
$links = [];
$undefined = $this->languageManager->getLanguage('und');
foreach ($this->utils->getMedia($node) as $media) {
$url = Url::fromRoute(
"rest.entity.media.GET",
['media' => $media->id()],
['absolute' => TRUE, 'language' => $undefined]
)->toString();
$url = $this->utils->getEntityUrl($media);
foreach ($media->referencedEntities() as $term) {
if ($term->getEntityTypeId() == 'taxonomy_term' && $term->hasField('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 NotSupportingVisibilityTrait;
/**
* Fedora client.
*
* @var \Islandora\Chullo\IFedoraApi
*/
protected $fedora;
/**
* Mimetype guesser.
*
* @var \Symfony\Component\HttpFoundation\File\Mimetype\MimeTypeGuesserInterface
*/
protected $mimeTypeGuesser;
/**
@ -75,7 +86,6 @@ class FedoraAdapter implements AdapterInterface {
$meta = $this->getMetadataFromHeaders($response);
$meta['path'] = $path;
if ($meta['type'] == 'file') {
$meta['stream'] = StreamWrapper::getResource($response->getBody());
}

10
src/Flysystem/Fedora.php

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

74
src/IslandoraUtils.php

@ -4,12 +4,15 @@ namespace Drupal\islandora;
use Drupal\context\ContextManager;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Entity\Query\QueryException;
use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Drupal\file\FileInterface;
use Drupal\flysystem\FlysystemFactory;
use Drupal\islandora\ContextProvider\NodeContextProvider;
@ -64,6 +67,13 @@ class IslandoraUtils {
*/
protected $flysystemFactory;
/**
* Language manager.
*
* @var \Drupal\Core\Language\LanguageManagerInterface
*/
protected $languageManager;
/**
* Constructor.
*
@ -77,19 +87,23 @@ class IslandoraUtils {
* Context manager.
* @param \Drupal\flysystem\FlysystemFactory $flysystem_factory
* Flysystem factory.
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
* Language manager.
*/
public function __construct(
EntityTypeManager $entity_type_manager,
EntityFieldManager $entity_field_manager,
QueryFactory $entity_query,
ContextManager $context_manager,
FlysystemFactory $flysystem_factory
FlysystemFactory $flysystem_factory,
LanguageManagerInterface $language_manager
) {
$this->entityTypeManager = $entity_type_manager;
$this->entityFieldManager = $entity_field_manager;
$this->entityQuery = $entity_query;
$this->contextManager = $context_manager;
$this->flysystemFactory = $flysystem_factory;
$this->languageManager = $language_manager;
}
/**
@ -498,4 +512,62 @@ class IslandoraUtils {
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);
}
$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
// 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\jsonld\Normalizer\NormalizerBase;
use Drupal\media\MediaInterface;
use Drupal\islandora\IslandoraUtils;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
@ -23,6 +24,11 @@ class MappingUriPredicateReaction extends NormalizerAlterReaction {
const URI_PREDICATE = 'drupal_uri_predicate';
/**
* Media source service.
*
* @var \Drupal\islandora\MediaSource\MediaSourceService
*/
protected $mediaSource;
/**
@ -32,13 +38,15 @@ class MappingUriPredicateReaction extends NormalizerAlterReaction {
$plugin_id,
$plugin_definition,
ConfigFactoryInterface $config_factory,
IslandoraUtils $utils,
MediaSourceService $media_source) {
parent::__construct(
$configuration,
$plugin_id,
$plugin_definition,
$config_factory
$config_factory,
$utils
);
$this->mediaSource = $media_source;
}
@ -52,6 +60,7 @@ class MappingUriPredicateReaction extends NormalizerAlterReaction {
$plugin_id,
$plugin_definition,
$container->get('config.factory'),
$container->get('islandora.utils'),
$container->get('islandora.media_source_service')
);
}
@ -80,7 +89,7 @@ class MappingUriPredicateReaction extends NormalizerAlterReaction {
// Swap media and file urls.
if ($entity instanceof MediaInterface) {
$file = $this->mediaSource->getSourceFile($entity);
$graph['@id'] = $file->url('canonical', ['absolute' => TRUE]);
$graph['@id'] = $this->utils->getDownloadUrl($file);
}
if (isset($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 {
/**
* Action storage.
*
* @var \Drupal\Core\Entity\EntityStorageInterface
*/
protected $actionStorage;
/**

25
tests/src/Functional/DeleteMediaTest.php

@ -35,31 +35,6 @@ class DeleteMediaTest extends IslandoraFunctionalTestBase {
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.
*

3
tests/src/Functional/GenerateDerivativeTestBase.php

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

26
tests/src/Functional/IslandoraFunctionalTestBase.php

@ -20,8 +20,14 @@ class IslandoraFunctionalTestBase extends BrowserTestBase {
use TestFileCreationTrait;
use MediaTypeCreationTrait;
/**
* {@inheritdoc}
*/
protected static $modules = ['context_ui', 'field_ui', 'islandora'];
/**
* {@inheritdoc}
*/
protected static $configSchemaCheckerExclusions = [
'jwt.config',
'context.context.test',
@ -29,12 +35,28 @@ class IslandoraFunctionalTestBase extends BrowserTestBase {
'context.context.media',
'context.context.file',
'key.key.test',
'media.settings',
];
/**
* Test node type.
*
* @var \Drupal\node\Entity\NodeType
*/
protected $testType;
/**
* Test media type.
*
* @var \Drupal\media\Entity\MediaType
*/
protected $testMediaType;
/**
* Test vocabulary.
*
* @var \Drupal\taxonomy\Entity\Vocabulary
*/
protected $testVocabulary;
/**
@ -170,6 +192,10 @@ EOD;
$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.
drupal_flush_all_caches();
$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.
$this->eventGenerator = new EventGenerator(
$this->container->get('language_manager'),
$this->container->get('islandora.utils'),
$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 {
/**
* Logger.
*
* @var \Psr\Log\LoggerInterface
*/
private $logger;
/**

35
tests/src/Kernel/GeminiLookupTest.php

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

Loading…
Cancel
Save