diff --git a/includes/datastream.version.inc b/includes/datastream.version.inc
index f245830c..515094bd 100644
--- a/includes/datastream.version.inc
+++ b/includes/datastream.version.inc
@@ -280,17 +280,16 @@ 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;
- $extensions = islandora_get_object_extensions($object);
+ $datastream_mime_map = islandora_get_object_extensions($object);
$mime_detect = new MimeDetect();
$ext = array();
- if (isset($extensions[$datastream->id])) {
- foreach ($extensions[$datastream->id]['mime'] as $key => $value) {
- $str = $mime_detect->getExtension($value);
- array_push($ext, $str);
+ if (isset($datastream_mime_map[$datastream->id])) {
+ foreach ($datastream_mime_map[$datastream->id]['mime'] as $key => $value) {
+ $extensions = $mime_detect->getValidExtensions($value);
+ $ext = array_merge($ext, $extensions);
}
}
- $comma = count($ext) > 1 ? "," : "";
- $ext = array(implode($comma, $ext));
+
$upload_size = min((int) ini_get('post_max_size'), (int) ini_get('upload_max_filesize'));
return array(
'dsid_fieldset' => array(
diff --git a/includes/ingest.form.inc b/includes/ingest.form.inc
index f7979063..b5a4740d 100644
--- a/includes/ingest.form.inc
+++ b/includes/ingest.form.inc
@@ -706,7 +706,11 @@ function islandora_ingest_form_ingest_button(array &$form_state) {
$validate_callback = $form_id . '_validate';
$validate = function_exists($validate_callback) ? array($validate_callback) : NULL;
$submit_callback = $form_id . '_submit';
- $submit = function_exists($submit_callback) ? array($submit_callback, 'islandora_ingest_form_submit') : array('islandora_ingest_form_submit');
+ $submit = function_exists($submit_callback) ? array(
+ $submit_callback,
+ 'islandora_ingest_form_pre_submit',
+ 'islandora_ingest_form_submit',
+ ) : array('islandora_ingest_form_pre_submit', 'islandora_ingest_form_submit');
return array(
'#type' => 'submit',
'#name' => 'ingest',
diff --git a/includes/mime_detect.inc b/includes/mime_detect.inc
index 03ece01f..74b87fd6 100644
--- a/includes/mime_detect.inc
+++ b/includes/mime_detect.inc
@@ -132,7 +132,8 @@ class MimeDetect {
'wbxml' => 'application/vnd.wap.wbxml',
'xht' => 'application/xhtml+xml',
'xhtml' => 'application/xhtml+xml',
- 'xsl' => 'text/xml',
+ 'xsl' => 'text/xsl',
+ 'xslt' => 'text/xsl',
'xml' => 'text/xml',
'csv' => 'text/csv',
'tsv' => 'text/tab-separated-values',
@@ -224,6 +225,8 @@ class MimeDetect {
"zip" => "application/x-zip",
// others:
'bin' => 'application/octet-stream',
+ // Web Archives:
+ "warc" => "application/warc",
);
protected $protectedFileExtensions;
protected $extensionExceptions = array(
diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc
index 573d7c62..348ac60a 100644
--- a/includes/tuque_wrapper.inc
+++ b/includes/tuque_wrapper.inc
@@ -144,6 +144,41 @@ class IslandoraFedoraObject extends FedoraObject {
protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream';
protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt';
+ /**
+ * Magical magic, to allow recursive modifications.
+ *
+ * So... Magic functions in PHP are not re-entrant... Meaning that if you
+ * have something which tries to call __set on an object anywhere later in
+ * the callstack after it has already been called, it will not call the
+ * magic method again; instead, it will set the property on the object
+ * proper. Here, we detect the property being set on the object proper, and
+ * restore the magic functionality as long as it keeps getting set...
+ *
+ * Not necessary to try to account for this in Tuque proper, as Tuque itself
+ * does not have a mechanism to trigger modifications resulting from other
+ * modifications.
+ *
+ * @param string $name
+ * The name of the property being set.
+ * @param mixed $value
+ * The value to which the property should be set.
+ */
+ public function __set($name, $value) {
+ parent::__set($name, $value);
+
+ // XXX: Due to the structure of the code, we cannot use property_exists()
+ // (because many of the properties are declared in the class, and the magic
+ // triggers due them being NULLed), nor can we use isset() (because it is
+ // implemented as another magic function...).
+ $vars = get_object_vars($this);
+ while (isset($vars[$name])) {
+ $new_value = $this->$name;
+ unset($this->$name);
+ parent::__set($name, $new_value);
+ $vars = get_object_vars($this);
+ }
+ }
+
/**
* Ingest the given datastream.
*
@@ -173,6 +208,30 @@ class IslandoraFedoraObject extends FedoraObject {
throw $e;
}
}
+
+ /**
+ * Inherits.
+ *
+ * Calls parent and invokes object modified and deleted(/purged) hooks.
+ *
+ * @see FedoraObject::modifyObject()
+ */
+ protected function modifyObject($params) {
+ try {
+ parent::modifyObject($params);
+ islandora_invoke_object_hooks(ISLANDORA_OBJECT_MODIFIED_HOOK, $this->models, $this);
+ if ($this->state == 'D') {
+ islandora_invoke_object_hooks(ISLANDORA_OBJECT_PURGED_HOOK, $this->models, $this->id);
+ }
+ }
+ catch (Exception $e) {
+ watchdog('islandora', 'Failed to modify object: @pidcode: @code
message: @msg', array(
+ '@pid' => $this->id,
+ '@code' => $e->getCode(),
+ '@msg' => $e->getMessage()), WATCHDOG_ERROR);
+ throw $e;
+ }
+ }
}
class IslandoraRepositoryConnection extends RepositoryConnection {}
@@ -219,25 +278,10 @@ class IslandoraFedoraApiM extends FedoraApiM {
if (isset($params['lastModifiedDate'])) {
$params['lastModifiedDate'] = (string) $object[$dsid]->createdDate;
}
- try {
- if ($context['block']) {
- throw new Exception('Modify Datastream was blocked.');
- }
- $ret = parent::modifyDatastream($pid, $dsid, $params);
- islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_MODIFIED_HOOK, $object->models, $dsid, $object, $datastream);
- if (isset($params['dsState']) && $params['dsState'] == 'D') {
- islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_PURGED_HOOK, $object->models, $dsid, $object, $dsid);
- }
- return $ret;
- }
- catch (Exception $e) {
- watchdog('islandora', 'Failed to modify datastream @dsid from @pidcode: @code
message: @msg', array(
- '@pid' => $pid,
- '@dsid' => $dsid,
- '@code' => $e->getCode(),
- '@msg' => $e->getMessage()), WATCHDOG_ERROR);
- throw $e;
+ if ($context['block']) {
+ throw new Exception('Modify Datastream was blocked.');
}
+ return parent::modifyDatastream($pid, $dsid, $params);
}
/**
@@ -254,24 +298,10 @@ class IslandoraFedoraApiM extends FedoraApiM {
);
islandora_alter_object($object, $context);
$params = $context['params'];
- try {
- if ($context['block']) {
- throw new Exception('Modify Object was blocked.');
- }
- $ret = parent::modifyObject($pid, $params);
- islandora_invoke_object_hooks(ISLANDORA_OBJECT_MODIFIED_HOOK, $object->models, $object);
- if (isset($params['state']) && $params['state'] == 'D') {
- islandora_invoke_object_hooks(ISLANDORA_OBJECT_PURGED_HOOK, $object->models, $object->id);
- }
- return $ret;
- }
- catch (Exception $e) {
- watchdog('islandora', 'Failed to modify object: @pidcode: @code
message: @msg', array(
- '@pid' => $pid,
- '@code' => $e->getCode(),
- '@msg' => $e->getMessage()), WATCHDOG_ERROR);
- throw $e;
+ if ($context['block']) {
+ throw new Exception('Modify Object was blocked.');
}
+ return parent::modifyObject($pid, $params);
}
/**
@@ -377,6 +407,66 @@ class IslandoraNewFedoraDatastream extends NewFedoraDatastream {
class IslandoraFedoraDatastream extends FedoraDatastream {
protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt';
protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion';
+
+ /**
+ * Magical magic, to allow recursive modifications.
+ *
+ * So... Magic functions in PHP are not re-entrant... Meaning that if you
+ * have something which tries to call __set on an object anywhere later in
+ * the callstack after it has already been called, it will not call the
+ * magic method again; instead, it will set the property on the object
+ * proper. Here, we detect the property being set on the object proper, and
+ * restore the magic functionality as long as it keeps getting set...
+ *
+ * Not necessary to try to account for this in Tuque proper, as Tuque itself
+ * does not have a mechanism to trigger modifications resulting from other
+ * modifications.
+ *
+ * @param string $name
+ * The name of the property being set.
+ * @param mixed $value
+ * The value to which the property should be set.
+ */
+ public function __set($name, $value) {
+ parent::__set($name, $value);
+
+ // XXX: Due to the structure of the code, we cannot use property_exists()
+ // (because many of the properties are declared in the class, and the magic
+ // triggers due them being NULLed), nor can we use isset() (because it is
+ // implemented as another magic function...).
+ $vars = get_object_vars($this);
+ while (isset($vars[$name])) {
+ $new_value = $this->$name;
+ unset($this->$name);
+ parent::__set($name, $new_value);
+ $vars = get_object_vars($this);
+ }
+ }
+
+ /**
+ * Inherits.
+ *
+ * Calls parent and invokes modified and purged hooks.
+ *
+ * @see FedoraDatastream::modifyDatastream()
+ */
+ protected function modifyDatastream(array $args) {
+ try {
+ parent::modifyDatastream($args);
+ islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_MODIFIED_HOOK, $this->parent->models, $this->id, $this->parent, $this);
+ if ($this->state == 'D') {
+ islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_PURGED_HOOK, $this->parent->models, $this->id, $this->parent, $this->id);
+ }
+ }
+ catch (Exception $e) {
+ watchdog('islandora', 'Failed to modify datastream @dsid from @pidcode: @code
message: @msg', array(
+ '@pid' => $this->parent->id,
+ '@dsid' => $this->id,
+ '@code' => $e->getCode(),
+ '@msg' => $e->getMessage()), WATCHDOG_ERROR);
+ throw $e;
+ }
+ }
}
class IslandoraFedoraDatastreamVersion extends FedoraDatastreamVersion {
diff --git a/includes/utilities.inc b/includes/utilities.inc
index 050921cc..26633df5 100644
--- a/includes/utilities.inc
+++ b/includes/utilities.inc
@@ -30,16 +30,16 @@ function islandora_convert_bytes_to_human_readable($bytes, $precision = 2) {
return $bytes . ' B';
}
elseif (($bytes >= $kilobyte) && ($bytes < $megabyte)) {
- return round($bytes / $kilobyte, $precision) . ' KB';
+ return round($bytes / $kilobyte, $precision) . ' KiB';
}
elseif (($bytes >= $megabyte) && ($bytes < $gigabyte)) {
- return round($bytes / $megabyte, $precision) . ' MB';
+ return round($bytes / $megabyte, $precision) . ' MiB';
}
elseif (($bytes >= $gigabyte) && ($bytes < $terabyte)) {
- return round($bytes / $gigabyte, $precision) . ' GB';
+ return round($bytes / $gigabyte, $precision) . ' GiB';
}
elseif ($bytes >= $terabyte) {
- return round($bytes / $terabyte, $precision) . ' TB';
+ return round($bytes / $terabyte, $precision) . ' TiB';
}
else {
return $bytes . ' B';
@@ -649,54 +649,6 @@ function islandora_system_settings_form_default_value($name, $default_value, arr
return isset($form_state['values'][$name]) ? $form_state['values'][$name] : variable_get($name, $default_value);
}
-/**
- * Returns basic information about DS-COMPOSITE-MODEL.
- *
- * @deprecated
- * The pre-existing--and more flexible--
- * islandora_get_datastreams_requirements_from_content_model() should be
- * preferred, as it addresses the case where a stream can be allowed to have
- * one of a set of mimetypes (this functions appears to only return the last
- * declared mimetype for a given datastream).
- *
- * @param string $pid
- * The PID of content model containing DS_COMP stream.
- *
- * @return array
- * An associative array mapping datastream IDs to an associative array
- * representing the parsed DS-COMPOSITE-MODEL of the form:
- * - DSID: A string containing the datastream ID.
- * - "mimetype": A string containing the last mimetype declared for the
- * given datastream ID.
- * - "optional": An optional boolean indicating that the given datastream
- * is optional.
- */
-function islandora_get_comp_ds_mappings($pid) {
- $message = islandora_deprecated('7.x-1.2', t('Refactor to use the more flexible islandora_get_datastreams_requirements_from_content_model().'));
- trigger_error(filter_xss($message), E_USER_DEPRECATED);
-
- $cm_object = islandora_object_load($pid);
- if (!isset($cm_object) || !isset($cm_object['DS-COMPOSITE-MODEL'])) {
- return FALSE;
- }
- $datastream = $cm_object['DS-COMPOSITE-MODEL'];
- $ds_comp_stream = $datastream->content;
- $sxml = new SimpleXMLElement($ds_comp_stream);
- $mappings = array();
- foreach ($sxml->dsTypeModel as $ds) {
- $dsid = (string) $ds['ID'];
- $optional = (string) $ds['optional'];
- foreach ($ds->form as $form) {
- $mime = (string) $form['MIME'];
- if ($optional) {
- $mappings[$dsid]['optional'] = $optional;
- }
- $mappings[$dsid]['mimetype'] = $mime;
- }
- }
- return $mappings;
-}
-
/**
* Checks that the given/current account has all the given permissions.
*
diff --git a/islandora.module b/islandora.module
index 31ea4e65..f0bf796b 100644
--- a/islandora.module
+++ b/islandora.module
@@ -184,7 +184,6 @@ function islandora_menu() {
ISLANDORA_INGEST,
), 2),
);
- $islandora_path = drupal_get_path('module', 'islandora');
$items['islandora/object/%islandora_object/manage/overview'] = array(
'title' => 'Overview',
'type' => MENU_DEFAULT_LOCAL_TASK,
@@ -1906,6 +1905,22 @@ function islandora_find_package($package_name) {
return $found && user_access('administer site configuration');
}
+/**
+ * Helper function for ingest steps and batches.
+ *
+ * When batches within batches are triggered within ingest steps
+ * the submit handler becomes out of scope. When it becomes time to execute the
+ * submit the function cannot be found and fails. This pre-submit is to
+ * get around this problem.
+ *
+ * @see https://www.drupal.org/node/2300367
+ *
+ * @see https://www.drupal.org/node/1300928
+ */
+function islandora_ingest_form_pre_submit($form, &$form_state) {
+ module_load_include('inc', 'islandora', 'includes/ingest.form');
+}
+
/**
* Implements hook_menu_local_tasks_alter().
*/
diff --git a/tests/hooks.test b/tests/hooks.test
index d08c537b..b8846c52 100644
--- a/tests/hooks.test
+++ b/tests/hooks.test
@@ -109,9 +109,11 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$this->repository->ingestObject($object);
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE;
+ $_SESSION['islandora_hooks']['iteration'][ISLANDORA_OBJECT_MODIFIED_HOOK] = 0;
$object->label = "New Label!";
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called "hook_islandora_object_alter" when modifying via set magic functions.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called ISLANDORA_OBJECT_MODIFIED_HOOK when modifying via set magic functions.');
+ $this->assertEqual('New Label! + 3', $object->label, 'Re-entered ISLANDORA_OBJECT_MODIFIED_HOOK when modifying via set magic functions.');
// Test blocking the modification.
try {
@@ -191,10 +193,12 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase {
$ds = $object->constructDatastream('TEST');
$object->ingestDatastream($ds);
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE;
+ $_SESSION['islandora_hooks']['iteration'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = 0;
$_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE;
$ds->label = "New Label!";
$this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called "hook_islandora_datastream_alter" when modifying via set magic functions.');
$this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called ISLANDORA_DATASTREAM_MODIFIED_HOOK when modifying via set magic functions.');
+ $this->assertEqual('New Label! + 3', $ds->label, 'Re-entered ISLANDORA_DATASTREAM_MODIFIED_HOOK when modifying via set magic functions.');
// Test blocking modifying.
try {
diff --git a/tests/islandora_hooks_test.module b/tests/islandora_hooks_test.module
index a6b8a5b6..cceb4dbc 100644
--- a/tests/islandora_hooks_test.module
+++ b/tests/islandora_hooks_test.module
@@ -112,6 +112,10 @@ function islandora_hooks_test_islandora_object_ingested(AbstractObject $object)
function islandora_hooks_test_islandora_object_modified(AbstractObject $object) {
if ($object->id == 'test:testModifiedObjectHook') {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = TRUE;
+ if ($_SESSION['islandora_hooks']['iteration'][ISLANDORA_OBJECT_MODIFIED_HOOK]++ < 3) {
+ $new_label = 'New Label! + ' . $_SESSION['islandora_hooks']['iteration'][ISLANDORA_OBJECT_MODIFIED_HOOK];
+ $object->label = $new_label;
+ }
}
}
@@ -139,6 +143,10 @@ function islandora_hooks_test_islandora_datastream_ingested(AbstractObject $obje
function islandora_hooks_test_islandora_datastream_modified(AbstractObject $object, AbstractDatastream $datastream) {
if ($object->id == 'test:testModifiedDatastreamHook' && $datastream->id == "TEST") {
$_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = TRUE;
+ if ($_SESSION['islandora_hooks']['iteration'][ISLANDORA_DATASTREAM_MODIFIED_HOOK]++ < 3) {
+ $new_label = 'New Label! + ' . $_SESSION['islandora_hooks']['iteration'][ISLANDORA_DATASTREAM_MODIFIED_HOOK];
+ $datastream->label = $new_label;
+ }
}
}