Compare commits

..

5 Commits

Author SHA1 Message Date
Don Richards e4639be409
Fix phpcs errors 2 years ago
Don Richards c1ace5a2da
Replace the watchdog output 2 years ago
Don Richards 9bd4e8c5c0
Update MediaSourceService.php 2 years ago
Don Richards 80391bc372
Moved into existing check 2 years ago
Don Richards 5585f89e9a
Update MediaSourceService.php 2 years ago
  1. 53
      .github/workflows/build-2.x.yml
  2. 26
      .github/workflows/gitlab-mirror.yml
  3. 26
      README.md
  4. 17
      composer.json
  5. 1
      config/install/islandora.settings.yml
  6. 6
      config/schema/islandora.schema.yml
  7. 38
      islandora.info.yml
  8. 14
      islandora.install
  9. 24
      islandora.module
  10. 5
      islandora.services.yml
  11. 33
      islandora.tokens.inc
  12. 4
      modules/islandora_advanced_search/islandora_advanced_search.info.yml
  13. 102
      modules/islandora_advanced_search/islandora_advanced_search.module
  14. 147
      modules/islandora_advanced_search/js/facets/facets-views-ajax.js
  15. 70
      modules/islandora_advanced_search/js/facets/soft-limit.js
  16. 2
      modules/islandora_advanced_search/src/Form/AdvancedSearchForm.php
  17. 2
      modules/islandora_advanced_search/src/Plugin/Block/AdvancedSearchBlock.php
  18. 2
      modules/islandora_advanced_search/src/Plugin/Block/SearchResultsPagerBlock.php
  19. 3
      modules/islandora_audio/islandora_audio.info.yml
  20. 9
      modules/islandora_audio/tests/src/Functional/GenerateAudioDerivativeTest.php
  21. 6
      modules/islandora_breadcrumbs/config/install/islandora_breadcrumbs.breadcrumbs.yml
  22. 5
      modules/islandora_breadcrumbs/islandora_breadcrumbs.info.yml
  23. 4
      modules/islandora_breadcrumbs/tests/src/Functional/BreadcrumbsTest.php
  24. 0
      modules/islandora_core_feature/config/install/core.entity_view_mode.media.source.yml
  25. 100
      modules/islandora_core_feature/config/install/features.bundle.islandora.yml
  26. 0
      modules/islandora_core_feature/config/install/field.field.taxonomy_term.islandora_media_use.field_external_uri.yml
  27. 0
      modules/islandora_core_feature/config/install/field.field.taxonomy_term.islandora_models.field_external_uri.yml
  28. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_file_size.yml
  29. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_height.yml
  30. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_media_audio_file.yml
  31. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_media_document.yml
  32. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_media_file.yml
  33. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_media_image.yml
  34. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_media_of.yml
  35. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_media_use.yml
  36. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_media_video_file.yml
  37. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_mime_type.yml
  38. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_original_name.yml
  39. 0
      modules/islandora_core_feature/config/install/field.storage.media.field_width.yml
  40. 0
      modules/islandora_core_feature/config/install/field.storage.node.field_member_of.yml
  41. 0
      modules/islandora_core_feature/config/install/field.storage.node.field_model.yml
  42. 0
      modules/islandora_core_feature/config/install/field.storage.node.field_weight.yml
  43. 0
      modules/islandora_core_feature/config/install/field.storage.taxonomy_term.field_external_uri.yml
  44. 0
      modules/islandora_core_feature/config/install/filehash.settings.yml
  45. 0
      modules/islandora_core_feature/config/install/migrate_plus.migration.islandora_tags.yml
  46. 0
      modules/islandora_core_feature/config/install/migrate_plus.migration_group.islandora.yml
  47. 0
      modules/islandora_core_feature/config/install/rest.resource.entity.file.yml
  48. 0
      modules/islandora_core_feature/config/install/rest.resource.entity.media.yml
  49. 0
      modules/islandora_core_feature/config/install/rest.resource.entity.node.yml
  50. 0
      modules/islandora_core_feature/config/install/rest.resource.entity.taxonomy_term.yml
  51. 0
      modules/islandora_core_feature/config/install/system.action.delete_file_as_fedora_external_content.yml
  52. 0
      modules/islandora_core_feature/config/install/system.action.delete_media_from_triplestore.yml
  53. 0
      modules/islandora_core_feature/config/install/system.action.delete_node_from_fedora.yml
  54. 0
      modules/islandora_core_feature/config/install/system.action.delete_node_from_triplestore.yml
  55. 0
      modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_fedora.yml
  56. 0
      modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_triplestore.yml
  57. 0
      modules/islandora_core_feature/config/install/system.action.index_file_as_fedora_external_content.yml
  58. 0
      modules/islandora_core_feature/config/install/system.action.index_media_in_fedora.yml
  59. 0
      modules/islandora_core_feature/config/install/system.action.index_media_in_triplestore.yml
  60. 0
      modules/islandora_core_feature/config/install/system.action.index_node_in_fedora.yml
  61. 0
      modules/islandora_core_feature/config/install/system.action.index_node_in_triplestore.yml
  62. 0
      modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_fedora.yml
  63. 0
      modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_the_triplestore.yml
  64. 0
      modules/islandora_core_feature/config/install/taxonomy.vocabulary.islandora_media_use.yml
  65. 0
      modules/islandora_core_feature/config/install/taxonomy.vocabulary.islandora_models.yml
  66. 1
      modules/islandora_core_feature/config/install/views.view.all_taxonomy_terms.yml
  67. 0
      modules/islandora_core_feature/config/install/views.view.display_media.yml
  68. 1
      modules/islandora_core_feature/config/install/views.view.file_checksum.yml
  69. 0
      modules/islandora_core_feature/config/install/views.view.manage_members.yml
  70. 0
      modules/islandora_core_feature/config/install/views.view.media_of.yml
  71. 1
      modules/islandora_core_feature/config/install/views.view.non_fedora_files.yml
  72. 0
      modules/islandora_core_feature/config/install/views.view.reorder_children.yml
  73. 16
      modules/islandora_core_feature/islandora_core_feature.features.yml
  74. 4
      modules/islandora_core_feature/islandora_core_feature.info.yml
  75. 10
      modules/islandora_iiif/README.md
  76. 18
      modules/islandora_iiif/config/schema/islandora_iiif.schema.yml
  77. 3
      modules/islandora_iiif/islandora_iiif.info.yml
  78. 26
      modules/islandora_iiif/src/Form/IslandoraIIIFConfigForm.php
  79. 331
      modules/islandora_iiif/src/Plugin/views/style/IIIFManifest.php
  80. 3
      modules/islandora_image/islandora_image.info.yml
  81. 9
      modules/islandora_image/tests/src/Functional/GenerateImageDerivativeTest.php
  82. 3
      modules/islandora_text_extraction/islandora_text_extraction.info.yml
  83. 4
      modules/islandora_text_extraction/islandora_text_extraction.module
  84. 24
      modules/islandora_text_extraction/src/Controller/MediaSourceController.php
  85. 11
      modules/islandora_text_extraction/src/Plugin/Action/GenerateOCRDerivative.php
  86. 2
      modules/islandora_text_extraction/src/Plugin/Action/GenerateOCRDerivativeFile.php
  87. 5
      modules/islandora_text_extraction/src/Plugin/Field/FieldFormatter/OcrTextFormatter.php
  88. 4
      modules/islandora_text_extraction/tests/src/Functional/LoadTest.php
  89. 0
      modules/islandora_text_extraction_defaults/config/install/core.entity_form_display.media.extracted_text.default.yml
  90. 0
      modules/islandora_text_extraction_defaults/config/install/core.entity_view_display.media.extracted_text.default.yml
  91. 0
      modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_edited_text.yml
  92. 0
      modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_media_file.yml
  93. 0
      modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_media_of.yml
  94. 0
      modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_media_use.yml
  95. 0
      modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_mime_type.yml
  96. 0
      modules/islandora_text_extraction_defaults/config/install/field.storage.media.field_edited_text.yml
  97. 0
      modules/islandora_text_extraction_defaults/config/install/language.content_settings.media.extracted_text.yml
  98. 0
      modules/islandora_text_extraction_defaults/config/install/media.type.extracted_text.yml
  99. 0
      modules/islandora_text_extraction_defaults/config/install/rdf.mapping.media.extracted_text.yml
  100. 0
      modules/islandora_text_extraction_defaults/config/install/system.action.get_ocr_from_image.yml
  101. Some files were not shown because too many files have changed in this diff Show More

53
.github/workflows/build-2.x.yml

