Browse Source

Merge pull request #4 from adam-vessey/7.x-datastream-validation

Slight change to logic, merged in 7.x HEAD.
pull/463/head
qadan 11 years ago
parent
commit
ec661c799b
  1. 13
      .travis.yml
  2. 11
      README.md
  3. 2
      includes/admin.form.inc
  4. 7
      includes/authtokens.inc
  5. 16
      includes/derivatives.inc
  6. 14
      includes/ingest.form.inc
  7. 2
      includes/manage_deleted_objects.inc
  8. 6
      includes/regenerate_derivatives.form.inc
  9. 18
      includes/solution_packs.inc
  10. 4
      includes/tuque_wrapper.inc
  11. 17
      islandora.api.php
  12. 58
      islandora.module
  13. 23
      islandora.rules.inc
  14. 26
      islandora.rules_defaults.inc
  15. 31
      policies/permit-apim-to-anonymous-user.xml
  16. 31
      policies/permit-upload-to-anonymous-user.xml
  17. 30
      tests/datastream_validators.inc
  18. 147
      tests/islandora_web_test_case.inc
  19. 19
      tests/scripts/travis_after_failure.sh
  20. 17
      tests/scripts/travis_setup.sh
  21. 2
      theme/islandora-dublin-core-display.tpl.php
  22. 48
      theme/islandora-object.tpl.php
  23. 6
      theme/theme.inc

13
.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

11
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
-------------

2
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' => '<div id="islandora-url">',
'#suffix' => '</div>',

7
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,

16
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,
),
);
}
}

14
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);

2
includes/manage_deleted_objects.inc

@ -332,7 +332,7 @@ function islandora_get_deleted_query($content_models, $offset = 0) {
$unions .= "UNION {?subject fm:hasModel <info:fedora/$contentmodel>;
fm:state fm:Deleted;
fm:hasModel ?object;
}
}
";
}
$optional = "OPTIONAL{?subject fm:label ?label}";

6
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;
}

18
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;
}
}

4
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) {

17
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;

58
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');
}

23
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;
}
/**

26
islandora.rules_defaults.inc

@ -0,0 +1,26 @@
<?php
/**
* @file
* Implementation of Rules hooks, giving default configurations.
*/
/**
* Implements hook_default_rules_configuration().
*/
function islandora_default_rules_configuration() {
$rule = rules_reaction_rule();
$rule->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);
}

31
policies/permit-apim-to-anonymous-user.xml

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<Policy xmlns="urn:oasis:names:tc:xacml:1.0:policy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
PolicyId="permit-apim-to-anonymous-user"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable">
<Description>note that other policies may provide exceptions to this broad policy. This policy assumes api-m users have to be authenticated</Description>
<Target>
<Subjects>
<Subject>
<SubjectMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">anonymous user</AttributeValue>
<SubjectAttributeDesignator AttributeId="fedoraRole" MustBePresent="false"
DataType="http://www.w3.org/2001/XMLSchema#string"/>
</SubjectMatch>
</Subject>
</Subjects>
<Resources>
<AnyResource/>
</Resources>
<Actions>
<Action>
<ActionMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">urn:fedora:names:fedora:2.1:action:api-m</AttributeValue>
<ActionAttributeDesignator DataType="http://www.w3.org/2001/XMLSchema#string"
AttributeId="urn:fedora:names:fedora:2.1:action:api"/>
</ActionMatch>
</Action>
</Actions>
</Target>
<Rule RuleId="1" Effect="Permit"/>
</Policy>

