diff --git a/.travis.yml b/.travis.yml
index 660fb448..84b226d0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,9 +6,14 @@ branches:
only:
- /^7.x/
env:
- - FEDORA_VERSION="3.5"
- - FEDORA_VERSION="3.6.2"
- - FEDORA_VERSION="3.7.0"
+ matrix:
+ - FEDORA_VERSION="3.5"
+ - FEDORA_VERSION="3.6.2"
+ - FEDORA_VERSION="3.7.0"
+ global:
+ # This key is unique to the Islandora/islandora repository; logging will
+ # fail on forked repositories unless a new unique key is generated for them.
+ - secure: "nTv2Zb/qKlECK+xE5ahbfXI9ZZbf2ZMd796q7oPlTxUwvu6nomHnUOjJATl6tq2cj23PyJ89Jlgl5cMZ5h0QMUzYpN5hPyY6oCJxWgFamFaE3bv5E/rBd1f6WVTJW7S4UKn8Mr9R2PrX+ZxQZGVIigAfR8VfhQuP8PcuO5eMLBk="
before_install:
- export ISLANDORA_DIR=$TRAVIS_BUILD_DIR
- $TRAVIS_BUILD_DIR/tests/scripts/travis_setup.sh
@@ -19,3 +24,5 @@ script:
- drush coder-review --reviews=production,security,style,i18n,potx,sniffer islandora
- phpcpd --names *.module,*.inc,*.test sites/all/modules/islandora
- drush test-run --uri=http://localhost:8081 Islandora
+after_failure:
+ - $ISLANDORA_DIR/tests/scripts/travis_after_failure.sh
diff --git a/README.md b/README.md
index 90d935cf..371797b2 100644
--- a/README.md
+++ b/README.md
@@ -42,11 +42,16 @@ INSTALLATION
Before installing Islandora the XACML policies located in the policies folder
should be copied into the Fedora global XACML policies folder. This will allow
-"authenticated users" in Drupal to access Fedora API-M functions.
+"authenticated users" in Drupal to access Fedora API-M functions. It is to be
+noted that the permit-upload-to-anonymous-user.xml and
+permit-apim-to-anonymous-user.xml files do not need to be present unless
+requirements for anonymous ingesting are present.
-You will also have to remove some default policies if you want full functionality as well.
+You will also have to remove some default policies if you want full
+functionality as well.
-Remove deny-purge-datastream-if-active-or-inactive.xml to allow for purging of datastream versions.
+Remove deny-purge-datastream-if-active-or-inactive.xml to allow for purging of
+datastream versions.
CONFIGURATION
-------------
diff --git a/includes/admin.form.inc b/includes/admin.form.inc
index b0bb0642..3dc97091 100644
--- a/includes/admin.form.inc
+++ b/includes/admin.form.inc
@@ -27,7 +27,7 @@ function islandora_repository_admin(array $form, array &$form_state) {
'#type' => 'vertical_tabs',
'islandora_general' => array(
'#type' => 'fieldset',
- '#title' => t('General Configuarion'),
+ '#title' => t('General Configuration'),
'wrapper' => array(
'#prefix' => '
',
'#suffix' => '
',
diff --git a/includes/authtokens.inc b/includes/authtokens.inc
index 36e8689f..d5d98117 100644
--- a/includes/authtokens.inc
+++ b/includes/authtokens.inc
@@ -36,12 +36,7 @@ define('ISLANDORA_AUTHTOKEN_TOKEN_TIMEOUT', 300);
function islandora_get_object_token($pid, $dsid, $uses = 1) {
global $user;
$time = time();
- // The function mt_rand is not considered cryptographically secure
- // and openssl_rando_pseudo_bytes() is only available in PHP > 5.3.
- // We might be safe in this case because mt_rand should never be using
- // the same seed, but this is still more secure.
- $token = hash("sha256", mt_rand() . $time);
-
+ $token = bin2hex(drupal_random_bytes(32));
$id = db_insert("islandora_authtokens")->fields(
array(
'token' => $token,
diff --git a/includes/derivatives.inc b/includes/derivatives.inc
index d25789cc..635c1c54 100644
--- a/includes/derivatives.inc
+++ b/includes/derivatives.inc
@@ -49,7 +49,7 @@ function islandora_do_derivatives(AbstractObject $object, array $options) {
}
foreach ($hook['function'] as $function) {
if (function_exists($function)) {
- $logging = call_user_func($function, $object, $options['force']);
+ $logging = call_user_func($function, $object, $options['force'], $hook);
if (!empty($logging)) {
$results[] = $logging;
}
@@ -142,11 +142,15 @@ function islandora_do_batch_derivatives(AbstractObject $object, array $options)
$file = $hook['file'];
}
foreach ($hook['function'] as $function) {
- $operations[] = array('islandora_derivative_perform_batch_operation', array(
- $function,
- $file,
- $object->id,
- $options['force']),
+ $operations[] = array(
+ 'islandora_derivative_perform_batch_operation',
+ array(
+ $function,
+ $file,
+ $object->id,
+ $options['force'],
+ $hook,
+ ),
);
}
}
diff --git a/includes/ingest.form.inc b/includes/ingest.form.inc
index 89376f7d..f7979063 100644
--- a/includes/ingest.form.inc
+++ b/includes/ingest.form.inc
@@ -467,12 +467,14 @@ function islandora_ingest_form_undo_consecutive_callback_steps(array $form, arra
* The step which the undo callback is being called on.
*/
function islandora_ingest_form_undo_callback_step(array $form, array &$form_state, array $step) {
- $args = array(&$form_state);
- $args = isset($step['undo_function']['args']) ? array_merge($args, $step['undo_function']['args']) : $args;
- if (isset($step['undo_function']['file'])) {
- require_once drupal_get_path('module', $step['module']) . "/" . $step['undo_function']['file'];
+ if (isset($step['undo_function'])) {
+ $args = array(&$form_state);
+ $args = isset($step['undo_function']['args']) ? array_merge($args, $step['undo_function']['args']) : $args;
+ if (isset($step['undo_function']['file'])) {
+ require_once drupal_get_path('module', $step['module']) . "/" . $step['undo_function']['file'];
+ }
+ call_user_func_array($step['undo_function']['function'], $args);
}
- call_user_func_array($step['undo_function']['function'], $args);
}
/**
@@ -769,7 +771,7 @@ function islandora_ingest_form_submit(array $form, array &$form_state) {
islandora_ingest_form_execute_consecutive_callback_steps($form, $form_state, $step);
}
// Ingest the objects.
- $set_redirect = TRUE;
+ $set_redirect = isset($form_state['redirect']) ? FALSE : TRUE;
foreach ($form_state['islandora']['objects'] as &$object) {
try {
islandora_add_object($object);
diff --git a/includes/manage_deleted_objects.inc b/includes/manage_deleted_objects.inc
index 48796304..a6b5e96e 100644
--- a/includes/manage_deleted_objects.inc
+++ b/includes/manage_deleted_objects.inc
@@ -332,7 +332,7 @@ function islandora_get_deleted_query($content_models, $offset = 0) {
$unions .= "UNION {?subject fm:hasModel ;
fm:state fm:Deleted;
fm:hasModel ?object;
- }
+ }
";
}
$optional = "OPTIONAL{?subject fm:label ?label}";
diff --git a/includes/regenerate_derivatives.form.inc b/includes/regenerate_derivatives.form.inc
index 7fd8d059..9a7a097e 100644
--- a/includes/regenerate_derivatives.form.inc
+++ b/includes/regenerate_derivatives.form.inc
@@ -142,15 +142,17 @@ function islandora_regenerate_datastream_derivative_batch(AbstractDatastream $da
* The pid of the object we are performing.
* @param bool $force
* Whether we are forcing derivative regeneration or not.
+ * @param array $hook
+ * The derivative definition.
* @param array $context
* The context of the current batch operation.
*/
-function islandora_derivative_perform_batch_operation($function, $file, $pid, $force, &$context) {
+function islandora_derivative_perform_batch_operation($function, $file, $pid, $force, $hook, &$context) {
if ($file) {
require_once $file;
}
if (function_exists($function)) {
- $logging = call_user_func($function, islandora_object_load($pid), $force);
+ $logging = call_user_func($function, islandora_object_load($pid), $force, $hook);
if (!empty($logging)) {
$context['results']['logging'][] = $logging;
}
diff --git a/includes/solution_packs.inc b/includes/solution_packs.inc
index e07e76e7..47a8f23c 100644
--- a/includes/solution_packs.inc
+++ b/includes/solution_packs.inc
@@ -256,7 +256,7 @@ function islandora_solution_pack_form_submit(array $form, array &$form_state) {
* the batch.
* @param array $not_checked
* The object that will bot be install.
- *
+ *
* @return array
* An array defining a batch which can be passed on to batch_set().
*/
@@ -367,7 +367,7 @@ function islandora_install_solution_pack($module, $op = 'install', $force = FALS
$t = get_t();
// Some general replacements.
- $admin_link = l($t('Solution Pack admin'), 'admin/islandora/solution_packs');
+ $admin_link = l($t('Solution Pack admin'), 'admin/islandora/solution_pack_config');
$config_link = l($t('Islandora configuration'), 'admin/islandora/configure');
$t_params = array(
'@module' => $module,
@@ -712,9 +712,8 @@ function islandora_viewers_form($variable_id = NULL, $mimetype = NULL, $model =
* given, than any viewer that supports either the give $mimetype or $model will
* be listed.
*
- * @param string $mimetype
- * Specify a mimetype to return only viewers that support this certain
- * mimetype.
+ * @param array $mimetype
+ * List of mimetypes that the viewer supports.
* @param string $content_model
* Specify a content model to return only viewers that support the content
* model.
@@ -722,14 +721,19 @@ function islandora_viewers_form($variable_id = NULL, $mimetype = NULL, $model =
* @return array
* Viewer definitions, or FALSE if none are found.
*/
-function islandora_get_viewers($mimetype = NULL, $content_model = NULL) {
+function islandora_get_viewers($mimetype = array(), $content_model = NULL) {
$viewers = array();
$defined_viewers = module_invoke_all('islandora_viewer_info');
+
+ if (!is_array($mimetype)) {
+ $mimetype = array($mimetype);
+ }
+
// Filter viewers by MIME type.
foreach ($defined_viewers as $key => $value) {
$value['mimetype'] = isset($value['mimetype']) ? $value['mimetype'] : array();
$value['model'] = isset($value['model']) ? $value['model'] : array();
- if (in_array($mimetype, $value['mimetype']) OR in_array($content_model, $value['model'])) {
+ if (array_intersect($mimetype, $value['mimetype']) OR in_array($content_model, $value['model'])) {
$viewers[$key] = $value;
}
}
diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc
index d30af147..573d7c62 100644
--- a/includes/tuque_wrapper.inc
+++ b/includes/tuque_wrapper.inc
@@ -115,6 +115,10 @@ 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) {
diff --git a/islandora.api.php b/islandora.api.php
index 0534ffe7..eeeeae1c 100644
--- a/islandora.api.php
+++ b/islandora.api.php
@@ -423,13 +423,13 @@ function hook_islandora_undeletable_datastreams(array $models) {
* - form_id: The form building function to call to get the form structure
* for this step.
* - args: An array of arguments to pass to the form building function.
- * Required "callback" type specific parameters:
- * - do_function: An associate array including:
+ * "Callback" type specific parameters:
+ * - do_function: A required associative array including:
* - 'function': The callback function to be called.
* - 'args': An array of arguments to pass to the callback function.
* - 'file': A file to include (relative to the module's path, including
* the file's extension).
- * - undo_function: An associate array including:
+ * - undo_function: An optional associative array including:
* - 'function': The callback function to be called to reverse the
* executed action in the ingest steps.
* - 'args': An array of arguments to pass to the callback function.
@@ -472,7 +472,7 @@ function hook_islandora_ingest_steps(array $form_state) {
*
* @param array $steps
* An array of steps as generated by hook_islandora_ingest_steps().
- *
+ *
* @param array $form_state
* An array containing the Drupal form_state.
*/
@@ -497,7 +497,7 @@ function hook_CMODEL_PID_islandora_ingest_steps(array $form_state) {
*
* @param array $steps
* An array of steps as generated by hook_islandora_ingest_steps().
- *
+ *
* @param array $form_state
* An array containing the Drupal form_state.
*/
@@ -635,10 +635,11 @@ function hook_CMODEL_PID_islandora_overview_object_alter(AbstractObject &$object
* - 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)
+ * module_name_derivative_creation_function($object, $force = FALSE, $hook)
* These functions must return an array in the structure of:
* - success: Bool denoting whether the operation was successful.
- * - messages: An array structure containing:
+ * - messages: An array structure containing zero or more array's with the
+ * following fields:
* - message: A string passed through t() describing the
* outcome of the operation.
* - message_sub: (Optional) Substitutions to be passed along to t() or
@@ -704,7 +705,7 @@ function hook_CMODEL_PID_islandora_derivative() {
function hook_islandora_update_related_objects_properties(AbstractObject $object) {
$related_objects = get_all_children_siblings_and_friends($object);
$pids_to_return = array();
- foreach($related_objects as $related_object) {
+ foreach ($related_objects as $related_object) {
$pids_to_return[] = $related_object->id;
}
return $pids_to_return;
diff --git a/islandora.module b/islandora.module
index 9e7809eb..cc4cee4b 100644
--- a/islandora.module
+++ b/islandora.module
@@ -109,13 +109,35 @@ function islandora_menu() {
'file' => 'includes/metadata.inc',
'access arguments' => array('administer site configuration'),
);
- $items['admin/islandora/solution_packs'] = array(
- 'title' => 'Solution packs',
+ $items['admin/islandora/solution_pack_config'] = array(
+ 'title' => 'Solution pack configuration',
+ 'description' => 'Configure Islandora solution packs.',
+ 'access callback' => 'islandora_find_package',
+ 'access arguments' => array('Islandora Solution Packs'),
+ 'type' => MENU_NORMAL_ITEM,
+ );
+ $items['admin/islandora/islandora_viewers'] = array(
+ 'title' => 'Islandora Viewers',
+ 'description' => 'Configure custom viewers.',
+ 'access callback' => 'islandora_find_package',
+ 'access arguments' => array('Islandora Viewers'),
+ 'type' => MENU_NORMAL_ITEM,
+ );
+ $items['admin/islandora/tools'] = array(
+ 'title' => 'Islandora Utility Modules',
+ 'description' => 'Configure Islandora utility modules.',
+ 'access callback' => 'islandora_find_package',
+ 'access arguments' => array('Islandora Tools'),
+ 'type' => MENU_NORMAL_ITEM,
+ );
+ $items['admin/islandora/solution_pack_config/solution_packs'] = array(
+ 'title' => 'Solution packs required objects',
'description' => 'Install content models and collections required by installed solution packs.',
'page callback' => 'islandora_solution_packs_admin',
'access arguments' => array(ISLANDORA_ADD_DS),
'file' => 'includes/solution_packs.inc',
'type' => MENU_NORMAL_ITEM,
+ 'weight' => -1,
);
$items['islandora'] = array(
'title' => 'Islandora Repository',
@@ -1531,6 +1553,11 @@ function islandora_entity_property_info() {
'label' => t('Content Models'),
'description' => t('The list of content models which the object has.'),
);
+ $p['createdDate'] = array(
+ 'type' => 'text',
+ 'label' => t('Created Date'),
+ 'description' => t('When the object was created.'),
+ );
return $info;
}
@@ -1825,9 +1852,9 @@ function islandora_repair_drupal_filter() {
}
}
- /**
- * Implements hook_islandora_metadata_display_info().
- */
+/**
+ * Implements hook_islandora_metadata_display_info().
+ */
function islandora_islandora_metadata_display_info() {
return array(
'dublin_core' => array(
@@ -1864,3 +1891,24 @@ function islandora_islandora_datastream_access($op, AbstractDatastream $datastre
}
return $result;
}
+
+/**
+ * Access for submenu items.
+ *
+ * @param string $package_name
+ * Name of the package
+ *
+ * @return bool
+ * Access granted
+ */
+function islandora_find_package($package_name) {
+ $results = system_get_info('module');
+ $found = FALSE;
+ foreach ($results as $name => $values) {
+ if ($values['package'] == $package_name) {
+ $found = TRUE;
+ break;
+ }
+ }
+ return $found && user_access('administer site configuration');
+}
diff --git a/islandora.rules.inc b/islandora.rules.inc
index 4045b1b9..02f5c822 100644
--- a/islandora.rules.inc
+++ b/islandora.rules.inc
@@ -5,11 +5,30 @@
* Does rule type stuff,
*/
+/**
+ * Implements hook_rules_event_info().
+ */
+function islandora_rules_event_info() {
+ return array(
+ 'islandora_object_ingested' => array(
+ 'group' => t('Islandora'),
+ 'label' => t('Object ingested'),
+ 'variables' => array(
+ 'object' => array(
+ 'type' => 'islandora_object',
+ 'label' => t('The ingested object'),
+ 'description' => t('A Tuque object for the ingested Fedora object, as an entity.'),
+ ),
+ ),
+ ),
+ );
+}
+
/**
* Helper function to get reused "parameter" array.
*/
function islandora_rules_relationship_parameter_array() {
- $to_return = array(
+ return array(
'subject' => array(
'type' => 'islandora_object',
'label' => t('Subject'),
@@ -39,8 +58,6 @@ function islandora_rules_relationship_parameter_array() {
'default value' => 0,
),
);
-
- return $to_return;
}
/**
diff --git a/islandora.rules_defaults.inc b/islandora.rules_defaults.inc
new file mode 100644
index 00000000..17f83b63
--- /dev/null
+++ b/islandora.rules_defaults.inc
@@ -0,0 +1,26 @@
+label = 'E-mail admin';
+ $rule->active = FALSE;
+ $rule
+ ->event('islandora_object_ingested')
+ ->action(
+ 'mail',
+ array(
+ 'to' => '[site:mail]',
+ 'subject' => '[[site:name]] "[object:label]" has been ingested',
+ 'message' => '[object:label] has been ingested as [object:id].',
+ )
+ );
+ return array('islandora_object_ingested_notify_admin' => $rule);
+}
diff --git a/policies/permit-apim-to-anonymous-user.xml b/policies/permit-apim-to-anonymous-user.xml
new file mode 100644
index 00000000..4fc711f5
--- /dev/null
+++ b/policies/permit-apim-to-anonymous-user.xml
@@ -0,0 +1,31 @@
+
+
+ note that other policies may provide exceptions to this broad policy. This policy assumes api-m users have to be authenticated
+
+
+
+
+ anonymous user
+
+
+
+
+
+
+
+
+
+
+ urn:fedora:names:fedora:2.1:action:api-m
+
+
+
+
+
+
+
diff --git a/policies/permit-upload-to-anonymous-user.xml b/policies/permit-upload-to-anonymous-user.xml
new file mode 100644
index 00000000..bebcd37b
--- /dev/null
+++ b/policies/permit-upload-to-anonymous-user.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+ anonymous user
+
+
+
+
+
+
+
+
+
+
+ urn:fedora:names:fedora:2.1:action:id-upload
+
+
+
+
+
+
+
diff --git a/tests/datastream_validators.inc b/tests/datastream_validators.inc
index 854f6db5..802f32d2 100644
--- a/tests/datastream_validators.inc
+++ b/tests/datastream_validators.inc
@@ -192,7 +192,6 @@ abstract class DatastreamValidator {
$this->params = $params;
if ($object[$datastream]) {
$this->datastreamContent = $object[$datastream]->content;
- $this->runValidators();
}
else {
drupal_set_message(t("Error grabbing content from datastream %datastream in object %id", 'error'), array(
@@ -226,6 +225,9 @@ abstract class DatastreamValidator {
* The results.
*/
public function getResults() {
+ if (empty($this->results)) {
+ $this->runValidators();
+ }
return $this->results;
}
@@ -415,19 +417,24 @@ class PDFDatastreamValidator extends DatastreamValidator {
* integer representing the number of times it should appear in the datastream.
*/
class TextDatastreamValidator extends DatastreamValidator {
+ /**
+ * Constructor override; blow up if we don't have our two values.
+ */
+ public function __construct(IslandoraFedoraObject $object, $datastream, array $params = array()) {
+ if (count($params) < 2) {
+ throw new InvalidArgumentException('$params must contain at least two values to instantiate a TextDatastreamValidator.');
+ }
+ parent::__construct($object, $datastream, $params);
+ }
/**
* Asserts that the string given appears the correct number of times.
*/
protected function assertTextStringCount() {
- if (!isset($this->params[1])) {
- $this->addResult(FALSE, "TextDatastreamValidator cannot be instantiated without two keys in the 'params' variable.");
- return;
- }
$string_count = self::getTextStringCount();
- $expected = $this->params[1];
+ list($string, $expected) = $this->params;
$assertion = $string_count === $expected;
- $this->addResult($assertion, "{$this->datastream} datastream contains the word(s) '{$this->params[0]}' repeated {$string_count} time(s) (expected: {$expected}).");
+ $this->addResult($assertion, "{$this->datastream} datastream contains the word(s) '{$string}' repeated {$string_count} time(s) (expected: {$expected}).");
}
/**
@@ -463,12 +470,9 @@ class WAVDatastreamValidator extends DatastreamValidator {
* @param array $params
* An extra array of parameters the validator might need.
*/
- public function __construct($object, $datastream, array $params = array()) {
- $this->object = $object;
- $this->datastream = $datastream;
- $this->params = $params;
- $this->datastreamContent = bin2hex($object[$datastream]->content);
- $this->runValidators();
+ public function __construct(IslandoraFedoraObject $object, $datastream, array $params = array()) {
+ parent::__construct($object, $datastream, $params);
+ $this->datastreamContent = bin2hex($this->datastreamContent);
}
/**
diff --git a/tests/islandora_web_test_case.inc b/tests/islandora_web_test_case.inc
index e866a929..8a1e5ce8 100644
--- a/tests/islandora_web_test_case.inc
+++ b/tests/islandora_web_test_case.inc
@@ -345,7 +345,8 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
* An array containing object information using these keys:
* 'label' - The object label; randomized if not set.
* 'pid' - 'namespace:pid', or just 'namespace' to generate the suffix.
- * 'models' - An array that can contain multiple content model PIDs.
+ * 'models' - An array that can contain multiple content model PIDs, or a
+ * string containing a single content model PID.
* 'owner' - The object's owner. Defaults to the currently logged-in user,
* if available. It is recommended to set this to a value that can be found
* in $this->users; otherwise, this object will have to be manually deleted.
@@ -361,8 +362,7 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
* FALSE if the object ingest failed, or the object array if successful.
*/
public function ingestConstructedObject(array $properties = array(), array $datastreams = array()) {
- module_load_include('inc', 'islandora', 'includes/tuque');
- $tuque = new IslandoraTuque();
+ $tuque = islandora_get_tuque_connection($this->admin);
$repository = $tuque->repository;
if (!isset($properties['pid'])) {
$properties['pid'] = "islandora";
@@ -385,13 +385,14 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
$object->owner = $this->loggedInUser->name;
}
- if (isset($properties['models']) && is_array($properties['models'])) {
- foreach ($properties['models'] as $model) {
- $object->relationships->add(FEDORA_MODEL_URI, 'hasModel', $model);
+ if (isset($properties['models'])) {
+ try {
+ $object->models = (array) $properties['models'];
+ }
+ catch (Exception $e) {
+ $this->fail("Encountered an exception when trying to add content models to {$object->id}: $e");
+ return FALSE;
}
- }
- elseif (isset($properties['models']) && !is_array($properties['models'])) {
- $this->fail(t("'models' key of properties variable is not an array. Content model(s) will not be set."), 'Islandora');
}
$repository->ingestObject($object);
@@ -472,4 +473,132 @@ QUERY;
}
}
+ /**
+ * These are a few quick helper functions to fill in a gap in the standard
+ * DrupalWebTestCase where no function exists to test for the simple existence
+ * or non-existence of an error.
+ */
+
+ /**
+ * Asserts that an error is found in $this->content.
+ *
+ * @param string $message
+ * The message to pass on to the results.
+ * @param string $group
+ * The group to place the result in.
+ *
+ * @return bool
+ * TRUE on success, FALSE on failure.
+ */
+ public function assertError($message = '', $group = 'Other') {
+ if (!$message) {
+ $message = "Error found on current page when error was expected.";
+ }
+ return $this->assertRaw("
", $message, $group);
+ }
+
+ /**
+ * Asserts that no error is found in $this->content.
+ *
+ * @param string $message
+ * The message to pass on to the results.
+ * @param string $group
+ * The group to place the result in.
+ *
+ * @return bool
+ * TRUE on success, FALSE on failure.
+ */
+ public function assertNoError($message = '', $group = 'Other') {
+ if (!$message) {
+ $message = "No error found on current page when no error was expected.";
+ }
+ return $this->assertNoRaw("
", $message, $group);
+ }
+
+ /**
+ * Asserts that a warning is found in $this->content.
+ *
+ * @param string $message
+ * The message to pass on to the results.
+ * @param string $group
+ * The group to place the result in.
+ *
+ * @return bool
+ * TRUE on success, FALSE on failure.
+ */
+ public function assertWarning($message = '', $group = 'Other') {
+ if (!$message) {
+ $message = "Warning found on current page when warning was expected.";
+ }
+ return $this->assertRaw("
", $message, $group);
+ }
+
+ /**
+ * Asserts that no warning is found in $this->content.
+ *
+ * @param string $message
+ * The message to pass on to the results.
+ * @param string $group
+ * The group to place the result in.
+ *
+ * @return bool
+ * TRUE on success, FALSE on failure.
+ */
+ public function assertNoWarning($message = '', $group = 'Other') {
+ if (!$message) {
+ $message = "No warning found on current page when no warning was expected.";
+ }
+ return $this->assertNoRaw("
", $message, $group);
+ }
+
+ /**
+ * Makes a drupalPost() request, using the form submit button's ID.
+ *
+ * Because drupalPost() is silly and doesn't let us choose which button we'd
+ * like to select if multiple buttons have the same value, this function
+ * allows us to select whatever button we'd like based on the ID instead.
+ *
+ * This is done via the absolutely hilarious method of fudging the actual
+ * button labels that don't have the ID we want, so that the only one left
+ * with the correct label is the one with the right ID.
+ *
+ * @see DrupalWebTestCase::drupalPost()
+ *
+ * @param string $path
+ * Location of the post form.
+ * @param array $edit
+ * Field data in an associative array.
+ * @param string $submit
+ * Value of the submit button whose click is to be emulated.
+ * @param string $id
+ * ID of the submit button whose click is to be emulated.
+ * @param array $options
+ * Options to be forwarded to url().
+ * @param array $headers
+ * An array containing additional HTTP request headers, each formatted as
+ * "name: value".
+ * @param null $form_html_id
+ * (optional) HTML ID of the form to be submitted.
+ * @param null $extra_post
+ * (optional) A string of additional data to append to the POST submission.
+ *
+ * @return bool|string
+ * The content from the POST request's curlExec, or FALSE on fail.
+ */
+ public function drupalPostByID($path, $edit, $submit, $id, array $options = array(), array $headers = array(), $form_html_id = NULL, $extra_post = NULL) {
+ $buttons = $this->xpath("//input[@type=\"submit\" and @value=\"{$submit}\"]");
+ if (empty($buttons)) {
+ $this->fail("No buttons found on the page with value '$submit'");
+ return FALSE;
+ }
+ $i = 0;
+ foreach ($buttons as $button) {
+ if ($button['id'] !== $id) {
+ $button['value'] .= "_$i";
+ $i++;
+ }
+ }
+ return $this->drupalPost($path, $edit, $submit, $options, $headers, $form_html_id, $extra_post);
+ }
+
}
diff --git a/tests/scripts/travis_after_failure.sh b/tests/scripts/travis_after_failure.sh
new file mode 100755
index 00000000..288cb75c
--- /dev/null
+++ b/tests/scripts/travis_after_failure.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# Get the end portion of the TRAVIS_REPO_SLUG for the branch name.
+DELIMITED_SLUG = $(echo $TRAVIS_REPO_SLUG | tr "/" "\n")
+CURRENT_REPO = "${DELIMITED_SLUG[1]}"
+
+# Git business
+export VERBOSE_DIR = $HOME/sites/default/files/simpletest/verbose
+cd $HOME
+git clone https://islandora-logger:$LOGGER_PW@github.com/Islandora/islandora_travis_logs.git
+cd islandora_travis_logs
+git checkout -B $CURRENT_REPO
+
+# Out with the old, in with the new
+git rm $HOME/islandora_travis_logs/*.*
+cp $VERBOSE_DIR/*.* $HOME/islandora_travis_logs
+git add -A
+git commit -m "Job: $TRAVIS_JOB_NUMBER Commit: $TRAVIS_COMMIT"
+git push origin $CURRENT_REPO
diff --git a/tests/scripts/travis_setup.sh b/tests/scripts/travis_setup.sh
index c1bd7751..3991afcd 100755
--- a/tests/scripts/travis_setup.sh
+++ b/tests/scripts/travis_setup.sh
@@ -12,15 +12,16 @@ export CATALINA_HOME='.'
export JAVA_OPTS="-Xms1024m -Xmx1024m -XX:MaxPermSize=512m -XX:+CMSClassUnloadingEnabled -Djavax.net.ssl.trustStore=$CATALINA_HOME/fedora/server/truststore -Djavax.net.ssl.trustStorePassword=tomcat"
./bin/startup.sh
cd $HOME
+pear channel-discover pear.drush.org
pear upgrade --force Console_Getopt
pear upgrade --force pear
-pear upgrade-all
-pear channel-discover pear.drush.org
pear channel-discover pear.drush.org
-pear channel-discover pear.phpqatools.org
-pear channel-discover pear.netpirates.net
-pear install pear/PHP_CodeSniffer-1.4.8
-pear install pear.phpunit.de/phpcpd
+
+# "prefer-source" required due to SSL shenanigans on the Travis boxes...
+composer global require --prefer-source 'squizlabs/php_codesniffer=*' 'sebastian/phpcpd=*'
+# Because we can't add to the PATH here and this file is used in many repos,
+# let's just throw symlinks in.
+find $HOME/.composer/vendor/bin -executable \! -type d -exec sudo ln -s {} /usr/local/sbin/ \;
# Install Drush
git clone https://github.com/drush-ops/drush.git
@@ -34,6 +35,10 @@ phpenv rehash
drush dl --yes drupal
cd drupal-*
drush si minimal --db-url=mysql://drupal:drupal@localhost/drupal --yes
+# Needs to make things from Composer be available (PHP CS, primarily)
+sudo chmod a+w sites/default/settings.php
+echo "include_once '$HOME/.composer/vendor/autoload.php';" >> sites/default/settings.php
+sudo chmod a-w sites/default/settings.php
drush runserver --php-cgi=$HOME/.phpenv/shims/php-cgi localhost:8081 &>/dev/null &
ln -s $ISLANDORA_DIR sites/all/modules/islandora
mv sites/all/modules/islandora/tests/travis.test_config.ini sites/all/modules/islandora/tests/test_config.ini
diff --git a/theme/islandora-dublin-core-display.tpl.php b/theme/islandora-dublin-core-display.tpl.php
index 2c2a02ee..52c80607 100644
--- a/theme/islandora-dublin-core-display.tpl.php
+++ b/theme/islandora-dublin-core-display.tpl.php
@@ -17,7 +17,7 @@
+
+
+
+
+
+
label, "islandora/object/{$collection->id}"); ?>
+
+
+
+
diff --git a/theme/theme.inc b/theme/theme.inc
index b783cfa8..feac06b2 100644
--- a/theme/theme.inc
+++ b/theme/theme.inc
@@ -109,6 +109,7 @@ function islandora_preprocess_islandora_default(&$variables) {
$islandora_object = $variables['islandora_object'];
module_load_include('inc', 'islandora', 'includes/utilities');
module_load_include('inc', 'islandora', 'includes/datastream');
+ module_load_include('inc', 'islandora', 'includes/metadata');
$variables['parent_collections'] = islandora_get_parents_from_rels_ext($islandora_object);
@@ -140,8 +141,13 @@ function islandora_preprocess_islandora_default(&$variables) {
$dc_object = DublinCore::importFromXMLString($islandora_object['DC']->content);
$dc_array = $dc_object->asArray();
}
+ // We should eventually remove the DC object and dc_array code as it only
+ // exists to not break legacy implementations.
$variables['dc_array'] = isset($dc_array) ? $dc_array : array();
$variables['islandora_dublin_core'] = isset($dc_object) ? $dc_object : NULL;
+
+ $variables['metadata'] = islandora_retrieve_metadata_markup($islandora_object, TRUE);
+ $variables['description'] = islandora_retrieve_description_markup($islandora_object);
$variables['islandora_object_label'] = $islandora_object->label;
if (isset($islandora_object['TN']) && islandora_datastream_access(ISLANDORA_VIEW_OBJECTS, $islandora_object['TN'])) {
$variables['islandora_thumbnail_url'] = url("islandora/object/{$islandora_object->id}/datastream/TN/view");