@ -1,33 +1,36 @@
# This is a basic workflow to help you get started with Actions
name: CI
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the 2.x branch
push:
branches: [ 2.x ]
pull_request:
branches: [ 2.x ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
env:
DRUPAL_VERSION: ${{ matrix.drupal-version }}
SCRIPT_DIR: ${{ github.workspace }}/islandora_ci
DRUPAL_DIR: /opt/drupal
PHPUNIT_FILE: ${{ github.workspace }}/build_dir/phpunit.xml
# The type of runner that the job will run on
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.allowed_failure }}
strategy:
fail-fast: false
matrix:
php-versions: ["8.1", "8.2", "8.3"]
# PHP 8.1 fails - see https://github.com/Islandora/islandora/issues/887
php-versions: ["7.4", "8.0"]
# test-suite functional-javascript will appear to pass but will skip tests; missing chromedriver.
test-suite: ["kernel", "functional", "functional-javascript"]
drupal-version: ["10.1.x", "10.2.x", "10.3.x-dev"]
# Not yet Drupal 10 ready - see https://github.com/Islandora/islandora/issues/888
drupal-version: ["9.3.x", "9.4.x", "9.5.x-dev"]
mysql: ["8.0"]
allowed_failure: [false]
exclude:
- php-versions: "8.3"
drupal-version: "10.1.x"
name: PHP ${{ matrix.php-versions }} | drupal ${{ matrix.drupal-version }} | mysql ${{ matrix.mysql }} | test-suite ${{ matrix.test-suite }}
@ -47,15 +50,17 @@ jobs:
- 61616:61616
- 61613:61613
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
path: build_dir
- name: Checkout islandora_ci
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
repository: islandora/islandora_ci
ref: github-actions
@ -73,8 +78,15 @@ jobs:
sudo apt-get remove -y mysql-client mysql-common
sudo apt-get install -y mysql-client
- name: Set environment variables
run: |
echo "DRUPAL_VERSION=${{ matrix.drupal-version }}" >> $GITHUB_ENV
echo "SCRIPT_DIR=$GITHUB_WORKSPACE/islandora_ci" >> $GITHUB_ENV
echo "DRUPAL_DIR=/opt/drupal" >> $GITHUB_ENV
echo "PHPUNIT_FILE=$GITHUB_WORKSPACE/build_dir/phpunit.xml" >> $GITHUB_ENV
- name: Cache Composer dependencies
uses: actions/cache@v3
uses: actions/cache@v2
with:
path: /tmp/composer-cache
key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }}
@ -99,27 +111,16 @@ jobs:
run: |
cd $DRUPAL_DIR/web
drush --uri=127.0.0.1:8282 en -y islandora_audio islandora_breadcrumbs islandora_iiif islandora_image islandora_video islandora_text_extraction_defaults
drush --uri=127.0.0.1:8282 fim -y islandora_core_feature,islandora_text_extraction_defaults
- name: Copy PHPunit file
run: cp $PHPUNIT_FILE $DRUPAL_DIR/web/core/phpunit.xml
- name: Test scripts
run: $SCRIPT_DIR/travis_scripts.sh
- name: Start chromedriver
if: matrix.test-suite == 'functional-javascript'
run: |-
/usr/local/share/chromedriver-linux64/chromedriver \
--log-path=/tmp/chromedriver.log \
--verbose \
--allowed-ips= \
--allowed-origins=* &
- name: PHPUNIT tests
run: |
cd $DRUPAL_DIR/web/core
$DRUPAL_DIR/vendor/bin/phpunit --verbose --testsuite "${{ matrix.test-suite }}"
- name: Print chromedriver logs
if: matrix.test-suite == 'functional-javascript'
run: cat /tmp/chromedriver.log

26
.github/workflows/gitlab-mirror.yml

@ -1,26 +0,0 @@
name: Mirror and run GitLab CI
on:
push:
branches: [2.x]
tags: '*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Mirror + trigger CI
uses: SvanBoxel/gitlab-mirror-and-ci-action@master
with:
args: "https://git.drupalcode.org/project/islandora"
env:
FOLLOW_TAGS: "true"
FORCE_PUSH: "false"
GITLAB_HOSTNAME: "git.drupal.org"
GITLAB_USERNAME: "project_34868_bot"
GITLAB_PASSWORD: ${{ secrets.GITLAB_PASSWORD }}
GITLAB_PROJECT_ID: "34868"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

26
README.md

