From 762f10eb474c10901edd90c8a990afd4c974f647 Mon Sep 17 00:00:00 2001 From: dannylamb Date: Wed, 13 Nov 2019 16:29:15 +0000 Subject: [PATCH 1/5] Upload form --- config/schema/islandora.schema.yml | 21 +++ islandora.links.action.yml | 10 +- islandora.routing.yml | 23 ++- src/Form/AddChildrenForm.php | 179 +++++++++++++++++++ src/Form/AddMediaForm.php | 246 +++++++++++++++++++++++++++ src/Form/IslandoraSettingsForm.php | 86 +++++++++- src/IslandoraUtils.php | 27 +++ src/Plugin/Condition/NodeHasTerm.php | 42 ++++- 8 files changed, 608 insertions(+), 26 deletions(-) create mode 100644 src/Form/AddChildrenForm.php create mode 100644 src/Form/AddMediaForm.php diff --git a/config/schema/islandora.schema.yml b/config/schema/islandora.schema.yml index 8fd719ced..b4983fa20 100644 --- a/config/schema/islandora.schema.yml +++ b/config/schema/islandora.schema.yml @@ -14,6 +14,18 @@ islandora.settings: jwt_expiry: type: string label: 'How long JWTs should last before expiring.' + upload_form_bundle: + type: string + label: 'Upload Form Content Type' + upload_form_location: + type: string + label: 'Upload Form Location' + upload_form_term: + type: string + label: 'Upload Form Media Use Term' + upload_form_allowed_extensions: + type: string + label: 'Upload Form Allowed Extensions' gemini_url: type: uri label: 'Url to Gemini microservice' @@ -78,6 +90,9 @@ condition.plugin.node_has_term: uri: type: text label: 'Taxonomy Term URI' + logic: + type: string + label: 'Logic (AND or OR)' condition.plugin.node_has_parent: type: condition.plugin @@ -95,6 +110,9 @@ condition.plugin.media_has_term: uri: type: text label: 'Taxonomy Term URI' + logic: + type: string + label: 'Logic (AND or OR)' condition.plugin.parent_node_has_term: type: condition.plugin @@ -102,6 +120,9 @@ condition.plugin.parent_node_has_term: uri: type: text label: 'Taxonomy Term URI' + logic: + type: text + label: 'Logic (AND or OR)' condition.plugin.file_uses_filesystem: type: condition.plugin diff --git a/islandora.links.action.yml b/islandora.links.action.yml index f8bf7d2b3..8a1f67687 100644 --- a/islandora.links.action.yml +++ b/islandora.links.action.yml @@ -1,12 +1,12 @@ islandora.add_media_to_node: - route_name: islandora.add_media_to_node_page - title: Add media + route_name: islandora.add_media_form + title: Add Media appears_on: - view.media_of.page_1 -islandora.add_member_to_node: - route_name: islandora.add_member_to_node_page - title: Add child +islandora.add_children_to_node: + route_name: islandora.add_children_form + title: Add Children appears_on: - view.manage_members.page_1 diff --git a/islandora.routing.yml b/islandora.routing.yml index 58dea1a25..814bacab3 100644 --- a/islandora.routing.yml +++ b/islandora.routing.yml @@ -16,27 +16,24 @@ system.islandora_settings: requirements: _permission: 'administer site configuration' -islandora.add_member_to_node_page: +islandora.add_children_form: path: '/node/{node}/members/add' defaults: - _controller: '\Drupal\islandora\Controller\ManageMembersController::addToNodePage' - _title_callback: '\Drupal\islandora\Controller\ManageMembersController::addTitle' - entity_type_id: node + _form: '\Drupal\islandora\Form\AddChildrenForm' + _title: 'Add children' options: - _admin_route: 'true' + _admin_route: 'TRUE' requirements: - _entity_create_any_access: 'node' + _permssion: 'create node,create media' -islandora.add_media_to_node_page: +islandora.add_media_form: path: '/node/{node}/media/add' - defaults: - _controller: '\Drupal\islandora\Controller\ManageMediaController::addToNodePage' - _title_callback: '\Drupal\islandora\Controller\ManageMediaController::addTitle' - entity_type_id: media + _form: '\Drupal\islandora\Form\AddMediaForm' + _title: 'Add media' options: - _admin_route: 'true' + _admin_route: 'TRUE' requirements: - _entity_create_any_access: 'media' + _permssion: 'create media' islandora.media_source_update: path: '/media/{media}/source' diff --git a/src/Form/AddChildrenForm.php b/src/Form/AddChildrenForm.php new file mode 100644 index 000000000..14b787b32 --- /dev/null +++ b/src/Form/AddChildrenForm.php @@ -0,0 +1,179 @@ +config->get(IslandoraSettingsForm::UPLOAD_FORM_LOCATION); + $upload_location = $this->token->replace($upload_pattern); + + $valid_extensions = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_ALLOWED_MIMETYPES); + + $this->parentId = $this->routeMatch->getParameter('node'); + $parent = $this->entityTypeManager->getStorage('node')->load($this->parentId); + + $form['upload'] = [ + '#type' => 'managed_file', + '#title' => $this->t('Files'), + '#description' => $this->t("Upload one or more files to add children to @title", ['@title' => $parent->getTitle()]), + '#upload_location' => $upload_location, + '#upload_validators' => [ + 'file_validate_extensions' => [$valid_extensions], + ], + '#multiple' => TRUE, + ]; + $form['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Submit'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $parent_id = $this->routeMatch->getParameter('node'); + $parent = $this->entityTypeManager->getStorage('node')->load($parent_id); + + $fids = $form_state->getValue('upload'); + + $operations = []; + foreach ($fids as $fid) { + $operations[] = [[$this, 'buildNodeForFile'], [$fid, $parent_id]]; + } + + $batch = [ + 'title' => $this->t("Uploading Children for @title", ['@title' => $parent->getTitle()]), + 'operations' => $operations, + 'progress_message' => t('Processed @current out of @total. Estimated time: @estimate.'), + 'error_message' => t('The process has encountered an error.'), + 'finished' => [$this, 'buildNodeFinished'], + ]; + + batch_set($batch); + } + + /** + * Wires up a file/media/node combo for a file upload. + * + * @param int $fid + * Uploaded file id. + * @param int $parent_id + * Id of the parent node. + * @param array $context + * Batch context. + * + * @throws \Symfony\Component\HttpKernel\Exception\HttpException + */ + public function buildNodeForFile($fid, $parent_id, array &$context) { + // Since we make 3 different entities, do this in a transaction. + $transaction = $this->database->startTransaction(); + + try { + $file = $this->entityTypeManager->getStorage('file')->load($fid); + $file->setPermanent(); + $file->save(); + + $parent = $this->entityTypeManager->getStorage('node')->load($parent_id); + + $mime = $file->getMimetype(); + $exploded_mime = explode('/', $mime); + if ($exploded_mime[0] == 'image') { + if (in_array($exploded_mime[1], ['tiff', 'jp2'])) { + $media_type = 'file'; + } + else { + $media_type = 'image'; + } + $model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_c513'); + } + elseif ($exploded_mime[0] == 'audio') { + $media_type = 'audio'; + $model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_18cc'); + } + elseif ($exploded_mime[0] == 'video') { + $media_type = 'video'; + $model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_12ce'); + } + else { + $media_type = 'file'; + if ($mime == 'application/pdf') { + $model = $this->utils->getTermForUri('https://schema.org/DigitalDocument'); + } + else { + $model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_1843'); + } + } + $source_field = $this->mediaSource->getSourceFieldName($media_type); + + $node = $this->entityTypeManager->getStorage('node')->create([ + 'type' => $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_BUNDLE), + 'title' => $file->getFileName(), + IslandoraUtils::MODEL_FIELD => $model, + IslandoraUtils::MEMBER_OF_FIELD => $parent, + 'uid' => $this->account->id(), + 'status' => 1, + ]); + $node->save(); + + $uri = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_TERM); + $term = $this->utils->getTermForUri($uri); + $media = $this->entityTypeManager->getStorage('media')->create([ + 'bundle' => $media_type, + $source_field => $fid, + 'name' => $file->getFileName(), + IslandoraUtils::MEDIA_USAGE_FIELD => $term, + IslandoraUtils::MEDIA_OF_FIELD => $node, + ]); + $media->save(); + } + catch (HttpException $e) { + $transaction->rollBack(); + throw $e; + } + catch (\Exception $e) { + $transaction->rollBack(); + throw new HttpException(500, $e->getMessage()); + } + } + + /** + * Batch finished callback. + * + * $success bool + * Success status + * $results mixed + * The 'results' from the batch context. + * $operations array + * Remaining operations. + */ + public function buildNodeFinished($success, $results, $operations) { + return new RedirectResponse( + Url::fromRoute('view.manage_members.page_1', ['node' => $this->parentId])->toString() + ); + } + +} diff --git a/src/Form/AddMediaForm.php b/src/Form/AddMediaForm.php new file mode 100644 index 000000000..bb02b414c --- /dev/null +++ b/src/Form/AddMediaForm.php @@ -0,0 +1,246 @@ +entityTypeManager = $entity_type_manager; + $this->utils = $utils; + $this->mediaSource = $media_source; + $this->config = $config; + $this->token = $token; + $this->account = $account; + $this->routeMatch = $route_match; + $this->database = $database; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity_type.manager'), + $container->get('islandora.utils'), + $container->get('islandora.media_source_service'), + $container->get('config.factory')->get('islandora.settings'), + $container->get('token'), + $container->get('current_user'), + $container->get('current_route_match'), + $container->get('database') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return 'add_media_form'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $upload_pattern = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_LOCATION); + $upload_location = $this->token->replace($upload_pattern); + + $valid_extensions = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_ALLOWED_MIMETYPES); + + $this->parentId = $this->routeMatch->getParameter('node'); + $parent = $this->entityTypeManager->getStorage('node')->load($this->parentId); + + $form['upload'] = [ + '#type' => 'managed_file', + '#title' => $this->t('File'), + '#description' => $this->t("Upload a file for @title", ['@title' => $parent->getTitle()]), + '#upload_location' => $upload_location, + '#upload_validators' => [ + 'file_validate_extensions' => [$valid_extensions], + ], + '#required' => TRUE, + ]; + + $options = []; + $terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadTree('islandora_media_use', 0, NULL, TRUE); + foreach ($terms as $term) { + $options[$this->utils->getUriForTerm($term)] = $term->getName(); + }; + $form['use'] = [ + '#type' => 'checkboxes', + '#title' => $this->t('Usage'), + '#description' => $this->t("Defined by Portland Common Data Model: Use Extension https://pcdm.org/2015/05/12/use. ''Original File'' will trigger creation of derivatives."), + '#options' => $options, + '#required' => TRUE, + ]; + + $form['submit'] = [ + '#type' => 'submit', + '#value' => $this->t('Submit'), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + $parent_id = $this->routeMatch->getParameter('node'); + $parent = $this->entityTypeManager->getStorage('node')->load($parent_id); + + $fid = $form_state->getValue('upload')[0]; + $external_uris = $form_state->getValue('use'); + + // Since we make 2 different entities, do this in a transaction. + $transaction = $this->database->startTransaction(); + + try { + $file = $this->entityTypeManager->getStorage('file')->load($fid); + $file->setPermanent(); + $file->save(); + + $parent = $this->entityTypeManager->getStorage('node')->load($parent_id); + + $mime = $file->getMimetype(); + $exploded_mime = explode('/', $mime); + if ($exploded_mime[0] == 'image') { + if (in_array($exploded_mime[1], ['tiff', 'jp2'])) { + $media_type = 'file'; + } + else { + $media_type = 'image'; + } + } + elseif ($exploded_mime[0] == 'audio') { + $media_type = 'audio'; + } + elseif ($exploded_mime[0] == 'video') { + $media_type = 'video'; + } + else { + $media_type = 'file'; + } + $source_field = $this->mediaSource->getSourceFieldName($media_type); + + $terms = []; + foreach ($external_uris as $uri) { + $terms[] = $this->utils->getTermForUri($uri); + } + $media = $this->entityTypeManager->getStorage('media')->create([ + 'bundle' => $media_type, + 'uid' => $this->account->id(), + $source_field => $fid, + 'name' => $file->getFileName(), + IslandoraUtils::MEDIA_USAGE_FIELD => $terms, + IslandoraUtils::MEDIA_OF_FIELD => $parent, + ]); + $media->save(); + + $form_state->setRedirect( + 'view.media_of.page_1', + ['node' => $parent_id] + ); + } + catch (HttpException $e) { + $transaction->rollBack(); + throw $e; + } + catch (\Exception $e) { + $transaction->rollBack(); + throw new HttpException(500, $e->getMessage()); + } + } + +} diff --git a/src/Form/IslandoraSettingsForm.php b/src/Form/IslandoraSettingsForm.php index f71cb93c0..141b02874 100644 --- a/src/Form/IslandoraSettingsForm.php +++ b/src/Form/IslandoraSettingsForm.php @@ -4,9 +4,11 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeBundleInfo; +use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; +use Drupal\islandora\IslandoraUtils; use GuzzleHttp\Exception\ConnectException; use Islandora\Crayfish\Commons\Client\GeminiClient; use Stomp\Client; @@ -22,6 +24,11 @@ class IslandoraSettingsForm extends ConfigFormBase { const CONFIG_NAME = 'islandora.settings'; const BROKER_URL = 'broker_url'; const JWT_EXPIRY = 'jwt_expiry'; + const UPLOAD_FORM = 'upload_form'; + const UPLOAD_FORM_BUNDLE = 'upload_form_bundle'; + const UPLOAD_FORM_TERM = 'upload_form_term'; + const UPLOAD_FORM_LOCATION = 'upload_form_location'; + const UPLOAD_FORM_ALLOWED_MIMETYPES = 'upload_form_allowed_mimetypes'; const GEMINI_URL = 'gemini_url'; const GEMINI_PSEUDO = 'gemini_pseudo_bundles'; @@ -32,6 +39,15 @@ class IslandoraSettingsForm extends ConfigFormBase { */ private $entityTypeBundleInfo; + /** + * Islandora utils. + * + * @var \Drupal\islandora\IslandoraUtils + */ + private $utils; + + private $termStorage; + /** * Constructs a \Drupal\system\ConfigFormBase object. * @@ -39,10 +55,21 @@ class IslandoraSettingsForm extends ConfigFormBase { * The factory for configuration objects. * @param \Drupal\Core\Entity\EntityTypeBundleInfo $entity_type_bundle_info * The EntityTypeBundleInfo service. + * @param \Drupal\islandora\IslandoraUtils $utils + * Islandora utils. + * @param \Drupal\Core\Entity\EntityStorageInterface $term_storage + * Term storage. */ - public function __construct(ConfigFactoryInterface $config_factory, EntityTypeBundleInfo $entity_type_bundle_info) { + public function __construct( + ConfigFactoryInterface $config_factory, + EntityTypeBundleInfo $entity_type_bundle_info, + IslandoraUtils $utils, + EntityStorageInterface $term_storage + ) { $this->setConfigFactory($config_factory); $this->entityTypeBundleInfo = $entity_type_bundle_info; + $this->utils = $utils; + $this->termStorage = $term_storage; } /** @@ -51,7 +78,9 @@ public function __construct(ConfigFactoryInterface $config_factory, EntityTypeBu public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('entity_type.bundle.info') + $container->get('entity_type.bundle.info'), + $container->get('islandora.utils'), + $container->get('entity_type.manager')->getStorage('taxonomy_term') ); } @@ -90,6 +119,55 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#description' => 'Eg: 60, "2 days", "10h", "7d". A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120" is equal to "120ms").', ]; + $form[self::UPLOAD_FORM] = [ + '#type' => 'fieldset', + '#title' => $this->t('Add Children / Media Form'), + ]; + + $form[self::UPLOAD_FORM][self::UPLOAD_FORM_LOCATION] = [ + '#type' => 'textfield', + '#title' => $this->t('Upload location'), + '#description' => $this->t('Tokenized URI pattern where the uploaded file should go. You may use tokens to provide a pattern (e.g. "fedora://[date:custom:Y]-[date:custom:m]")'), + '#default_value' => $config->get(self::UPLOAD_FORM_LOCATION), + '#element_validate' => ['token_element_validate'], + '#token_types' => ['system'], + ]; + $form[self::UPLOAD_FORM]['TOKEN_HELP'] = [ + '#theme' => 'token_tree_link', + '#token_type' => ['system'], + ]; + + $form[self::UPLOAD_FORM][self::UPLOAD_FORM_ALLOWED_MIMETYPES] = [ + '#type' => 'textarea', + '#title' => $this->t('Allowed Mimetypes'), + '#description' => $this->t('Add mimetypes as a space delimited list with no periods before the extension.'), + '#default_value' => $config->get(self::UPLOAD_FORM_ALLOWED_MIMETYPES), + ]; + + $options = []; + foreach ($this->entityTypeBundleInfo->getBundleInfo('node') as $bundle_id => $bundle) { + if ($this->utils->isIslandoraType('node', $bundle_id)) { + $options[$bundle_id] = $bundle['label']; + } + }; + $form[self::UPLOAD_FORM][self::UPLOAD_FORM_BUNDLE] = [ + '#type' => 'select', + '#title' => $this->t('Content type to create (Add Children Form Only)'), + '#default_value' => $config->get(self::UPLOAD_FORM_BUNDLE), + '#options' => $options, + ]; + + $options = []; + foreach ($this->termStorage->loadTree('islandora_media_use', 0, NULL, TRUE) as $term) { + $options[$this->utils->getUriForTerm($term)] = $term->getName(); + }; + $form[self::UPLOAD_FORM][self::UPLOAD_FORM_TERM] = [ + '#type' => 'select', + '#title' => $this->t('Media Use Term for Uploaded Files (Add Children Form Only)'), + '#default_value' => $config->get(self::UPLOAD_FORM_TERM), + '#options' => $options, + ]; + $form[self::GEMINI_URL] = [ '#type' => 'textfield', '#title' => $this->t('Gemini URL'), @@ -216,6 +294,10 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $config ->set(self::BROKER_URL, $form_state->getValue(self::BROKER_URL)) ->set(self::JWT_EXPIRY, $form_state->getValue(self::JWT_EXPIRY)) + ->set(self::UPLOAD_FORM_BUNDLE, $form_state->getValue(self::UPLOAD_FORM_BUNDLE)) + ->set(self::UPLOAD_FORM_TERM, $form_state->getValue(self::UPLOAD_FORM_TERM)) + ->set(self::UPLOAD_FORM_LOCATION, $form_state->getValue(self::UPLOAD_FORM_LOCATION)) + ->set(self::UPLOAD_FORM_ALLOWED_MIMETYPES, $form_state->getValue(self::UPLOAD_FORM_ALLOWED_MIMETYPES)) ->set(self::GEMINI_URL, $form_state->getValue(self::GEMINI_URL)) ->set(self::GEMINI_PSEUDO, $pseudo_types) ->save(); diff --git a/src/IslandoraUtils.php b/src/IslandoraUtils.php index e98766c73..3ebf9aa8a 100644 --- a/src/IslandoraUtils.php +++ b/src/IslandoraUtils.php @@ -31,6 +31,8 @@ class IslandoraUtils { const EXTERNAL_URI_FIELD = 'field_external_uri'; const MEDIA_OF_FIELD = 'field_media_of'; const MEDIA_USAGE_FIELD = 'field_media_use'; + const MEMBER_OF_FIELD = 'field_member_of'; + const MODEL_FIELD = 'field_model'; /** * The entity type manager. @@ -570,4 +572,29 @@ public function getRestUrl(EntityInterface $entity, $format = '') { return $rest_url; } + /** + * Determines if an entity type and bundle make an 'Islandora' type entity. + * + * @param string $entity_type + * The entity type ('node', 'media', etc...). + * @param string $bundle + * Entity bundle ('article', 'page', etc...). + * + * @return bool + * TRUE if the bundle has the correct fields to be an 'Islandora' type. + */ + public function isIslandoraType($entity_type, $bundle) { + $fields = $this->entityFieldManager->getFieldDefinitions($entity_type, $bundle); + switch ($entity_type) { + case 'media': + return isset($fields[self::MEDIA_OF_FIELD]) && isset($fields[self::MEDIA_USAGE_FIELD]); + + case 'taxonomy_term': + return isset($fields[self::EXTERNAL_URI_FIELD]); + + default: + return isset($fields[self::MEMBER_OF_FIELD]) && isset($fields[self::MODEL_FIELD]); + } + } + } diff --git a/src/Plugin/Condition/NodeHasTerm.php b/src/Plugin/Condition/NodeHasTerm.php index dae52ad0e..c912ea9b7 100644 --- a/src/Plugin/Condition/NodeHasTerm.php +++ b/src/Plugin/Condition/NodeHasTerm.php @@ -79,6 +79,16 @@ public static function create(ContainerInterface $container, array $configuratio ); } + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return array_merge( + ['logic' => 'and'], + parent::defaultConfiguration() + ); + } + /** * {@inheritdoc} */ @@ -100,6 +110,16 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#required' => TRUE, ]; + $form['logic'] = [ + '#type' => 'radios', + '#title' => $this->t('Logic'), + '#description' => $this->t('Whether to use AND or OR logic to evaluate multiple terms'), + '#options' => [ + 'and' => 'And', + 'or' => 'Or', + ], + '#default_value' => $this->configuration['logic'], + ]; return parent::buildConfigurationForm($form, $form_state); } @@ -124,6 +144,9 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s $this->configuration['uri'] = implode(',', $uris); } } + + $this->configuration['logic'] = $form_state->getValue('logic'); + parent::submitConfigurationForm($form, $form_state); } @@ -168,7 +191,7 @@ protected function evaluateEntity(EntityInterface $entity) { // FALSE if there's no URIs on the node. if (empty($haystack)) { - return $this->isNegated() ? TRUE : FALSE; + return FALSE; } // Get the URIs to look for. It's a required field, so there @@ -176,12 +199,19 @@ protected function evaluateEntity(EntityInterface $entity) { $needles = explode(',', $this->configuration['uri']); // TRUE if every needle is in the haystack. - if (count(array_intersect($needles, $haystack)) == count($needles)) { - return $this->isNegated() ? FALSE : TRUE; + if ($this->configuration['logic'] == 'and') { + if (count(array_intersect($needles, $haystack)) == count($needles)) { + return TRUE; + } + return FALSE; + } + // TRUE if any needle is in the haystack. + else { + if (count(array_intersect($needles, $haystack)) > 0) { + return TRUE; + } + return FALSE; } - - // Otherwise, FALSE. - return $this->isNegated() ? TRUE : FALSE; } /** From a1af28faf5d793a1e03e8fb4ddd79870cb5e20f8 Mon Sep 17 00:00:00 2001 From: dannylamb Date: Wed, 13 Nov 2019 16:33:33 +0000 Subject: [PATCH 2/5] Missing var doc comment --- src/Form/IslandoraSettingsForm.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Form/IslandoraSettingsForm.php b/src/Form/IslandoraSettingsForm.php index 141b02874..43016d008 100644 --- a/src/Form/IslandoraSettingsForm.php +++ b/src/Form/IslandoraSettingsForm.php @@ -46,6 +46,11 @@ class IslandoraSettingsForm extends ConfigFormBase { */ private $utils; + /** + * Term storage. + * + * @var \Drupal\Core\Entity\EntityStorageInterface + */ private $termStorage; /** From 7338f9ff9eb0c23626510736230af91691c95a9b Mon Sep 17 00:00:00 2001 From: dannylamb Date: Fri, 15 Nov 2019 17:58:17 +0000 Subject: [PATCH 3/5] Manage Collections Page --- islandora.links.action.yml | 26 +- islandora.routing.yml | 45 +- .../config/install/views.view.collections.yml | 481 ++++++++++++++++++ .../islandora_core_feature.features.yml | 1 + .../islandora_core_feature.info.yml | 1 + src/Controller/AddCollectionController.php | 47 ++ src/Controller/ManageMediaController.php | 9 +- src/Controller/ManageMembersController.php | 26 +- src/Form/AddChildrenForm.php | 21 + src/Form/AddMediaForm.php | 55 ++ src/IslandoraUtils.php | 33 ++ tests/src/Functional/AddChildTest.php | 60 +++ tests/src/Functional/AddCollectionTest.php | 62 +++ tests/src/Functional/AddMediaTest.php | 46 ++ .../Functional/GenerateDerivativeTestBase.php | 2 +- .../IslandoraFunctionalTestBase.php | 4 +- tests/src/Functional/LinkHeaderTest.php | 4 +- tests/src/Functional/NodeHasTermTest.php | 6 +- 18 files changed, 903 insertions(+), 26 deletions(-) create mode 100644 modules/islandora_core_feature/config/install/views.view.collections.yml create mode 100644 src/Controller/AddCollectionController.php create mode 100644 tests/src/Functional/AddChildTest.php create mode 100644 tests/src/Functional/AddCollectionTest.php create mode 100644 tests/src/Functional/AddMediaTest.php diff --git a/islandora.links.action.yml b/islandora.links.action.yml index 8a1f67687..ffd1dd71c 100644 --- a/islandora.links.action.yml +++ b/islandora.links.action.yml @@ -1,12 +1,24 @@ +islandora.upload_media: + route_name: islandora.upload_media + title: Upload Media + appears_on: + - view.media_of.page_1 + islandora.add_media_to_node: - route_name: islandora.add_media_form + route_name: islandora.add_media_to_node_page title: Add Media appears_on: - view.media_of.page_1 -islandora.add_children_to_node: - route_name: islandora.add_children_form - title: Add Children +islandora.upload_children: + route_name: islandora.upload_children + title: Upload Children + appears_on: + - view.manage_members.page_1 + +islandora.add_member_to_node: + route_name: islandora.add_member_to_node_page + title: Add Child appears_on: - view.manage_members.page_1 @@ -15,3 +27,9 @@ islandora.reorder_children: title: Reorder Children appears_on: - view.manage_members.page_1 + +islandora.add_collection: + route_name: islandora.add_collection + title: Add Collection + appears_on: + - view.collections.page_1 diff --git a/islandora.routing.yml b/islandora.routing.yml index 814bacab3..464dd9a09 100644 --- a/islandora.routing.yml +++ b/islandora.routing.yml @@ -16,24 +16,58 @@ system.islandora_settings: requirements: _permission: 'administer site configuration' -islandora.add_children_form: +islandora.add_member_to_node_page: path: '/node/{node}/members/add' + defaults: + _controller: '\Drupal\islandora\Controller\ManageMembersController::addToNodePage' + _title_callback: '\Drupal\islandora\Controller\ManageMembersController::addTitle' + entity_type_id: node + options: + _admin_route: 'true' + requirements: + _entity_create_any_access: 'node' + +islandora.upload_children: + path: '/node/{node}/members/upload' defaults: _form: '\Drupal\islandora\Form\AddChildrenForm' - _title: 'Add children' + _title: 'Upload Children' options: _admin_route: 'TRUE' requirements: - _permssion: 'create node,create media' + _access: 'TRUE' + #_permssion: 'create node,create media' -islandora.add_media_form: +islandora.add_media_to_node_page: path: '/node/{node}/media/add' + defaults: + _controller: '\Drupal\islandora\Controller\ManageMediaController::addToNodePage' + _title_callback: '\Drupal\islandora\Controller\ManageMediaController::addTitle' + entity_type_id: media + options: + _admin_route: 'true' + requirements: + _entity_create_any_access: 'media' + +islandora.upload_media: + path: '/node/{node}/media/upload' + defaults: _form: '\Drupal\islandora\Form\AddMediaForm' _title: 'Add media' options: _admin_route: 'TRUE' requirements: - _permssion: 'create media' + _custom_access: '\Drupal\islandora\Form\AddMediaForm::access' + +islandora.add_collection: + path: '/collection/add' + defaults: + _controller: '\Drupal\islandora\Controller\AddCollectionController::addCollectionPage' + _title: 'Add Collection' + options: + _admin_route: 'true' + requirements: + _custom_access: '\Drupal\islandora\Controller\AddCollectionController::access' islandora.media_source_update: path: '/media/{media}/source' @@ -49,6 +83,7 @@ islandora.media_source_put_to_node: path: '/node/{node}/media/{media_type}/{taxonomy_term}' defaults: _controller: '\Drupal\islandora\Controller\MediaSourceController::putToNode' + methods: [PUT] requirements: _custom_access: '\Drupal\islandora\Controller\MediaSourceController::putToNodeAccess' diff --git a/modules/islandora_core_feature/config/install/views.view.collections.yml b/modules/islandora_core_feature/config/install/views.view.collections.yml new file mode 100644 index 000000000..f682cf2e4 --- /dev/null +++ b/modules/islandora_core_feature/config/install/views.view.collections.yml @@ -0,0 +1,481 @@ +langcode: en +status: true +dependencies: + config: + - core.entity_view_mode.node.teaser + module: + - media + - node + - taxonomy + - user +id: collections +label: Collections +module: views +description: 'All collections in the repository' +tag: '' +base_table: node_field_data +base_field: nid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'access content' + cache: + type: tag + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: mini + options: + items_per_page: 10 + offset: 0 + id: 0 + total_pages: null + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + tags: + previous: ‹‹ + next: ›› + style: + type: table + options: + grouping: { } + row_class: '' + default_row_class: true + override: true + sticky: false + caption: '' + summary: '' + description: '' + columns: + title: title + info: + title: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + default: '-1' + empty_table: false + row: + type: 'entity:node' + options: + view_mode: teaser + fields: + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + label: Title + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: false + ellipsis: false + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: node + entity_field: title + plugin_id: field + field_member_of: + id: field_member_of + table: node__field_member_of + field: field_member_of + relationship: reverse__node__field_member_of + group_type: count + admin_label: '' + label: Children + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + set_precision: false + precision: 0 + decimal: . + separator: ', ' + format_plural: 0 + format_plural_string: !!binary MQNAY291bnQ= + prefix: '' + suffix: '' + click_sort_column: target_id + type: entity_reference_label + settings: { } + group_column: entity_id + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + field_api_classes: false + plugin_id: field + field_file_size: + id: field_file_size + table: media__field_file_size + field: field_file_size + relationship: reverse__media__field_media_of + group_type: sum + admin_label: '' + label: 'Disk Usage' + exclude: false + alter: + alter_text: true + text: "{% if field_file_size > (1024 ** 5) %}\r\n {% set size = field_file_size / (1024 ** 5) %}\r\n {% set abbreviation = 'PB' %}\r\n{% elseif field_file_size > (1024 ** 4) %}\r\n {% set size = field_file_size / (1024 ** 4) %}\r\n {% set abbreviation = 'TB' %}\r\n{% elseif field_file_size > (1024 ** 3) %}\r\n {% set size = field_file_size / (1024 ** 3) %}\r\n {% set abbreviation = 'GB' %}\r\n{% elseif field_file_size > (1024 ** 2) %}\r\n {% set size = field_file_size / (1024 ** 2) %}\r\n {% set abbreviation = 'MB' %}\r\n{% elseif field_file_size > 1024 %}\r\n {% set size = field_file_size / 1024 %}\r\n {% set abbreviation = 'KB' %}\r\n{% else %}\r\n {% set size = field_file_size %}\r\n {% set abbreviation = 'B' %}\r\n{% endif %}\r\n\r\n{{ size|round(2, 'common') }} {{ abbreviation }}" + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + set_precision: false + precision: 0 + decimal: . + separator: '' + format_plural: 0 + format_plural_string: !!binary MQNAY291bnQ= + prefix: '' + suffix: '' + click_sort_column: value + type: number_integer + settings: { } + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + field_api_classes: false + plugin_id: field + operations: + id: operations + table: node + field: operations + relationship: none + group_type: group + admin_label: '' + label: 'Operations links' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + destination: true + entity_type: node + plugin_id: entity_operations + filters: + status: + value: '1' + table: node_field_data + field: status + plugin_id: boolean + entity_type: node + entity_field: status + id: status + expose: + operator: '' + group: 1 + field_external_uri_uri: + id: field_external_uri_uri + table: taxonomy_term__field_external_uri + field: field_external_uri_uri + relationship: field_model + group_type: group + admin_label: '' + operator: '=' + value: 'http://purl.org/dc/dcmitype/Collection' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + placeholder: '' + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: string + sorts: { } + title: Collections + header: { } + footer: { } + empty: { } + relationships: + field_model: + id: field_model + table: node__field_model + field: field_model + relationship: none + group_type: group + admin_label: 'field_model: Taxonomy term' + required: true + plugin_id: standard + reverse__node__field_member_of: + id: reverse__node__field_member_of + table: node_field_data + field: reverse__node__field_member_of + relationship: none + group_type: group + admin_label: field_member_of + required: false + entity_type: node + plugin_id: entity_reverse + reverse__media__field_media_of: + id: reverse__media__field_media_of + table: node_field_data + field: reverse__media__field_media_of + relationship: none + group_type: group + admin_label: field_media_of + required: false + entity_type: node + plugin_id: entity_reverse + arguments: { } + display_extenders: { } + filter_groups: + operator: AND + groups: + 1: AND + group_by: true + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: 1 + display_options: + display_extenders: { } + path: admin/content/collections + menu: + type: tab + title: Collections + description: '' + expanded: false + parent: '' + weight: -100 + context: '0' + menu_name: admin + tab_options: + type: normal + title: Collections + description: '' + weight: 0 + cache_metadata: + max-age: -1 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url.query_args + - 'user.node_grants:view' + - user.permissions + tags: { } diff --git a/modules/islandora_core_feature/islandora_core_feature.features.yml b/modules/islandora_core_feature/islandora_core_feature.features.yml index 5af003a72..7afcb1b19 100755 --- a/modules/islandora_core_feature/islandora_core_feature.features.yml +++ b/modules/islandora_core_feature/islandora_core_feature.features.yml @@ -14,3 +14,4 @@ required: - field.storage.node.field_model - field.storage.node.field_weight - field.storage.taxonomy_term.field_external_uri + - views.view.collections diff --git a/modules/islandora_core_feature/islandora_core_feature.info.yml b/modules/islandora_core_feature/islandora_core_feature.info.yml index eda5da438..1e5f10b97 100755 --- a/modules/islandora_core_feature/islandora_core_feature.info.yml +++ b/modules/islandora_core_feature/islandora_core_feature.info.yml @@ -12,6 +12,7 @@ dependencies: - filehash - image - islandora + - islandora_defaults - jsonld - jwt - language diff --git a/src/Controller/AddCollectionController.php b/src/Controller/AddCollectionController.php new file mode 100644 index 000000000..97f03ad9e --- /dev/null +++ b/src/Controller/AddCollectionController.php @@ -0,0 +1,47 @@ +utils->getTermForUri('http://purl.org/dc/dcmitype/Collection'); + $field = IslandoraUtils::MODEL_FIELD; + + return $this->generateTypeList( + 'node', + 'node_type', + 'node.add', + 'node.type_add', + $field, + ['query' => ["edit[$field][widget]" => $term->id()]] + ); + } + + /** + * Check if the object being displayed "is Islandora". + * + * @param \Drupal\Core\Routing\RouteMatch $route_match + * The current routing match. + * + * @return \Drupal\Core\Access\AccessResultAllowed|\Drupal\Core\Access\AccessResultForbidden + * Whether we can or can't show the "thing". + */ + public function access(RouteMatch $route_match) { + if ($this->utils->canCreateIslandoraEntity('node', 'node_type')) { + return AccessResult::allowed(); + } + return AccessResult::forbidden(); + } + +} diff --git a/src/Controller/ManageMediaController.php b/src/Controller/ManageMediaController.php index 776a68086..56e0b5c50 100644 --- a/src/Controller/ManageMediaController.php +++ b/src/Controller/ManageMediaController.php @@ -2,6 +2,7 @@ namespace Drupal\islandora\Controller; +use Drupal\islandora\IslandoraUtils; use Drupal\Core\Access\AccessResult; use Drupal\Core\Routing\RouteMatch; use Drupal\node\Entity\Node; @@ -22,13 +23,15 @@ class ManageMediaController extends ManageMembersController { * Array of media types to add. */ public function addToNodePage(NodeInterface $node) { + $field = IslandoraUtils::MEDIA_OF_FIELD; + return $this->generateTypeList( 'media', 'media_type', 'entity.media.add_form', 'entity.media_type.add_form', - $node, - 'field_media_of' + $field, + ['query' => ["edit[$field][widget][0][target_id]" => $node->id()]] ); } @@ -47,7 +50,7 @@ public function access(RouteMatch $route_match) { if (!$node instanceof NodeInterface) { $node = Node::load($node); } - if ($node->hasField('field_model') && $node->hasField('field_member_of')) { + if ($this->utils->isIslandoraType($node->getEntityTypeId(), $node->bundle())) { return AccessResult::allowed(); } } diff --git a/src/Controller/ManageMembersController.php b/src/Controller/ManageMembersController.php index 7f54706ca..b73dc73f2 100644 --- a/src/Controller/ManageMembersController.php +++ b/src/Controller/ManageMembersController.php @@ -7,6 +7,7 @@ use Drupal\Core\Entity\Controller\EntityController; use Drupal\Core\Entity\EntityFieldManager; use Drupal\Core\Link; +use Drupal\islandora\IslandoraUtils; use Drupal\node\NodeInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -36,6 +37,13 @@ class ManageMembersController extends EntityController { */ protected $renderer; + /** + * Islandora Utils. + * + * @var \Drupal\islandora\IslandoraUtils + */ + protected $utils; + /** * Constructor. * @@ -45,15 +53,19 @@ class ManageMembersController extends EntityController { * The entity field manager. * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer. + * @param \Drupal\islandora\IslandoraUtils $utils + * Islandora utils. */ public function __construct( EntityTypeManagerInterface $entity_type_manager, EntityFieldManager $entity_field_manager, - RendererInterface $renderer + RendererInterface $renderer, + IslandoraUtils $utils ) { $this->entityTypeManager = $entity_type_manager; $this->entityFieldManager = $entity_field_manager; $this->renderer = $renderer; + $this->utils = $utils; } /** @@ -63,7 +75,8 @@ public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager'), $container->get('entity_field.manager'), - $container->get('renderer') + $container->get('renderer'), + $container->get('islandora.utils') ); } @@ -74,20 +87,21 @@ public static function create(ContainerInterface $container) { * Node you want to add a member to. */ public function addToNodePage(NodeInterface $node) { + $field = IslandoraUtils::MEMBER_OF_FIELD; return $this->generateTypeList( 'node', 'node_type', 'node.add', 'node.type_add', - $node, - 'field_member_of' + $field, + ['query' => ["edit[$field][widget][0][target_id]" => $node->id()]] ); } /** * Renders a list of content types to add as members. */ - protected function generateTypeList($entity_type, $bundle_type, $entity_add_form, $bundle_add_form, NodeInterface $node, $field) { + protected function generateTypeList($entity_type, $bundle_type, $entity_add_form, $bundle_add_form, $field, array $url_options) { $type_definition = $this->entityTypeManager->getDefinition($bundle_type); $build = [ @@ -115,7 +129,7 @@ protected function generateTypeList($entity_type, $bundle_type, $entity_add_form $bundle->label(), $entity_add_form, [$bundle_type => $bundle->id()], - ['query' => ["edit[$field][widget][0][target_id]" => $node->id()]] + $url_options ), ]; } diff --git a/src/Form/AddChildrenForm.php b/src/Form/AddChildrenForm.php index 14b787b32..82332ca88 100644 --- a/src/Form/AddChildrenForm.php +++ b/src/Form/AddChildrenForm.php @@ -4,6 +4,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; +use Drupal\Core\Routing\RouteMatch; use Drupal\islandora\IslandoraUtils; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\Exception\HttpException; @@ -176,4 +177,24 @@ public function buildNodeFinished($success, $results, $operations) { ); } + /** + * Check if the user can create any "Islandora" nodes and media. + * + * @param \Drupal\Core\Routing\RouteMatch $route_match + * The current routing match. + * + * @return \Drupal\Core\Access\AccessResultAllowed|\Drupal\Core\Access\AccessResultForbidden + * Whether we can or can't show the "thing". + */ + public function access(RouteMatch $route_match) { + $can_create_media = $this->utils->canCreateIslandoraEntity('media', 'media_type'); + $can_create_node = $this->utils->canCreateIslandoraEntity('node', 'node_type'); + + if ($can_create_media && $can_create_node) { + return AccessResult::allowed(); + } + + return AccessResult::forbidden(); + } + } diff --git a/src/Form/AddMediaForm.php b/src/Form/AddMediaForm.php index bb02b414c..9b70461ee 100644 --- a/src/Form/AddMediaForm.php +++ b/src/Form/AddMediaForm.php @@ -2,11 +2,13 @@ namespace Drupal\islandora\Form; +use Drupal\Core\Access\AccessResult; use Drupal\Core\Config\ImmutableConfig; use Drupal\Core\Database\Connection; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\islandora\IslandoraUtils; use Drupal\islandora\MediaSource\MediaSourceService; @@ -14,6 +16,7 @@ use Symfony\Component\HttpKernel\Exception\HttpException; use Drupal\Core\Utility\Token; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\Core\Routing\RouteMatch; /** * Form that lets users upload one or more files as children to a resource node. @@ -27,6 +30,13 @@ class AddMediaForm extends FormBase { */ protected $entityTypeManager; + /** + * Entity field manager. + * + * @var \Drupal\Core\Entity\EntityFieldManagerInterface + */ + protected $entityFieldManager; + /** * Media source service. * @@ -88,6 +98,7 @@ class AddMediaForm extends FormBase { */ public function __construct( EntityTypeManagerInterface $entity_type_manager, + EntityFieldManagerInterface $entity_field_manager, IslandoraUtils $utils, MediaSourceService $media_source, ImmutableConfig $config, @@ -97,6 +108,7 @@ public function __construct( Connection $database ) { $this->entityTypeManager = $entity_type_manager; + $this->entityFieldManager = $entity_field_manager; $this->utils = $utils; $this->mediaSource = $media_source; $this->config = $config; @@ -112,6 +124,7 @@ public function __construct( public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager'), + $container->get('entity_field.manager'), $container->get('islandora.utils'), $container->get('islandora.media_source_service'), $container->get('config.factory')->get('islandora.settings'), @@ -243,4 +256,46 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } } + /** + * Check if the user can create any "Islandora" media. + * + * @param \Drupal\Core\Routing\RouteMatch $route_match + * The current routing match. + * + * @return \Drupal\Core\Access\AccessResultAllowed|\Drupal\Core\Access\AccessResultForbidden + * Whether we can or can't show the "thing". + */ + public function access(RouteMatch $route_match) { + if ($this->utils->canCreateIslandoraEntity('media', 'media_type')) { + return AccessResult::allowed(); + } + + return AccessResult::forbidden(); + } + + /** + * Utility function to check if user can create 'Islandora' entity types. + */ + protected function canCreateIslandoraEntity($entity_type, $bundle_type) { + $bundles = $this->entityTypeManager->getStorage($bundle_type)->loadMultiple(); + $access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type); + + $allowed = []; + foreach (array_keys($bundles) as $bundle) { + // Skip bundles that aren't 'Islandora' types. + if (!$this->utils->isIslandoraType($entity_type, $bundle)) { + continue; + } + + $access = $access_control_handler->createAccess($bundle, NULL, [], TRUE); + if (!$access->isAllowed()) { + continue; + } + + return TRUE; + } + + return FALSE; + } + } diff --git a/src/IslandoraUtils.php b/src/IslandoraUtils.php index 3ebf9aa8a..e32a5d03b 100644 --- a/src/IslandoraUtils.php +++ b/src/IslandoraUtils.php @@ -597,4 +597,37 @@ public function isIslandoraType($entity_type, $bundle) { } } + /** + * Util function for access handlers . + * + * @param string $entity_type + * Entity type such as 'node', 'media', 'taxonomy_term', etc.. + * @param string $bundle_type + * Bundle type such as 'node_type', 'media_type', 'vocabulary', etc... + * + * @return bool + * If user can create _at least one_ of the 'Islandora' types requested. + */ + public function canCreateIslandoraEntity($entity_type, $bundle_type) { + $bundles = $this->entityTypeManager->getStorage($bundle_type)->loadMultiple(); + $access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type); + + $allowed = []; + foreach (array_keys($bundles) as $bundle) { + // Skip bundles that aren't 'Islandora' types. + if (!$this->isIslandoraType($entity_type, $bundle)) { + continue; + } + + $access = $access_control_handler->createAccess($bundle, NULL, [], TRUE); + if (!$access->isAllowed()) { + continue; + } + + return TRUE; + } + + return FALSE; + } + } diff --git a/tests/src/Functional/AddChildTest.php b/tests/src/Functional/AddChildTest.php new file mode 100644 index 000000000..67bc62335 --- /dev/null +++ b/tests/src/Functional/AddChildTest.php @@ -0,0 +1,60 @@ +parent = + $this->collectionTerm = $this->container->get('entity_type.manager')->getStorage('taxonomy_term')->create([ + 'name' => 'Collection', + 'vid' => $this->testVocabulary->id(), + 'field_external_uri' => [['uri' => "http://purl.org/dc/dcmitype/Collection"]], + ]); + $this->collectionTerm->save(); + } + + /** + * @covers \Drupal\islandora\Controller\AddCollectionController::addToNodePage + * @covers \Drupal\islandora\Controller\AddCollectionController::access + * @covers \Drupal\islandora\IslandoraUtils::isIslandoraType + */ + public function testAddChild() { + $account = $this->drupalCreateUser([ + 'bypass node access', + ]); + $this->drupalLogin($account); + + $parent = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'Parent', + ]); + $parent->save(); + + // Visit the add member page. + $this->drupalGet("/node/{$parent->id()}/members/add"); + + // Assert that test_type is on the list. + $this->assertSession()->pageTextContains($this->testType->label()); + $this->clickLink($this->testType->label()); + $url = $this->getUrl(); + + // Assert that the link creates the correct prepopulate query param. + $substring = 'node/add/test_type?edit%5Bfield_member_of%5D%5Bwidget%5D%5B0%5D%5Btarget_id%5D=1'; + $this->assertTrue( + strpos($url, $substring) !== FALSE, + "Malformed URL, could not find $substring in $url." + ); + } + +} diff --git a/tests/src/Functional/AddCollectionTest.php b/tests/src/Functional/AddCollectionTest.php new file mode 100644 index 000000000..f1a87ab7d --- /dev/null +++ b/tests/src/Functional/AddCollectionTest.php @@ -0,0 +1,62 @@ +collectionTerm = $this->container->get('entity_type.manager')->getStorage('taxonomy_term')->create([ + 'name' => 'Collection', + 'vid' => $this->testVocabulary->id(), + 'field_external_uri' => [['uri' => "http://purl.org/dc/dcmitype/Collection"]], + ]); + $this->collectionTerm->save(); + } + + /** + * @covers \Drupal\islandora\Controller\AddCollectionController::addCollectionPage + * @covers \Drupal\islandora\Controller\AddCollectionController::access + * @covers \Drupal\islandora\IslandoraUtils::isIslandoraType + */ + public function testAddCollection() { + $account = $this->drupalCreateUser([ + 'bypass node access', + ]); + $this->drupalLogin($account); + + // Visit the add collection page. + $this->drupalGet('/collection/add'); + + // Assert the test type is in the list of available types. + $this->assertSession()->pageTextContains($this->testType->label()); + + // Click the test type and make sure you get sent to the right form. + $this->clickLink($this->testType->label()); + $url = $this->getUrl(); + + // Assert that the link creates the correct prepopulate query param. + $substring = 'node/add/test_type?edit%5Bfield_model%5D%5Bwidget%5D=1'; + $this->assertTrue( + strpos($url, 'node/add/test_type?edit%5Bfield_model%5D%5Bwidget%5D=1') !== FALSE, + "Malformed URL, could not find $substring in $url." + ); + } + +} diff --git a/tests/src/Functional/AddMediaTest.php b/tests/src/Functional/AddMediaTest.php new file mode 100644 index 000000000..f91cef825 --- /dev/null +++ b/tests/src/Functional/AddMediaTest.php @@ -0,0 +1,46 @@ +drupalCreateUser([ + 'bypass node access', + 'create media', + ]); + $this->drupalLogin($account); + + $parent = $this->container->get('entity_type.manager')->getStorage('node')->create([ + 'type' => 'test_type', + 'title' => 'Parent', + ]); + $parent->save(); + + // Visit the add media page. + $this->drupalGet("/node/{$parent->id()}/media/add"); + + // Assert that test_meida_type is on the list. + $this->assertSession()->pageTextContains($this->testMediaType->label()); + $this->clickLink($this->testMediaType->label()); + $url = $this->getUrl(); + + // Assert that the link creates the correct prepopulate query param. + $substring = 'media/add/test_media_type?edit%5Bfield_media_of%5D%5Bwidget%5D%5B0%5D%5Btarget_id%5D=1'; + $this->assertTrue( + strpos($url, $substring) !== FALSE, + "Malformed URL, could not find $substring in $url." + ); + } + +} diff --git a/tests/src/Functional/GenerateDerivativeTestBase.php b/tests/src/Functional/GenerateDerivativeTestBase.php index c74ff2555..0f67d5919 100644 --- a/tests/src/Functional/GenerateDerivativeTestBase.php +++ b/tests/src/Functional/GenerateDerivativeTestBase.php @@ -48,7 +48,7 @@ public function setUp() { $this->node = $this->container->get('entity_type.manager')->getStorage('node')->create([ 'type' => $this->testType->id(), 'title' => 'Test Node', - 'field_tags' => [$this->imageTerm->id()], + 'field_model' => [$this->imageTerm->id()], ]); $this->node->save(); } diff --git a/tests/src/Functional/IslandoraFunctionalTestBase.php b/tests/src/Functional/IslandoraFunctionalTestBase.php index 9a50fb050..838c1ee4e 100644 --- a/tests/src/Functional/IslandoraFunctionalTestBase.php +++ b/tests/src/Functional/IslandoraFunctionalTestBase.php @@ -176,13 +176,13 @@ public function setUp() { ]); $this->testType->save(); $this->createEntityReferenceField('node', 'test_type', 'field_member_of', 'Member Of', 'node', 'default', [], 2); - $this->createEntityReferenceField('node', 'test_type', 'field_tags', 'Tags', 'taxonomy_term', 'default', [], 2); + $this->createEntityReferenceField('node', 'test_type', 'field_model', 'Model', 'taxonomy_term', 'default', [], 2); // Create a media type. $this->testMediaType = $this->createMediaType('file', ['id' => 'test_media_type']); $this->testMediaType->save(); $this->createEntityReferenceField('media', $this->testMediaType->id(), 'field_media_of', 'Media Of', 'node', 'default', [], 2); - $this->createEntityReferenceField('media', $this->testMediaType->id(), 'field_tags', 'Tags', 'taxonomy_term', 'default', [], 2); + $this->createEntityReferenceField('media', $this->testMediaType->id(), 'field_media_use', 'Tags', 'taxonomy_term', 'default', [], 2); // Copy over the rest of the config from yml files. $source = new FileStorage(__DIR__ . '/../../fixtures/config'); diff --git a/tests/src/Functional/LinkHeaderTest.php b/tests/src/Functional/LinkHeaderTest.php index 472986c20..57122aaa8 100644 --- a/tests/src/Functional/LinkHeaderTest.php +++ b/tests/src/Functional/LinkHeaderTest.php @@ -61,13 +61,13 @@ public function setUp() { 'type' => $this->testType->id(), 'title' => 'Referencer', 'field_member_of' => [$this->referenced->id()], - 'field_tags' => [$this->imageTerm->id()], + 'field_model' => [$this->imageTerm->id()], ]); $this->referencer->save(); list($this->file, $this->media) = $this->makeMediaAndFile($account); $this->media->set('field_media_of', $this->referencer); - $this->media->set('field_tags', $this->preservationMasterTerm); + $this->media->set('field_media_use', $this->preservationMasterTerm); $this->media->save(); } diff --git a/tests/src/Functional/NodeHasTermTest.php b/tests/src/Functional/NodeHasTermTest.php index a27cf4749..1e560109e 100644 --- a/tests/src/Functional/NodeHasTermTest.php +++ b/tests/src/Functional/NodeHasTermTest.php @@ -33,7 +33,7 @@ public function testNodeHasTerm() { $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ 'type' => 'test_type', 'title' => 'Test Node', - 'field_tags' => [$this->imageTerm->id()], + 'field_model' => [$this->imageTerm->id()], ]); // Create and execute the condition. @@ -60,7 +60,7 @@ public function testNodeHasTerm() { $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ 'type' => 'test_type', 'title' => 'Test Node', - 'field_tags' => [$this->preservationMasterTerm->id()], + 'field_model' => [$this->preservationMasterTerm->id()], ]); $condition->setContextValue('node', $node); @@ -81,7 +81,7 @@ public function testNodeHasTerm() { $node = $this->container->get('entity_type.manager')->getStorage('node')->create([ 'type' => 'test_type', 'title' => 'Test Node', - 'field_tags' => [$this->imageTerm->id(), $this->preservationMasterTerm->id()], + 'field_model' => [$this->imageTerm->id(), $this->preservationMasterTerm->id()], ]); $condition->setContextValue('node', $node); $this->assertTrue($condition->execute(), "Condition should pass if node has both terms"); From 21b916b427354ff5f5ea63af0aa6f81f33177f0c Mon Sep 17 00:00:00 2001 From: dannylamb Date: Fri, 15 Nov 2019 18:11:14 +0000 Subject: [PATCH 4/5] Removing dependency loop in view --- config/schema/islandora.schema.yml | 21 ------------- islandora.links.action.yml | 18 ++--------- islandora.routing.yml | 22 ------------- .../config/install/views.view.collections.yml | 31 ++++++++++++++++--- 4 files changed, 30 insertions(+), 62 deletions(-) diff --git a/config/schema/islandora.schema.yml b/config/schema/islandora.schema.yml index b4983fa20..8fd719ced 100644 --- a/config/schema/islandora.schema.yml +++ b/config/schema/islandora.schema.yml @@ -14,18 +14,6 @@ islandora.settings: jwt_expiry: type: string label: 'How long JWTs should last before expiring.' - upload_form_bundle: - type: string - label: 'Upload Form Content Type' - upload_form_location: - type: string - label: 'Upload Form Location' - upload_form_term: - type: string - label: 'Upload Form Media Use Term' - upload_form_allowed_extensions: - type: string - label: 'Upload Form Allowed Extensions' gemini_url: type: uri label: 'Url to Gemini microservice' @@ -90,9 +78,6 @@ condition.plugin.node_has_term: uri: type: text label: 'Taxonomy Term URI' - logic: - type: string - label: 'Logic (AND or OR)' condition.plugin.node_has_parent: type: condition.plugin @@ -110,9 +95,6 @@ condition.plugin.media_has_term: uri: type: text label: 'Taxonomy Term URI' - logic: - type: string - label: 'Logic (AND or OR)' condition.plugin.parent_node_has_term: type: condition.plugin @@ -120,9 +102,6 @@ condition.plugin.parent_node_has_term: uri: type: text label: 'Taxonomy Term URI' - logic: - type: text - label: 'Logic (AND or OR)' condition.plugin.file_uses_filesystem: type: condition.plugin diff --git a/islandora.links.action.yml b/islandora.links.action.yml index ffd1dd71c..4b0a01bec 100644 --- a/islandora.links.action.yml +++ b/islandora.links.action.yml @@ -1,24 +1,12 @@ -islandora.upload_media: - route_name: islandora.upload_media - title: Upload Media - appears_on: - - view.media_of.page_1 - islandora.add_media_to_node: route_name: islandora.add_media_to_node_page - title: Add Media + title: Add media appears_on: - view.media_of.page_1 -islandora.upload_children: - route_name: islandora.upload_children - title: Upload Children - appears_on: - - view.manage_members.page_1 - islandora.add_member_to_node: route_name: islandora.add_member_to_node_page - title: Add Child + title: Add child appears_on: - view.manage_members.page_1 @@ -30,6 +18,6 @@ islandora.reorder_children: islandora.add_collection: route_name: islandora.add_collection - title: Add Collection + title: Add collection appears_on: - view.collections.page_1 diff --git a/islandora.routing.yml b/islandora.routing.yml index 464dd9a09..72529c775 100644 --- a/islandora.routing.yml +++ b/islandora.routing.yml @@ -27,17 +27,6 @@ islandora.add_member_to_node_page: requirements: _entity_create_any_access: 'node' -islandora.upload_children: - path: '/node/{node}/members/upload' - defaults: - _form: '\Drupal\islandora\Form\AddChildrenForm' - _title: 'Upload Children' - options: - _admin_route: 'TRUE' - requirements: - _access: 'TRUE' - #_permssion: 'create node,create media' - islandora.add_media_to_node_page: path: '/node/{node}/media/add' defaults: @@ -49,16 +38,6 @@ islandora.add_media_to_node_page: requirements: _entity_create_any_access: 'media' -islandora.upload_media: - path: '/node/{node}/media/upload' - defaults: - _form: '\Drupal\islandora\Form\AddMediaForm' - _title: 'Add media' - options: - _admin_route: 'TRUE' - requirements: - _custom_access: '\Drupal\islandora\Form\AddMediaForm::access' - islandora.add_collection: path: '/collection/add' defaults: @@ -83,7 +62,6 @@ islandora.media_source_put_to_node: path: '/node/{node}/media/{media_type}/{taxonomy_term}' defaults: _controller: '\Drupal\islandora\Controller\MediaSourceController::putToNode' - methods: [PUT] requirements: _custom_access: '\Drupal\islandora\Controller\MediaSourceController::putToNodeAccess' diff --git a/modules/islandora_core_feature/config/install/views.view.collections.yml b/modules/islandora_core_feature/config/install/views.view.collections.yml index f682cf2e4..ab6c47ab9 100644 --- a/modules/islandora_core_feature/config/install/views.view.collections.yml +++ b/modules/islandora_core_feature/config/install/views.view.collections.yml @@ -1,8 +1,6 @@ langcode: en status: true dependencies: - config: - - core.entity_view_mode.node.teaser module: - media - node @@ -79,6 +77,9 @@ display: description: '' columns: title: title + field_member_of: field_member_of + field_file_size: field_file_size + operations: operations info: title: sortable: false @@ -87,12 +88,34 @@ display: separator: '' empty_column: false responsive: '' + field_member_of: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + field_file_size: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + operations: + align: '' + separator: '' + empty_column: false + responsive: '' default: '-1' empty_table: false row: - type: 'entity:node' + type: fields options: - view_mode: teaser + default_field_elements: true + inline: { } + separator: '' + hide_empty: false fields: title: id: title From 3cc49ee38411c8c0a3c74a9b01b90956a7880752 Mon Sep 17 00:00:00 2001 From: dannylamb Date: Fri, 15 Nov 2019 18:17:38 +0000 Subject: [PATCH 5/5] Reverting the upload form stuff --- .../islandora_core_feature.info.yml | 1 - src/Form/AddChildrenForm.php | 200 ------------ src/Form/AddMediaForm.php | 301 ------------------ src/Form/IslandoraSettingsForm.php | 91 +----- src/Plugin/Condition/NodeHasTerm.php | 42 +-- 5 files changed, 8 insertions(+), 627 deletions(-) delete mode 100644 src/Form/AddChildrenForm.php delete mode 100644 src/Form/AddMediaForm.php diff --git a/modules/islandora_core_feature/islandora_core_feature.info.yml b/modules/islandora_core_feature/islandora_core_feature.info.yml index 1e5f10b97..eda5da438 100755 --- a/modules/islandora_core_feature/islandora_core_feature.info.yml +++ b/modules/islandora_core_feature/islandora_core_feature.info.yml @@ -12,7 +12,6 @@ dependencies: - filehash - image - islandora - - islandora_defaults - jsonld - jwt - language diff --git a/src/Form/AddChildrenForm.php b/src/Form/AddChildrenForm.php deleted file mode 100644 index 82332ca88..000000000 --- a/src/Form/AddChildrenForm.php +++ /dev/null @@ -1,200 +0,0 @@ -config->get(IslandoraSettingsForm::UPLOAD_FORM_LOCATION); - $upload_location = $this->token->replace($upload_pattern); - - $valid_extensions = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_ALLOWED_MIMETYPES); - - $this->parentId = $this->routeMatch->getParameter('node'); - $parent = $this->entityTypeManager->getStorage('node')->load($this->parentId); - - $form['upload'] = [ - '#type' => 'managed_file', - '#title' => $this->t('Files'), - '#description' => $this->t("Upload one or more files to add children to @title", ['@title' => $parent->getTitle()]), - '#upload_location' => $upload_location, - '#upload_validators' => [ - 'file_validate_extensions' => [$valid_extensions], - ], - '#multiple' => TRUE, - ]; - $form['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Submit'), - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $parent_id = $this->routeMatch->getParameter('node'); - $parent = $this->entityTypeManager->getStorage('node')->load($parent_id); - - $fids = $form_state->getValue('upload'); - - $operations = []; - foreach ($fids as $fid) { - $operations[] = [[$this, 'buildNodeForFile'], [$fid, $parent_id]]; - } - - $batch = [ - 'title' => $this->t("Uploading Children for @title", ['@title' => $parent->getTitle()]), - 'operations' => $operations, - 'progress_message' => t('Processed @current out of @total. Estimated time: @estimate.'), - 'error_message' => t('The process has encountered an error.'), - 'finished' => [$this, 'buildNodeFinished'], - ]; - - batch_set($batch); - } - - /** - * Wires up a file/media/node combo for a file upload. - * - * @param int $fid - * Uploaded file id. - * @param int $parent_id - * Id of the parent node. - * @param array $context - * Batch context. - * - * @throws \Symfony\Component\HttpKernel\Exception\HttpException - */ - public function buildNodeForFile($fid, $parent_id, array &$context) { - // Since we make 3 different entities, do this in a transaction. - $transaction = $this->database->startTransaction(); - - try { - $file = $this->entityTypeManager->getStorage('file')->load($fid); - $file->setPermanent(); - $file->save(); - - $parent = $this->entityTypeManager->getStorage('node')->load($parent_id); - - $mime = $file->getMimetype(); - $exploded_mime = explode('/', $mime); - if ($exploded_mime[0] == 'image') { - if (in_array($exploded_mime[1], ['tiff', 'jp2'])) { - $media_type = 'file'; - } - else { - $media_type = 'image'; - } - $model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_c513'); - } - elseif ($exploded_mime[0] == 'audio') { - $media_type = 'audio'; - $model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_18cc'); - } - elseif ($exploded_mime[0] == 'video') { - $media_type = 'video'; - $model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_12ce'); - } - else { - $media_type = 'file'; - if ($mime == 'application/pdf') { - $model = $this->utils->getTermForUri('https://schema.org/DigitalDocument'); - } - else { - $model = $this->utils->getTermForUri('http://purl.org/coar/resource_type/c_1843'); - } - } - $source_field = $this->mediaSource->getSourceFieldName($media_type); - - $node = $this->entityTypeManager->getStorage('node')->create([ - 'type' => $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_BUNDLE), - 'title' => $file->getFileName(), - IslandoraUtils::MODEL_FIELD => $model, - IslandoraUtils::MEMBER_OF_FIELD => $parent, - 'uid' => $this->account->id(), - 'status' => 1, - ]); - $node->save(); - - $uri = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_TERM); - $term = $this->utils->getTermForUri($uri); - $media = $this->entityTypeManager->getStorage('media')->create([ - 'bundle' => $media_type, - $source_field => $fid, - 'name' => $file->getFileName(), - IslandoraUtils::MEDIA_USAGE_FIELD => $term, - IslandoraUtils::MEDIA_OF_FIELD => $node, - ]); - $media->save(); - } - catch (HttpException $e) { - $transaction->rollBack(); - throw $e; - } - catch (\Exception $e) { - $transaction->rollBack(); - throw new HttpException(500, $e->getMessage()); - } - } - - /** - * Batch finished callback. - * - * $success bool - * Success status - * $results mixed - * The 'results' from the batch context. - * $operations array - * Remaining operations. - */ - public function buildNodeFinished($success, $results, $operations) { - return new RedirectResponse( - Url::fromRoute('view.manage_members.page_1', ['node' => $this->parentId])->toString() - ); - } - - /** - * Check if the user can create any "Islandora" nodes and media. - * - * @param \Drupal\Core\Routing\RouteMatch $route_match - * The current routing match. - * - * @return \Drupal\Core\Access\AccessResultAllowed|\Drupal\Core\Access\AccessResultForbidden - * Whether we can or can't show the "thing". - */ - public function access(RouteMatch $route_match) { - $can_create_media = $this->utils->canCreateIslandoraEntity('media', 'media_type'); - $can_create_node = $this->utils->canCreateIslandoraEntity('node', 'node_type'); - - if ($can_create_media && $can_create_node) { - return AccessResult::allowed(); - } - - return AccessResult::forbidden(); - } - -} diff --git a/src/Form/AddMediaForm.php b/src/Form/AddMediaForm.php deleted file mode 100644 index 9b70461ee..000000000 --- a/src/Form/AddMediaForm.php +++ /dev/null @@ -1,301 +0,0 @@ -entityTypeManager = $entity_type_manager; - $this->entityFieldManager = $entity_field_manager; - $this->utils = $utils; - $this->mediaSource = $media_source; - $this->config = $config; - $this->token = $token; - $this->account = $account; - $this->routeMatch = $route_match; - $this->database = $database; - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('entity_type.manager'), - $container->get('entity_field.manager'), - $container->get('islandora.utils'), - $container->get('islandora.media_source_service'), - $container->get('config.factory')->get('islandora.settings'), - $container->get('token'), - $container->get('current_user'), - $container->get('current_route_match'), - $container->get('database') - ); - } - - /** - * {@inheritdoc} - */ - public function getFormId() { - return 'add_media_form'; - } - - /** - * {@inheritdoc} - */ - public function buildForm(array $form, FormStateInterface $form_state) { - $upload_pattern = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_LOCATION); - $upload_location = $this->token->replace($upload_pattern); - - $valid_extensions = $this->config->get(IslandoraSettingsForm::UPLOAD_FORM_ALLOWED_MIMETYPES); - - $this->parentId = $this->routeMatch->getParameter('node'); - $parent = $this->entityTypeManager->getStorage('node')->load($this->parentId); - - $form['upload'] = [ - '#type' => 'managed_file', - '#title' => $this->t('File'), - '#description' => $this->t("Upload a file for @title", ['@title' => $parent->getTitle()]), - '#upload_location' => $upload_location, - '#upload_validators' => [ - 'file_validate_extensions' => [$valid_extensions], - ], - '#required' => TRUE, - ]; - - $options = []; - $terms = $this->entityTypeManager->getStorage('taxonomy_term')->loadTree('islandora_media_use', 0, NULL, TRUE); - foreach ($terms as $term) { - $options[$this->utils->getUriForTerm($term)] = $term->getName(); - }; - $form['use'] = [ - '#type' => 'checkboxes', - '#title' => $this->t('Usage'), - '#description' => $this->t("Defined by Portland Common Data Model: Use Extension https://pcdm.org/2015/05/12/use. ''Original File'' will trigger creation of derivatives."), - '#options' => $options, - '#required' => TRUE, - ]; - - $form['submit'] = [ - '#type' => 'submit', - '#value' => $this->t('Submit'), - ]; - - return $form; - } - - /** - * {@inheritdoc} - */ - public function submitForm(array &$form, FormStateInterface $form_state) { - $parent_id = $this->routeMatch->getParameter('node'); - $parent = $this->entityTypeManager->getStorage('node')->load($parent_id); - - $fid = $form_state->getValue('upload')[0]; - $external_uris = $form_state->getValue('use'); - - // Since we make 2 different entities, do this in a transaction. - $transaction = $this->database->startTransaction(); - - try { - $file = $this->entityTypeManager->getStorage('file')->load($fid); - $file->setPermanent(); - $file->save(); - - $parent = $this->entityTypeManager->getStorage('node')->load($parent_id); - - $mime = $file->getMimetype(); - $exploded_mime = explode('/', $mime); - if ($exploded_mime[0] == 'image') { - if (in_array($exploded_mime[1], ['tiff', 'jp2'])) { - $media_type = 'file'; - } - else { - $media_type = 'image'; - } - } - elseif ($exploded_mime[0] == 'audio') { - $media_type = 'audio'; - } - elseif ($exploded_mime[0] == 'video') { - $media_type = 'video'; - } - else { - $media_type = 'file'; - } - $source_field = $this->mediaSource->getSourceFieldName($media_type); - - $terms = []; - foreach ($external_uris as $uri) { - $terms[] = $this->utils->getTermForUri($uri); - } - $media = $this->entityTypeManager->getStorage('media')->create([ - 'bundle' => $media_type, - 'uid' => $this->account->id(), - $source_field => $fid, - 'name' => $file->getFileName(), - IslandoraUtils::MEDIA_USAGE_FIELD => $terms, - IslandoraUtils::MEDIA_OF_FIELD => $parent, - ]); - $media->save(); - - $form_state->setRedirect( - 'view.media_of.page_1', - ['node' => $parent_id] - ); - } - catch (HttpException $e) { - $transaction->rollBack(); - throw $e; - } - catch (\Exception $e) { - $transaction->rollBack(); - throw new HttpException(500, $e->getMessage()); - } - } - - /** - * Check if the user can create any "Islandora" media. - * - * @param \Drupal\Core\Routing\RouteMatch $route_match - * The current routing match. - * - * @return \Drupal\Core\Access\AccessResultAllowed|\Drupal\Core\Access\AccessResultForbidden - * Whether we can or can't show the "thing". - */ - public function access(RouteMatch $route_match) { - if ($this->utils->canCreateIslandoraEntity('media', 'media_type')) { - return AccessResult::allowed(); - } - - return AccessResult::forbidden(); - } - - /** - * Utility function to check if user can create 'Islandora' entity types. - */ - protected function canCreateIslandoraEntity($entity_type, $bundle_type) { - $bundles = $this->entityTypeManager->getStorage($bundle_type)->loadMultiple(); - $access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type); - - $allowed = []; - foreach (array_keys($bundles) as $bundle) { - // Skip bundles that aren't 'Islandora' types. - if (!$this->utils->isIslandoraType($entity_type, $bundle)) { - continue; - } - - $access = $access_control_handler->createAccess($bundle, NULL, [], TRUE); - if (!$access->isAllowed()) { - continue; - } - - return TRUE; - } - - return FALSE; - } - -} diff --git a/src/Form/IslandoraSettingsForm.php b/src/Form/IslandoraSettingsForm.php index 43016d008..f71cb93c0 100644 --- a/src/Form/IslandoraSettingsForm.php +++ b/src/Form/IslandoraSettingsForm.php @@ -4,11 +4,9 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Entity\EntityTypeBundleInfo; -use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; -use Drupal\islandora\IslandoraUtils; use GuzzleHttp\Exception\ConnectException; use Islandora\Crayfish\Commons\Client\GeminiClient; use Stomp\Client; @@ -24,11 +22,6 @@ class IslandoraSettingsForm extends ConfigFormBase { const CONFIG_NAME = 'islandora.settings'; const BROKER_URL = 'broker_url'; const JWT_EXPIRY = 'jwt_expiry'; - const UPLOAD_FORM = 'upload_form'; - const UPLOAD_FORM_BUNDLE = 'upload_form_bundle'; - const UPLOAD_FORM_TERM = 'upload_form_term'; - const UPLOAD_FORM_LOCATION = 'upload_form_location'; - const UPLOAD_FORM_ALLOWED_MIMETYPES = 'upload_form_allowed_mimetypes'; const GEMINI_URL = 'gemini_url'; const GEMINI_PSEUDO = 'gemini_pseudo_bundles'; @@ -39,20 +32,6 @@ class IslandoraSettingsForm extends ConfigFormBase { */ private $entityTypeBundleInfo; - /** - * Islandora utils. - * - * @var \Drupal\islandora\IslandoraUtils - */ - private $utils; - - /** - * Term storage. - * - * @var \Drupal\Core\Entity\EntityStorageInterface - */ - private $termStorage; - /** * Constructs a \Drupal\system\ConfigFormBase object. * @@ -60,21 +39,10 @@ class IslandoraSettingsForm extends ConfigFormBase { * The factory for configuration objects. * @param \Drupal\Core\Entity\EntityTypeBundleInfo $entity_type_bundle_info * The EntityTypeBundleInfo service. - * @param \Drupal\islandora\IslandoraUtils $utils - * Islandora utils. - * @param \Drupal\Core\Entity\EntityStorageInterface $term_storage - * Term storage. */ - public function __construct( - ConfigFactoryInterface $config_factory, - EntityTypeBundleInfo $entity_type_bundle_info, - IslandoraUtils $utils, - EntityStorageInterface $term_storage - ) { + public function __construct(ConfigFactoryInterface $config_factory, EntityTypeBundleInfo $entity_type_bundle_info) { $this->setConfigFactory($config_factory); $this->entityTypeBundleInfo = $entity_type_bundle_info; - $this->utils = $utils; - $this->termStorage = $term_storage; } /** @@ -83,9 +51,7 @@ public function __construct( public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), - $container->get('entity_type.bundle.info'), - $container->get('islandora.utils'), - $container->get('entity_type.manager')->getStorage('taxonomy_term') + $container->get('entity_type.bundle.info') ); } @@ -124,55 +90,6 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#description' => 'Eg: 60, "2 days", "10h", "7d". A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120" is equal to "120ms").', ]; - $form[self::UPLOAD_FORM] = [ - '#type' => 'fieldset', - '#title' => $this->t('Add Children / Media Form'), - ]; - - $form[self::UPLOAD_FORM][self::UPLOAD_FORM_LOCATION] = [ - '#type' => 'textfield', - '#title' => $this->t('Upload location'), - '#description' => $this->t('Tokenized URI pattern where the uploaded file should go. You may use tokens to provide a pattern (e.g. "fedora://[date:custom:Y]-[date:custom:m]")'), - '#default_value' => $config->get(self::UPLOAD_FORM_LOCATION), - '#element_validate' => ['token_element_validate'], - '#token_types' => ['system'], - ]; - $form[self::UPLOAD_FORM]['TOKEN_HELP'] = [ - '#theme' => 'token_tree_link', - '#token_type' => ['system'], - ]; - - $form[self::UPLOAD_FORM][self::UPLOAD_FORM_ALLOWED_MIMETYPES] = [ - '#type' => 'textarea', - '#title' => $this->t('Allowed Mimetypes'), - '#description' => $this->t('Add mimetypes as a space delimited list with no periods before the extension.'), - '#default_value' => $config->get(self::UPLOAD_FORM_ALLOWED_MIMETYPES), - ]; - - $options = []; - foreach ($this->entityTypeBundleInfo->getBundleInfo('node') as $bundle_id => $bundle) { - if ($this->utils->isIslandoraType('node', $bundle_id)) { - $options[$bundle_id] = $bundle['label']; - } - }; - $form[self::UPLOAD_FORM][self::UPLOAD_FORM_BUNDLE] = [ - '#type' => 'select', - '#title' => $this->t('Content type to create (Add Children Form Only)'), - '#default_value' => $config->get(self::UPLOAD_FORM_BUNDLE), - '#options' => $options, - ]; - - $options = []; - foreach ($this->termStorage->loadTree('islandora_media_use', 0, NULL, TRUE) as $term) { - $options[$this->utils->getUriForTerm($term)] = $term->getName(); - }; - $form[self::UPLOAD_FORM][self::UPLOAD_FORM_TERM] = [ - '#type' => 'select', - '#title' => $this->t('Media Use Term for Uploaded Files (Add Children Form Only)'), - '#default_value' => $config->get(self::UPLOAD_FORM_TERM), - '#options' => $options, - ]; - $form[self::GEMINI_URL] = [ '#type' => 'textfield', '#title' => $this->t('Gemini URL'), @@ -299,10 +216,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $config ->set(self::BROKER_URL, $form_state->getValue(self::BROKER_URL)) ->set(self::JWT_EXPIRY, $form_state->getValue(self::JWT_EXPIRY)) - ->set(self::UPLOAD_FORM_BUNDLE, $form_state->getValue(self::UPLOAD_FORM_BUNDLE)) - ->set(self::UPLOAD_FORM_TERM, $form_state->getValue(self::UPLOAD_FORM_TERM)) - ->set(self::UPLOAD_FORM_LOCATION, $form_state->getValue(self::UPLOAD_FORM_LOCATION)) - ->set(self::UPLOAD_FORM_ALLOWED_MIMETYPES, $form_state->getValue(self::UPLOAD_FORM_ALLOWED_MIMETYPES)) ->set(self::GEMINI_URL, $form_state->getValue(self::GEMINI_URL)) ->set(self::GEMINI_PSEUDO, $pseudo_types) ->save(); diff --git a/src/Plugin/Condition/NodeHasTerm.php b/src/Plugin/Condition/NodeHasTerm.php index c912ea9b7..dae52ad0e 100644 --- a/src/Plugin/Condition/NodeHasTerm.php +++ b/src/Plugin/Condition/NodeHasTerm.php @@ -79,16 +79,6 @@ public static function create(ContainerInterface $container, array $configuratio ); } - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return array_merge( - ['logic' => 'and'], - parent::defaultConfiguration() - ); - } - /** * {@inheritdoc} */ @@ -110,16 +100,6 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta '#required' => TRUE, ]; - $form['logic'] = [ - '#type' => 'radios', - '#title' => $this->t('Logic'), - '#description' => $this->t('Whether to use AND or OR logic to evaluate multiple terms'), - '#options' => [ - 'and' => 'And', - 'or' => 'Or', - ], - '#default_value' => $this->configuration['logic'], - ]; return parent::buildConfigurationForm($form, $form_state); } @@ -144,9 +124,6 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s $this->configuration['uri'] = implode(',', $uris); } } - - $this->configuration['logic'] = $form_state->getValue('logic'); - parent::submitConfigurationForm($form, $form_state); } @@ -191,7 +168,7 @@ protected function evaluateEntity(EntityInterface $entity) { // FALSE if there's no URIs on the node. if (empty($haystack)) { - return FALSE; + return $this->isNegated() ? TRUE : FALSE; } // Get the URIs to look for. It's a required field, so there @@ -199,19 +176,12 @@ protected function evaluateEntity(EntityInterface $entity) { $needles = explode(',', $this->configuration['uri']); // TRUE if every needle is in the haystack. - if ($this->configuration['logic'] == 'and') { - if (count(array_intersect($needles, $haystack)) == count($needles)) { - return TRUE; - } - return FALSE; - } - // TRUE if any needle is in the haystack. - else { - if (count(array_intersect($needles, $haystack)) > 0) { - return TRUE; - } - return FALSE; + if (count(array_intersect($needles, $haystack)) == count($needles)) { + return $this->isNegated() ? FALSE : TRUE; } + + // Otherwise, FALSE. + return $this->isNegated() ? TRUE : FALSE; } /**