diff --git a/includes/derivatives.inc b/includes/derivatives.inc new file mode 100644 index 00000000..4a422535 --- /dev/null +++ b/includes/derivatives.inc @@ -0,0 +1,105 @@ + FALSE, + ); + $hooks = islandora_invoke_hook_list(ISLANDORA_DERVIATIVE_CREATION_HOOK, $object->models, array()); + uasort($hooks, 'drupal_sort_weight'); + $results = array(); + + if (array_key_exists('source_dsid', $options)) { + $hooks = array_filter($hooks, function($filter_hook) use($options) { + return array_key_exists('source_dsid', $filter_hook) && + $filter_hook['source_dsid'] == $options['source_dsid']; + }); + } + + if (array_key_exists('destination_dsid', $options)) { + $hooks = array_filter($hooks, function($filter_hook) use($options) { + return array_key_exists('destination_dsid', $filter_hook) && + $filter_hook['destination_dsid'] == $options['destination_dsid']; + }); + } + + foreach ($hooks as $hook) { + if (isset($hook['file'])) { + require_once $hook['file']; + } + foreach ($hook['function'] as $function) { + $logging = call_user_func($function, $object, $options['force']); + if (!empty($logging)) { + $results[] = $logging; + } + } + } + return $results; +} + +/** + * Handles the logging of derivative messages. + * + * @param array $logging_results + * An array of messages describing the outcome of the derivative events. + * Each individual message array has the following structure: + * - success: Bool denoting whether the operation was successful. + * - messages: An array structure containing: + * - message: A string passed through t() describing the + * outcome of the operation. + * - message_sub: (Optional) Substitutions to be passed along to t() or + * watchdog. + * - type: A string denoting whether the output is to be + * drupal_set_messaged (dsm) or watchdogged (watchdog). + * - severity: (Optional) A severity level / status to be used when + * logging messages. Uses the defaults of drupal_set_message and + * watchdog if not defined. + */ +function islandora_derivative_logging(array $logging_results) { + foreach ($logging_results as $result) { + foreach ($result['messages'] as $message) { + if ($message['type'] === 'dsm') { + drupal_set_message(filter_xss(format_string($message['message'], isset($message['message_sub']) ? $message['message_sub'] : array())), isset($message['severity']) ? $message['severity'] : 'status'); + } + else { + // We know what we are doing here. Passing through the translated + // message and the substitutions needed. We are using + // call_user_func until such time as the @ignore changes + // are merged into the standard release for Coder. + call_user_func('watchdog', $message['message'], isset($message['message_sub']) ? $message['message_sub'] : array(), isset($message['severity']) ? $message['severity'] : WATCHDOG_NOTICE); + } + } + } +} diff --git a/islandora.api.php b/islandora.api.php index 4d54a00f..c4a041ac 100644 --- a/islandora.api.php +++ b/islandora.api.php @@ -541,3 +541,77 @@ function hook_islandora_datastream_access($op, $object, $user) { */ function hook_CMODEL_PID_islandora_datastream_access($op, $object, $user) { } + +/** + * Defines derivative functions to be executed based on certain conditions. + * + * This hook fires when an object/datastream is ingested or a datastream is + * modified. + * + * @return array + * An array containing an entry for each derivative to be created. Each entry + * is an array of parameters containing: + * - force: Bool denoting whether we are forcing the generation of + * derivatives. + * - source_dsid: (Optional) String of the datastream id we are generating + * from or NULL if it's the object itself. + * - destination_dsid: (Optional) String of the datastream id that is being + * created. To be used in the UI. + * - weight: A string denoting the weight of the function. This value is + * sorted upon to run functions in order. + * - function: An array of function(s) to be ran when constructing + * derivatives. Functions that are defined to be called for derivation + * creation must have the following structure: + * module_name_derivative_creation_function($object, $force = FALSE) + * These functions must return an array in the structure of: + * - success: Bool denoting whether the operation was successful. + * - messages: An array structure containing: + * - message: A string passed through t() describing the + * outcome of the operation. + * - message_sub: (Optional) Substitutions to be passed along to t() or + * watchdog. + * - type: A string denoting whether the output is to be + * drupal_set_messaged (dsm) or watchdogged (watchdog). + * - severity: (Optional) A severity level / status to be used when + * logging messages. Uses the defaults of drupal_set_message and + * watchdog if not defined. + * - file: A string denoting the path to the file where the function + * is being called from. + */ +function hook_islandora_derivative() { + return array( + array( + 'source_dsid' => 'OBJ', + 'destination_dsid' => 'DERIV', + 'weight' => '0', + 'function' => array( + 'islandora_derivatives_test_create_deriv_datastream', + ), + ), + array( + 'source_dsid' => 'SOMEWEIRDDATASTREAM', + 'destination_dsid' => 'STANLEY', + 'weight' => '-1', + 'function' => array( + 'islandora_derivatives_test_create_some_weird_datastream', + ), + ), + array( + 'source_dsid' => NULL, + 'destination_dsid' => 'NOSOURCE', + 'weight' => '-3', + 'function' => array( + 'islandora_derivatives_test_create_nosource_datastream', + ), + ), + ); +} + +/** + * Content model specific version of hook_islandora_derivative(). + * + * @see hook_islandora_derivative() + */ +function hook_CMODEL_PID_islandora_derivative() { + +} diff --git a/islandora.info b/islandora.info index fea3ead2..4b48bc29 100644 --- a/islandora.info +++ b/islandora.info @@ -18,4 +18,5 @@ files[] = tests/ingest.test files[] = tests/hooked_access.test files[] = tests/islandora_manage_permissions.test files[] = tests/datastream_versions.test +files[] = tests/derivatives.test php = 5.3 diff --git a/islandora.module b/islandora.module index 7d58c865..30eb0e71 100644 --- a/islandora.module +++ b/islandora.module @@ -53,6 +53,7 @@ define('ISLANDORA_DATASTREAM_INGESTED_HOOK', 'islandora_datastream_ingested'); define('ISLANDORA_DATASTREAM_MODIFIED_HOOK', 'islandora_datastream_modified'); define('ISLANDORA_DATASTREAM_PURGED_HOOK', 'islandora_datastream_purged'); define('ISLANDORA_INGEST_STEP_HOOK', 'islandora_ingest_steps'); +define('ISLANDORA_DERVIATIVE_CREATION_HOOK', 'islandora_derivative'); // Autocomplete paths. define('ISLANDORA_CONTENT_MODELS_AUTOCOMPLETE', 'islandora/autocomplete/content-models'); @@ -1493,3 +1494,49 @@ function islandora_islandora_basic_collection_get_query_filters() { )); } } + + +/** + * Implements hook_islandora_object_ingested(). + * + * On object ingestion we call the case of source_dsid being NULL only as + * the islandora_islandora_datastream_ingested hook will handle the cases + * where specific values of source_dsid can occur. + */ +function islandora_islandora_object_ingested(AbstractObject $object) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + $logging_results = islandora_do_derivatives($object, array( + 'source_dsid' => NULL, + )); + islandora_derivative_logging($logging_results); +} + +/** + * Implements hook_islandora_datastream_ingested(). + * + * When a datastream is ingested we filter the derivatives on source_dsid being + * equal to the current ingested datastream's id. + */ +function islandora_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + $logging_results = islandora_do_derivatives($object, array( + 'source_dsid' => $datastream->id, + )); + islandora_derivative_logging($logging_results); +} + +/** + * Implements hook_islandora_datastream_modified(). + * + * When a datastream is modified we filter the derivatives on source_dsid being + * equal to the current ingested datastream's id. Force is set to TRUE such that + * existing derivatives will be updated to reflect the change in the source. + */ +function islandora_islandora_datastream_modified(AbstractObject $object, AbstractDatastream $datastream) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + $logging_results = islandora_do_derivatives($object, array( + 'source_dsid' => $datastream->id, + 'force' => TRUE, + )); + islandora_derivative_logging($logging_results); +} diff --git a/tests/derivatives.test b/tests/derivatives.test new file mode 100644 index 00000000..13014880 --- /dev/null +++ b/tests/derivatives.test @@ -0,0 +1,296 @@ + 'Islandora Derivative Generation', + 'description' => 'Ensure that the derivative generation hooks return appropriate results.', + 'group' => 'Islandora', + ); + } + + /** + * Creates an admin user and a connection to a fedora repository. + * + * @see IslandoraWebTestCase::setUp() + */ + public function setUp() { + parent::setUp( + array( + 'islandora_derivatives_test', + ) + ); + $url = variable_get('islandora_base_url', 'http://localhost:8080/fedora'); + $this->connection = new RepositoryConnection($url, $this->admin->name, $this->admin->pass); + $this->connection->reuseConnection = TRUE; + $this->api = new FedoraApi($this->connection); + $this->cache = new SimpleCache(); + $this->repository = new FedoraRepository($this->api, $this->cache); + $this->pid = $this->randomName() . ":" . $this->randomName(); + } + + /** + * Free any objects/resources created for this test. + * + * @see IslandoraWebTestCase::tearDown() + */ + public function tearDown() { + $tuque = islandora_get_tuque_connection(); + parent::tearDown(); + } + + /** + * Tests that the islandora_islandora_object_ingested hook gets fired. + */ + public function testDerivativeOnIngest() { + global $_islandora_derivative_test_ingest_method; + $_islandora_derivative_test_ingest_method = 'modifyDatastream'; + $tuque = islandora_get_tuque_connection(); + $object = $tuque->repository->constructObject($this->pid); + $object->models = array( + 'some:cmodel', + ); + $dsid = 'OBJ'; + $ds = $object->constructDatastream($dsid); + $ds->label = 'Test'; + $ds->content = 'test'; + $object->ingestDatastream($ds); + $tuque->repository->ingestObject($object); + $this->assertDatastreams($object, array( + 'RELS-EXT', + 'DC', + 'OBJ', + 'DERIV', + 'NOSOURCE', + )); + $this->assertEqual('ingestDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "ingestDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); + $this->assertEqual('test some string', $object['DERIV']->content, 'The expected content of the DERIV datastream is "test some string", got "' . $object['DERIV']->content . '".'); + $this->assertEqual('NOSOURCE', $object['NOSOURCE']->content, 'The expected content of the NOSOURCE datastream is "NOSOURCE", got "' . $object['NOSOURCE']->content . '".'); + + } + + /** + * Tests the ingest method when when forcing on existing datastreams. + */ + public function testDerivativeOnForceExistingDatastream() { + global $_islandora_derivative_test_ingest_method; + $_islandora_derivative_test_ingest_method = 'ingestDatastream'; + $object = $this->constructBaseObject(); + $object = $this->constructDERIVDatastream($object); + $this->constructNOSOURCEDatastream($object); + $islandora_object = islandora_object_load($this->pid); + islandora_do_derivatives($islandora_object, array( + 'force' => TRUE, + )); + $this->assertEqual('modifyDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "modifyDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); + $this->assertEqual('FORCEFULLY APPENDING CONTENT TO test', $islandora_object['DERIV']->content, 'The expected content of the DERIV datastream is "FORCEFULLY APPENDING CONTENT TO test", got "' . $islandora_object['DERIV']->content . '".'); + } + + /** + * Tests the ingest method when forcing on non-existing datastreams. + */ + public function testDerivativeOnForceNonExistingDatastream() { + global $_islandora_derivative_test_ingest_method; + $_islandora_derivative_test_ingest_method = 'modifyDatastream'; + $this->constructBaseObject(); + $object = islandora_object_load($this->pid); + islandora_do_derivatives($object, array( + 'force' => TRUE, + )); + $this->assertEqual('ingestDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "ingestDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); + $this->assertEqual('test some string', $object['DERIV']->content, 'The expected content of the DERIV datastream is "test some string", got "' . $object['DERIV']->content . '".'); + } + + /** + * Tests the islandora_datastream_modified hook when there are existing DSes. + */ + public function testDerivativeOnModifyExistingDatastream() { + global $_islandora_derivative_test_ingest_method; + $_islandora_derivative_test_ingest_method = 'ingestDatastream'; + $object = $this->constructBaseObject(); + $this->constructDERIVDatastream($object); + // Need to do this as Tuque caches. + $connection = islandora_get_tuque_connection(); + $connection->cache->resetCache(); + $islandora_object = islandora_object_load($this->pid); + $changed_content = 'islandora beast'; + $islandora_object['OBJ']->content = $changed_content; + $this->assertEqual('modifyDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "modifyDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); + $this->assertEqual('FORCEFULLY APPENDING CONTENT TO ' . $changed_content, $islandora_object['DERIV']->content, 'The expected content of the DERIV datastream is "FORCEFULLY APPENDING CONTENT TO islandora beast", got "' . $islandora_object['DERIV']->content . '".'); + } + + /** + * Tests islandora_datastream_modified hook when there are no existing DSes. + */ + public function testDerivativeOnModifyNonExistingDatastream() { + global $_islandora_derivative_test_ingest_method; + $_islandora_derivative_test_ingest_method = 'modifyDatastream'; + $this->constructBaseObject(); + // Need to do this as Tuque caches. + $connection = islandora_get_tuque_connection(); + $connection->cache->resetCache(); + $islandora_object = islandora_object_load($this->pid); + $changed_content = 'islandora beast'; + $islandora_object['OBJ']->content = $changed_content; + $this->assertEqual('ingestDatastream', $_islandora_derivative_test_ingest_method, 'The expected ingest method is "ingestDatastream", got "' . $_islandora_derivative_test_ingest_method . '".'); + $this->assertEqual($changed_content . ' some string', $islandora_object['DERIV']->content, 'The expected content of the DERIV datastream is "islandora beast string", got "' . $islandora_object['DERIV']->content . '".'); + } + + /** + * Tests derivative hook filtering based upon source_dsid. + */ + public function testDerivativeFilteringOnSourceDSID() { + global $_islandora_derivative_test_derivative_functions; + $_islandora_derivative_test_derivative_functions = array(); + $this->constructBaseObject(); + $object = islandora_object_load($this->pid); + islandora_do_derivatives($object, array( + 'source_dsid' => 'OBJ', + )); + $this->assertEqual(1, count($_islandora_derivative_test_derivative_functions), 'Expected 1 derivative function for the source_dsid of "OBJ", got ' . count($_islandora_derivative_test_derivative_functions) . '.'); + $called_function = (string) reset($_islandora_derivative_test_derivative_functions); + $this->assertEqual('islandora_derivatives_test_create_deriv_datastream', $called_function, 'Expected derivative function is "islandora_derivatives_test_create_deriv_datastream", got "' . $called_function . '".'); + + // Reset the derivative functions array as we are going to use it again. + $_islandora_derivative_test_derivative_functions = array(); + islandora_do_derivatives($object, array( + 'source_dsid' => 'SOMEWEIRDDATASTREAM', + )); + $this->assertEqual(1, count($_islandora_derivative_test_derivative_functions), 'Expected 1 derivative function for the source_dsid of "SOMEWEIRDDATASTREAM", got ' . count($_islandora_derivative_test_derivative_functions) . '.'); + $called_function = (string) reset($_islandora_derivative_test_derivative_functions); + $this->assertEqual('islandora_derivatives_test_create_some_weird_datastream', $called_function, 'Expected derivative function is "islandora_derivatives_test_create_some_weird_datastream", got "' . $called_function . '".'); + } + + /** + * Tests that only functions were the source_dsid is NULL are fired. + */ + public function testNULLSourceDSID() { + global $_islandora_derivative_test_derivative_functions; + $_islandora_derivative_test_derivative_functions = array(); + $this->constructBaseObject(); + $object = islandora_object_load($this->pid); + islandora_do_derivatives($object, array( + 'source_dsid' => NULL, + )); + $this->assertDatastreams($object, array( + 'DC', + 'RELS-EXT', + 'OBJ', + 'NOSOURCE', + )); + $this->assertEqual(1, count($_islandora_derivative_test_derivative_functions), 'Expected 1 derivative function for the source_dsid of "NULL", got ' . count($_islandora_derivative_test_derivative_functions) . '.'); + $called_function = (string) reset($_islandora_derivative_test_derivative_functions); + $this->assertEqual('islandora_derivatives_test_create_nosource_datastream', $called_function, 'Expected derivative function is "islandora_derivatives_test_create_nosource_datastream", got "' . $called_function . '".'); + $this->assertEqual('NOSOURCE', $object['NOSOURCE']->content, 'The expected content of the NOSOURCE datastream is "NOSOURCE", got "' . $object['NOSOURCE']->content . '".'); + } + + /** + * Tests that when no source_dsid all derivative functions are called. + */ + public function testNoSourceDSIDNoForce() { + global $_islandora_derivative_test_derivative_functions; + $_islandora_derivative_test_derivative_functions = array(); + $this->constructBaseObject(); + $object = islandora_object_load($this->pid); + islandora_do_derivatives($object, array()); + $this->assertDatastreams($object, array( + 'DC', + 'RELS-EXT', + 'OBJ', + 'DERIV', + 'NOSOURCE', + )); + $this->assertEqual(3, count($_islandora_derivative_test_derivative_functions), 'Expected 3 derivative functions when there is no source_dsid, got ' . count($_islandora_derivative_test_derivative_functions) . '.'); + } + + /** + * Tests that when no source_dsid all derivative functions are called. + */ + public function testNoSourceDSIDForce() { + global $_islandora_derivative_test_derivative_functions; + $_islandora_derivative_test_derivative_functions = array(); + $this->constructBaseObject(); + $object = islandora_object_load($this->pid); + islandora_do_derivatives($object, array( + 'force' => TRUE, + )); + $this->assertDatastreams($object, array( + 'DC', + 'RELS-EXT', + 'OBJ', + 'DERIV', + 'NOSOURCE', + )); + $this->assertEqual(3, count($_islandora_derivative_test_derivative_functions), 'Expected 3 derivative functions when there is no source_dsid, got ' . count($_islandora_derivative_test_derivative_functions) . '.'); + } + + /** + * Helper function that will construct a base object. + */ + public function constructBaseObject() { + $object = $this->repository->constructObject($this->pid); + $object->models = array( + 'some:cmodel', + ); + $dsid = 'OBJ'; + $ds = $object->constructDatastream($dsid); + $ds->label = 'Test'; + $ds->content = 'test'; + $object->ingestDatastream($ds); + $this->repository->ingestObject($object); + return $object; + } + + /** + * Helper function to construct the DERIV datastream without firing hooks. + * + * @param AbstractObject $object + * An AbstractObject representing a FedoraObject. + * + * @return AbstractObject + * The modified AbstractObject. + */ + public function constructDERIVDatastream(AbstractObject $object) { + $dsid = 'DERIV'; + $ds = $object->constructDatastream($dsid); + $ds->label = 'Test'; + $ds->content = 'test some string'; + $object->ingestDatastream($ds); + return $object; + } + + /** + * Helper function to construct the NOSOURCE datastream without firing hooks. + * + * @param AbstractObject $object + * An AbstractObject representing a FedoraObject. + * + * @return AbstractObject + * The modified AbstractObject. + */ + public function constructNOSOURCEDatastream(AbstractObject $object) { + $dsid = 'NOSOURCE'; + $ds = $object->constructDatastream($dsid); + $ds->label = 'Test'; + $ds->content = 'NOSOURCE'; + $object->ingestDatastream($ds); + return $object; + } +} diff --git a/tests/islandora_derivatives_test.info b/tests/islandora_derivatives_test.info new file mode 100644 index 00000000..338b39fe --- /dev/null +++ b/tests/islandora_derivatives_test.info @@ -0,0 +1,7 @@ +name = Islandora Derivatives Generation testing +description = Tests derivative generation hooks. Do not enable. +core = 7.x +package = Testing +hidden = TRUE +files[] = islandora_derivatives_test.module +dependencies[] = islandora diff --git a/tests/islandora_derivatives_test.module b/tests/islandora_derivatives_test.module new file mode 100644 index 00000000..80530296 --- /dev/null +++ b/tests/islandora_derivatives_test.module @@ -0,0 +1,202 @@ + 'OBJ', + 'destination_dsid' => 'DERIV', + 'weight' => '0', + 'function' => array( + 'islandora_derivatives_test_create_deriv_datastream', + ), + ), + array( + 'source_dsid' => 'SOMEWEIRDDATASTREAM', + 'destination_dsid' => 'STANLEY', + 'weight' => '-1', + 'function' => array( + 'islandora_derivatives_test_create_some_weird_datastream', + ), + ), + array( + 'source_dsid' => NULL, + 'destination_dsid' => 'NOSOURCE', + 'weight' => '-3', + 'function' => array( + 'islandora_derivatives_test_create_nosource_datastream', + ), + ), + ); +} + +/** + * Creates the DERIV datastream for use in testing. + * + * @param AbstractObject $object + * An AbstractObject representing a Fedora object. + * @param bool $force + * Whether or not derivative generation is to be forced. + * @return array + * An array detailing the success of the operation. + * + * @see hook_islandora_derivative() + */ +function islandora_derivatives_test_create_deriv_datastream(AbstractObject $object, $force = FALSE) { + global $_islandora_derivative_test_derivative_functions; + $_islandora_derivative_test_derivative_functions[] = 'islandora_derivatives_test_create_deriv_datastream'; + $return = ''; + if (!isset($object['DERIV']) || (isset($object['DERIV']) && $force === TRUE)) { + if ($force !== TRUE || !isset($object['DERIV'])) { + $deriv_string = $object['OBJ']->content . ' some string'; + } + else { + $deriv_string = "FORCEFULLY APPENDING CONTENT TO " . $object['OBJ']->content; + } + $added_successfully = islandora_derivatives_test_add_datastream($object, 'DERIV', $deriv_string); + if ($added_successfully !== TRUE) { + $return = islandora_derivatives_test_failed_adding($added_successfully); + } + else { + $return = array( + 'success' => TRUE, + 'messages' => array( + array( + 'message' => t('The DERIV datastream was added successfully for @pid!'), + 'message_sub' => array('@pid' => $object->id), + 'type' => 'dsm', + ), + ), + ); + } + return $return; + } +} + +/** + * Stub function that used only for datastream filtering counts. + * + * @param AbstractObject $object + * An AbstractObject representing a Fedora object. + * @param bool $force + * Whether the derivatives are being forcefully generated or not. + */ +function islandora_derivatives_test_create_some_weird_datastream(AbstractObject $object, $force = FALSE) { + global $_islandora_derivative_test_derivative_functions; + // Add to the global that we got to this function. + $_islandora_derivative_test_derivative_functions[] = 'islandora_derivatives_test_create_some_weird_datastream'; +} + +/** + * Creates the NOSOURCE datastream for use in testing. + * + * @param AbstractObject $object + * An AbstractObject representing a Fedora object. + * @param bool $force + * Whether or not derivative generation is to be forced. + * @return array + * An array detailing the success of the operation. + * + * @see hook_islandora_derivative() + */ +function islandora_derivatives_test_create_nosource_datastream(AbstractObject $object, $force = FALSE) { + global $_islandora_derivative_test_derivative_functions; + $_islandora_derivative_test_derivative_functions[] = 'islandora_derivatives_test_create_nosource_datastream'; + $return = ''; + if (!isset($object['NOSOURCE']) || (isset($object['NOSOURCE']) && $force === TRUE)) { + if ($force !== TRUE || !isset($object['NOSOURCE'])) { + $deriv_string = 'NOSOURCE'; + } + else { + $deriv_string = "FORCEFULLY APPENDING CONTENT TO " . $object['NOSOURCE']->content; + } + $added_successfully = islandora_derivatives_test_add_datastream($object, 'NOSOURCE', $deriv_string); + if ($added_successfully !== TRUE) { + $return = islandora_derivatives_test_failed_adding($added_successfully); + } + else { + $return = array( + 'success' => TRUE, + 'messages' => array( + array( + 'message' => t('The DERIV datastream was added successfully for @pid!'), + 'message_sub' => array('@pid' => $object->id), + 'type' => 'dsm', + ), + ), + ); + } + return $return; + } +} + +/** + * Helper function that adds/modifies the datastream to the object in testing. + * + * @param AbstractObject $object + * An AbstractObject representing a Fedora object. + * @param string $dsid + * The datastream id for which we are adding/modifying. + * @param string $deriv_string + * The content of the datastream we are adding. + * + * @return bool|string + * A bool if the operation was successfully, the error message otherwise. + */ +function islandora_derivatives_test_add_datastream(AbstractObject $object, $dsid, $deriv_string) { + global $_islandora_derivative_test_ingest_method; + try { + $ingest = !isset($object[$dsid]); + if ($ingest) { + $ds = $object->constructDatastream($dsid, 'M'); + $ds->label = $dsid; + } + else { + $ds = $object[$dsid]; + } + $ds->content = $deriv_string; + if ($ingest) { + $_islandora_derivative_test_ingest_method = 'ingestDatastream'; + $object->ingestDatastream($ds); + } + else { + $_islandora_derivative_test_ingest_method = 'modifyDatastream'; + } + return TRUE; + } + catch (exception $e) { + $message = $e->getMessage(); + return $message; + } +} + +/** + * Returns a message if we failed to add a derivative. + * + * @see hook_islandora_derivative() + * + * @param string $message + * The error message to be returned back. + * + * @return array + * An array describing the outcome of our failure. + */ +function islandora_derivatives_test_failed_adding($message) { + return array( + 'success' => FALSE, + 'messages' => array( + array( + 'message' => $message, + 'type' => 'watchdog', + 'severity' => WATCHDOG_ERROR, + ), + ), + ); +}