@ -1,4 +1,4 @@
# Islandora
# ![Islandora](https://cloud.githubusercontent.com/assets/2371345/25624809/f95b0972-2f30-11e7-8992-a8f135402cdc.png) Islandora
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.4-8892BF.svg?style=flat-square)](https://php.net/)
[![Build Status](https://github.com/islandora/islandora/actions/workflows/build-2.x.yml/badge.svg)](https://github.com/Islandora/islandora/actions)
@ -91,21 +91,21 @@ Having problems or solved a problem? Check out the Islandora google groups for a
Current maintainers:
* [Islandora Technical Advisory Group](https://github.com/Islandora/islandora-community/wiki/Technical-Advisory-Group-%28TAG%29)
* [Danny Lamb](https://github.com/dannylamb)
## Sponsors
* [American Philosophical Society](https://www.amphilsoc.org/)
* [Born-Digital, Inc.](https://www.born-digital.com/)
* [discoverygarden inc.](https://www.discoverygarden.ca/)
* [LYRASIS](https://www.lyrasis.org/)
* [McMaster University](https://www.mcmaster.ca/)
* [PALS](https://www.mnpals.org/)
* [University of Limerick](https://www.ul.ie/)
* [University of Manitoba](https://umanitoba.ca/)
* [UPEI](https://www.upei.ca/)
* [Simon Fraser University](https://www.sfu.ca/)
* [York University](https://www.yorku.ca/)
* UPEI
* discoverygarden inc.
* LYRASIS
* McMaster University
* University of Limerick
* York University
* University of Manitoba
* Simon Fraser University
* PALS
* American Philosophical Society
* Common Media Inc.
## Development

17
composer.json

@ -14,32 +14,31 @@
}
],
"require": {
"drupal/context": "^4 || ^5@RC",
"drupal/context": "^4",
"drupal/ctools": "^3.8 || ^4",
"drupal/eva" : "^3.0",
"drupal/features" : "^3.7",
"drupal/file_replace": "^1.1",
"drupal/filehash": "^2 || ^3",
"drupal/filehash": "^2",
"drupal/flysystem" : "^2.0@alpha",
"drupal/jwt": "^1.1 || ^2",
"drupal/jwt": "^1.0",
"drupal/migrate_plus" : "^5.1 || ^6",
"drupal/migrate_source_csv" : "^3.4",
"drupal/prepopulate" : "^2.2",
"drupal/search_api": "^1.8",
"drupal/token" : "^1.3",
"islandora/chullo": "^2.0",
"islandora/fedora-entity-mapper": "^1.0",
"islandora/jsonld": "^2 || ^3",
"islandora/crayfish-commons": "^2",
"islandora/jsonld": "^2",
"stomp-php/stomp-php": "4.* || ^5"
},
"require-dev": {
"phpunit/phpunit": "^6",
"squizlabs/php_codesniffer": "^2.7.1",
"squizlabs/php_codesniffer": "2.7.1",
"drupal/coder": "*",
"sebastian/phpcpd": "*"
},
"suggest": {
"drupal/transliterate_filenames": "Sanitizes filenames when they are uploaded so they don't break your repository.",
"drupal/coi": "Some configuration fields work with Config Override Inspector."
"drupal/transliterate_filenames": "Sanitizes filenames when they are uploaded so they don't break your repository."
},
"license": "GPL-2.0-or-later",
"authors": [

1
config/install/islandora.settings.yml

@ -1,4 +1,5 @@
broker_url: 'tcp://localhost:61613'
jwt_expiry: '+2 hour'
gemini_url: ''
delete_media_and_files: TRUE
gemini_pseudo_bundles: []

6
config/schema/islandora.schema.yml

@ -17,15 +17,15 @@ islandora.settings:
delete_media_and_files:
type: boolean
label: 'Node Delete with Media and Files'
redirect_after_media_save:
type: boolean
label: 'Redirect to node after media save.'
upload_form_location:
type: string
label: 'Upload Form Location'
upload_form_allowed_mimetypes:
type: string
label: 'Upload Form Allowed Extensions'
gemini_url:
type: uri
label: 'Url to Gemini microservice'
gemini_pseudo_bundles:
type: sequence
label: 'List of node, media and taxonomy terms that should include the linked Fedora URI'

38
islandora.info.yml

@ -4,30 +4,32 @@ name: 'islandora'
description: "Islandora Core"
type: module
package: Islandora
core_version_requirement: ^9 || ^10
core: 8.x
core_version_requirement: ^8 || ^9
dependencies:
- context:context_ui
- ctools:ctools
- drupal:action
- drupal:basic_auth
- drupal:block
- drupal:content_translation
- drupal:link
- drupal:media
- drupal:node
- drupal:options
- drupal:path
- drupal:rest
- drupal:taxonomy
- drupal:text
- drupal:views_ui
- eva:eva
- file_replace:file_replace
- filehash:filehash
- flysystem:flysystem
- drupal:options
- drupal:link
- jsonld:jsonld
- search_api:search_api
- jwt:jwt
- migrate_source_csv:migrate_source_csv
- drupal:rest
- filehash:filehash
- drupal:basic_auth
- context:context_ui
- drupal:action
- eva:eva
- drupal:taxonomy
- drupal:views_ui
- drupal:media
- prepopulate:prepopulate
- search_api:search_api
- features:features_ui
- migrate_source_csv:migrate_source_csv
- drupal:content_translation
- flysystem:flysystem
- token:token
- file_replace:file_replace
- ctools:ctools

14
islandora.install

@ -212,17 +212,3 @@ function islandora_update_8007() {
// have the here, just in case?
throw new UpdateException('Failed; hit the end of the update hook implementation, which is not expected.');
}
/**
* Set config to no redirect after media save.
*/
function islandora_update_8008() {
$config = \Drupal::configFactory()->getEditable('islandora.settings');
if ($config) {
$config->set('redirect_after_media_save', FALSE);
$config->save(TRUE);
return t('A new configuration option, "Redirect after media save" is now available.
It has been turned off to preserve existing behaviour. To enable this setting visit
Configuration > Islandora > Core Settings.');
}
}

24
islandora.module

@ -332,7 +332,6 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id)
if ($node) {
$form['name']['widget'][0]['value']['#default_value'] = $node->getTitle();
}
$form['actions']['submit']['#submit'][] = 'islandora_media_custom_form_submit';
}
}
@ -388,22 +387,6 @@ function islandora_form_alter(&$form, FormStateInterface $form_state, $form_id)
return $form;
}
/**
* Redirect submit handler for media save.
*/
function islandora_media_custom_form_submit(&$form, FormStateInterface $form_state) {
// Check configuration to see whether a redirect is desired.
$redirect = \Drupal::config('islandora.settings')->get('redirect_after_media_save');
if ($redirect) {
$params = \Drupal::request()->query->all();
if (!empty($params)) {
$target_id = $params['edit']['field_media_of']['widget'][0]['target_id'];
$url = Url::fromRoute('view.media_of.page_1', ['node' => $target_id]);
$form_state->setRedirectUrl($url);
}
}
}
/**
* Implements a submit handler for the delete form.
*/
@ -545,14 +528,14 @@ function islandora_object_delete_form_submit($form, FormStateInterface $form_sta
}
/**
* Implements hook_field_widget_single_element_WIDGET_TYPE_form_alter().
* Implements hook_field_widget_WIDGET_TYPE_form_alter().
*/
function islandora_field_widget_single_element_image_image_form_alter(&$element, $form_state, $context) {
function islandora_field_widget_image_image_form_alter(&$element, $form_state, $context) {
$element['#process'][] = 'islandora_add_default_image_alt_text';
}
/**
* Callback for hook_field_widget_single_element_WIDGET_TYPE_form_alter().
* Callback for hook_field_widget_WIDGET_TYPE_form_alter().
*/
function islandora_add_default_image_alt_text($element, $form_state, $form) {
if ($element['alt']['#access']) {
@ -615,7 +598,6 @@ function islandora_form_block_form_alter(&$form, FormStateInterface $form_state,
unset($form['visibility']['media_is_islandora_media']);
unset($form['visibility']['media_uses_filesystem']);
unset($form['visibility']['node_had_namespace']);
unset($form['visibility']['node_has_ancestor']);
unset($form['visibility']['node_has_parent']);
unset($form['visibility']['node_has_term']);
unset($form['visibility']['node_is_islandora_object']);

5
islandora.services.yml

@ -31,9 +31,6 @@ services:
logger.channel.islandora:
parent: logger.channel_base
arguments: ['islandora']
logger.channel.fedora_flysystem:
parent: logger.channel_base
arguments: ['fedora_flysystem']
islandora.media_route_context_provider:
class: Drupal\islandora\ContextProvider\MediaRouteContextProvider
arguments: ['@current_route_match']
@ -56,7 +53,7 @@ services:
class: Drupal\islandora\IslandoraUtils
arguments: ['@entity_type.manager', '@entity_field.manager', '@context.manager', '@flysystem_factory', '@language_manager']
islandora.entity_mapper:
class: Islandora\EntityMapper\EntityMapper
class: Islandora\Crayfish\Commons\EntityMapper\EntityMapper
islandora.stomp.auth_header_listener:
class: Drupal\islandora\EventSubscriber\StompHeaderEventSubscriber
arguments: ['@jwt.authentication.jwt']

33
islandora.tokens.inc

@ -19,18 +19,6 @@ function islandora_token_info() {
'name' => t('Islandora Tokens'),
'description' => t('Tokens for Islandora objects.'),
];
$node['media-original-file:filename'] = [
'name' => t('Media: Original File filename without extension.'),
'description' => t('File name without extension of original uploaded file associated with Islandora Object via Media.'),
];
$node['media-original-file:basename'] = [
'name' => t('Media: Original File filename with extension.'),
'description' => t('File name with extension of original uploaded file associated with Islandora Object via Media.'),
];
$node['media-original-file:extension'] = [
'name' => t('Media: Original File extension.'),
'description' => t('File extension of original uploaded file associated with Islandora Object via Media.'),
];
$node['media-thumbnail-image:url'] = [
'name' => t('Media: Thumbnail Image URL.'),
'description' => t('URL of Thumbnail Image associated with Islandora Object via Media.'),
@ -82,24 +70,6 @@ function islandora_tokens($type, $tokens, array $data, array $options, Bubbleabl
$islandoraUtils = \Drupal::service('islandora.utils');
foreach ($tokens as $name => $original) {
switch ($name) {
case 'media-original-file:basename':
case 'media-original-file:filename':
case 'media-original-file:extension':
$term = $islandoraUtils->getTermForUri('http://pcdm.org/use#OriginalFile');
$media = $islandoraUtils->getMediaWithTerm($data['node'], $term);
// Is there media?
if ($media) {
$file = \Drupal::service('islandora.media_source_service')->getSourceFile($media);
if (!empty($file)) {
$path_info = pathinfo($file->createFileUrl());
$key = explode(':', $name)[1];
if (array_key_exists($key, $path_info)) {
$replacements[$original] = $path_info[$key];
}
}
}
break;
case 'media-thumbnail-image:url':
case 'media_thumbnail_image:url':
$term = $islandoraUtils->getTermForUri('http://pcdm.org/use#ThumbnailImage');
@ -134,7 +104,7 @@ function islandora_tokens($type, $tokens, array $data, array $options, Bubbleabl
break;
case 'pdf_url':
$replacements[$original] = islandora_url_to_service_file_media_by_mimetype($data['node'], 'application/pdf');
$replacements[$original] = ' ' . islandora_url_to_service_file_media_by_mimetype($data['node'], 'application/pdf');
break;
}
}
@ -188,5 +158,4 @@ function islandora_url_to_service_file_media_by_mimetype($node, $mime_type) {
}
}
}
return '';
}

4
modules/islandora_advanced_search/islandora_advanced_search.info.yml

@ -4,10 +4,8 @@ name: 'Islandora Advanced Search'
description: "Creates an Advanced Search block and other enhancements to search."
type: module
package: Islandora
core_version_requirement: ^9 || ^10
core_version_requirement: ^8 || ^9
dependencies:
- drupal:facets
- drupal:facets_summary
- drupal:search_api_solr
lifecycle: deprecated
lifecycle_link: https://groups.google.com/g/islandora/c/SEOAWJrfE_M

102
modules/islandora_advanced_search/islandora_advanced_search.module

@ -13,13 +13,51 @@
*/
use Drupal\block\Entity\Block;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Form\FormStateInterface;
use Drupal\islandora_advanced_search\AdvancedSearchQuery;
use Drupal\islandora_advanced_search\Form\SettingsForm;
use Drupal\islandora_advanced_search\Utilities;
use Drupal\search_api\Query\QueryInterface as DrupalQueryInterface;
use Drupal\views\ViewExecutable;
use Solarium\Core\Query\QueryInterface as SolariumQueryInterface;
/**
* Implements hook_theme().
*/
function islandora_advanced_search_theme() {
return [
'facets_item_list__include_exclude_links' => [
'template' => 'facets/facets-item-list--include-exclude-links',
'base hook' => 'facets_item_list',
],
'facets_result_item__include_exclude_links' => [
'template' => 'facets/facets-result-item--include-exclude-links',
'base hook' => 'facets_result_item',
],
'facets_result_item__summary' => [
'template' => 'facets/facets-result-item--summary',
'base hook' => 'facets_result_item',
],
];
}
/**
* Implements hook_library_info_alter().
*/
function islandora_advanced_search_library_info_alter(&$libraries, $extension) {
if ($extension == 'facets') {
// Override facets module javascript with customizations.
$path = '/' . drupal_get_path('module', 'islandora_advanced_search') . '/js/facets';
$libraries['soft-limit']['js'] = [
"$path/soft-limit.js" => [],
];
$libraries['drupal.facets.views-ajax']['js'] = [
"$path/facets-views-ajax.js" => [],
];
}
}
/**
* Implements hook_search_api_solr_converted_query_alter().
*/
@ -61,6 +99,20 @@ function islandora_advanced_search_form_block_form_alter(&$form, FormStateInterf
$form['visibility'][$condition_id] = $condition_form;
}
/**
* Implements hook_preprocess_block__facets_summary().
*/
function islandora_advanced_search_preprocess_block__facets_summary(&$variables) {
// Copy data-attributes to the content as the javascript expects
// there to be no elements between the data declaration and the
// content of the block.
foreach ($variables['attributes'] as $key => $value) {
if (substr($key, 0, 4) === "data") {
$variables['content_attributes'][$key] = $value;
}
}
}
/**
* Implements hook_preprocess_preprocess_views_view().
*/
@ -87,3 +139,53 @@ function islandora_advanced_search_views_pre_view(ViewExecutable $view, $display
$advanced_search_query = new AdvancedSearchQuery();
$advanced_search_query->alterView(\Drupal::request(), $view, $display_id);
}
/**
* Implements hook_preprocess_facets_summary_item_list().
*/
function islandora_advanced_search_preprocess_facets_summary_item_list(&$variables) {
foreach ($variables['items'] as &$item) {
$item['attributes']['class'][] = 'facet-summary-item';
}
}
/**
* Implements hook_preprocess_facets_item_list().
*/
function islandora_advanced_search_preprocess_facets_item_list(&$variables) {
$widget = $variables['facet']->getWidget();
$soft_limit = $widget['config']['soft_limit'];
// Break into two groups less / more which can display be toggled as a single
// element change rather than showing / hiding all <li> elements individually.
// As its slow and causes the page to snap when loading.
$variables['less'] = array_slice($variables['items'], 0, $soft_limit);
$variables['more'] = array_slice($variables['items'], $soft_limit);
$variables['show_more_label'] = $widget['config']['soft_limit_settings']['show_more_label'];
}
/**
* Implements hook_preprocess_facets_result_item().
*/
function islandora_advanced_search_preprocess_facets_result_item(&$variables) {
$settings = \Drupal::config(SettingsForm::CONFIG_NAME);
$length = $settings->get(SettingsForm::FACET_TRUNCATE);
if (is_numeric($length)) {
// Limit the length of facets display to at most 32 characters.
if (is_string($variables['value'])) {
$variables['value'] = Unicode::truncate(
$variables['value'],
$length,
TRUE,
TRUE
);
}
elseif (is_string($variables['value']['text']['#title'])) {
$variables['value']['text']['#title'] = Unicode::truncate(
$variables['value']['text']['#title'],
$length,
TRUE,
TRUE
);
}
}
}

147
modules/islandora_advanced_search/js/facets/facets-views-ajax.js

@ -0,0 +1,147 @@
//# sourceURL=modules/contrib/islandora/modules/islandora_advanced_search/js/facets/facets-view.ajax.js
/**
* @file
* Overrides the facets-view-ajax.js behavior from the 'facets' module.
*/
(function ($, Drupal) {
"use strict";
// Generate events on push state.
(function (history) {
var pushState = history.pushState;
history.pushState = function (state, title, url) {
var ret = pushState.apply(this, arguments);
var event = new Event("pushstate");
window.dispatchEvent(event);
return ret;
};
})(window.history);
function reload(url) {
// Update View.
if (drupalSettings && drupalSettings.views && drupalSettings.views.ajaxViews) {
var view_path = drupalSettings.views.ajax_path;
$.each(drupalSettings.views.ajaxViews, function (views_dom_id) {
var views_parameters = Drupal.Views.parseQueryString(url);
var views_arguments = Drupal.Views.parseViewArgs(url, "search");
var views_settings = $.extend(
{},
Drupal.views.instances[views_dom_id].settings,
views_arguments,
views_parameters
);
var views_ajax_settings =
Drupal.views.instances[views_dom_id].element_settings;
views_ajax_settings.submit = views_settings;
views_ajax_settings.url =
view_path + "?" + $.param(Drupal.Views.parseQueryString(url));
Drupal.ajax(views_ajax_settings).execute();
});
}
// Replace filter, pager, summary, and facet blocks.
var blocks = {};
$(
".block[class*='block-plugin-id--islandora-advanced-search-result-pager'], .block[class*='block-plugin-id--views-exposed-filter-block'], .block[class*='block-plugin-id--facet']"
).each(function () {
var id = $(this).attr("id");
var block_id = id
.slice("block-".length, id.length)
.replace(/--.*$/g, "")
.replace(/-/g, "_");
blocks[block_id] = "#" + id;
});
Drupal.ajax({
url: Drupal.url("islandora-advanced-search-ajax-blocks"),
submit: {
link: url,
blocks: blocks,
},
}).execute();
}
// On location change reload all the blocks / ajax view.
window.addEventListener("pushstate", function (e) {
reload(window.location.href);
});
window.addEventListener("popstate", function (e) {
if (e.state != null) {
reload(window.location.href);
}
});
/**
* Push state on form/pager/facet change.
*/
Drupal.behaviors.islandoraAdvancedSearchViewsAjax = {
attach: function (context, settings) {
window.historyInitiated = true;
// Remove existing behavior from form.
if (settings && settings.views && settings.views.ajaxViews) {
$.each(settings.views.ajaxViews, function (index, settings) {
var exposed_form = $(
"form#views-exposed-form-" +
settings.view_name.replace(/_/g, "-") +
"-" +
settings.view_display_id.replace(/_/g, "-")
);
exposed_form
.once()
.find("input[type=submit], input[type=image]")
.not("[data-drupal-selector=edit-reset]")
.each(function (index) {
$(this).unbind("click");
$(this).click(function (e) {
// Let ctrl/cmd click open in a new window.
if (e.shiftKey || e.ctrlKey || e.metaKey) {
return;
}
e.preventDefault();
e.stopPropagation();
var href = window.location.href;
var params = Drupal.Views.parseQueryString(href);
// Remove the page if set as submitting the form should always take
// the user to the first page (facets do the same).
delete params.page;
// Include values from the form in the URL.
$.each(exposed_form.serializeArray(), function () {
params[this.name] = this.value;
});
href = href.split("?")[0] + "?" + $.param(params);
window.history.pushState(null, document.title, href);
});
});
});
}
// Attach behavior to pager, summary, facet links.
$("[data-drupal-pager-id], [data-drupal-facets-summary-id], [data-drupal-facet-id]")
.once()
.find("a:not(.facets-soft-limit-link)")
.click(function (e) {
// Let ctrl/cmd click open in a new window.
if (e.shiftKey || e.ctrlKey || e.metaKey) {
return;
}
e.preventDefault();
window.history.pushState(null, document.title, $(this).attr("href"));
});
// Trigger on sort change.
$('[data-drupal-pager-id] select[name="order"]')
.once()
.change(function () {
var href = window.location.href;
var params = Drupal.Views.parseQueryString(href);
var selection = $(this).val();
var option = $('option[value="' + selection + '"]');
params.sort_order = option.data("sort_order");
params.sort_by = option.data("sort_by");
href = href.split("?")[0] + "?" + $.param(params);
window.history.pushState(null, document.title, href);
});
},
};
})(jQuery, Drupal);

70
modules/islandora_advanced_search/js/facets/soft-limit.js

@ -0,0 +1,70 @@
//# sourceURL=modules/contrib/islandora/modules/islandora_advanced_search/js/facets/soft-limit.js
/**
* @file
* Overrides the soft-limit.js behavior from the 'facets' module.
* As when having many facets the original version causes the page to slow down and snap to hidden when rendering.
*/
(function ($) {
'use strict';
Drupal.behaviors.facetSoftLimit = {
attach: function (context, settings) {
if (settings.facets.softLimit !== 'undefined') {
$.each(settings.facets.softLimit, function (facet, limit) {
Drupal.facets.applySoftLimit(facet, limit, settings);
});
}
}
};
Drupal.facets = Drupal.facets || {};
/**
* Applies the soft limit UI feature to a specific facets list.
*
* @param {string} facet
* The facet id.
* @param {string} limit
* The maximum amount of items to show.
* @param {object} settings
* Settings.
*/
Drupal.facets.applySoftLimit = function (facet, limit, settings) {
var zero_based_limit = (limit - 1);
var facet_id = facet;
var facetsList = $('ul[data-drupal-facet-id="' + facet_id + '"]');
// In case of multiple instances of a facet, we need to key them.
if (facetsList.length > 1) {
facetsList.each(function (key, $value) {
$(this).attr('data-drupal-facet-id', facet_id + '-' + key);
});
}
// Add "Show more" / "Show less" links.
facetsList.filter(function () {
return $(this).next('ul').length == 1; // Has expanding list.
}).each(function () {
var facet = $(this);
var expand = facet.next('ul');
var link = expand.next('a');
var showLessLabel = settings.facets.softLimitSettings[facet_id].showLessLabel;
var showMoreLabel = settings.facets.softLimitSettings[facet_id].showMoreLabel;
link.text(showMoreLabel)
.once()
.on('click', function () {
if (!expand.is(":visible")) {
expand.slideDown();
$(this).addClass('open').text(showLessLabel);
}
else {
expand.slideUp();
$(this).removeClass('open').text(showMoreLabel);
}
return false;
})
});
};
})(jQuery);

2
modules/islandora_advanced_search/src/Form/AdvancedSearchForm.php

@ -71,7 +71,7 @@ class AdvancedSearchForm extends FormBase {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('request_stack')->getMainRequest(),
$container->get('request_stack')->getMasterRequest(),
$container->get('current_route_match')
);
}

2
modules/islandora_advanced_search/src/Plugin/Block/AdvancedSearchBlock.php

@ -108,7 +108,7 @@ class AdvancedSearchBlock extends BlockBase implements ContainerFactoryPluginInt
$plugin_definition,
$container->get('plugin.manager.search_api.display'),
$container->get('form_builder'),
$container->get('request_stack')->getMainRequest()
$container->get('request_stack')->getMasterRequest()
);
}

2
modules/islandora_advanced_search/src/Plugin/Block/SearchResultsPagerBlock.php

@ -58,7 +58,7 @@ class SearchResultsPagerBlock extends BlockBase implements ContainerFactoryPlugi
$configuration,
$plugin_id,
$plugin_definition,
$container->get('request_stack')->getMainRequest()
$container->get('request_stack')->getMasterRequest()
);
}

3
modules/islandora_audio/islandora_audio.info.yml

@ -2,6 +2,7 @@ name: 'Islandora Audio'
description: 'Islandora audio derivative actions'
type: module
package: Islandora
core_version_requirement: ^9 || ^10
core: 8.x
core_version_requirement: ^8 || ^9
dependencies:
- drupal:islandora

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

@ -40,7 +40,7 @@ class GenerateAudioDerivativeTest extends GenerateDerivativeTestBase {
// Create an action to generate a audio derivative.
$this->drupalGet('admin/config/system/actions');
$this->getSession()->getPage()->findById("edit-action")->selectOption("Generate a audio derivative");
$this->getSession()->getPage()->pressButton('Create');
$this->getSession()->getPage()->pressButton($this->t('Create'));
$this->assertSession()->statusCodeEquals(200);
$this->getSession()->getPage()->fillField('edit-label', "Generate audio test derivative");
@ -53,7 +53,7 @@ class GenerateAudioDerivativeTest extends GenerateDerivativeTestBase {
$this->getSession()->getPage()->fillField('edit-args', "-f mp3");
$this->getSession()->getPage()->fillField('edit-scheme', "public");
$this->getSession()->getPage()->fillField('edit-path', "derp.mov");
$this->getSession()->getPage()->pressButton('Save');
$this->getSession()->getPage()->pressButton($this->t('Save'));
$this->assertSession()->statusCodeEquals(200);
// Create a context and add the action as a derivative reaction.
@ -66,10 +66,9 @@ class GenerateAudioDerivativeTest extends GenerateDerivativeTestBase {
'name[0][value]' => 'Test Media',
'files[field_media_file_0]' => __DIR__ . '/../../fixtures/test_file.txt',
'field_media_of[0][target_id]' => 'Test Node',
'field_media_use[0][target_id]' => $this->preservationMasterTerm->label(),
'field_tags[0][target_id]' => 'Preservation Master',
];
$this->drupalGet('media/add/' . $this->testMediaType->id());
$this->submitForm($values, 'Save');
$this->drupalPostForm('media/add/' . $this->testMediaType->id(), $values, $this->t('Save'));
$expected = [
'source_uri' => 'test_file.txt',

6
modules/islandora_breadcrumbs/config/install/islandora_breadcrumbs.breadcrumbs.yml

@ -2,3 +2,9 @@ maxDepth: -1
includeSelf: FALSE
referenceFields:
- field_member_of
dependencies:
module:
- islandora
enforced:
module:
- islandora_breadcrumbs

5
modules/islandora_breadcrumbs/islandora_breadcrumbs.info.yml

@ -1,7 +1,8 @@
name: 'Islandora Breadcrumbs'
type: module
description: 'Builds breadcrumbs based on field_member_of relationships.'
core_version_requirement: ^9 || ^10
core: 8.x
core_version_requirement: ^8 || ^9
package: Islandora
dependencies:
- islandora:islandora
- drupal:islandora

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

@ -20,7 +20,7 @@ class BreadcrumbsTest extends IslandoraFunctionalTestBase {
*
* @var array
*/
protected static $modules = [
public static $modules = [
'islandora_breadcrumbs',
];
@ -56,7 +56,7 @@ class BreadcrumbsTest extends IslandoraFunctionalTestBase {
/**
* {@inheritdoc}
*/
public function setUp(): void {
public function setUp() {
parent::setUp();
// Create some nodes.

0
modules/islandora_core_feature/config/optional/core.entity_view_mode.media.source.yml → modules/islandora_core_feature/config/install/core.entity_view_mode.media.source.yml

100
modules/islandora_core_feature/config/install/features.bundle.islandora.yml

@ -0,0 +1,100 @@
langcode: en
status: true
dependencies:
enforced:
module:
- islandora_core_feature
name: Islandora
machine_name: islandora
description: 'Features for islandora'
assignments:
alter:
core: true
uuid: true
user_permissions: true
enabled: true
weight: 0
base:
types:
config:
comment_type: comment_type
node_type: node_type
content:
user: user
enabled: true
weight: -2
core:
types:
config:
date_format: date_format
field_storage_config: field_storage_config
entity_form_mode: entity_form_mode
image_style: image_style
menu: menu
responsive_image_style: responsive_image_style
user_role: user_role
entity_view_mode: entity_view_mode
enabled: true
weight: 5
dependency:
enabled: true
weight: 15
exclude:
types:
config:
features_bundle: features_bundle
curated: true
module:
installed: true
profile: true
namespace: true
namespace_any: false
enabled: true
weight: -5
existing:
enabled: true
weight: 12
forward_dependency:
enabled: true
weight: 4
namespace:
enabled: true
weight: 0
optional:
types:
config: { }
enabled: true
weight: 0
packages:
enabled: true
weight: -20
profile:
curated: true
standard:
files: true
dependencies: true
types:
config:
block: block
language_content_settings: language_content_settings
configurable_language: configurable_language
migration: migration
shortcut_set: shortcut_set
tour: tour
enabled: true
weight: 10
site:
types:
config:
action: action
contact_form: contact_form
block_content_type: block_content_type
rdf_mapping: rdf_mapping
search_page: search_page
taxonomy_vocabulary: taxonomy_vocabulary
editor: editor
filter_format: filter_format
enabled: true
weight: 7
profile_name: ''
is_profile: false

0
modules/islandora_core_feature/config/optional/field.field.taxonomy_term.islandora_media_use.field_external_uri.yml → modules/islandora_core_feature/config/install/field.field.taxonomy_term.islandora_media_use.field_external_uri.yml

0
modules/islandora_core_feature/config/optional/field.field.taxonomy_term.islandora_models.field_external_uri.yml → modules/islandora_core_feature/config/install/field.field.taxonomy_term.islandora_models.field_external_uri.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_file_size.yml → modules/islandora_core_feature/config/install/field.storage.media.field_file_size.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_height.yml → modules/islandora_core_feature/config/install/field.storage.media.field_height.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_media_audio_file.yml → modules/islandora_core_feature/config/install/field.storage.media.field_media_audio_file.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_media_document.yml → modules/islandora_core_feature/config/install/field.storage.media.field_media_document.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_media_file.yml → modules/islandora_core_feature/config/install/field.storage.media.field_media_file.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_media_image.yml → modules/islandora_core_feature/config/install/field.storage.media.field_media_image.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_media_of.yml → modules/islandora_core_feature/config/install/field.storage.media.field_media_of.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_media_use.yml → modules/islandora_core_feature/config/install/field.storage.media.field_media_use.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_media_video_file.yml → modules/islandora_core_feature/config/install/field.storage.media.field_media_video_file.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_mime_type.yml → modules/islandora_core_feature/config/install/field.storage.media.field_mime_type.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_original_name.yml → modules/islandora_core_feature/config/install/field.storage.media.field_original_name.yml

0
modules/islandora_core_feature/config/optional/field.storage.media.field_width.yml → modules/islandora_core_feature/config/install/field.storage.media.field_width.yml

0
modules/islandora_core_feature/config/optional/field.storage.node.field_member_of.yml → modules/islandora_core_feature/config/install/field.storage.node.field_member_of.yml

0
modules/islandora_core_feature/config/optional/field.storage.node.field_model.yml → modules/islandora_core_feature/config/install/field.storage.node.field_model.yml

0
modules/islandora_core_feature/config/optional/field.storage.node.field_weight.yml → modules/islandora_core_feature/config/install/field.storage.node.field_weight.yml

0
modules/islandora_core_feature/config/optional/field.storage.taxonomy_term.field_external_uri.yml → modules/islandora_core_feature/config/install/field.storage.taxonomy_term.field_external_uri.yml

0
modules/islandora_core_feature/config/optional/filehash.settings.yml → modules/islandora_core_feature/config/install/filehash.settings.yml

0
modules/islandora_core_feature/config/optional/migrate_plus.migration.islandora_tags.yml → modules/islandora_core_feature/config/install/migrate_plus.migration.islandora_tags.yml

0
modules/islandora_core_feature/config/optional/migrate_plus.migration_group.islandora.yml → modules/islandora_core_feature/config/install/migrate_plus.migration_group.islandora.yml

0
modules/islandora_core_feature/config/optional/rest.resource.entity.file.yml → modules/islandora_core_feature/config/install/rest.resource.entity.file.yml

0
modules/islandora_core_feature/config/optional/rest.resource.entity.media.yml → modules/islandora_core_feature/config/install/rest.resource.entity.media.yml

0
modules/islandora_core_feature/config/optional/rest.resource.entity.node.yml → modules/islandora_core_feature/config/install/rest.resource.entity.node.yml

0
modules/islandora_core_feature/config/optional/rest.resource.entity.taxonomy_term.yml → modules/islandora_core_feature/config/install/rest.resource.entity.taxonomy_term.yml

0
modules/islandora_core_feature/config/optional/system.action.delete_file_as_fedora_external_content.yml → modules/islandora_core_feature/config/install/system.action.delete_file_as_fedora_external_content.yml

0
modules/islandora_core_feature/config/optional/system.action.delete_media_from_triplestore.yml → modules/islandora_core_feature/config/install/system.action.delete_media_from_triplestore.yml

0
modules/islandora_core_feature/config/optional/system.action.delete_node_from_fedora.yml → modules/islandora_core_feature/config/install/system.action.delete_node_from_fedora.yml

0
modules/islandora_core_feature/config/optional/system.action.delete_node_from_triplestore.yml → modules/islandora_core_feature/config/install/system.action.delete_node_from_triplestore.yml

0
modules/islandora_core_feature/config/optional/system.action.delete_taxonomy_term_in_fedora.yml → modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_fedora.yml

0
modules/islandora_core_feature/config/optional/system.action.delete_taxonomy_term_in_triplestore.yml → modules/islandora_core_feature/config/install/system.action.delete_taxonomy_term_in_triplestore.yml

0
modules/islandora_core_feature/config/optional/system.action.index_file_as_fedora_external_content.yml → modules/islandora_core_feature/config/install/system.action.index_file_as_fedora_external_content.yml

0
modules/islandora_core_feature/config/optional/system.action.index_media_in_fedora.yml → modules/islandora_core_feature/config/install/system.action.index_media_in_fedora.yml

0
modules/islandora_core_feature/config/optional/system.action.index_media_in_triplestore.yml → modules/islandora_core_feature/config/install/system.action.index_media_in_triplestore.yml

0
modules/islandora_core_feature/config/optional/system.action.index_node_in_fedora.yml → modules/islandora_core_feature/config/install/system.action.index_node_in_fedora.yml

0
modules/islandora_core_feature/config/optional/system.action.index_node_in_triplestore.yml → modules/islandora_core_feature/config/install/system.action.index_node_in_triplestore.yml

0
modules/islandora_core_feature/config/optional/system.action.index_taxonomy_term_in_fedora.yml → modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_fedora.yml

0
modules/islandora_core_feature/config/optional/system.action.index_taxonomy_term_in_the_triplestore.yml → modules/islandora_core_feature/config/install/system.action.index_taxonomy_term_in_the_triplestore.yml

0
modules/islandora_core_feature/config/optional/taxonomy.vocabulary.islandora_media_use.yml → modules/islandora_core_feature/config/install/taxonomy.vocabulary.islandora_media_use.yml

0
modules/islandora_core_feature/config/optional/taxonomy.vocabulary.islandora_models.yml → modules/islandora_core_feature/config/install/taxonomy.vocabulary.islandora_models.yml

1
modules/islandora_core_feature/config/optional/views.view.all_taxonomy_terms.yml → modules/islandora_core_feature/config/install/views.view.all_taxonomy_terms.yml

@ -168,3 +168,4 @@ display:
- url.query_args
- user.permissions
tags: { }

0
modules/islandora_core_feature/config/optional/views.view.display_media.yml → modules/islandora_core_feature/config/install/views.view.display_media.yml

1
modules/islandora_core_feature/config/optional/views.view.file_checksum.yml → modules/islandora_core_feature/config/install/views.view.file_checksum.yml

@ -304,3 +304,4 @@ display:
- url
- user.permissions
tags: { }

0
modules/islandora_core_feature/config/optional/views.view.manage_members.yml → modules/islandora_core_feature/config/install/views.view.manage_members.yml

0
modules/islandora_core_feature/config/optional/views.view.media_of.yml → modules/islandora_core_feature/config/install/views.view.media_of.yml

1
modules/islandora_core_feature/config/optional/views.view.non_fedora_files.yml → modules/islandora_core_feature/config/install/views.view.non_fedora_files.yml

@ -194,3 +194,4 @@ display:
- url.query_args
- user.permissions
tags: { }

0
modules/islandora_core_feature/config/optional/views.view.reorder_children.yml → modules/islandora_core_feature/config/install/views.view.reorder_children.yml

16
modules/islandora_core_feature/islandora_core_feature.features.yml

@ -0,0 +1,16 @@
bundle: islandora
excluded:
- language.content_settings.taxonomy_term.islandora_media_use
- language.content_settings.taxonomy_term.islandora_models
required:
- features.bundle.islandora
- field.storage.media.field_file_size
- field.storage.media.field_height
- field.storage.media.field_media_of
- field.storage.media.field_media_use
- field.storage.media.field_mime_type
- field.storage.media.field_width
- field.storage.node.field_member_of
- field.storage.node.field_model
- field.storage.node.field_weight
- field.storage.taxonomy_term.field_external_uri

4
modules/islandora_core_feature/islandora_core_feature.info.yml

@ -1,11 +1,13 @@
name: 'Islandora Core Feature'
description: 'Minimum configuration required for Islandora.'
type: module
core_version_requirement: ^9 || ^10
core: 8.x
core_version_requirement: ^8 || ^9
dependencies:
- drupal:basic_auth
- drupal:content_translation
- drupal:eva
- drupal:features
- drupal:field
- drupal:file
- drupal:filehash

10
modules/islandora_iiif/README.md

@ -1,4 +1,4 @@
# Islandora IIIF
# Islandora IIIF
[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.2-8892BF.svg?style=flat-square)](https://php.net/)
[![Contribution Guidelines](http://img.shields.io/badge/CONTRIBUTING-Guidelines-blue.svg)](./CONTRIBUTING.md)
@ -11,7 +11,7 @@ Provides IIIF manifests using views.
## Requirements
- `islandora` and `islandora_core_feature`
- A IIIF image server (such as Cantaloupe)
- A IIIF image server (such as Cantaloupe)
## Installation
@ -32,12 +32,6 @@ You can set the following configuration at `admin/config/islandora/iiif`:
- IIIF Image server location
- The URL to your IIIF image server (without trailing slash).
### Views Style Plugin
This module implements a Views Style plugin. It provides the following settings:
1. Tile Source: A field that was added to the views list of fields with the image to be served. This should be a File or Image type field on a Media.
2. Structured Text field: This lets you specify a file field where OCR text with positional data, e.g., hOCR can be found.
## Documentation
Official documentation is available on the [Islandora 8 documentation site](https://islandora.github.io/documentation/).

18
modules/islandora_iiif/config/schema/islandora_iiif.schema.yml

@ -5,29 +5,11 @@ islandora_iiif.settings:
iiif_server:
type: string
label: 'IIIF Server Url'
use_relative_paths:
type: boolean
label: 'Use relative paths in manifest.'
show_title:
type: string
label: 'Show title in view'
views.style.iiif_manifest:
type: views_style
mapping:
iiif_tile_field:
type: sequence
label: "Tile source field(s)"
sequence:
type: string
iiif_ocr_file_field:
type: sequence
label: "Structured OCR data file field"
sequence:
type: string
structured_text_term_uri:
type: string
label: "Structured text term"
search_endpoint:
type: string
label: "Search endpoint path"

3
modules/islandora_iiif/islandora_iiif.info.yml

@ -1,7 +1,8 @@
name: 'Islandora IIIF'
type: module
description: 'IIIF support for Islandora'
core_version_requirement: ^9 || ^10
core: 8.x
core_version_requirement: ^8 || ^9
package: Islandora
dependencies:
- drupal:islandora

26
modules/islandora_iiif/src/Form/IslandoraIIIFConfigForm.php

@ -66,37 +66,13 @@ class IslandoraIIIFConfigForm extends ConfigFormBase {
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$options = [
'none' => $this->t('None'),
'view' => $this->t("From view title"),
'node' => $this->t("From node title"),
];
$config = $this->config('islandora_iiif.settings');
$form['iiif_server'] = [
'#type' => 'url',
'#title' => $this->t('IIIF Image server location'),
'#description' => $this->t('Please enter the image server location without trailing slash. e.g. http://www.example.org/iiif/2.'),
'#default_value' => $config->get('iiif_server'),
'#config' => [
'key' => 'islandora_iiif.settings:iiif_server',
],
];
$form['use_relative_paths'] = [
'#type' => 'checkbox',
'#title' => $this->t("Use relative file paths in manifest."),
'#description' => $this->t("Check this if your IIIF Server is configured to access files locally. If unchecked, the absolute URL will be given and the IIIF server will make requests to this site to retrieve images."),
'#default_value' => $config->get('use_relative_paths'),
];
$form['show_title'] = [
'#type' => 'select',
'#options' => $options,
'#title' => $this->t("Show title in viewer."),
'#description' => $this->t("Show title on your viewer, if viewer allows"),
'#default_value' => $config->get('show_title'),
];
return parent::buildForm($form, $form_state);
}
@ -123,8 +99,6 @@ class IslandoraIIIFConfigForm extends ConfigFormBase {
$this->config('islandora_iiif.settings')
->set('iiif_server', $form_state->getValue('iiif_server'))
->set('use_relative_paths', $form_state->getValue('use_relative_paths'))
->set('show_title', $form_state->getValue('show_title'))
->save();
}

331
modules/islandora_iiif/src/Plugin/views/style/IIIFManifest.php

@ -2,26 +2,21 @@
namespace Drupal\islandora_iiif\Plugin\views\style;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Entity\EntityInterface;
use Drupal\views\Plugin\views\style\StylePluginBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Url;
use Drupal\islandora\IslandoraUtils;
use Drupal\taxonomy\TermInterface;
use Drupal\views\Plugin\views\style\StylePluginBase;
use Drupal\views\ResultRow;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\File\FileSystemInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\ServerException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Provide serializer format for IIIF Manifest.
@ -37,13 +32,6 @@ use Symfony\Component\HttpFoundation\Request;
*/
class IIIFManifest extends StylePluginBase {
/**
* Islandora utility functions.
*
* @var \Drupal\islandora\IslandoraUtils
*/
protected $utils;
/**
* {@inheritdoc}
*/
@ -96,13 +84,6 @@ class IIIFManifest extends StylePluginBase {
*/
protected $fileSystem;
/**
* The Guzzle HTTP Client.
*
* @var \GuzzleHttp\Client
*/
protected $httpClient;
/**
* The messenger.
*
@ -110,31 +91,10 @@ class IIIFManifest extends StylePluginBase {
*/
protected $messenger;
/**
* Module Handler for running hooks.
*
* @var \Drupal\Core\Extention\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Memoized structured text term.
*
* @var \Drupal\taxonomy\TermInterface|null
*/
protected ?TermInterface $structuredTextTerm;
/**
* Flag to track if we _have_ attempted a lookup, as the value is nullable.
*
* @var bool
*/
protected bool $structuredTextTermMemoized = FALSE;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, SerializerInterface $serializer, Request $request, ImmutableConfig $iiif_config, EntityTypeManagerInterface $entity_type_manager, FileSystemInterface $file_system, Client $http_client, MessengerInterface $messenger, ModuleHandlerInterface $moduleHandler, IslandoraUtils $utils) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, SerializerInterface $serializer, Request $request, ImmutableConfig $iiif_config, EntityTypeManagerInterface $entity_type_manager, FileSystemInterface $file_system, Client $http_client, MessengerInterface $messenger) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->serializer = $serializer;
@ -144,8 +104,6 @@ class IIIFManifest extends StylePluginBase {
$this->fileSystem = $file_system;
$this->httpClient = $http_client;
$this->messenger = $messenger;
$this->utils = $utils;
$this->moduleHandler = $moduleHandler;
}
/**
@ -162,22 +120,10 @@ class IIIFManifest extends StylePluginBase {
$container->get('entity_type.manager'),
$container->get('file_system'),
$container->get('http_client'),
$container->get('messenger'),
$container->get('module_handler'),
$container->get('islandora.utils')
$container->get('messenger')
);
}
/**
* Return the request property.
*
* @return \Symfony\Component\HttpFoundation\Request
* The Symfony request object
*/
public function getRequest() {
return $this->request;
}
/**
* {@inheritdoc}
*/
@ -190,35 +136,17 @@ class IIIFManifest extends StylePluginBase {
$request_url = $this->request->getRequestUri();
// Strip off the last URI component to get the base ID of the URL.
// @todo assumming the view is a path like /node/1/manifest.json
$url_components = explode('/', trim($request_url, '/'));
$url_components = explode('/', $request_url);
array_pop($url_components);
$content_path = '/' . implode('/', $url_components);
$iiif_base_id = "{$request_host}{$content_path}";
$display = $this->iiifConfig->get('show_title');
switch ($display) {
case 'none':
$label = '';
break;
case 'view':
$label = $this->view->getTitle();
break;
case 'node':
$label = $this->getEntityTitle($content_path);
break;
default:
$label = $this->t("IIIF Manifest");
}
$content_path = implode('/', $url_components);
$iiif_base_id = $request_host . '/' . $content_path;
// @see https://iiif.io/api/presentation/2.1/#manifest
$json += [
'@type' => 'sc:Manifest',
'@id' => $request_url,
// If the View has a title, set the View title as the manifest label.
'label' => $label,
'label' => $this->view->getTitle() ?: $this->getEntityTitle($content_path),
'@context' => 'http://iiif.io/api/presentation/2/context.json',
// @see https://iiif.io/api/presentation/2.1/#sequence
'sequences' => [
@ -242,12 +170,6 @@ class IIIFManifest extends StylePluginBase {
$content_type = 'json';
// Add a search endpoint if one is defined.
$this->addSearchEndpoint($json, $url_components);
// Give other modules a chance to alter the manifest.
$this->moduleHandler->alter('islandora_iiif_manifest', $json, $this);
return $this->serializer->serialize($json, $content_type, ['views_style_plugin' => $this]);
}
@ -269,9 +191,12 @@ class IIIFManifest extends StylePluginBase {
$canvases = [];
foreach (array_filter(array_values($this->options['iiif_tile_field'])) as $iiif_tile_field) {
$viewsField = $this->view->field[$iiif_tile_field];
$iiif_ocr_file_field = !empty($this->options['iiif_ocr_file_field']) ? array_filter(array_values($this->options['iiif_ocr_file_field'])) : [];
$ocrField = count($iiif_ocr_file_field) > 0 ? $this->view->field[$iiif_ocr_file_field[0]] : NULL;
$entity = $viewsField->getEntity($row);
if (isset($entity->{$viewsField->definition['field_name']})) {
/** @var \Drupal\Core\Field\FieldItemListInterface $images */
$images = $entity->{$viewsField->definition['field_name']};
foreach ($images as $i => $image) {
@ -280,15 +205,14 @@ class IIIFManifest extends StylePluginBase {
continue;
}
// Create the IIIF URL for this file
// Visiting $iiif_url will resolve to the info.json for the image.
if ($this->iiifConfig->get('use_relative_paths')) {
$file_url = ltrim($image->entity->createFileUrl(TRUE), '/');
}
else {
$file_url = $image->entity->createFileUrl(FALSE);
if (!is_null($ocrField)) {
$ocrs = $entity->{$ocrField->definition['field_name']};
$ocr = isset($ocrs[$i]) ? $ocrs[$i] : FALSE;
}
// Create the IIIF URL for this file
// Visiting $iiif_url will resolve to the info.json for the image.
$file_url = $image->entity->createFileUrl(FALSE);
$mime_type = $image->entity->getMimeType();
$iiif_url = rtrim($iiif_address, '/') . '/' . urlencode($file_url);
@ -296,8 +220,35 @@ class IIIFManifest extends StylePluginBase {
$canvas_id = $iiif_base_id . '/canvas/' . $entity->id();
$annotation_id = $iiif_base_id . '/annotation/' . $entity->id();
[$width, $height] = $this->getCanvasDimensions($iiif_url, $image, $mime_type);
// Try to fetch the IIIF metadata for the image.
try {
$info_json = $this->httpClient->get($iiif_url)->getBody();
$resource = json_decode($info_json, TRUE);
$width = $resource['width'];
$height = $resource['height'];
}
catch (ClientException | ServerException | ConnectException $e) {
// If we couldn't get the info.json from IIIF
// try seeing if we can get it from Drupal.
if (empty($width) || empty($height)) {
// Get the image properties so we know the image width/height.
$properties = $image->getProperties();
$width = isset($properties['width']) ? $properties['width'] : 0;
$height = isset($properties['height']) ? $properties['height'] : 0;
// If this is a TIFF AND we don't know the width/height
// see if we can get the image size via PHP's core function.
if ($mime_type === 'image/tiff' && !$width || !$height) {
$uri = $image->entity->getFileUri();
$path = $this->fileSystem->realpath($uri);
$image_size = getimagesize($path);
if ($image_size) {
$width = $image_size[0];
$height = $image_size[1];
}
}
}
}
$tmp_canvas = [
// @see https://iiif.io/api/presentation/2.1/#canvas
'@id' => $canvas_id,
@ -328,22 +279,15 @@ class IIIFManifest extends StylePluginBase {
],
];
if ($ocr_url = $this->getOcrUrl($entity)) {
if (isset($ocr) && $ocr != FALSE) {
$tmp_canvas['seeAlso'] = [
'@id' => $ocr_url,
'@id' => $ocr->entity->createFileUrl(FALSE),
'format' => 'text/vnd.hocr+html',
'profile' => 'http://kba.cloud/hocr-spec',
'label' => 'hOCR embedded text',
];
}
// Give other modules a chance to alter the canvas.
$alter_options = [
'options' => $this->options,
'views_plugin' => $this,
];
$this->moduleHandler->alter('islandora_iiif_manifest_canvas', $tmp_canvas, $row, $alter_options);
$canvases[] = $tmp_canvas;
}
}
@ -352,98 +296,6 @@ class IIIFManifest extends StylePluginBase {
return $canvases;
}
/**
* Try to fetch the IIIF metadata for the image.
*
* @param string $iiif_url
* Base URL of the canvas.
* @param \Drupal\Core\Field\FieldItemInterface $image
* The image field.
* @param string $mime_type
* The mime type of the image.
*
* @return [string]
* The width and height of the image.
*/
protected function getCanvasDimensions(string $iiif_url, FieldItemInterface $image, string $mime_type) {
if (isset($image->width) && is_numeric($image->width)
&& isset($image->height) && is_numeric($image->height)) {
return [intval($image->width), intval($image->height)];
}
try {
$info_json = $this->httpClient->get($iiif_url)->getBody();
$resource = json_decode($info_json, TRUE);
$width = $resource['width'];
$height = $resource['height'];
}
catch (ClientException | ServerException | ConnectException $e) {
// If we couldn't get the info.json from IIIF
// try seeing if we can get it from Drupal.
if (empty($width) || empty($height)) {
// Get the image properties so we know the image width/height.
$properties = $image->getProperties();
$width = isset($properties['width']) ? $properties['width'] : 0;
$height = isset($properties['height']) ? $properties['height'] : 0;
// If this is a TIFF AND we don't know the width/height
// see if we can get the image size via PHP's core function.
if ($mime_type === 'image/tiff' && (!$width || !$height)) {
$uri = $image->entity->getFileUri();
$path = $this->fileSystem->realpath($uri);
$image_size = getimagesize($path);
if ($image_size) {
$width = $image_size[0];
$height = $image_size[1];
}
}
}
}
return [$width, $height];
}
/**
* Retrieves a URL text with positional data such as hOCR.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity at the current row.
*
* @return string|false
* The absolute URL of the current row's structured text,
* or FALSE if none.
*/
protected function getOcrUrl(EntityInterface $entity) {
$ocr_url = FALSE;
$iiif_ocr_file_field = !empty($this->options['iiif_ocr_file_field']) ? array_filter(array_values($this->options['iiif_ocr_file_field'])) : [];
$ocrField = count($iiif_ocr_file_field) > 0 ? $this->view->field[$iiif_ocr_file_field[0]] : NULL;
if ($ocrField) {
$ocr_entity = $entity;
$ocr_field_name = $ocrField->definition['field_name'];
if (!is_null($ocr_field_name)) {
$ocrs = $ocr_entity->{$ocr_field_name};
$ocr = $ocrs[0] ?? FALSE;
if ($ocr) {
$ocr_url = $ocr->entity->createFileUrl(FALSE);
}
}
}
elseif ($structured_text_term = $this->getStructuredTextTerm()) {
$parent_node = $this->utils->getParentNode($entity);
$ocr_entity_array = $this->utils->getMediaReferencingNodeAndTerm($parent_node, $structured_text_term);
$ocr_entity_id = is_array($ocr_entity_array) ? array_shift($ocr_entity_array) : NULL;
$ocr_entity = $ocr_entity_id ? $this->entityTypeManager->getStorage('media')->load($ocr_entity_id) : NULL;
if ($ocr_entity) {
$ocr_file_source = $ocr_entity->getSource();
$ocr_fid = $ocr_file_source->getSourceFieldValue($ocr_entity);
$ocr_file = $this->entityTypeManager->getStorage('file')->load($ocr_fid);
$ocr_url = $ocr_file->createFileUrl(FALSE);
}
}
return $ocr_url;
}
/**
* Pull a title from the node or media passed to this view.
*
@ -484,29 +336,6 @@ class IIIFManifest extends StylePluginBase {
return $options;
}
/**
* Add the configured search endpoint to the manifest.
*
* @param array $json
* The IIIF manifest.
* @param array $url_components
* The search endpoint URL as array.
*/
protected function addSearchEndpoint(array &$json, array $url_components) {
$url_base = $this->getRequest()->getSchemeAndHttpHost();
$hocr_search_path = $this->options['search_endpoint'];
$hocr_search_url = $url_base . '/' . ltrim($hocr_search_path, '/');
$hocr_search_url = str_replace('%node', $url_components[1], $hocr_search_url);
$json['service'][] = [
"@context" => "http://iiif.io/api/search/0/context.json",
"@id" => $hocr_search_url,
"profile" => "http://iiif.io/api/search/0/search",
"label" => t("Search inside this work"),
];
}
/**
* {@inheritdoc}
*/
@ -563,27 +392,10 @@ class IIIFManifest extends StylePluginBase {
'#title' => $this->t('Structured OCR data file field'),
'#type' => 'checkboxes',
'#default_value' => $this->options['iiif_ocr_file_field'],
'#description' => $this->t("If the hOCR is a field on the same entity as the image source field above, select it here. If it's found in a related entity via the term below, leave this blank."),
'#description' => $this->t('The source of structured OCR text for each entity.'),
'#options' => $field_options,
'#required' => FALSE,
];
$form['structured_text_term'] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'taxonomy_term',
'#title' => $this->t('Structured OCR text term'),
'#default_value' => $this->getStructuredTextTerm(),
'#required' => FALSE,
'#description' => $this->t('Term indicating the media that holds structured text, such as hOCR, for the given object. Use this if the text is on a separate media from the tile source.'),
];
$form['search_endpoint'] = [
'#type' => 'textfield',
'#title' => $this->t("Search endpoint path."),
'#description' => $this->t("If there is a search endpoint to search within the book that returns IIIF annotations, put it here. Use %node substitution where needed.<br>E.g., paged-content-search/%node"),
'#default_value' => $this->options['search_endpoint'],
'#required' => FALSE,
];
}
/**
@ -596,41 +408,4 @@ class IIIFManifest extends StylePluginBase {
return ['json' => 'json'];
}
/**
* Submit handler for options form.
*
* Used to store the structured text media term by URL instead of Ttid.
*
* @param array $form
* The form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
*/
// @codingStandardsIgnoreStart
public function submitOptionsForm(&$form, FormStateInterface $form_state) {
// @codingStandardsIgnoreEnd
$style_options = $form_state->getValue('style_options');
$tid = $style_options['structured_text_term'];
unset($style_options['structured_text_term']);
$term = $this->entityTypeManager->getStorage('taxonomy_term')->load($tid);
$style_options['structured_text_term_uri'] = $this->utils->getUriForTerm($term);
$form_state->setValue('style_options', $style_options);
parent::submitOptionsForm($form, $form_state);
}
/**
* Get the structured text term.
*
* @return \Drupal\taxonomy\TermInterface|null
* The term if it could be found; otherwise, NULL.
*/
protected function getStructuredTextTerm() : ?TermInterface {
if (!$this->structuredTextTermMemoized) {
$this->structuredTextTermMemoized = TRUE;
$this->structuredTextTerm = $this->utils->getTermForUri($this->options['structured_text_term_uri']);
}
return $this->structuredTextTerm;
}
}

3
modules/islandora_image/islandora_image.info.yml

@ -1,7 +1,8 @@
name: 'Islandora Image'
type: module
description: 'Islandora Image derivative actions'
core_version_requirement: ^9 || ^10
core: 8.x
core_version_requirement: ^8 || ^9
package: Islandora
dependencies:
- drupal:islandora

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

@ -42,7 +42,7 @@ class GenerateImageDerivativeTest extends GenerateDerivativeTestBase {
// Create an action to generate a jpeg thumbnail.
$this->drupalGet('admin/config/system/actions');
$this->getSession()->getPage()->findById("edit-action")->selectOption("Generate an image derivative");
$this->getSession()->getPage()->pressButton('Create');
$this->getSession()->getPage()->pressButton($this->t('Create'));
$this->assertSession()->statusCodeEquals(200);
$this->getSession()->getPage()->fillField('edit-label', "Generate image test derivative");
@ -55,7 +55,7 @@ class GenerateImageDerivativeTest extends GenerateDerivativeTestBase {
$this->getSession()->getPage()->fillField('edit-args', "-thumbnail 20x20");
$this->getSession()->getPage()->fillField('edit-scheme', "public");
$this->getSession()->getPage()->fillField('edit-path', "derp.jpeg");
$this->getSession()->getPage()->pressButton('Save');
$this->getSession()->getPage()->pressButton($this->t('Save'));
$this->assertSession()->statusCodeEquals(200);
// Create a context and add the action as a derivative reaction.
@ -68,10 +68,9 @@ class GenerateImageDerivativeTest extends GenerateDerivativeTestBase {
'name[0][value]' => 'Test Media',
'files[field_media_file_0]' => __DIR__ . '/../../fixtures/test_file.txt',
'field_media_of[0][target_id]' => 'Test Node',
'field_media_use[0][target_id]' => $this->preservationMasterTerm->label(),
'field_tags[0][target_id]' => 'Preservation Master',
];
$this->drupalGet('media/add/' . $this->testMediaType->id());
$this->submitForm($values, 'Save');
$this->drupalPostForm('media/add/' . $this->testMediaType->id(), $values, $this->t('Save'));
$expected = [
'source_uri' => 'test_file.txt',

3
modules/islandora_text_extraction/islandora_text_extraction.info.yml

@ -1,7 +1,8 @@
name: 'Islandora Text Extraction'
type: module
description: 'Islandora 8 module to connect to Hypercube microservice, and to get text from PDF ingest'
core_version_requirement: ^9 || ^10
core: 8.x
core_version_requirement: ^8 || ^9
package: 'Islandora'
dependencies:
- drupal:islandora

4
modules/islandora_text_extraction/islandora_text_extraction.module

@ -40,10 +40,6 @@ function islandora_text_extraction_media_presave(MediaInterface $media) {
$file = File::load($file_id);
if ($file) {
$data = file_get_contents($file->getFileUri());
// Check if it's already markup like hOCR.
if (substr($data, 0, 5) == '<?xml') {
return;
}
$data = nl2br($data);
$media->set('field_edited_text', $data);
$media->field_edited_text->format = 'basic_html';

24
modules/islandora_text_extraction/src/Controller/MediaSourceController.php

@ -5,7 +5,6 @@ namespace Drupal\islandora_text_extraction\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\File\FileSystem;
use Drupal\Core\File\FileSystemInterface;
use Drupal\file\FileRepository;
use Drupal\media\Entity\Media;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
@ -43,24 +42,14 @@ class MediaSourceController extends ControllerBase {
*/
protected $fileSystem;
/**
* File repository service.
*
* @var \Drupal\file\FileRepository
*/
protected $fileRepository;
/**
* MediaSourceController constructor.
*
* @param \Drupal\Core\File\FileSystem $fileSystem
* Filesystem service.
* @param \Drupal\file\FileRepository $fileRepository
* File Repository service.
*/
public function __construct(FileSystem $fileSystem, FileRepository $fileRepository) {
public function __construct(FileSystem $fileSystem) {
$this->fileSystem = $fileSystem;
$this->fileRepository = $fileRepository;
}
/**
@ -74,8 +63,7 @@ class MediaSourceController extends ControllerBase {
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('file_system'),
$container->get('file.repository'),
$container->get('file_system')
);
}
@ -110,7 +98,7 @@ class MediaSourceController extends ControllerBase {
if (!$this->fileSystem->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS)) {
throw new HttpException(500, "The destination directory does not exist, could not be created, or is not writable");
}
$file = $this->fileRepository->writeData($contents, $content_location, FileSystemInterface::EXISTS_REPLACE);
$file = file_save_data($contents, $content_location, FileSystemInterface::EXISTS_REPLACE);
if ($media->hasField($destination_field)) {
$media->{$destination_field}->setValue([
'target_id' => $file->id(),
@ -120,11 +108,7 @@ class MediaSourceController extends ControllerBase {
$this->getLogger('islandora')->warning("Field $destination_field is not defined in Media Type {$media->bundle()}");
}
if ($media->hasField($destination_text_field)) {
// @todo The request actually has a malformed parameter string, ?text_format=plain_text?connection_close=true.
if (substr($request->query->get('text_format'), 0, 10) == 'plain_text') {
$contents = nl2br($contents);
}
$media->{$destination_text_field}->setValue($contents);
$media->{$destination_text_field}->setValue(nl2br($contents));
}
else {
$this->getLogger('islandora')->warning("Field $destination_text_field is not defined in Media Type {$media->bundle()}");

11
modules/islandora_text_extraction/src/Plugin/Action/GenerateOCRDerivative.php

@ -37,9 +37,11 @@ class GenerateOCRDerivative extends AbstractGenerateDerivative {
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$form['mimetype']['#description'] = $this->t('Mimetype to convert to (e.g. application/xml, etc...)');
$form['mimetype']['#value'] = 'text/plain';
$form['mimetype']['#type'] = 'textfield';
$form['args']['#description'] = $this->t("Arguments to send to Tesseract. To generate hOCR, use:<br /><code>-c tessedit_create_hocr=1 -c hocr_font_info=0</code>");
unset($form['args']);
return $form;
}
@ -48,9 +50,8 @@ class GenerateOCRDerivative extends AbstractGenerateDerivative {
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
parent::validateConfigurationForm($form, $form_state);
$mime = $form_state->getValue('mimetype');
$exploded_mime = explode('/', $mime);
if ($exploded_mime[0] != 'text' && $mime != 'application/xml') {
$exploded_mime = explode('/', $form_state->getValue('mimetype'));
if ($exploded_mime[0] != 'text') {
$form_state->setErrorByName(
'mimetype',
$this->t('Please enter file mimetype (e.g. text/plain.)')

2
modules/islandora_text_extraction/src/Plugin/Action/GenerateOCRDerivativeFile.php

@ -99,7 +99,7 @@ class GenerateOCRDerivativeFile extends AbstractGenerateDerivativeMediaFile {
break;
case 'plain_text':
$this->configuration['args'] = '';
$his->configuration['args'] = '';
break;
}
}

5
modules/islandora_text_extraction/src/Plugin/Field/FieldFormatter/OcrTextFormatter.php

@ -132,9 +132,8 @@ class OcrTextFormatter extends FormatterBase implements ContainerFactoryPluginIn
$fileItem = $item->getValue();
$file = $this->entityTypeManager->getStorage('file')->load($fileItem['target_id']);
$contents = file_get_contents($file->getFileUri());
$detected_encoding = mb_detect_encoding($contents);
if ($detected_encoding != 'UTF-8') {
$contents = mb_convert_encoding($contents, 'UTF-8', $detected_encoding);
if (mb_detect_encoding($contents) != 'UTF-8') {
$contents = utf8_encode($contents);
}
$contents = nl2br($contents);
return $contents;

4
modules/islandora_text_extraction/tests/src/Functional/LoadTest.php

@ -17,7 +17,7 @@ class LoadTest extends IslandoraFunctionalTestBase {
*
* @var array
*/
protected static $modules = ['islandora_text_extraction'];
public static $modules = ['islandora_text_extraction'];
/**
* A user with permission to administer site configuration.
@ -29,7 +29,7 @@ class LoadTest extends IslandoraFunctionalTestBase {
/**
* {@inheritdoc}
*/
public function setUp(): void {
public function setUp() {
parent::setUp();
$this->user = $this->drupalCreateUser(['administer site configuration']);
$this->drupalLogin($this->user);

0
modules/islandora_text_extraction_defaults/config/optional/core.entity_form_display.media.extracted_text.default.yml → modules/islandora_text_extraction_defaults/config/install/core.entity_form_display.media.extracted_text.default.yml

0
modules/islandora_text_extraction_defaults/config/optional/core.entity_view_display.media.extracted_text.default.yml → modules/islandora_text_extraction_defaults/config/install/core.entity_view_display.media.extracted_text.default.yml

0
modules/islandora_text_extraction_defaults/config/optional/field.field.media.extracted_text.field_edited_text.yml → modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_edited_text.yml

0
modules/islandora_text_extraction_defaults/config/optional/field.field.media.extracted_text.field_media_file.yml → modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_media_file.yml

0
modules/islandora_text_extraction_defaults/config/optional/field.field.media.extracted_text.field_media_of.yml → modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_media_of.yml

0
modules/islandora_text_extraction_defaults/config/optional/field.field.media.extracted_text.field_media_use.yml → modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_media_use.yml

0
modules/islandora_text_extraction_defaults/config/optional/field.field.media.extracted_text.field_mime_type.yml → modules/islandora_text_extraction_defaults/config/install/field.field.media.extracted_text.field_mime_type.yml

0
modules/islandora_text_extraction_defaults/config/optional/field.storage.media.field_edited_text.yml → modules/islandora_text_extraction_defaults/config/install/field.storage.media.field_edited_text.yml

0
modules/islandora_text_extraction_defaults/config/optional/language.content_settings.media.extracted_text.yml → modules/islandora_text_extraction_defaults/config/install/language.content_settings.media.extracted_text.yml

0
modules/islandora_text_extraction_defaults/config/optional/media.type.extracted_text.yml → modules/islandora_text_extraction_defaults/config/install/media.type.extracted_text.yml

0
modules/islandora_text_extraction_defaults/config/optional/rdf.mapping.media.extracted_text.yml → modules/islandora_text_extraction_defaults/config/install/rdf.mapping.media.extracted_text.yml

0
modules/islandora_text_extraction_defaults/config/optional/system.action.get_ocr_from_image.yml → modules/islandora_text_extraction_defaults/config/install/system.action.get_ocr_from_image.yml

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save