31
policies/permit-upload-to-anonymous-user.xml

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<Policy xmlns="urn:oasis:names:tc:xacml:1.0:policy"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
PolicyId="permit-upload-to-anonymous-user"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable">
<Description></Description>
<Target>
<Subjects>
<Subject>
<SubjectMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">anonymous user</AttributeValue>
<SubjectAttributeDesignator AttributeId="fedoraRole" MustBePresent="false"
DataType="http://www.w3.org/2001/XMLSchema#string"/>
</SubjectMatch>
</Subject>
</Subjects>
<Resources>
<AnyResource/>
</Resources>
<Actions>
<Action>
<ActionMatch MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">urn:fedora:names:fedora:2.1:action:id-upload</AttributeValue>
<ActionAttributeDesignator DataType="http://www.w3.org/2001/XMLSchema#string"
AttributeId="urn:fedora:names:fedora:2.1:action:id"/>
</ActionMatch>
</Action>
</Actions>
</Target>
<Rule RuleId="1" Effect="Permit"/>
</Policy>

30
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);
}
/**

147
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("<div class=\"messages error\">", $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("<div class=\"messages error\">", $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("<div class=\"messages warning\">", $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("<div class=\"messages error\">", $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);
}
}

19
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

17
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

2
theme/islandora-dublin-core-display.tpl.php

@ -17,7 +17,7 @@
<fieldset <?php $print ? print('class="islandora islandora-metadata"') : print('class="islandora islandora-metadata collapsible collapsed"');?>>
<legend><span class="fieldset-legend"><?php print t('Details'); ?></span></legend>
<div class="fieldset-wrapper">
<dl xmlns:dcterms="http://purl.org/dc/terms/" class="islandora-inline-metadata islandora-metadata-fields">
<dl xmlns:dcterms="http://purl.org/dc/terms/" class="islandora-inline-metadata islandora-metadata-fields islandora-object-fields">
<?php $row_field = 0; ?>
<?php foreach($dc_array as $key => $value): ?>
<dt property="<?php print $value['dcterms']; ?>" content="<?php print filter_xss($value['value']); ?>" class="<?php print $value['class']; ?><?php print $row_field == 0 ? ' first' : ''; ?>">

48
theme/islandora-object.tpl.php

@ -60,34 +60,18 @@
?>
<div class="islandora-object islandora">
<h2><?php print t('Details'); ?></h2>
<dl class="islandora-object-tn">
<dt>
<?php if (isset($variables['islandora_thumbnail_url'])): ?>
<img src="<?php print $variables['islandora_thumbnail_url']; ?>"/></dt>
<?php endif; ?>
<dd></dd>
</dl>
<dl class="islandora-inline-metadata islandora-object-fields">
<?php $row_field = 0; ?>
<?php foreach ($dc_array as $key => $value): ?>
<dt class="<?php print $value['class']; ?><?php print $row_field == 0 ? ' first' : ''; ?>">
<?php print $value['label']; ?>
</dt>
<dd class="<?php print $value['class']; ?><?php print $row_field == 0 ? ' first' : ''; ?>">
<?php print $value['value']; ?>
</dd>
<?php $row_field++; ?>
<?php endforeach; ?>
<?php if ($parent_collections): ?>
<dt>Collections</dt>
<dd>
<?php foreach ($parent_collections as $collection): ?>
<div><?php print l($collection->label, "islandora/object/{$collection->id}"); ?></div>
<?php endforeach; ?>
</dd>
<?php endif; ?>
<?php if (isset($variables['islandora_thumbnail_url'])): ?>
<dl class="islandora-object-tn">
<dt>
<img src="<?php print $variables['islandora_thumbnail_url']; ?>"/>
</dt>
</dl>
<?php endif; ?>
<div class="islandora-default-metadata">
<?php print $description; ?>
<?php print $metadata; ?>
</div>
</div>
<fieldset class="collapsible collapsed" style="display: block; clear:both">
<legend><span class="fieldset-legend"><?php print t('File details'); ?></span></legend>
@ -112,3 +96,13 @@
</table>
</div>
</fieldset>
<?php if ($parent_collections): ?>
<div>
<h2><?php print t('In collections'); ?></h2>
<ul>
<?php foreach ($parent_collections as $collection): ?>
<li><?php print l($collection->label, "islandora/object/{$collection->id}"); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>

6
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");

Loading…
Cancel
Save