From 79f9cc9f96dff4fb1e636f464da1f0ca5f312c10 Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 25 Sep 2014 12:09:34 -0300 Subject: [PATCH 01/36] simple at-a-glance verification of drupal filter writability --- islandora.module | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/islandora.module b/islandora.module index b692438e..5f098bab 100644 --- a/islandora.module +++ b/islandora.module @@ -1766,10 +1766,20 @@ function islandora_islandora_datastream_modified(AbstractObject $object, Abstrac */ function islandora_form_simpletest_test_form_alter(array &$form) { module_load_include('inc', 'simpletest', 'simpletest.pages'); + + $filter_path = variable_get('islandora_simpletest_drupal_filter_path', '/usr/local/fedora/server/config/filter-drupal.xml'); + $filter_status = is_writable($filter_path); + if ($filter_status) { + $filter_status_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())); + $filter_status_message .= t(" Drupal filter at $filter_path is writable by the server."); + } else { + $filter_status_message = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())); + $filter_status_message .= t(" Drupal filter at $filter_path is not writable by the server. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, try setting the correct path in the test settings to see if this error is no longer present."); + } $form['tests'] = array( '#type' => 'fieldset', '#title' => t('Tests'), - '#description' => t('Select the test(s) or test group(s) you would like to run, and click Run tests.

NOTE: Tests in groups prefixed with Islandora generally require a configuration file, found in the Islandora module "tests" folder, as well as the use of the Islandora Drupal filter. Before any tests are run, please ensure that your web server has the appropriate permissions to alter the drupal_filter.xml file in your Fedora config folder. Your original Islandora Drupal filter configuration will NOT be overwritten by tests; HOWEVER, if PHP exits abnormally before the filter is reset, please use the "Repair Drupal Filter" button below.'), + '#description' => t("Select the test(s) or test group(s) you would like to run, and click Run tests.

NOTE: Tests in groups prefixed with Islandora generally require a configuration file, found in the Islandora module 'tests' folder, as well as the use of the Islandora Drupal filter. Before any tests are run, please ensure that your web server has the appropriate permissions to alter the drupal-filter.xml file in your Fedora config folder. Your original Islandora Drupal filter configuration will NOT be overwritten by tests; HOWEVER, if PHP exits abnormally before the filter is reset, please use the 'Repair Drupal Filter' button below.

Drupal Filter Write Status: $filter_status_message

"), ); $form['tests']['table'] = array( @@ -1812,6 +1822,24 @@ function islandora_form_simpletest_test_form_alter(array &$form) { ); } +/** + * Implements hook_form_simpletest_settings_form_alter() + */ +function islandora_form_simpletest_settings_form_alter(&$form, &$form_state) { + $form['islandora_drupal_filter'] = array( + '#type' => 'fieldset', + '#title' => t('Islandora Drupal Filter Location'), + '#collapsible' => FALSE, + '#collapsed' => FALSE, + ); + $form['islandora_drupal_filter']['islandora_simpletest_drupal_filter_path'] = array( + '#type' => 'textfield', + '#title' => t('Path to the Drupal Filter'), + '#description' => t('The absolute path on the server to the Drupal filter XML file in the Fedora configuration. NOTE: This is simply used to populate the at-a-glance "is the Filter writeable" notice on the top of the list of tests, and DOES NOT actually have any bearing on its function within Islandora.'), + '#default_value' => variable_get('islandora_simpletest_drupal_filter_path', '/usr/local/fedora/server/config/filter-drupal.xml'), + ); +} + /** * Submit handler for islandora_form_simpletest_test_form_alter(). */ From b29a66d99093d1c8eb0d30187049c686f44ad4f8 Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 25 Sep 2014 12:42:23 -0300 Subject: [PATCH 02/36] oh qadan you goof --- islandora.module | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/islandora.module b/islandora.module index 5f098bab..0b41329f 100644 --- a/islandora.module +++ b/islandora.module @@ -1770,16 +1770,23 @@ function islandora_form_simpletest_test_form_alter(array &$form) { $filter_path = variable_get('islandora_simpletest_drupal_filter_path', '/usr/local/fedora/server/config/filter-drupal.xml'); $filter_status = is_writable($filter_path); if ($filter_status) { - $filter_status_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())); - $filter_status_message .= t(" Drupal filter at $filter_path is writable by the server."); - } else { - $filter_status_message = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())); - $filter_status_message .= t(" Drupal filter at $filter_path is not writable by the server. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, try setting the correct path in the test settings to see if this error is no longer present."); + $filter_status_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())) . " "; + $filter_status_message .= t("Drupal filter at !filter_path is writable by the server.", array( + '!filter_path' => $filter_path, + )); + } + else { + $filter_status_message = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())) . " "; + $filter_status_message .= t("Drupal filter at !filter_path is not writable by the server. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, try setting the correct path in the test settings to see if this error is no longer present.", array( + '!filter_path' => $filter_path, + )); } $form['tests'] = array( '#type' => 'fieldset', '#title' => t('Tests'), - '#description' => t("Select the test(s) or test group(s) you would like to run, and click Run tests.

NOTE: Tests in groups prefixed with Islandora generally require a configuration file, found in the Islandora module 'tests' folder, as well as the use of the Islandora Drupal filter. Before any tests are run, please ensure that your web server has the appropriate permissions to alter the drupal-filter.xml file in your Fedora config folder. Your original Islandora Drupal filter configuration will NOT be overwritten by tests; HOWEVER, if PHP exits abnormally before the filter is reset, please use the 'Repair Drupal Filter' button below.

Drupal Filter Write Status: $filter_status_message

"), + '#description' => t("Select the test(s) or test group(s) you would like to run, and click Run tests.

NOTE: Tests in groups prefixed with Islandora generally require a configuration file, found in the Islandora module 'tests' folder, as well as the use of the Islandora Drupal filter. Before any tests are run, please ensure that your web server has the appropriate permissions to alter the drupal-filter.xml file in your Fedora config folder. Your original Islandora Drupal filter configuration will NOT be overwritten by tests; HOWEVER, if PHP exits abnormally before the filter is reset, please use the 'Repair Drupal Filter' button below.

Drupal Filter Write Status: !filter_status_message

", array( + '!filter_status_message' => $filter_status_message, + )), ); $form['tests']['table'] = array( @@ -1823,7 +1830,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { } /** - * Implements hook_form_simpletest_settings_form_alter() + * Implements hook_form_alter(). */ function islandora_form_simpletest_settings_form_alter(&$form, &$form_state) { $form['islandora_drupal_filter'] = array( From e6eb5d93f2d54ad14f1b3bfbf7e9c5bfc2c48d20 Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 25 Sep 2014 14:58:17 -0300 Subject: [PATCH 03/36] doing this the less stupid way --- islandora.module | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/islandora.module b/islandora.module index 0b41329f..87082468 100644 --- a/islandora.module +++ b/islandora.module @@ -1766,8 +1766,9 @@ function islandora_islandora_datastream_modified(AbstractObject $object, Abstrac */ function islandora_form_simpletest_test_form_alter(array &$form) { module_load_include('inc', 'simpletest', 'simpletest.pages'); - - $filter_path = variable_get('islandora_simpletest_drupal_filter_path', '/usr/local/fedora/server/config/filter-drupal.xml'); + module_load_include('inc', 'islandora', 'tests/includes/test_utility_abstraction'); + $configuration = IslandoraTestUtilityClass::getTestConfiguration(); + $filter_path = variable_get('islandora_simpletest_drupal_filter_path', $configuration['drupal_filter_file']); $filter_status = is_writable($filter_path); if ($filter_status) { $filter_status_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())) . " "; @@ -1781,6 +1782,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { '!filter_path' => $filter_path, )); } + $form['tests'] = array( '#type' => 'fieldset', '#title' => t('Tests'), @@ -1833,6 +1835,8 @@ function islandora_form_simpletest_test_form_alter(array &$form) { * Implements hook_form_alter(). */ function islandora_form_simpletest_settings_form_alter(&$form, &$form_state) { + module_load_include('inc', 'islandora', 'tests/includes/test_utility_abstraction'); + $configuration = IslandoraTestUtilityClass::getTestConfiguration(); $form['islandora_drupal_filter'] = array( '#type' => 'fieldset', '#title' => t('Islandora Drupal Filter Location'), @@ -1843,7 +1847,7 @@ function islandora_form_simpletest_settings_form_alter(&$form, &$form_state) { '#type' => 'textfield', '#title' => t('Path to the Drupal Filter'), '#description' => t('The absolute path on the server to the Drupal filter XML file in the Fedora configuration. NOTE: This is simply used to populate the at-a-glance "is the Filter writeable" notice on the top of the list of tests, and DOES NOT actually have any bearing on its function within Islandora.'), - '#default_value' => variable_get('islandora_simpletest_drupal_filter_path', '/usr/local/fedora/server/config/filter-drupal.xml'), + '#default_value' => variable_get('islandora_simpletest_drupal_filter_path', $configuration['drupal_filter_file']), ); } From 0bc26560fb269d461754fc71dc4891482adb3a3e Mon Sep 17 00:00:00 2001 From: qadan Date: Fri, 26 Sep 2014 09:56:59 -0300 Subject: [PATCH 04/36] let's just do this right --- islandora.module | 27 ++++---------------- tests/includes/islandora_web_test_case.inc | 29 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/islandora.module b/islandora.module index 87082468..626f4921 100644 --- a/islandora.module +++ b/islandora.module @@ -1768,7 +1768,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { module_load_include('inc', 'simpletest', 'simpletest.pages'); module_load_include('inc', 'islandora', 'tests/includes/test_utility_abstraction'); $configuration = IslandoraTestUtilityClass::getTestConfiguration(); - $filter_path = variable_get('islandora_simpletest_drupal_filter_path', $configuration['drupal_filter_file']); + $filter_path = $configuration['drupal_filter_file']; $filter_status = is_writable($filter_path); if ($filter_status) { $filter_status_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())) . " "; @@ -1778,7 +1778,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { } else { $filter_status_message = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())) . " "; - $filter_status_message .= t("Drupal filter at !filter_path is not writable by the server. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, try setting the correct path in the test settings to see if this error is no longer present.", array( + $filter_status_message .= t("Drupal filter at !filter_path is not writable by the server. Tests relying on the filter will be disabled. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, you will need to change the drupal_filter_file entry in the Islandora module's tests/test_config.ini or tests/default.test_config.ini file.", array( '!filter_path' => $filter_path, )); } @@ -1808,6 +1808,9 @@ function islandora_form_simpletest_test_form_alter(array &$form) { '#title' => filter_xss($info['name']), '#description' => filter_xss($info['description']), ); + if (is_subclass_of($class, 'IslandoraWebTestCase') && !$filter_status) { + $form['tests']['table'][$group][$class]['#disabled'] = TRUE; + } } } @@ -1831,26 +1834,6 @@ function islandora_form_simpletest_test_form_alter(array &$form) { ); } -/** - * Implements hook_form_alter(). - */ -function islandora_form_simpletest_settings_form_alter(&$form, &$form_state) { - module_load_include('inc', 'islandora', 'tests/includes/test_utility_abstraction'); - $configuration = IslandoraTestUtilityClass::getTestConfiguration(); - $form['islandora_drupal_filter'] = array( - '#type' => 'fieldset', - '#title' => t('Islandora Drupal Filter Location'), - '#collapsible' => FALSE, - '#collapsed' => FALSE, - ); - $form['islandora_drupal_filter']['islandora_simpletest_drupal_filter_path'] = array( - '#type' => 'textfield', - '#title' => t('Path to the Drupal Filter'), - '#description' => t('The absolute path on the server to the Drupal filter XML file in the Fedora configuration. NOTE: This is simply used to populate the at-a-glance "is the Filter writeable" notice on the top of the list of tests, and DOES NOT actually have any bearing on its function within Islandora.'), - '#default_value' => variable_get('islandora_simpletest_drupal_filter_path', $configuration['drupal_filter_file']), - ); -} - /** * Submit handler for islandora_form_simpletest_test_form_alter(). */ diff --git a/tests/includes/islandora_web_test_case.inc b/tests/includes/islandora_web_test_case.inc index 55ee5824..8e29d893 100644 --- a/tests/includes/islandora_web_test_case.inc +++ b/tests/includes/islandora_web_test_case.inc @@ -57,6 +57,34 @@ class IslandoraWebTestCase extends DrupalWebTestCase { } } + /** + * Run all tests in this class. + * + * Attempts to figure out if the Drupal filter is writable before running any + * tests. + * + * @see DrupalWebTestCase::run() + */ + public function run(array $methods = array()) { + $this->configuration = IslandoraTestUtilityClass::getTestConfiguration(); + if (is_writable($this->configuration['drupal_filter_file'])) { + parent::run($methods); + } + else { + $method_info = new ReflectionMethod($this, 'run'); + $class = get_class($this); + set_error_handler(array($this, 'errorHandler')); + $caller = array( + 'file' => $method_info->getFileName(), + 'line' => $method_info->getStartLine(), + 'function' => $class . '->run()', + ); + $this->assert(FALSE, "Unable to proceed; the Drupal filter is not writable by the server.", "Completion check", $caller); + drupal_get_messages(); + restore_error_handler(); + } + } + /** * Sets up the web test case. * @@ -74,7 +102,6 @@ class IslandoraWebTestCase extends DrupalWebTestCase { module_load_include('inc', 'islandora', 'includes/tuque_wrapper'); module_load_include('inc', 'islandora', 'tests/includes/utilities'); - $this->configuration = IslandoraTestUtilityClass::getTestConfiguration(); if ($this->configuration['use_drupal_filter']) { $this->setUpDrupalFilter(); } From d275eb43a446d60423f3566afb5e547bc0dcee73 Mon Sep 17 00:00:00 2001 From: willtp87 Date: Mon, 29 Sep 2014 11:15:31 -0300 Subject: [PATCH 05/36] potx no longer having recomended dl --- tests/scripts/travis_setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/scripts/travis_setup.sh b/tests/scripts/travis_setup.sh index 5a8c78ef..84b6c44c 100755 --- a/tests/scripts/travis_setup.sh +++ b/tests/scripts/travis_setup.sh @@ -39,7 +39,7 @@ mv sites/all/modules/islandora/tests/travis.test_config.ini sites/all/modules/is mkdir sites/all/libraries ln -s $HOME/tuque sites/all/libraries/tuque drush dl --yes coder -drush dl --yes potx +drush dl --yes potx-7.x-1.0 drush en --yes coder_review drush en --yes simpletest drush en --yes potx From 3f9ed4cf461dd2619fd5952bb1d43f53dcea3ef3 Mon Sep 17 00:00:00 2001 From: Matthew Perry Date: Thu, 2 Oct 2014 10:52:37 -0300 Subject: [PATCH 06/36] Fixing spelling mistake in ingest message: notifiy changed to notify. --- includes/ingest.form.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/ingest.form.inc b/includes/ingest.form.inc index b5a4740d..6c802f44 100644 --- a/includes/ingest.form.inc +++ b/includes/ingest.form.inc @@ -799,7 +799,7 @@ function islandora_ingest_form_submit(array $form, array &$form_state) { WATCHDOG_ERROR ); drupal_set_message( - t('A problem occured while ingesting "@label" (ID: @pid), please notifiy the administrator.', + t('A problem occured while ingesting "@label" (ID: @pid), please notify the administrator.', array('@label' => $object->label, '@pid' => $object->id)), 'error' ); From d2a86da5457ae45fe5c7fc0a048a1c1280c4f0ed Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Thu, 2 Oct 2014 14:56:40 -0300 Subject: [PATCH 07/36] Fix the invalid markup generated by the printer icon. --- islandora.module | 2 ++ 1 file changed, 2 insertions(+) diff --git a/islandora.module b/islandora.module index b692438e..207c9367 100644 --- a/islandora.module +++ b/islandora.module @@ -1940,6 +1940,8 @@ function islandora_menu_local_tasks_alter(&$data, $router_item, $root_path) { if ($tab['#link']['path'] == 'islandora/object/%/print_object') { if ($root_path == 'islandora/object/%') { $islandora_path = drupal_get_path('module', 'islandora'); + $tab['#prefix'] = '
  • '; + $tab['#suffix'] = '
  • '; $tab['#theme'] = 'link'; $tab['#text'] = theme('image', array( 'path' => "$islandora_path/images/print-icon.png", From 35e965c7b874f998839d85bb9fab7f4dfa2b5ba7 Mon Sep 17 00:00:00 2001 From: willtp87 Date: Thu, 2 Oct 2014 16:11:29 -0300 Subject: [PATCH 08/36] datastream entity --- islandora.module | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/islandora.module b/islandora.module index b692438e..3e4525d4 100644 --- a/islandora.module +++ b/islandora.module @@ -1511,6 +1511,14 @@ function islandora_entity_info() { 'label' => 'label', ), ); + $entities['islandora_datastream'] = array( + 'label' => t('Islandora Datastream'), + 'fieldable' => FALSE, + 'entity keys' => array( + 'id' => 'id', + 'label' => 'label', + ), + ); return $entities; } @@ -1523,39 +1531,56 @@ function islandora_entity_info() { function islandora_entity_property_info() { $info = array(); - $p = &$info['islandora_object']['properties']; + $object_properties = &$info['islandora_object']['properties']; + $datastream_properties = &$info['islandora_datastream']['properties']; - $p['id'] = array( + $object_properties['id'] = array( 'type' => 'text', 'label' => t('ID'), 'description' => t('The identifier of the object.'), ); - $p['label'] = array( + $object_properties['label'] = array( 'type' => 'text', 'label' => t('Object Label'), 'description' => t('The label of the object.'), ); - $p['owner'] = array( + $object_properties['owner'] = array( 'type' => 'text', 'label' => t('Object Owner'), 'description' => t('The name of the owner of the object.'), ); - $p['state'] = array( + $object_properties['state'] = array( 'type' => 'text', 'label' => t('Object State'), 'description' => t('An initial representing the state of the object.'), ); - $p['models'] = array( + $object_properties['models'] = array( 'type' => 'list', 'label' => t('Content Models'), 'description' => t('The list of content models which the object has.'), ); - $p['createdDate'] = array( + $object_properties['createdDate'] = array( 'type' => 'text', 'label' => t('Created Date'), 'description' => t('When the object was created.'), ); + $datastream_properties['id'] = array( + 'type' => 'text', + 'label' => t('ID'), + 'description' => t('The identifier of the datastream.'), + ); + $datastream_properties['label'] = array( + 'type' => 'text', + 'label' => t('Datastream Label'), + 'description' => t('The label of the datastream.'), + ); + $datastream_properties['mimetype'] = array( + 'type' => 'text', + 'label' => t('MIME type'), + 'description' => t('Content type of the datastream.'), + ); + return $info; } From f548041cf7dbea2234e4b9d91720a77441dc03a6 Mon Sep 17 00:00:00 2001 From: MorganDawe Date: Fri, 3 Oct 2014 13:59:12 -0300 Subject: [PATCH 09/36] Updated mimetype mappings. --- includes/mime_detect.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/mime_detect.inc b/includes/mime_detect.inc index da2c69f3..a0c3dcf2 100644 --- a/includes/mime_detect.inc +++ b/includes/mime_detect.inc @@ -214,7 +214,6 @@ class MimeDetect { // OpenDX Grid. "dx" => "chemical/x-jcamp-dx", // MOPAC Cartesian. - "mop" => "chemical/x-mopac-input", // Compressed formats: // (note: http://svn.cleancode.org/svn/email/trunk/mime.types) "tgz" => "application/x-gzip", @@ -222,6 +221,7 @@ class MimeDetect { "tar" => "application/x-tar", "gtar" => "application/x-gtar", "zip" => "application/x-zip", + "dat" => "application/octet-stream", // others: 'bin' => 'application/octet-stream', // Web Archives: From 4d9a1ce26ef558c53d5b95d7975d95b7530d6fb2 Mon Sep 17 00:00:00 2001 From: MorganDawe Date: Fri, 3 Oct 2014 14:14:22 -0300 Subject: [PATCH 10/36] added mop back to mimedetect. --- includes/mime_detect.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/mime_detect.inc b/includes/mime_detect.inc index a0c3dcf2..8da0ebe7 100644 --- a/includes/mime_detect.inc +++ b/includes/mime_detect.inc @@ -214,6 +214,7 @@ class MimeDetect { // OpenDX Grid. "dx" => "chemical/x-jcamp-dx", // MOPAC Cartesian. + "mop" => "chemical/x-mopac-input", // Compressed formats: // (note: http://svn.cleancode.org/svn/email/trunk/mime.types) "tgz" => "application/x-gzip", From 03ca4ac116d546f3f4a6811315f355b5013f9cc8 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Wed, 8 Oct 2014 17:09:40 -0300 Subject: [PATCH 11/36] Basic implentation of other hooks and XPath Rules condition. --- includes/tuque_wrapper.inc | 4 ++ islandora.module | 8 ++++ islandora.rules.inc | 92 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc index 2f4ea1df..53942554 100644 --- a/includes/tuque_wrapper.inc +++ b/includes/tuque_wrapper.inc @@ -228,6 +228,10 @@ class IslandoraFedoraObject extends FedoraObject { if ($this->state == 'D') { islandora_invoke_object_hooks(ISLANDORA_OBJECT_PURGED_HOOK, $this->models, $this->id); } + // Fire of event if rules is enabled. + if (module_exists('rules')) { + rules_invoke_event('islandora_object_modified', $object); + } } catch (Exception $e) { watchdog('islandora', 'Failed to modify object: @pid
    code: @code
    message: @msg', array( diff --git a/islandora.module b/islandora.module index 603ab6a0..0b2a3ce8 100644 --- a/islandora.module +++ b/islandora.module @@ -1762,6 +1762,10 @@ function islandora_islandora_object_ingested(AbstractObject $object) { * equal to the current ingested datastream's id. */ function islandora_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) { + if (module_exists('rules')) { + rules_invoke_event('islandora_datastream_ingested', $object, $datastream->id); + } + module_load_include('inc', 'islandora', 'includes/derivatives'); // Defer derivatives if necessary. if (islandora_get_defer_derivatives_flag($object)) { @@ -1778,6 +1782,10 @@ function islandora_islandora_datastream_ingested(AbstractObject $object, Abstrac * existing derivatives will be updated to reflect the change in the source. */ function islandora_islandora_datastream_modified(AbstractObject $object, AbstractDatastream $datastream) { + if (module_exists('rules')) { + rules_invoke_event('islandora_datastream_modified', $object, $datastream->id); + } + module_load_include('inc', 'islandora', 'includes/derivatives'); $logging_results = islandora_do_derivatives($object, array( 'source_dsid' => $datastream->id, diff --git a/islandora.rules.inc b/islandora.rules.inc index 02f5c822..17fa8227 100644 --- a/islandora.rules.inc +++ b/islandora.rules.inc @@ -21,6 +21,49 @@ function islandora_rules_event_info() { ), ), ), + 'islandora_datastream_ingested' => array( + 'group' => t('Islandora'), + 'label' => t('Datastream ingested'), + 'variables' => array( + 'object' => array( + 'type' => 'islandora_object', + 'label' => t('The ingested object'), + 'description' => t('A Tuque object for the Fedora object on which the datastream exists, as an entity.'), + ), + 'datastream' => array( + 'type' => 'text', + 'label' => t('Datastream ID'), + 'description' => t('The ID of the ingested datastream.'), + ), + ), + ), + 'islandora_object_modified' => array( + 'group' => t('Islandora'), + 'label' => t('Object modified'), + 'variables' => array( + 'object' => array( + 'type' => 'islandora_object', + 'label' => t('The modified object'), + 'description' => t('A Tuque object for the modified Fedora object, as an entity.'), + ), + ), + ), + 'islandora_datastream_modified' => array( + 'group' => t('Islandora'), + 'label' => t('Datastream modified'), + 'variables' => array( + 'object' => array( + 'type' => 'islandora_object', + 'label' => t('The modified object'), + 'description' => t('A Tuque object for the Fedora object on which the datastream exists, as an entity.'), + ), + 'datastream' => array( + 'type' => 'text', + 'label' => t('Datastream ID'), + 'description' => t('The ID of the ingested datastream.'), + ), + ), + ), ); } @@ -60,6 +103,32 @@ function islandora_rules_relationship_parameter_array() { ); } +function islandora_rules_base_xpath_parameters() { + return array( + 'object' => array( + 'type' => 'islandora_object', + 'label' => t('Object'), + 'description' => t('The object in which to check the XPath.'), + ), + 'datastream' => array( + 'type' => 'text', + 'label' => t('Datastream ID'), + 'description' => t('The ID of the XML datastream to check.'), + ), + 'xpath' => array( + 'type' => 'text', + 'label' => t('XPath'), + 'description' => t('An XPath to evaluate.'), + ), + 'xpath_namespaces' => array( + 'type' => 'taxonomy_vocabulary', + 'label' => t('XPath Namespace Taxonomy'), + 'description' => t('A flat taxonomy of which the terms are namespace prefixes and the description contains the URI for the namespace.') + ), + ); +} + + /** * Implements hook_rules_condition_info(). */ @@ -71,6 +140,11 @@ function islandora_rules_condition_info() { 'group' => t('Islandora'), 'parameter' => islandora_rules_relationship_parameter_array(), ); + $cond['islandora_rules_datastream_has_xpath'] = array( + 'label' => t('Check for an XPath match in an XML datastream'), + 'group' => t('Islandora'), + 'parameter' => islandora_rules_base_xpath_parameters(), + ); return $cond; } @@ -92,6 +166,7 @@ function islandora_rules_action_info() { 'group' => t('Islandora'), 'parameter' => islandora_rules_relationship_parameter_array(), ); + return $cond; } /** @@ -133,3 +208,20 @@ function islandora_object_remove_relationship($sub, $pred_uri, $pred, $object, $ function islandora_object_add_relationship($sub, $pred_uri, $pred, $object, $type) { $sub->relationships->add($pred_uri, $pred, $object, $type); } + +function islandora_rules_datastream_has_xpath(AbstractObject $object, $datastream_id, $search_xpath, $xpath_vocab) { + if (!isset($object[$datastream_id])) { + // Datastream does no exists... No match. + return FALSE; + } + + $datastream = $object[$datastream_id]; + $doc = new DOMDocument(); + $doc->loadXML($datastream->content); + $xpath = new DOMXPath($doc); + foreach (taxonomy_get_tree($xpath_vocab->vid, 0, 1, FALSE) as $term) { + $xpath->registerNamespace($term->name, $term->description); + } + $result = $xpath->query($search_xpath); + return $result->length > 0; +} From 5ee659430739a7b01260dfe840c5177c4927f8df Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 9 Oct 2014 12:03:50 -0300 Subject: [PATCH 12/36] forgot you can't just run the parent run() --- islandora.module | 26 ++++++++- tests/includes/islandora_web_test_case.inc | 66 ++++++++++++++++++++-- 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/islandora.module b/islandora.module index 626f4921..a79391f0 100644 --- a/islandora.module +++ b/islandora.module @@ -1768,7 +1768,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { module_load_include('inc', 'simpletest', 'simpletest.pages'); module_load_include('inc', 'islandora', 'tests/includes/test_utility_abstraction'); $configuration = IslandoraTestUtilityClass::getTestConfiguration(); - $filter_path = $configuration['drupal_filter_file']; + $filter_path = variable_get('islandora_simpletest_drupal_filter_path', $configuration['drupal_filter_file']); $filter_status = is_writable($filter_path); if ($filter_status) { $filter_status_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())) . " "; @@ -1778,7 +1778,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { } else { $filter_status_message = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())) . " "; - $filter_status_message .= t("Drupal filter at !filter_path is not writable by the server. Tests relying on the filter will be disabled. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, you will need to change the drupal_filter_file entry in the Islandora module's tests/test_config.ini or tests/default.test_config.ini file.", array( + $filter_status_message .= t("Drupal filter at !filter_path is not writable by the server. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, try setting the correct path in the test settings to see if this error is no longer present.", array( '!filter_path' => $filter_path, )); } @@ -1808,7 +1808,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { '#title' => filter_xss($info['name']), '#description' => filter_xss($info['description']), ); - if (is_subclass_of($class, 'IslandoraWebTestCase') && !$filter_status) { + if (get_parent_class($class) === 'IslandoraWebTestCase' && !$filter_path) { $form['tests']['table'][$group][$class]['#disabled'] = TRUE; } } @@ -1834,6 +1834,26 @@ function islandora_form_simpletest_test_form_alter(array &$form) { ); } +/** + * Implements hook_form_alter(). + */ +function islandora_form_simpletest_settings_form_alter(&$form, &$form_state) { + module_load_include('inc', 'islandora', 'tests/includes/test_utility_abstraction'); + $configuration = IslandoraTestUtilityClass::getTestConfiguration(); + $form['islandora_drupal_filter'] = array( + '#type' => 'fieldset', + '#title' => t('Islandora Drupal Filter Location'), + '#collapsible' => FALSE, + '#collapsed' => FALSE, + ); + $form['islandora_drupal_filter']['islandora_simpletest_drupal_filter_path'] = array( + '#type' => 'textfield', + '#title' => t('Path to the Drupal Filter'), + '#description' => t('The absolute path on the server to the Drupal filter XML file in the Fedora configuration. NOTE: This is simply used to populate the at-a-glance "is the Filter writeable" notice on the top of the list of tests, and DOES NOT actually have any bearing on its function within Islandora.'), + '#default_value' => variable_get('islandora_simpletest_drupal_filter_path', $configuration['drupal_filter_file']), + ); +} + /** * Submit handler for islandora_form_simpletest_test_form_alter(). */ diff --git a/tests/includes/islandora_web_test_case.inc b/tests/includes/islandora_web_test_case.inc index 8e29d893..fac1b725 100644 --- a/tests/includes/islandora_web_test_case.inc +++ b/tests/includes/islandora_web_test_case.inc @@ -21,6 +21,17 @@ class IslandoraWebTestCase extends DrupalWebTestCase { */ protected $deleteObjectsOnTeardown = TRUE; + /** + * Instantiates an IslandoraWebTestCase with a configuration. + * + * @throws Exception + * If the required test config file is not found. + */ + public function __construct($test_id = NULL) { + $this->configuration = IslandoraTestUtilityClass::getTestConfiguration(); + parent::__construct($test_id); + } + /** * Defers to IslandoraTestUtilities for missing methods. * @@ -28,6 +39,9 @@ class IslandoraWebTestCase extends DrupalWebTestCase { * The method being called. * @param array $args * The arguments for that method. + * + * @return bool + * TRUE if the result was a pass, or FALSE otherwise. */ public function __call($method, $args) { module_load_include('inc', 'islandora', 'tests/includes/utilities'); @@ -66,10 +80,50 @@ class IslandoraWebTestCase extends DrupalWebTestCase { * @see DrupalWebTestCase::run() */ public function run(array $methods = array()) { - $this->configuration = IslandoraTestUtilityClass::getTestConfiguration(); + // Determine if the Drupal filter is writable so we know if we can proceed. if (is_writable($this->configuration['drupal_filter_file'])) { - parent::run($methods); + // Set up the SimpleTest environment. + simpletest_verbose(NULL, variable_get('file_public_path', conf_path() . '/files'), get_class($this)); + $this->httpauth_method = variable_get('simpletest_httpauth_method', CURLAUTH_BASIC); + $username = variable_get('simpletest_httpauth_username', NULL); + $password = variable_get('simpletest_httpauth_password', NULL); + if ($username && $password) { + $this->httpauth_credentials = $username . ':' . $password; + } + set_error_handler(array($this, 'errorHandler')); + $class = get_class($this); + // Iterate through all the methods in this class, unless a specific list of + // methods to run was passed. + $class_methods = get_class_methods($class); + if ($methods) { + $class_methods = array_intersect($class_methods, $methods); + } + foreach ($class_methods as $method) { + // If the current method starts with "test", run it - it's a test. + if (strtolower(substr($method, 0, 4)) == 'test') { + // Insert a fail record. This will be deleted on completion to ensure + // that testing completed. + $method_info = new ReflectionMethod($class, $method); + $caller = array( + 'file' => $method_info->getFileName(), + 'line' => $method_info->getStartLine(), + 'function' => $class . '->' . $method . '()', + ); + $completion_check_id = DrupalTestCase::insertAssert($this->testId, $class, FALSE, t('The test did not complete due to a fatal error.'), 'Completion check', $caller); + try { + $this->setUp(); + $this->$method(); + } + catch (Exception $e) { + $this->exceptionHandler($e); + } + $this->tearDown(); + // Remove the completion check record. + DrupalTestCase::deleteAssert($completion_check_id); + } + } } + // If the Drupal filter is not writable, skip testing and error out. else { $method_info = new ReflectionMethod($this, 'run'); $class = get_class($this); @@ -80,9 +134,9 @@ class IslandoraWebTestCase extends DrupalWebTestCase { 'function' => $class . '->run()', ); $this->assert(FALSE, "Unable to proceed; the Drupal filter is not writable by the server.", "Completion check", $caller); - drupal_get_messages(); - restore_error_handler(); } + drupal_get_messages(); + restore_error_handler(); } /** @@ -169,7 +223,6 @@ class IslandoraWebTestCase extends DrupalWebTestCase { islandora_repair_drupal_filter(); } unset($this->admin); - unset($this->configuration); parent::tearDown(); } @@ -205,6 +258,9 @@ class IslandoraWebTestCase extends DrupalWebTestCase { * The label of the first 'Delete' button * @param bool $safety * If TRUE, this will only delete objects owned by users in $this->users. + * + * @return bool + * If the deletion fails, return FALSE TRUE, this will only delete objects owned by users in $this->users. */ public function deleteObject($pid, $button = NULL, $safety = TRUE) { $object = islandora_object_load($pid); From 8d296881f0c30dae59c8b108f868fba869ce945a Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 9 Oct 2014 12:45:07 -0300 Subject: [PATCH 13/36] coder issues --- tests/includes/islandora_web_test_case.inc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/includes/islandora_web_test_case.inc b/tests/includes/islandora_web_test_case.inc index fac1b725..16146b12 100644 --- a/tests/includes/islandora_web_test_case.inc +++ b/tests/includes/islandora_web_test_case.inc @@ -92,8 +92,8 @@ class IslandoraWebTestCase extends DrupalWebTestCase { } set_error_handler(array($this, 'errorHandler')); $class = get_class($this); - // Iterate through all the methods in this class, unless a specific list of - // methods to run was passed. + // Iterate through all the methods in this class, unless a specific list + // of methods to run was passed. $class_methods = get_class_methods($class); if ($methods) { $class_methods = array_intersect($class_methods, $methods); @@ -260,7 +260,8 @@ class IslandoraWebTestCase extends DrupalWebTestCase { * If TRUE, this will only delete objects owned by users in $this->users. * * @return bool - * If the deletion fails, return FALSE TRUE, this will only delete objects owned by users in $this->users. + * If the deletion fails, return FALSE TRUE, this will only delete objects + * owned by users in $this->users. */ public function deleteObject($pid, $button = NULL, $safety = TRUE) { $object = islandora_object_load($pid); From e77af2db9c478c1401ff8c7e77fb75d76481a564 Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 9 Oct 2014 13:59:19 -0300 Subject: [PATCH 14/36] accidental reversion of features --- islandora.module | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/islandora.module b/islandora.module index 920025c2..eceaecbf 100644 --- a/islandora.module +++ b/islandora.module @@ -1793,7 +1793,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { module_load_include('inc', 'simpletest', 'simpletest.pages'); module_load_include('inc', 'islandora', 'tests/includes/test_utility_abstraction'); $configuration = IslandoraTestUtilityClass::getTestConfiguration(); - $filter_path = variable_get('islandora_simpletest_drupal_filter_path', $configuration['drupal_filter_file']); + $filter_path = $configuration['drupal_filter_file']; $filter_status = is_writable($filter_path); if ($filter_status) { $filter_status_message = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())) . " "; @@ -1803,7 +1803,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { } else { $filter_status_message = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())) . " "; - $filter_status_message .= t("Drupal filter at !filter_path is not writable by the server. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, try setting the correct path in the test settings to see if this error is no longer present.", array( + $filter_status_message .= t("Drupal filter at !filter_path is not writable by the server. Please make sure your webserver has permission to write to the Drupal filter. If the path given is incorrect, you will need to change it in your server's test config file, located in the Islandora module's 'tests' folder as test_config.ini or default.test_config.ini.", array( '!filter_path' => $filter_path, )); } @@ -1860,27 +1860,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { } /** - * Implements hook_form_alter(). - */ -function islandora_form_simpletest_settings_form_alter(&$form, &$form_state) { - module_load_include('inc', 'islandora', 'tests/includes/test_utility_abstraction'); - $configuration = IslandoraTestUtilityClass::getTestConfiguration(); - $form['islandora_drupal_filter'] = array( - '#type' => 'fieldset', - '#title' => t('Islandora Drupal Filter Location'), - '#collapsible' => FALSE, - '#collapsed' => FALSE, - ); - $form['islandora_drupal_filter']['islandora_simpletest_drupal_filter_path'] = array( - '#type' => 'textfield', - '#title' => t('Path to the Drupal Filter'), - '#description' => t('The absolute path on the server to the Drupal filter XML file in the Fedora configuration. NOTE: This is simply used to populate the at-a-glance "is the Filter writeable" notice on the top of the list of tests, and DOES NOT actually have any bearing on its function within Islandora.'), - '#default_value' => variable_get('islandora_simpletest_drupal_filter_path', $configuration['drupal_filter_file']), - ); -} - -/** - * Submit handler for islandora_form_simpletest_test_form_alter(). + * Removes simpletest entries from the Drupal filter. */ function islandora_repair_drupal_filter() { From e96ae222895f65292686ddf0ab150906fee8a61b Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 9 Oct 2014 14:01:57 -0300 Subject: [PATCH 15/36] accidental reversion of even more features --- islandora.module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/islandora.module b/islandora.module index eceaecbf..f43b545c 100644 --- a/islandora.module +++ b/islandora.module @@ -1833,7 +1833,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { '#title' => filter_xss($info['name']), '#description' => filter_xss($info['description']), ); - if (get_parent_class($class) === 'IslandoraWebTestCase' && !$filter_path) { + if (is_subclass_of($class, 'IslandoraWebTestCase') && !$filter_path) { $form['tests']['table'][$group][$class]['#disabled'] = TRUE; } } From 3f2e923c928f66d7908ed208d136ae27fd6ff804 Mon Sep 17 00:00:00 2001 From: qadan Date: Thu, 9 Oct 2014 14:20:28 -0300 Subject: [PATCH 16/36] will the accidental reversions never end --- islandora.module | 2 +- tests/default.test_config.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/islandora.module b/islandora.module index f43b545c..b6c40f1b 100644 --- a/islandora.module +++ b/islandora.module @@ -1833,7 +1833,7 @@ function islandora_form_simpletest_test_form_alter(array &$form) { '#title' => filter_xss($info['name']), '#description' => filter_xss($info['description']), ); - if (is_subclass_of($class, 'IslandoraWebTestCase') && !$filter_path) { + if (is_subclass_of($class, 'IslandoraWebTestCase', TRUE) && !$filter_status) { $form['tests']['table'][$group][$class]['#disabled'] = TRUE; } } diff --git a/tests/default.test_config.ini b/tests/default.test_config.ini index f07fb4c3..28128574 100644 --- a/tests/default.test_config.ini +++ b/tests/default.test_config.ini @@ -1,6 +1,6 @@ [fedora] fedora_url = "http://localhost:8080/fedora" use_drupal_filter = TRUE -drupal_filter_file = "/usr/local/fedora/server/config/filter-drupal.xml" +drupal_filter_file = "/usr/local/fedora/server/config/filter-drupal.xmll" admin_user = "fedoraAdmin" admin_pass = "fedoraAdmin" From fd95c8dce72a8c6fbb7e36021b448781a3055909 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Fri, 10 Oct 2014 16:08:23 -0300 Subject: [PATCH 17/36] Somewhat further. Have a one-off and the ability to query, iterate and set values of multiple nodes in XML in one shot. Going to add some temporary "entity" implementation. --- includes/object.entity_controller.inc | 1 + includes/tuque_wrapper.inc | 8 - includes/utilities.inc | 10 +- islandora.info | 1 + islandora.module | 25 ++- islandora.rules.inc | 234 +++++++++++++++++++++++--- 6 files changed, 242 insertions(+), 37 deletions(-) diff --git a/includes/object.entity_controller.inc b/includes/object.entity_controller.inc index 9464d7b5..87b5e4de 100644 --- a/includes/object.entity_controller.inc +++ b/includes/object.entity_controller.inc @@ -30,6 +30,7 @@ class IslandoraObjectEntityController implements DrupalEntityControllerInterface */ public function load($ids = array(), $conditions = array()) { if (!empty($conditions)) { + // TODO: Allow loading by specifying IDs in the condition. throw new Exception('Conditions not implemented.'); } diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc index 53942554..d14a86b3 100644 --- a/includes/tuque_wrapper.inc +++ b/includes/tuque_wrapper.inc @@ -115,10 +115,6 @@ class IslandoraFedoraRepository extends FedoraRepository { foreach ($object as $dsid => $datastream) { islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_INGESTED_HOOK, $object->models, $dsid, $object, $datastream); } - // Fire of event if rules is enabled. - if (module_exists('rules')) { - rules_invoke_event('islandora_object_ingested', $object); - } return $ret; } catch (Exception $e) { @@ -228,10 +224,6 @@ class IslandoraFedoraObject extends FedoraObject { if ($this->state == 'D') { islandora_invoke_object_hooks(ISLANDORA_OBJECT_PURGED_HOOK, $this->models, $this->id); } - // Fire of event if rules is enabled. - if (module_exists('rules')) { - rules_invoke_event('islandora_object_modified', $object); - } } catch (Exception $e) { watchdog('islandora', 'Failed to modify object: @pid
    code: @code
    message: @msg', array( diff --git a/includes/utilities.inc b/includes/utilities.inc index 26633df5..7476948b 100644 --- a/includes/utilities.inc +++ b/includes/utilities.inc @@ -188,12 +188,18 @@ function islandora_describe_repository($url = NULL) { */ function islandora_invoke_hook_list($hook, array $refinements, array $args) { $return = array(); - foreach (islandora_build_hook_list($hook, $refinements) as $hook) { - array_unshift($args, $hook); + foreach (islandora_build_hook_list($hook, $refinements) as $refined_hook) { + array_unshift($args, $refined_hook); $result = call_user_func_array('module_invoke_all', $args); $return = array_merge_recursive($return, $result); array_shift($args); } + if (module_exists('rules') && $event = rules_get_cache("event_$hook")) { + $parameters = $event->parameterInfo(); + $rule_args = array_slice($args, 0, count($parameters)); + array_unshift($rule_args, $hook); + $result = call_user_func_array('rules_invoke_event', $rule_args); + } return $return; } diff --git a/islandora.info b/islandora.info index 55c50359..580a81ac 100644 --- a/islandora.info +++ b/islandora.info @@ -13,6 +13,7 @@ files[] = includes/dublin_core.inc files[] = includes/tuque.inc files[] = includes/tuque_wrapper.inc files[] = includes/object.entity_controller.inc +files[] = includes/datastream.entity_controller.inc files[] = tests/includes/datastream_validators.inc files[] = tests/includes/islandora_web_test_case.inc files[] = tests/includes/islandora_unit_test_case.inc diff --git a/islandora.module b/islandora.module index 0b2a3ce8..85bcd2bc 100644 --- a/islandora.module +++ b/islandora.module @@ -1543,21 +1543,25 @@ function islandora_entity_property_info() { 'type' => 'text', 'label' => t('Object Label'), 'description' => t('The label of the object.'), + 'setter callback' => 'entity_property_verbatim_set', ); $object_properties['owner'] = array( 'type' => 'text', 'label' => t('Object Owner'), 'description' => t('The name of the owner of the object.'), + 'setter callback' => 'entity_property_verbatim_set', ); $object_properties['state'] = array( 'type' => 'text', 'label' => t('Object State'), 'description' => t('An initial representing the state of the object.'), + 'setter callback' => 'entity_property_verbatim_set', ); $object_properties['models'] = array( 'type' => 'list', 'label' => t('Content Models'), 'description' => t('The list of content models which the object has.'), + 'setter callback' => 'entity_property_verbatim_set', ); $object_properties['createdDate'] = array( 'type' => 'text', @@ -1574,11 +1578,24 @@ function islandora_entity_property_info() { 'type' => 'text', 'label' => t('Datastream Label'), 'description' => t('The label of the datastream.'), + 'setter callback' => 'entity_property_verbatim_set', ); $datastream_properties['mimetype'] = array( 'type' => 'text', 'label' => t('MIME type'), 'description' => t('Content type of the datastream.'), + 'setter callback' => 'entity_property_verbatim_set', + ); + $datastream_properties['parent'] = array( + 'type' => 'islandora_object', + 'label' => t('Object'), + 'description' => t('The Tuque object on which this datastream exists.'), + ); + $datastream_properties['content'] = array( + 'type' => 'text', + 'label' => t('Datastream content'), + 'description' => t('The contents of the datastream; only useful when the content is textual.'), + 'setter callback' => 'entity_property_verbatim_set', ); return $info; @@ -1762,10 +1779,6 @@ function islandora_islandora_object_ingested(AbstractObject $object) { * equal to the current ingested datastream's id. */ function islandora_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) { - if (module_exists('rules')) { - rules_invoke_event('islandora_datastream_ingested', $object, $datastream->id); - } - module_load_include('inc', 'islandora', 'includes/derivatives'); // Defer derivatives if necessary. if (islandora_get_defer_derivatives_flag($object)) { @@ -1782,10 +1795,6 @@ function islandora_islandora_datastream_ingested(AbstractObject $object, Abstrac * existing derivatives will be updated to reflect the change in the source. */ function islandora_islandora_datastream_modified(AbstractObject $object, AbstractDatastream $datastream) { - if (module_exists('rules')) { - rules_invoke_event('islandora_datastream_modified', $object, $datastream->id); - } - module_load_include('inc', 'islandora', 'includes/derivatives'); $logging_results = islandora_do_derivatives($object, array( 'source_dsid' => $datastream->id, diff --git a/islandora.rules.inc b/islandora.rules.inc index 17fa8227..aca1d9dc 100644 --- a/islandora.rules.inc +++ b/islandora.rules.inc @@ -31,7 +31,7 @@ function islandora_rules_event_info() { 'description' => t('A Tuque object for the Fedora object on which the datastream exists, as an entity.'), ), 'datastream' => array( - 'type' => 'text', + 'type' => 'islandora_datastream', 'label' => t('Datastream ID'), 'description' => t('The ID of the ingested datastream.'), ), @@ -57,10 +57,37 @@ function islandora_rules_event_info() { 'label' => t('The modified object'), 'description' => t('A Tuque object for the Fedora object on which the datastream exists, as an entity.'), ), + 'datastream' => array( + 'type' => 'islandora_datastream', + 'label' => t('Datastream'), + 'description' => t('The modified datastream.'), + ), + ), + ), + 'islandora_object_purged' => array( + 'group' => t('Islandora'), + 'label' => t('Object purged'), + 'variables' => array( + 'object' => array( + 'type' => 'text', + 'label' => t('Object ID'), + 'description' => t('The ID of the purged object.'), + ), + ), + ), + 'islandora_datastream_purged' => array( + 'group' => t('Islandora'), + 'label' => t('Datastream purged'), + 'variables' => array( + 'object' => array( + 'type' => 'islandora_object', + 'label' => t('Object'), + 'description' => t('A Tuque object for the Fedora object from which the datastream exists, as an entity.'), + ), 'datastream' => array( 'type' => 'text', 'label' => t('Datastream ID'), - 'description' => t('The ID of the ingested datastream.'), + 'description' => t('The identifier of the purged datastream.'), ), ), ), @@ -105,15 +132,10 @@ function islandora_rules_relationship_parameter_array() { function islandora_rules_base_xpath_parameters() { return array( - 'object' => array( - 'type' => 'islandora_object', - 'label' => t('Object'), - 'description' => t('The object in which to check the XPath.'), - ), 'datastream' => array( - 'type' => 'text', - 'label' => t('Datastream ID'), - 'description' => t('The ID of the XML datastream to check.'), + 'type' => 'islandora_datastream', + 'label' => t('Datastream'), + 'description' => t('The XML datastream to check.'), ), 'xpath' => array( 'type' => 'text', @@ -167,8 +189,94 @@ function islandora_rules_action_info() { 'parameter' => islandora_rules_relationship_parameter_array(), ); + $cond['islandora_rules_datastream_load_domxpath'] = array( + 'label' => t('Load a DOMXPath for a given XML.'), + 'group' => t('Islandora DOMXPath'), + 'parameter' => array( + 'datastrea,' => array( + 'type' => 'text', + 'label' => t('XML'), + 'description' => t('A string containing the XML to load.'), + ), + ), + 'provides' => array( + 'islandora_domxpath' => array( + 'type' => 'islandora_domxpath', + 'label' => t('Loaded DOMXPath instance'), + ), + ), + ); + $cond['islandora_rules_datastream_load_xpath'] = array( + 'label' => t('Load a DOMXPath from a datastream.'), + 'group' => t('Islandora DOMXPath'), + 'parameter' => array( + 'datastream' => array( + 'type' => 'islandora_datastream', + 'label' => t('Datastream'), + 'description' => t('A datastream containing the XML to load.'), + ), + ), + 'provides' => array( + 'islandora_domxpath' => array( + 'type' => 'islandora_domxpath', + 'label' => t('Loaded DOMXPath instance'), + ), + ), + ); + $cond['islandora_rules_datastream_load_namespace_vocab'] = array( + 'label' => t('Register namespaces on a DOMXPath instance.'), + 'group' => t('Islandora DOMXPath'), + 'parameter' => array( + 'value' => array( + 'type' => 'islandora_domxpath', + 'label' => t('DOMXPath instance'), + 'description' => t('The DOMXPath instance on which to register the namespaces.'), + ), + 'xpath_namespaces' => array( + 'type' => 'taxonomy_vocabulary', + 'label' => t('XPath Namespace Taxonomy'), + 'description' => t('A flat taxonomy of which the terms are namespace prefixes and the description contains the URI for the namespace.') + ), + ), + ); + $cond['islandora_rules_datastream_query_xpath'] = array( + 'label' => t('Query nodes from DOMXPath instance.'), + 'group' => t('Islandora DOMXPath'), + 'parameter' => array( + 'xpath' => array( + 'type' => 'islandora_domxpath', + 'label' => t('DOMXPath instance'), + 'description' => t('The DOMXPath instance on which to perform the query.'), + ), + 'query' => array( + 'type' => 'text', + 'label' => t('XPath query'), + 'description' => t('The XPath query to perform.') + ), + ), + 'provides' => array( + 'nodes' => array( + 'type' => 'list', + 'label' => t('Queried DOMNode elements'), + ), + ), + ); + + $cond['islandora_rules_datastream_set_xpath'] = array( + 'label' => t('Set value in elements matched by an XPath in an XML datastream'), + 'group' => t('Islandora'), + 'parameter' => islandora_rules_base_xpath_parameters() + array( + 'value' => array( + 'type' => 'text', + 'label' => t('Value'), + 'description' => t('The value to set in the XML on elements matched by the XPath.'), + ), + ), + ); + return $cond; } + /** * Checks that there is a relationship match on the given object. * @@ -209,19 +317,107 @@ function islandora_object_add_relationship($sub, $pred_uri, $pred, $object, $typ $sub->relationships->add($pred_uri, $pred, $object, $type); } -function islandora_rules_datastream_has_xpath(AbstractObject $object, $datastream_id, $search_xpath, $xpath_vocab) { - if (!isset($object[$datastream_id])) { - // Datastream does no exists... No match. - return FALSE; - } - - $datastream = $object[$datastream_id]; +function islandora_rules_datastream_load_domxpath($string) { $doc = new DOMDocument(); - $doc->loadXML($datastream->content); + $doc->loadXML($string); $xpath = new DOMXPath($doc); + return array('islandora_domxpath' => $xpath); +} + +function islandora_rules_datastream_load_namespace_vocab($xpath, $xpath_vocab) { foreach (taxonomy_get_tree($xpath_vocab->vid, 0, 1, FALSE) as $term) { $xpath->registerNamespace($term->name, $term->description); } - $result = $xpath->query($search_xpath); +} + +/** + * Rules XPath helper; grab the datastream content and build a DOMXPath. + */ +function islandora_rules_datastream_load_xpath(AbstractDatastream $datastream, $xpath_vocab) { + $result = islandora_rules_datastream_load_domxpath($datastream->content, $xpath_vocab); + islandora_rules_datastream_load_namespace_vocab($result['islandora_domxpath'], $xpath_vocab); + return $result; +} + +function islandora_rules_datastream_has_xpath(AbstractDatastream $datastream, $search_xpath, $xpath_vocab) { + $xpath = islandora_rules_datastream_load_xpath($datastream, $xpath_vocab); + $result = $xpath['islandora_domxpath']->query($search_xpath); return $result->length > 0; } + +function islandora_rules_datastream_set_xpath(AbstractDatastream $datastream, $search_xpath, $xpath_vocab, $value) { + $xpath = islandora_rules_datastream_load_xpath($datastream, $xpath_vocab); + $result = $xpath['islandora_domxpath']->query($search_xpath); + foreach ($result as $node) { + $node->nodeValue = $value; + } + $datastream->content = $xpath['islandora_domxpath']->document->saveXML(); +} + +/** + * Implements hook_rules_data_info(). + */ +function islandora_rules_data_info() { + return array( + 'islandora_domxpath' => array( + 'label' => t('DOMXPath instance'), + 'group' => t('Islandora'), + 'property info' => array( + 'content' => array( + 'type' => 'text', + 'label' => t('XML Content'), + 'computed' => TRUE, + 'getter callback' => 'islandora_rules_get_domxpath_document_content', + 'token type' => 'string', + ), + ), + 'wrap' => TRUE, + ), + 'islandora_domnode' => array( + 'label' => t('DOMNode instance'), + 'group' => t('Islandora'), + 'property info' => array( + 'node_value' => array( + 'type' => 'text', + 'label' => t('Node value'), + 'computed' => TRUE, + 'getter callback' => 'islandora_rules_domnode_get', + 'setter callback' => 'islandora_rules_domnode_set', + 'property' => 'nodeValue', + 'token type' => 'string', + ), + 'text_content' => array( + 'type' => 'text', + 'label' => t('Text content'), + 'computed' => TRUE, + 'getter callback' => 'islandora_rules_domnode_get', + 'property' => 'textContent', + 'token type' => 'string', + ), + ), + 'wrap' => TRUE, + ), + 'islandora_domelement' => array( + 'label' => t('DOMElement instance'), + 'group' => t('Islandora'), + 'parent' => 'islandora_domnode', + 'wrap' => TRUE, + ), + ); +} + +function islandora_rules_domnode_get($data, $options, $name, $type, $info) { + return $data->$info['property']; +} + +function islandora_rules_domnode_set(&$data, $name, $value, $langcode, $type, $info) { + $data->$info['property'] = $value; +} + +function islandora_rules_get_domxpath_document_content(DOMXPath $xpath) { + return $xpath->document->saveXML(); +} + +function islandora_rules_datastream_query_xpath(DOMXPath $xpath, $query) { + return array('nodes' => iterator_to_array($xpath->query($query))); +} From 2bc288d8b125bed581ca15280c0c55b75a4c1cd1 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 14 Oct 2014 13:27:30 -0300 Subject: [PATCH 18/36] Fix setting of properties and flesh out comments a bit. --- islandora.module | 26 +++++-- islandora.rules.inc | 184 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 183 insertions(+), 27 deletions(-) diff --git a/islandora.module b/islandora.module index 85bcd2bc..b98b713a 100644 --- a/islandora.module +++ b/islandora.module @@ -1543,25 +1543,25 @@ function islandora_entity_property_info() { 'type' => 'text', 'label' => t('Object Label'), 'description' => t('The label of the object.'), - 'setter callback' => 'entity_property_verbatim_set', + 'setter callback' => 'islandora_entity_set_property', ); $object_properties['owner'] = array( 'type' => 'text', 'label' => t('Object Owner'), 'description' => t('The name of the owner of the object.'), - 'setter callback' => 'entity_property_verbatim_set', + 'setter callback' => 'islandora_entity_set_property', ); $object_properties['state'] = array( 'type' => 'text', 'label' => t('Object State'), 'description' => t('An initial representing the state of the object.'), - 'setter callback' => 'entity_property_verbatim_set', + 'setter callback' => 'islandora_entity_set_property', ); $object_properties['models'] = array( 'type' => 'list', 'label' => t('Content Models'), 'description' => t('The list of content models which the object has.'), - 'setter callback' => 'entity_property_verbatim_set', + 'setter callback' => 'islandora_entity_set_property', ); $object_properties['createdDate'] = array( 'type' => 'text', @@ -1578,13 +1578,13 @@ function islandora_entity_property_info() { 'type' => 'text', 'label' => t('Datastream Label'), 'description' => t('The label of the datastream.'), - 'setter callback' => 'entity_property_verbatim_set', + 'setter callback' => 'islandora_entity_set_property', ); $datastream_properties['mimetype'] = array( 'type' => 'text', 'label' => t('MIME type'), 'description' => t('Content type of the datastream.'), - 'setter callback' => 'entity_property_verbatim_set', + 'setter callback' => 'islandora_entity_set_property', ); $datastream_properties['parent'] = array( 'type' => 'islandora_object', @@ -1595,7 +1595,7 @@ function islandora_entity_property_info() { 'type' => 'text', 'label' => t('Datastream content'), 'description' => t('The contents of the datastream; only useful when the content is textual.'), - 'setter callback' => 'entity_property_verbatim_set', + 'setter callback' => 'islandora_entity_set_property', ); return $info; @@ -2018,3 +2018,15 @@ function islandora_islandora_object_alter(AbstractObject $object, array &$contex islandora_set_defer_derivatives_flag($object); } } + +/** + * Set property on an entity. + * + * Drupal's usual entity_property_verbatim_set() does not work, as tries to use + * ArrayAccess stuff instead of setting properties directly. + */ +function islandora_entity_set_property(&$data, $name, $value, $langcode) { + if (is_object($data)) { + $data->$name = $value; + } +} diff --git a/islandora.rules.inc b/islandora.rules.inc index aca1d9dc..96e1fa5c 100644 --- a/islandora.rules.inc +++ b/islandora.rules.inc @@ -130,12 +130,20 @@ function islandora_rules_relationship_parameter_array() { ); } +/** + * Helper function; get default parameters for the XPath condition and action. + */ function islandora_rules_base_xpath_parameters() { return array( - 'datastream' => array( - 'type' => 'islandora_datastream', + 'object' => array( + 'type' => 'islandora_object', + 'label' => t('Object'), + 'description' => t('The object containing the datastream to check.'), + ), + 'datastream_id' => array( + 'type' => 'text', 'label' => t('Datastream'), - 'description' => t('The XML datastream to check.'), + 'description' => t('The identifier of the XML datastream to check.'), ), 'xpath' => array( 'type' => 'text', @@ -145,7 +153,7 @@ function islandora_rules_base_xpath_parameters() { 'xpath_namespaces' => array( 'type' => 'taxonomy_vocabulary', 'label' => t('XPath Namespace Taxonomy'), - 'description' => t('A flat taxonomy of which the terms are namespace prefixes and the description contains the URI for the namespace.') + 'description' => t('A flat taxonomy of which the terms are namespace prefixes and the description contains the URI for the namespace.'), ), ); } @@ -162,6 +170,22 @@ function islandora_rules_condition_info() { 'group' => t('Islandora'), 'parameter' => islandora_rules_relationship_parameter_array(), ); + $cond['islandora_object_has_datastream'] = array( + 'label' => t('Check object for existence of a datastream'), + 'group' => t('Islandora'), + 'parameter' => array( + 'object' => array( + 'type' => 'islandora_object', + 'label' => t('Object'), + 'description' => t('The object containing the datastream to check.'), + ), + 'datastream_id' => array( + 'type' => 'text', + 'label' => t('Datastream'), + 'description' => t('The identifier of the datastream to check.'), + ), + ), + ); $cond['islandora_rules_datastream_has_xpath'] = array( 'label' => t('Check for an XPath match in an XML datastream'), 'group' => t('Islandora'), @@ -189,11 +213,33 @@ function islandora_rules_action_info() { 'parameter' => islandora_rules_relationship_parameter_array(), ); + $cond['islandora_rules_datastream_load'] = array( + 'label' => t('Load a datastream from an object.'), + 'group' => t('Islandora'), + 'parameter' => array( + 'object' => array( + 'type' => 'islandora_object', + 'label' => t('Object'), + 'description' => t('A Tuque object for the Fedora object from which to load the datastream, as an entity.'), + ), + 'datastream_id' => array( + 'type' => 'text', + 'label' => t('Datastream ID'), + 'description' => t('A string containing the identity of the datastream to load from the object.'), + ), + ), + 'provides' => array( + 'datastream' => array( + 'type' => 'islandora_datastream', + 'label' => t('Loaded datastream instance'), + ), + ), + ); $cond['islandora_rules_datastream_load_domxpath'] = array( 'label' => t('Load a DOMXPath for a given XML.'), 'group' => t('Islandora DOMXPath'), 'parameter' => array( - 'datastrea,' => array( + 'datastream' => array( 'type' => 'text', 'label' => t('XML'), 'description' => t('A string containing the XML to load.'), @@ -235,7 +281,7 @@ function islandora_rules_action_info() { 'xpath_namespaces' => array( 'type' => 'taxonomy_vocabulary', 'label' => t('XPath Namespace Taxonomy'), - 'description' => t('A flat taxonomy of which the terms are namespace prefixes and the description contains the URI for the namespace.') + 'description' => t('A flat taxonomy of which the terms are namespace prefixes and the description contains the URI for the namespace.'), ), ), ); @@ -251,7 +297,7 @@ function islandora_rules_action_info() { 'query' => array( 'type' => 'text', 'label' => t('XPath query'), - 'description' => t('The XPath query to perform.') + 'description' => t('The XPath query to perform.'), ), ), 'provides' => array( @@ -277,6 +323,13 @@ function islandora_rules_action_info() { return $cond; } +/** + * Rules action callback; grab a datastream from an object. + */ +function islandora_rules_datastream_load(AbstractObject $object, $datastream_id) { + return array('datastream' => $object[$datastream_id]); +} + /** * Checks that there is a relationship match on the given object. * @@ -317,6 +370,9 @@ function islandora_object_add_relationship($sub, $pred_uri, $pred, $object, $typ $sub->relationships->add($pred_uri, $pred, $object, $type); } +/** + * Rules Action callback; instantiate a DOMXPath with some XML. + */ function islandora_rules_datastream_load_domxpath($string) { $doc = new DOMDocument(); $doc->loadXML($string); @@ -324,6 +380,15 @@ function islandora_rules_datastream_load_domxpath($string) { return array('islandora_domxpath' => $xpath); } +/** + * Rules Action callback; load namespaces onto a DOMXPath instance. + * + * @param DOMXPath $xpath + * A DOMXPath instance. + * @param object $xpath_vocab + * A loaded Drupal taxonomy vocabulary object, in which terms are understood + * to be namespace prefixes and descriptions are the namespace URIs. + */ function islandora_rules_datastream_load_namespace_vocab($xpath, $xpath_vocab) { foreach (taxonomy_get_tree($xpath_vocab->vid, 0, 1, FALSE) as $term) { $xpath->registerNamespace($term->name, $term->description); @@ -339,13 +404,21 @@ function islandora_rules_datastream_load_xpath(AbstractDatastream $datastream, $ return $result; } -function islandora_rules_datastream_has_xpath(AbstractDatastream $datastream, $search_xpath, $xpath_vocab) { +/** + * Rules Condition callback; test that an XPath returns a non-empty result set. + */ +function islandora_rules_datastream_has_xpath(AbstractObject $object, $datastream_id, $search_xpath, $xpath_vocab) { + $datastream = $object[$datastream_id]; $xpath = islandora_rules_datastream_load_xpath($datastream, $xpath_vocab); $result = $xpath['islandora_domxpath']->query($search_xpath); return $result->length > 0; } -function islandora_rules_datastream_set_xpath(AbstractDatastream $datastream, $search_xpath, $xpath_vocab, $value) { +/** + * Rules Action callback; set the value of all matched nodes. + */ +function islandora_rules_datastream_set_xpath(AbstractObject $object, $datastream_id, $search_xpath, $xpath_vocab, $value) { + $datastream = $object[$datastream_id]; $xpath = islandora_rules_datastream_load_xpath($datastream, $xpath_vocab); $result = $xpath['islandora_domxpath']->query($search_xpath); foreach ($result as $node) { @@ -364,12 +437,12 @@ function islandora_rules_data_info() { 'group' => t('Islandora'), 'property info' => array( 'content' => array( - 'type' => 'text', - 'label' => t('XML Content'), - 'computed' => TRUE, - 'getter callback' => 'islandora_rules_get_domxpath_document_content', - 'token type' => 'string', - ), + 'type' => 'text', + 'label' => t('XML Content'), + 'computed' => TRUE, + 'getter callback' => 'islandora_rules_get_domxpath_document_content', + 'token type' => 'string', + ), ), 'wrap' => TRUE, ), @@ -381,8 +454,8 @@ function islandora_rules_data_info() { 'type' => 'text', 'label' => t('Node value'), 'computed' => TRUE, - 'getter callback' => 'islandora_rules_domnode_get', - 'setter callback' => 'islandora_rules_domnode_set', + 'getter callback' => 'islandora_rules_property_get', + 'setter callback' => 'islandora_rules_property_set', 'property' => 'nodeValue', 'token type' => 'string', ), @@ -390,7 +463,7 @@ function islandora_rules_data_info() { 'type' => 'text', 'label' => t('Text content'), 'computed' => TRUE, - 'getter callback' => 'islandora_rules_domnode_get', + 'getter callback' => 'islandora_rules_property_get', 'property' => 'textContent', 'token type' => 'string', ), @@ -406,18 +479,89 @@ function islandora_rules_data_info() { ); } -function islandora_rules_domnode_get($data, $options, $name, $type, $info) { +/** + * Property setter helper; set a property on an object. + * + * In Rules, properties can contain lowercase and numeric characters. Since + * we want to refer to "nodeValue", we have to step around the Rules constraint. + * + * @param object $data + * The object on which to set the property, described by $info['property']. + * @param array $options + * An array of options... Not sure how it's used? Not touched by us, in any + * case. :P + * @param string $name + * The name of the property to set, as used by Rules. + * @param string $type + * The type of object on which the property is being set, as used by Rules. + * @param array $info + * An associative array describing this property. In addition to that + * required by Rules/the Entity API, should contain: + * - property: A string indicate the actual property on the $data we wish to + * set. + */ +function islandora_rules_property_get($data, array $options, $name, $type, $info) { return $data->$info['property']; } -function islandora_rules_domnode_set(&$data, $name, $value, $langcode, $type, $info) { +/** + * Property setter helper; set a property on an object. + * + * In Rules, properties can contain lowercase and numeric characters. Since + * we want to refer to "nodeValue", we have to step around the Rules constraint. + * + * @param object $data + * The object on which to set the property, described by $info['property']. + * @param string $name + * The name of the property to set, as used by Rules. + * @param mixed $value + * The value to set on the property. + * @param string $langcode + * A string indicating the language being set, or NULL. + * @param string $type + * The type of object on which the property is being set, as used by Rules. + * @param array $info + * An associative array describing this property. In addition to that + * required by Rules/the Entity API, should contain: + * - property: A string indicate the actual property on the $data we wish to + * set. + */ +function islandora_rules_property_set(&$data, $name, $value, $langcode, $type, $info) { $data->$info['property'] = $value; } +/** + * Rules property "get" callback; get XML contained in a DOMXPath instance. + * + * @param DOMXPath $xpath + * A DOMXPath instance. + * + * @return string + * The XML contained inside of the DOMXPath instance. + */ function islandora_rules_get_domxpath_document_content(DOMXPath $xpath) { return $xpath->document->saveXML(); } +/** + * Rules action callback; perform a query on a DOMXPath instance. + * + * @param DOMXPath $xpath + * A DOMXPath instance. + * @param string $query + * An XPath query. + * + * @return array + * An array containing: + * - nodes: An array containing the results of the query. + */ function islandora_rules_datastream_query_xpath(DOMXPath $xpath, $query) { return array('nodes' => iterator_to_array($xpath->query($query))); } + +/** + * Rules condition callback; check for the datastream on an object. + */ +function islandora_object_has_datastream(AbstractObject $object, $datastream_id) { + return isset($object[$datastream_id]); +} From f82be2ed9c39f933fa7540f699ad8995a00485bd Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 14 Oct 2014 13:47:00 -0300 Subject: [PATCH 19/36] Adjust string. --- islandora.rules.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/islandora.rules.inc b/islandora.rules.inc index 96e1fa5c..be6ec855 100644 --- a/islandora.rules.inc +++ b/islandora.rules.inc @@ -82,7 +82,7 @@ function islandora_rules_event_info() { 'object' => array( 'type' => 'islandora_object', 'label' => t('Object'), - 'description' => t('A Tuque object for the Fedora object from which the datastream exists, as an entity.'), + 'description' => t('A Tuque object for the Fedora object on which the datastream existed, as an entity.'), ), 'datastream' => array( 'type' => 'text', From 3b9eeef6da1c6d31c069fce95024944e28127103 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 14 Oct 2014 14:55:02 -0300 Subject: [PATCH 20/36] Add "state" property to datastreams. --- islandora.module | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/islandora.module b/islandora.module index b98b713a..ac63069c 100644 --- a/islandora.module +++ b/islandora.module @@ -1574,6 +1574,12 @@ function islandora_entity_property_info() { 'label' => t('ID'), 'description' => t('The identifier of the datastream.'), ); + $datastream_properties['state'] = array( + 'type' => 'text', + 'label' => t('Datastream State'), + 'description' => t('An initial representing the state of the datastream.'), + 'setter callback' => 'islandora_entity_set_property', + ); $datastream_properties['label'] = array( 'type' => 'text', 'label' => t('Datastream Label'), From 969ef483dc110debf69f908ca0d61667fe55b7db Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 14 Oct 2014 14:55:34 -0300 Subject: [PATCH 21/36] Add ability to specify context nodes when XPathing. --- islandora.rules.inc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/islandora.rules.inc b/islandora.rules.inc index be6ec855..2562656a 100644 --- a/islandora.rules.inc +++ b/islandora.rules.inc @@ -299,6 +299,14 @@ function islandora_rules_action_info() { 'label' => t('XPath query'), 'description' => t('The XPath query to perform.'), ), + 'context_node' => array( + 'type' => 'islandora_domnode', + 'label' => t('Context Node'), + 'description' => t('If provided, the query will be performed relative to the provided node.'), + 'optional' => TRUE, + 'default value' => NULL, + 'allow null' => TRUE, + ), ), 'provides' => array( 'nodes' => array( @@ -550,13 +558,16 @@ function islandora_rules_get_domxpath_document_content(DOMXPath $xpath) { * A DOMXPath instance. * @param string $query * An XPath query. + * @param DOMNode $context_node + * An optional DOMNode. If provided, the query will be performed relative to + * the given node. * * @return array * An array containing: * - nodes: An array containing the results of the query. */ -function islandora_rules_datastream_query_xpath(DOMXPath $xpath, $query) { - return array('nodes' => iterator_to_array($xpath->query($query))); +function islandora_rules_datastream_query_xpath(DOMXPath $xpath, $query, DOMNode $context_node = NULL) { + return array('nodes' => iterator_to_array($xpath->query($query, $context_node))); } /** From c4922ff4b41b2e07553444d5572aa4366ec17214 Mon Sep 17 00:00:00 2001 From: Adam Vessey Date: Tue, 14 Oct 2014 14:56:16 -0300 Subject: [PATCH 22/36] Drop reference to deleted "datastream entity controller". --- islandora.info | 1 - 1 file changed, 1 deletion(-) diff --git a/islandora.info b/islandora.info index 580a81ac..55c50359 100644 --- a/islandora.info +++ b/islandora.info @@ -13,7 +13,6 @@ files[] = includes/dublin_core.inc files[] = includes/tuque.inc files[] = includes/tuque_wrapper.inc files[] = includes/object.entity_controller.inc -files[] = includes/datastream.entity_controller.inc files[] = tests/includes/datastream_validators.inc files[] = tests/includes/islandora_web_test_case.inc files[] = tests/includes/islandora_unit_test_case.inc From 040ce23d84987c319b4afbec5e898410c7431e00 Mon Sep 17 00:00:00 2001 From: qadan Date: Wed, 15 Oct 2014 09:13:40 -0300 Subject: [PATCH 23/36] apparently not --- tests/default.test_config.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/default.test_config.ini b/tests/default.test_config.ini index 28128574..f07fb4c3 100644 --- a/tests/default.test_config.ini +++ b/tests/default.test_config.ini @@ -1,6 +1,6 @@ [fedora] fedora_url = "http://localhost:8080/fedora" use_drupal_filter = TRUE -drupal_filter_file = "/usr/local/fedora/server/config/filter-drupal.xmll" +drupal_filter_file = "/usr/local/fedora/server/config/filter-drupal.xml" admin_user = "fedoraAdmin" admin_pass = "fedoraAdmin" From 1f26d08c5cd3455877b5ea9582d62a3217f5dde9 Mon Sep 17 00:00:00 2001 From: qadan Date: Wed, 15 Oct 2014 09:26:34 -0300 Subject: [PATCH 24/36] super typo city --- tests/includes/islandora_web_test_case.inc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/includes/islandora_web_test_case.inc b/tests/includes/islandora_web_test_case.inc index 16146b12..5e422418 100644 --- a/tests/includes/islandora_web_test_case.inc +++ b/tests/includes/islandora_web_test_case.inc @@ -260,8 +260,7 @@ class IslandoraWebTestCase extends DrupalWebTestCase { * If TRUE, this will only delete objects owned by users in $this->users. * * @return bool - * If the deletion fails, return FALSE TRUE, this will only delete objects - * owned by users in $this->users. + * If the deletion fails, return FALSE. */ public function deleteObject($pid, $button = NULL, $safety = TRUE) { $object = islandora_object_load($pid); From 0732b7d142da13d67790d3445333fd8a48d4c0fb Mon Sep 17 00:00:00 2001 From: willtp87 Date: Wed, 5 Nov 2014 17:42:20 -0400 Subject: [PATCH 25/36] Less unnecessary datastream versions on replacement. --- includes/datastream.version.inc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/datastream.version.inc b/includes/datastream.version.inc index e97640d4..4f2a9960 100644 --- a/includes/datastream.version.inc +++ b/includes/datastream.version.inc @@ -344,7 +344,9 @@ function islandora_datastream_version_replace_form_submit($form, &$form_state) { $file = file_load($form_state['values']['file']); try { $ds = $object[$form_state['dsid']]; - $ds->mimetype = $file->filemime; + if ($ds->mimetype != $file->filemime) { + $ds->mimetype = $file->filemime; + } $path = drupal_realpath($file->uri); $ds->setContentFromFile($path); file_delete($file); From 64413a62a721788132fc5bfe7b60924d48ff7ab8 Mon Sep 17 00:00:00 2001 From: Jordan Dukart Date: Wed, 12 Nov 2014 15:27:49 -0400 Subject: [PATCH 26/36] Add json as a MIME. --- includes/mime_detect.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/mime_detect.inc b/includes/mime_detect.inc index 8da0ebe7..8eb681ab 100644 --- a/includes/mime_detect.inc +++ b/includes/mime_detect.inc @@ -227,6 +227,7 @@ class MimeDetect { 'bin' => 'application/octet-stream', // Web Archives: "warc" => "application/warc", + "json" => "application/json", ); protected $protectedFileExtensions; protected $extensionExceptions = array( From 1316c9a3841846c78840c4951028b65b033b71f6 Mon Sep 17 00:00:00 2001 From: Matthew Perry Date: Fri, 14 Nov 2014 12:55:56 -0400 Subject: [PATCH 27/36] Add a hidden next button at the top of the form so that it becomes the first button triggered if a user submits the form with the enter key. --- includes/ingest.form.inc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/includes/ingest.form.inc b/includes/ingest.form.inc index 6c802f44..c83b140c 100644 --- a/includes/ingest.form.inc +++ b/includes/ingest.form.inc @@ -499,6 +499,14 @@ function islandora_ingest_form_stepify(array $form, array &$form_state, array $s ); $form['prev'] = $first_form_step ? NULL : islandora_ingest_form_previous_button($form_state); $form['next'] = $last_form_step ? islandora_ingest_form_ingest_button($form_state) : islandora_ingest_form_next_button($form_state); + // Duplicate next button and hide it at the top of the form so that the form + // always triggers "next" if the user submits the form with the enter key. + if (!is_null($form['prev'])) { + $form['hidden_next'] = $form['next']; + $form['hidden_next']['#weight'] = -99; + $form['hidden_next']['#prefix'] = '
    '; + $form['hidden_next']['#suffix'] = '
    '; + } // Allow for a hook_form_FORM_ID_alter(). drupal_alter(array('form_' . $step['form_id'], 'form'), $form, $form_state, $step['form_id']); return $form; From b726f2d5b6cdd10e73a179b8dc39a9285293b4d5 Mon Sep 17 00:00:00 2001 From: Matthew Perry Date: Tue, 18 Nov 2014 09:05:56 -0400 Subject: [PATCH 28/36] Updated JS to ignore hidden next button when adding the spinner to the form so it does not add two. --- js/spinner.js | 59 +++++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/js/spinner.js b/js/spinner.js index a755bcb4..0b4a3c74 100755 --- a/js/spinner.js +++ b/js/spinner.js @@ -22,36 +22,39 @@ }); for (var base in settings.spinner) { var id = '#' + base; - $(id, context).once('spinner', function () { - var spinner = new Spinner(settings.spinner[base].opts); - $(id).parents('form').one('submit', function(event) { - if ($(this).data('clicked').is(id)) { - event.preventDefault(); - // Add Message. - var message = $('
    ').text(settings.spinner[base].message); - $(id).after(message); - // Make UI changes. - spinner.spin(this); - $('#edit-next').hide(); - $('#edit-prev').hide(); - // Submit the form after a set timeout, this handles problems with - // safari, in that safari submit's immediately.. - if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) { - $(':submit').attr('disabled', 'disabled'); + // Don't add spinner to the hidden next/ingest button. + if (id != '#edit-hidden-next') { + $(id, context).once('spinner', function () { + var spinner = new Spinner(settings.spinner[base].opts); + $(id).parents('form').one('submit', function (event) { + if ($(this).data('clicked').is(id)) { + event.preventDefault(); + // Add Message. + var message = $('
    ').text(settings.spinner[base].message); + $(id).after(message); + // Make UI changes. + spinner.spin(this); + $('#edit-next').hide(); + $('#edit-prev').hide(); + // Submit the form after a set timeout, this handles problems with + // safari, in that safari submit's immediately.. + if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) { + $(':submit').attr('disabled', 'disabled'); + } + setTimeout(function () { + // Allow for the button to be clicked, then click it then + // prevent the default behavoir. + $(id).removeAttr('disabled') + .click() + .click(function (event) { + event.preventDefault(); + }); + }, 500); } - setTimeout(function() { - // Allow for the button to be clicked, then click it then - // prevent the default behavoir. - $(id).removeAttr('disabled') - .click() - .click(function(event) { - event.preventDefault(); - }); - }, 500); - } - return true; + return true; + }); }); - }); + } } } }; From 7df506eaaab9a5a342542e3f65b51c6c26bfa509 Mon Sep 17 00:00:00 2001 From: Nigel Banks Date: Fri, 21 Nov 2014 19:44:36 -0500 Subject: [PATCH 29/36] Allow users to re-create derivatives even if only one hook is available. --- includes/object_properties.form.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/object_properties.form.inc b/includes/object_properties.form.inc index f9c8e23b..b8fcef7e 100644 --- a/includes/object_properties.form.inc +++ b/includes/object_properties.form.inc @@ -31,7 +31,7 @@ function islandora_object_properties_form(array $form, array &$form_state, Abstr module_load_include('inc', 'islandora', 'includes/derivatives'); $hooks = islandora_invoke_hook_list(ISLANDORA_DERVIATIVE_CREATION_HOOK, $object->models, array($object)); $hooks = islandora_filter_derivatives($hooks, array('force' => TRUE), $object); - if (count($hooks) > 1) { + if (count($hooks) >= 1) { $regenerate_derivatives_access = TRUE; } } From b7fb48017ec6dc0eb0bc43a54595c63522d801f0 Mon Sep 17 00:00:00 2001 From: willtp87 Date: Fri, 5 Dec 2014 14:26:50 -0400 Subject: [PATCH 30/36] Some fixes and improovements for datastream uploads. --- includes/add_datastream.form.inc | 58 +++++++++++++++----------------- includes/datastream.version.inc | 20 ++++------- includes/mimetype.utils.inc | 28 +++++++++++++++ 3 files changed, 61 insertions(+), 45 deletions(-) diff --git a/includes/add_datastream.form.inc b/includes/add_datastream.form.inc index dd5b0dbb..380880d2 100644 --- a/includes/add_datastream.form.inc +++ b/includes/add_datastream.form.inc @@ -27,8 +27,8 @@ function islandora_add_datastream_form(array $form, array &$form_state, Abstract // @deprecated Storing objects in $form_state is asking for a bad time... // Causes issues with derivative generation when we try to use it. $form_state['object'] = $object; - $form_state['datastream_requirements'] = islandora_get_missing_datastreams_requirements($object); - $unused_datastreams = array_keys($form_state['datastream_requirements']); + $datastream_requirements = islandora_get_missing_datastreams_requirements($object); + $unused_datastreams = array_keys($datastream_requirements); $unused_datastreams = "'" . implode("', '", $unused_datastreams) . "'"; $upload_size = min((int) ini_get('post_max_size'), (int) ini_get('upload_max_filesize')); return array( @@ -38,7 +38,7 @@ function islandora_add_datastream_form(array $form, array &$form_state, Abstract ), 'dsid_fieldset' => array( '#type' => 'fieldset', - '#title' => 'Add a datastream', + '#title' => 'Add a Datastream', '#collapsible' => FALSE, '#collapsed' => FALSE, 'dsid' => array( @@ -60,7 +60,7 @@ function islandora_add_datastream_form(array $form, array &$form_state, Abstract '#required' => TRUE, '#size' => 64, '#maxlength' => 64, - '#description' => t('A human-readable label'), + '#description' => t('A human-readable label.'), '#type' => 'textfield', '#element_validate' => array('islandora_add_datastream_form_field_does_not_contain_a_forward_slash'), ), @@ -69,10 +69,11 @@ function islandora_add_datastream_form(array $form, array &$form_state, Abstract '#required' => TRUE, '#title' => t('Upload Document'), '#size' => 48, - '#description' => t('Select a file to upload.
    Files must be less than @size MB.', array('@size' => $upload_size)), + '#description' => t('Select a file to upload.
    Files must be less than @size MB.', array('@size' => $upload_size)), '#default_value' => isset($form_state['values']['files']) ? $form_state['values']['files'] : NULL, - '#upload_location' => 'temporary://', + '#upload_location' => 'public://', '#upload_validators' => array( + // Disable default file_validate_extensions; we need direct control. 'file_validate_extensions' => array(NULL), // Assume its specified in MB. 'file_validate_size' => array($upload_size * 1024 * 1024), @@ -136,6 +137,26 @@ function islandora_add_datastream_form_field_is_valid_dsid(array $element, array } } +/** + * Validation callback for islandora_add_datastream_form. + * + * Checks if the given datastream can accept the given MIME type. + */ +function islandora_add_datastream_form_validate(array $form, array &$form_state) { + module_load_include('inc', 'islandora', 'includes/mimetype.utils'); + $extensions = islandora_get_extensions_for_datastream( + $form_state['object'], + $form_state['values']['dsid'] + ); + $file = file_load($form_state['values']['file']); + if ($file) { + $errors = file_validate_extensions($file, implode(' ', $extensions)); + if (count($errors) > 0) { + form_set_error('file', "{$errors[0]} (for the set DSID)"); + } + } +} + /** * Checks if the given form field contains a "/" character. * @@ -152,31 +173,6 @@ function islandora_add_datastream_form_field_does_not_contain_a_forward_slash(ar } } -/** - * Checks if the given datastream requires the upload to be a certain MIME type. - * - * @param array $form - * The Drupal form. - * @param array $form_state - * The Drupal form state. - */ -function islandora_add_datastream_form_validate(array $form, array &$form_state) { - $file = file_load($form_state['values']['file']); - $dsid = $form_state['values']['dsid']; - if (isset($form_state['datastream_requirements'][$dsid]) && $file) { - $allowed_types = $form_state['datastream_requirements'][$dsid]['mime']; - $mime_detect = new MimeDetect(); - $allowed_extensions = array(); - foreach ($allowed_types as $mime) { - $allowed_extensions = array_merge($allowed_extensions, $mime_detect->getValidExtensions($mime)); - } - $errors = file_validate_extensions($file, implode(' ', $allowed_extensions)); - if (count($errors) > 0) { - form_set_error('file', $errors[0]); - } - } -} - /** * Adds the new datastream based on the submitted values. * diff --git a/includes/datastream.version.inc b/includes/datastream.version.inc index 4f2a9960..225e5ff3 100644 --- a/includes/datastream.version.inc +++ b/includes/datastream.version.inc @@ -281,31 +281,23 @@ function islandora_datastream_version_replace_form($form, &$form_state, Abstract $form_state['object_id'] = $object->id; $form_state['dsid'] = $datastream->id; $form_state['object'] = $object; - $datastream_mime_map = islandora_get_object_extensions($object); - $current_mime = $datastream->mimetype; - $mimes = $datastream_mime_map[$datastream->id]['mime']; - if (!in_array($current_mime, $mimes)) { - $mimes[] = $current_mime; - } - $extensions = array(); - foreach ($mimes as $mime) { - $extensions = array_merge($extensions, islandora_get_extensions_for_mimetype($mime)); - } + + $extensions = islandora_get_extensions_for_datastream($object, $datastream->id); $valid_extensions = implode(' ', $extensions); $upload_size = min((int) ini_get('post_max_size'), (int) ini_get('upload_max_filesize')); return array( 'dsid_fieldset' => array( '#type' => 'fieldset', - '#title' => t("Update datastream with latest version"), + '#title' => t("Update Datastream"), '#collapsible' => FALSE, '#collapsed' => FALSE, 'dsid' => array( '#type' => 'markup', - '#markup' => "
    DSID: $datastream->id
    ", + '#markup' => "
    DSID: $datastream->id
    ", ), 'label' => array( '#type' => 'markup', - '#markup' => "
    Label: $datastream->label
    ", + '#markup' => "
    Label: $datastream->label
    ", ), 'file' => array( '#type' => 'managed_file', @@ -313,7 +305,7 @@ function islandora_datastream_version_replace_form($form, &$form_state, Abstract '#title' => t('Upload Document'), '#size' => 64, '#description' => t('Select a file to upload.
    Files must be less than @size MB.', array('@size' => $upload_size)), - '#upload_location' => 'temporary://', + '#upload_location' => 'public://', '#upload_validators' => array( 'file_validate_extensions' => array($valid_extensions), // Assume its specified in MB. diff --git a/includes/mimetype.utils.inc b/includes/mimetype.utils.inc index 1a20859d..4d87409d 100644 --- a/includes/mimetype.utils.inc +++ b/includes/mimetype.utils.inc @@ -58,3 +58,31 @@ function islandora_get_extensions_for_mimetype($mimetype) { } return $extensions; } + +/** + * Mimes accepted by a datastream. + * + * @param AbstractObject $object + * Object to check for extensions. + * @param string $dsid + * Datastream ID to check for extensions. + * + * @return array + * Mimes accepted by the datastream ID on the object. + */ +function islandora_get_extensions_for_datastream(AbstractObject $object, $dsid) { + module_load_include('inc', 'islandora', 'includes/utilities'); + $datastream_mime_map = islandora_get_datastreams_requirements_from_models($object->models); + $mimes = $datastream_mime_map[$dsid]['mime']; + if (isset($object[$dsid])) { + $current_mime = $object[$dsid]->mimetype; + if (!in_array($current_mime, $mimes)) { + $mimes[] = $current_mime; + } + } + $extensions = array(); + foreach ($mimes as $mime) { + $extensions = array_merge($extensions, islandora_get_extensions_for_mimetype($mime)); + } + return $extensions; +} From 548701584b0a0bc60bd68d5e02ed1c08991cf8d9 Mon Sep 17 00:00:00 2001 From: nruest Date: Fri, 5 Dec 2014 14:10:25 -0500 Subject: [PATCH 31/36] Update codesniffer. --- tests/scripts/travis_setup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/scripts/travis_setup.sh b/tests/scripts/travis_setup.sh index 84b6c44c..22fe9d7c 100755 --- a/tests/scripts/travis_setup.sh +++ b/tests/scripts/travis_setup.sh @@ -22,8 +22,8 @@ tar xf drush-6.3.tar.gz sudo mv drush-6.3 /opt/ sudo ln -s /opt/drush-6.3/drush /usr/bin/drush -wget http://alpha.library.yorku.ca/PHP_CodeSniffer-1.5.4.tgz -pear install PHP_CodeSniffer-1.5.4.tgz +wget http://alpha.library.yorku.ca/PHP_CodeSniffer-1.5.6.tgz +pear install PHP_CodeSniffer-1.5.6.tgz wget http://alpha.library.yorku.ca/phpcpd.phar sudo mv phpcpd.phar /usr/local/bin/phpcpd From e9b47575513d9a65330c81c9514c68907d44188d Mon Sep 17 00:00:00 2001 From: willtp87 Date: Fri, 5 Dec 2014 16:22:29 -0400 Subject: [PATCH 32/36] More translation. --- includes/add_datastream.form.inc | 7 +++++-- includes/datastream.version.inc | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/includes/add_datastream.form.inc b/includes/add_datastream.form.inc index 380880d2..40e1537d 100644 --- a/includes/add_datastream.form.inc +++ b/includes/add_datastream.form.inc @@ -38,7 +38,7 @@ function islandora_add_datastream_form(array $form, array &$form_state, Abstract ), 'dsid_fieldset' => array( '#type' => 'fieldset', - '#title' => 'Add a Datastream', + '#title' => t('Add a Datastream'), '#collapsible' => FALSE, '#collapsed' => FALSE, 'dsid' => array( @@ -152,7 +152,10 @@ function islandora_add_datastream_form_validate(array $form, array &$form_state) if ($file) { $errors = file_validate_extensions($file, implode(' ', $extensions)); if (count($errors) > 0) { - form_set_error('file', "{$errors[0]} (for the set DSID)"); + form_set_error( + 'file', + t("!error (for the set DSID)", array('!error' => $errors[0])) + ); } } } diff --git a/includes/datastream.version.inc b/includes/datastream.version.inc index 225e5ff3..a8ecf102 100644 --- a/includes/datastream.version.inc +++ b/includes/datastream.version.inc @@ -293,11 +293,11 @@ function islandora_datastream_version_replace_form($form, &$form_state, Abstract '#collapsed' => FALSE, 'dsid' => array( '#type' => 'markup', - '#markup' => "
    DSID: $datastream->id
    ", + '#markup' => t("
    DSID: @dsid
    ", array('@dsid' => $datastream->id)), ), 'label' => array( '#type' => 'markup', - '#markup' => "
    Label: $datastream->label
    ", + '#markup' => t("
    Label: @label
    ", array('@label' => $datastream->label)), ), 'file' => array( '#type' => 'managed_file', From 578b3e64ef048ffb4378e662c5b9768593cca3e0 Mon Sep 17 00:00:00 2001 From: willtp87 Date: Fri, 5 Dec 2014 21:30:52 -0400 Subject: [PATCH 33/36] better documentation --- includes/mimetype.utils.inc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/mimetype.utils.inc b/includes/mimetype.utils.inc index 4d87409d..beb4dfef 100644 --- a/includes/mimetype.utils.inc +++ b/includes/mimetype.utils.inc @@ -60,15 +60,15 @@ function islandora_get_extensions_for_mimetype($mimetype) { } /** - * Mimes accepted by a datastream. + * Extensions for the mimes accepted by a datastream. * * @param AbstractObject $object * Object to check for extensions. * @param string $dsid * Datastream ID to check for extensions. * - * @return array - * Mimes accepted by the datastream ID on the object. + * @return string[] + * Extensions for the mimes accepted by the datastream ID on the object. */ function islandora_get_extensions_for_datastream(AbstractObject $object, $dsid) { module_load_include('inc', 'islandora', 'includes/utilities'); From f6523225a3c842cf101e32fbdf6dfc5f3d27f34d Mon Sep 17 00:00:00 2001 From: willtp87 Date: Mon, 8 Dec 2014 11:01:31 -0400 Subject: [PATCH 34/36] Can have non-defined DSs again. --- includes/add_datastream.form.inc | 3 ++- includes/mimetype.utils.inc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/includes/add_datastream.form.inc b/includes/add_datastream.form.inc index 40e1537d..4484a903 100644 --- a/includes/add_datastream.form.inc +++ b/includes/add_datastream.form.inc @@ -149,7 +149,8 @@ function islandora_add_datastream_form_validate(array $form, array &$form_state) $form_state['values']['dsid'] ); $file = file_load($form_state['values']['file']); - if ($file) { + // Only validate extensions if mimes defined in ds-composite. + if ($file && $extensions) { $errors = file_validate_extensions($file, implode(' ', $extensions)); if (count($errors) > 0) { form_set_error( diff --git a/includes/mimetype.utils.inc b/includes/mimetype.utils.inc index beb4dfef..312302b2 100644 --- a/includes/mimetype.utils.inc +++ b/includes/mimetype.utils.inc @@ -73,7 +73,7 @@ function islandora_get_extensions_for_mimetype($mimetype) { function islandora_get_extensions_for_datastream(AbstractObject $object, $dsid) { module_load_include('inc', 'islandora', 'includes/utilities'); $datastream_mime_map = islandora_get_datastreams_requirements_from_models($object->models); - $mimes = $datastream_mime_map[$dsid]['mime']; + $mimes = isset($datastream_mime_map[$dsid]) ? $datastream_mime_map[$dsid]['mime'] : array(); if (isset($object[$dsid])) { $current_mime = $object[$dsid]->mimetype; if (!in_array($current_mime, $mimes)) { From fd2214695686c6ba2b5ee1c9812f2486d1535c65 Mon Sep 17 00:00:00 2001 From: willtp87 Date: Mon, 8 Dec 2014 11:13:38 -0400 Subject: [PATCH 35/36] Stripping out duplicate extensions. --- includes/mimetype.utils.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/mimetype.utils.inc b/includes/mimetype.utils.inc index 312302b2..03708f99 100644 --- a/includes/mimetype.utils.inc +++ b/includes/mimetype.utils.inc @@ -84,5 +84,5 @@ function islandora_get_extensions_for_datastream(AbstractObject $object, $dsid) foreach ($mimes as $mime) { $extensions = array_merge($extensions, islandora_get_extensions_for_mimetype($mime)); } - return $extensions; + return array_unique($extensions); } From ccfc302cf99e2137530243adc0b99e5bb97d7d0a Mon Sep 17 00:00:00 2001 From: willtp87 Date: Thu, 11 Dec 2014 16:21:43 -0400 Subject: [PATCH 36/36] Using file_default_schema now that consensus has been reached. --- includes/add_datastream.form.inc | 2 +- includes/datastream.version.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/add_datastream.form.inc b/includes/add_datastream.form.inc index 4484a903..55b45a04 100644 --- a/includes/add_datastream.form.inc +++ b/includes/add_datastream.form.inc @@ -71,7 +71,7 @@ function islandora_add_datastream_form(array $form, array &$form_state, Abstract '#size' => 48, '#description' => t('Select a file to upload.
    Files must be less than @size MB.', array('@size' => $upload_size)), '#default_value' => isset($form_state['values']['files']) ? $form_state['values']['files'] : NULL, - '#upload_location' => 'public://', + '#upload_location' => file_default_scheme() . '://', '#upload_validators' => array( // Disable default file_validate_extensions; we need direct control. 'file_validate_extensions' => array(NULL), diff --git a/includes/datastream.version.inc b/includes/datastream.version.inc index a8ecf102..b79b5a80 100644 --- a/includes/datastream.version.inc +++ b/includes/datastream.version.inc @@ -305,7 +305,7 @@ function islandora_datastream_version_replace_form($form, &$form_state, Abstract '#title' => t('Upload Document'), '#size' => 64, '#description' => t('Select a file to upload.
    Files must be less than @size MB.', array('@size' => $upload_size)), - '#upload_location' => 'public://', + '#upload_location' => file_default_scheme() . '://', '#upload_validators' => array( 'file_validate_extensions' => array($valid_extensions), // Assume its specified in MB.