Browse Source

Resolved merge conflict in info file.

pull/476/head
MorganDawe 11 years ago
parent
commit
dcb1e88a19
  1. 7
      .travis.yml
  2. 7
      includes/authtokens.inc
  3. 49
      includes/derivatives.inc
  4. 4
      includes/ingest.form.inc
  5. 6
      includes/regenerate_derivatives.form.inc
  6. 16
      includes/solution_packs.inc
  7. 4
      includes/tuque_wrapper.inc
  8. 15
      islandora.api.php
  9. 4
      islandora.info
  10. 65
      islandora.module
  11. 23
      islandora.rules.inc
  12. 26
      islandora.rules_defaults.inc
  13. 41
      tests/README.md
  14. 277
      tests/datastream_validator_tests.test
  15. 862
      tests/datastream_validators.inc
  16. 203
      tests/islandora_web_test_case.inc
  17. 22
      tests/scripts/travis_after_failure.sh
  18. 17
      tests/scripts/travis_setup.sh
  19. 8
      theme/islandora-object.tpl.php

7
.travis.yml

@ -6,9 +6,14 @@ branches:
only: only:
- /^7.x/ - /^7.x/
env: env:
matrix:
- FEDORA_VERSION="3.5" - FEDORA_VERSION="3.5"
- FEDORA_VERSION="3.6.2" - FEDORA_VERSION="3.6.2"
- FEDORA_VERSION="3.7.0" - 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: before_install:
- export ISLANDORA_DIR=$TRAVIS_BUILD_DIR - export ISLANDORA_DIR=$TRAVIS_BUILD_DIR
- $TRAVIS_BUILD_DIR/tests/scripts/travis_setup.sh - $TRAVIS_BUILD_DIR/tests/scripts/travis_setup.sh
@ -19,3 +24,5 @@ script:
- drush coder-review --reviews=production,security,style,i18n,potx,sniffer islandora - drush coder-review --reviews=production,security,style,i18n,potx,sniffer islandora
- phpcpd --names *.module,*.inc,*.test sites/all/modules/islandora - phpcpd --names *.module,*.inc,*.test sites/all/modules/islandora
- drush test-run --uri=http://localhost:8081 Islandora - drush test-run --uri=http://localhost:8081 Islandora
after_failure:
- $ISLANDORA_DIR/tests/scripts/travis_after_failure.sh

7
includes/authtokens.inc

@ -36,12 +36,7 @@ define('ISLANDORA_AUTHTOKEN_TOKEN_TIMEOUT', 300);
function islandora_get_object_token($pid, $dsid, $uses = 1) { function islandora_get_object_token($pid, $dsid, $uses = 1) {
global $user; global $user;
$time = time(); $time = time();
// The function mt_rand is not considered cryptographically secure $token = bin2hex(drupal_random_bytes(32));
// 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);
$id = db_insert("islandora_authtokens")->fields( $id = db_insert("islandora_authtokens")->fields(
array( array(
'token' => $token, 'token' => $token,

49
includes/derivatives.inc

@ -4,6 +4,45 @@
* Defines functions used when constructing derivatives. * Defines functions used when constructing derivatives.
*/ */
/**
* Decides which derivative function to call and runs it.
*
* @param AbstractObject $object
* The object to run the derivative function for.
* @param string $dsid
* The DSID to run the derivative function for.
*/
function islandora_run_derivatives(AbstractObject $object, $dsid) {
$batch_array = batch_get();
if (empty($batch_array)) {
$logging_results = islandora_do_derivatives($object, array(
'source_dsid' => $dsid,
));
islandora_derivative_logging($logging_results);
}
else {
batch_set(
// Title won't show for batch in a batch.
array(
'init_message' => t('Preparing derivatives for @label', array('@label' => $object->label)),
'error_message' => t('An error occured creating derivatives.'),
'progress_message' => t(
'Creating derivatives for @label <br/>Time elapsed: @elapsed <br/>
Estimated time remaining @estimate.',
array('@label' => $object->label)
),
'file' => drupal_get_path('module', 'islandora') . '/includes/regenerate_derivatives.form.inc',
'operations' => islandora_do_batch_derivatives(
$object,
array(
'source_dsid' => $dsid,
)
),
)
);
}
}
/** /**
* Kicks off derivative functions based upon hooks and conditions. * Kicks off derivative functions based upon hooks and conditions.
* *
@ -49,7 +88,7 @@ function islandora_do_derivatives(AbstractObject $object, array $options) {
} }
foreach ($hook['function'] as $function) { foreach ($hook['function'] as $function) {
if (function_exists($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)) { if (!empty($logging)) {
$results[] = $logging; $results[] = $logging;
} }
@ -142,11 +181,15 @@ function islandora_do_batch_derivatives(AbstractObject $object, array $options)
$file = $hook['file']; $file = $hook['file'];
} }
foreach ($hook['function'] as $function) { foreach ($hook['function'] as $function) {
$operations[] = array('islandora_derivative_perform_batch_operation', array( $operations[] = array(
'islandora_derivative_perform_batch_operation',
array(
$function, $function,
$file, $file,
$object->id, $object->id,
$options['force']), $options['force'],
$hook,
),
); );
} }
} }

4
includes/ingest.form.inc

@ -467,6 +467,7 @@ function islandora_ingest_form_undo_consecutive_callback_steps(array $form, arra
* The step which the undo callback is being called on. * The step which the undo callback is being called on.
*/ */
function islandora_ingest_form_undo_callback_step(array $form, array &$form_state, array $step) { function islandora_ingest_form_undo_callback_step(array $form, array &$form_state, array $step) {
if (isset($step['undo_function'])) {
$args = array(&$form_state); $args = array(&$form_state);
$args = isset($step['undo_function']['args']) ? array_merge($args, $step['undo_function']['args']) : $args; $args = isset($step['undo_function']['args']) ? array_merge($args, $step['undo_function']['args']) : $args;
if (isset($step['undo_function']['file'])) { if (isset($step['undo_function']['file'])) {
@ -474,6 +475,7 @@ function islandora_ingest_form_undo_callback_step(array $form, array &$form_stat
} }
call_user_func_array($step['undo_function']['function'], $args); call_user_func_array($step['undo_function']['function'], $args);
} }
}
/** /**
* Append Prev/Next buttons submit/validation handlers etc. * Append Prev/Next buttons submit/validation handlers etc.
@ -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); islandora_ingest_form_execute_consecutive_callback_steps($form, $form_state, $step);
} }
// Ingest the objects. // Ingest the objects.
$set_redirect = TRUE; $set_redirect = isset($form_state['redirect']) ? FALSE : TRUE;
foreach ($form_state['islandora']['objects'] as &$object) { foreach ($form_state['islandora']['objects'] as &$object) {
try { try {
islandora_add_object($object); islandora_add_object($object);

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. * The pid of the object we are performing.
* @param bool $force * @param bool $force
* Whether we are forcing derivative regeneration or not. * Whether we are forcing derivative regeneration or not.
* @param array $hook
* The derivative definition.
* @param array $context * @param array $context
* The context of the current batch operation. * 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) { if ($file) {
require_once $file; require_once $file;
} }
if (function_exists($function)) { 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)) { if (!empty($logging)) {
$context['results']['logging'][] = $logging; $context['results']['logging'][] = $logging;
} }

16
includes/solution_packs.inc

@ -367,7 +367,7 @@ function islandora_install_solution_pack($module, $op = 'install', $force = FALS
$t = get_t(); $t = get_t();
// Some general replacements. // 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'); $config_link = l($t('Islandora configuration'), 'admin/islandora/configure');
$t_params = array( $t_params = array(
'@module' => $module, '@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 * given, than any viewer that supports either the give $mimetype or $model will
* be listed. * be listed.
* *
* @param string $mimetype * @param array $mimetype
* Specify a mimetype to return only viewers that support this certain * List of mimetypes that the viewer supports.
* mimetype.
* @param string $content_model * @param string $content_model
* Specify a content model to return only viewers that support the content * Specify a content model to return only viewers that support the content
* model. * model.
@ -722,14 +721,19 @@ function islandora_viewers_form($variable_id = NULL, $mimetype = NULL, $model =
* @return array * @return array
* Viewer definitions, or FALSE if none are found. * 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(); $viewers = array();
$defined_viewers = module_invoke_all('islandora_viewer_info'); $defined_viewers = module_invoke_all('islandora_viewer_info');
if (!is_array($mimetype)) {
$mimetype = array($mimetype);
}
// Filter viewers by MIME type. // Filter viewers by MIME type.
foreach ($defined_viewers as $key => $value) { foreach ($defined_viewers as $key => $value) {
$value['mimetype'] = isset($value['mimetype']) ? $value['mimetype'] : array(); $value['mimetype'] = isset($value['mimetype']) ? $value['mimetype'] : array();
$value['model'] = isset($value['model']) ? $value['model'] : 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; $viewers[$key] = $value;
} }
} }

4
includes/tuque_wrapper.inc

@ -115,6 +115,10 @@ class IslandoraFedoraRepository extends FedoraRepository {
foreach ($object as $dsid => $datastream) { foreach ($object as $dsid => $datastream) {
islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_INGESTED_HOOK, $object->models, $dsid, $object, $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; return $ret;
} }
catch (Exception $e) { catch (Exception $e) {

15
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 * - form_id: The form building function to call to get the form structure
* for this step. * for this step.
* - args: An array of arguments to pass to the form building function. * - args: An array of arguments to pass to the form building function.
* Required "callback" type specific parameters: * "Callback" type specific parameters:
* - do_function: An associate array including: * - do_function: A required associative array including:
* - 'function': The callback function to be called. * - 'function': The callback function to be called.
* - 'args': An array of arguments to pass to the callback function. * - 'args': An array of arguments to pass to the callback function.
* - 'file': A file to include (relative to the module's path, including * - 'file': A file to include (relative to the module's path, including
* the file's extension). * 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 * - 'function': The callback function to be called to reverse the
* executed action in the ingest steps. * executed action in the ingest steps.
* - 'args': An array of arguments to pass to the callback function. * - 'args': An array of arguments to pass to the callback function.
@ -627,22 +627,23 @@ function hook_CMODEL_PID_islandora_overview_object_alter(AbstractObject &$object
* - force: Bool denoting whether we are forcing the generation of * - force: Bool denoting whether we are forcing the generation of
* derivatives. * derivatives.
* - source_dsid: (Optional) String of the datastream id we are generating * - source_dsid: (Optional) String of the datastream id we are generating
* from or NULL if it's the object itself. * from or NULL if it's the object itself. Does not impact function
* ordering.
* - destination_dsid: (Optional) String of the datastream id that is being * - destination_dsid: (Optional) String of the datastream id that is being
* created. To be used in the UI. * created. To be used in the UI. Does not impact function ordering.
* - weight: A string denoting the weight of the function. This value is * - weight: A string denoting the weight of the function. This value is
* sorted upon to run functions in order. * sorted upon to run functions in order.
* - function: An array of function(s) to be ran when constructing * - function: An array of function(s) to be ran when constructing
* derivatives. Functions that are defined to be called for derivation * derivatives. Functions that are defined to be called for derivation
* creation must have the following structure: * 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: * These functions must return an array in the structure of:
* - success: Bool denoting whether the operation was successful. * - success: Bool denoting whether the operation was successful.
* - messages: An array structure containing zero or more array's with the * - messages: An array structure containing zero or more array's with the
* following fields: * following fields:
* - message: A string passed through t() describing the * - message: A string passed through t() describing the
* outcome of the operation. * outcome of the operation.
* - message_sub: (Optional) Substitutions to be passed along to t() or * - message_sub: (Optional) A substitution array as acceptable by t() or
* watchdog. * watchdog.
* - type: A string denoting whether the output is to be * - type: A string denoting whether the output is to be
* drupal_set_messaged (dsm) or watchdogged (watchdog). * drupal_set_messaged (dsm) or watchdogged (watchdog).

4
islandora.info

@ -22,5 +22,9 @@ files[] = tests/islandora_manage_permissions.test
files[] = tests/datastream_versions.test files[] = tests/datastream_versions.test
files[] = tests/datastream_cache.test files[] = tests/datastream_cache.test
files[] = tests/derivatives.test files[] = tests/derivatives.test
<<<<<<< HEAD
files[] = tests/islandora_manage_temp_file.test files[] = tests/islandora_manage_temp_file.test
=======
files[] = tests/datastream_validator_tests.test
>>>>>>> 6c3fcb0381318857b6c2aa7f9059f939ab7ecef5
php = 5.3 php = 5.3

65
islandora.module

@ -109,13 +109,35 @@ function islandora_menu() {
'file' => 'includes/metadata.inc', 'file' => 'includes/metadata.inc',
'access arguments' => array('administer site configuration'), 'access arguments' => array('administer site configuration'),
); );
$items['admin/islandora/solution_packs'] = array( $items['admin/islandora/solution_pack_config'] = array(
'title' => 'Solution packs', '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.', 'description' => 'Install content models and collections required by installed solution packs.',
'page callback' => 'islandora_solution_packs_admin', 'page callback' => 'islandora_solution_packs_admin',
'access arguments' => array(ISLANDORA_ADD_DS), 'access arguments' => array(ISLANDORA_ADD_DS),
'file' => 'includes/solution_packs.inc', 'file' => 'includes/solution_packs.inc',
'type' => MENU_NORMAL_ITEM, 'type' => MENU_NORMAL_ITEM,
'weight' => -1,
); );
$items['islandora'] = array( $items['islandora'] = array(
'title' => 'Islandora Repository', 'title' => 'Islandora Repository',
@ -1531,6 +1553,11 @@ function islandora_entity_property_info() {
'label' => t('Content Models'), 'label' => t('Content Models'),
'description' => t('The list of content models which the object has.'), '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; return $info;
} }
@ -1695,10 +1722,7 @@ function islandora_islandora_basic_collection_get_query_filters() {
*/ */
function islandora_islandora_object_ingested(AbstractObject $object) { function islandora_islandora_object_ingested(AbstractObject $object) {
module_load_include('inc', 'islandora', 'includes/derivatives'); module_load_include('inc', 'islandora', 'includes/derivatives');
$logging_results = islandora_do_derivatives($object, array( islandora_run_derivatives($object, NULL);
'source_dsid' => NULL,
));
islandora_derivative_logging($logging_results);
} }
/** /**
@ -1709,10 +1733,7 @@ function islandora_islandora_object_ingested(AbstractObject $object) {
*/ */
function islandora_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) { function islandora_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) {
module_load_include('inc', 'islandora', 'includes/derivatives'); module_load_include('inc', 'islandora', 'includes/derivatives');
$logging_results = islandora_do_derivatives($object, array( islandora_run_derivatives($object, $datastream->id);
'source_dsid' => $datastream->id,
));
islandora_derivative_logging($logging_results);
} }
/** /**
@ -1853,7 +1874,8 @@ function islandora_islandora_datastream_access($op, AbstractDatastream $datastre
$hooks = islandora_invoke_hook_list(ISLANDORA_DERVIATIVE_CREATION_HOOK, $object->models, array($object)); $hooks = islandora_invoke_hook_list(ISLANDORA_DERVIATIVE_CREATION_HOOK, $object->models, array($object));
$hooks = islandora_filter_derivatives($hooks, array('force' => TRUE), $object); $hooks = islandora_filter_derivatives($hooks, array('force' => TRUE), $object);
foreach ($hooks as $hook) { foreach ($hooks as $hook) {
if ($hook['destination_dsid'] == $datastream->id && islandora_datastream_access(ISLANDORA_VIEW_OBJECTS, $object[$hook['source_dsid']], $user)) { if ($hook['destination_dsid'] == $datastream->id &&
(is_null($hook['source_dsid']) || islandora_datastream_access(ISLANDORA_VIEW_OBJECTS, $object[$hook['source_dsid']], $user))) {
$applicable_hook = TRUE; $applicable_hook = TRUE;
break; break;
} }
@ -1864,3 +1886,24 @@ function islandora_islandora_datastream_access($op, AbstractDatastream $datastre
} }
return $result; 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, * 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. * Helper function to get reused "parameter" array.
*/ */
function islandora_rules_relationship_parameter_array() { function islandora_rules_relationship_parameter_array() {
$to_return = array( return array(
'subject' => array( 'subject' => array(
'type' => 'islandora_object', 'type' => 'islandora_object',
'label' => t('Subject'), 'label' => t('Subject'),
@ -39,8 +58,6 @@ function islandora_rules_relationship_parameter_array() {
'default value' => 0, '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);
}

41
tests/README.md

@ -1,4 +1,43 @@
You can define your own configurations specific to your enviroment by copying OVERVIEW
********
You can define your own configurations specific to your environment by copying
default.test_config.ini to test_config.ini, making your changes in the copied default.test_config.ini to test_config.ini, making your changes in the copied
file. These test need write access to the system's $FEDORA_HOME/server/config file. These test need write access to the system's $FEDORA_HOME/server/config
directory as well as the filter-drupal.xml file. directory as well as the filter-drupal.xml file.
DATASTREAM VALIDATION TESTS
***************************
The datastream validator included in the Islandora testing suite is able to
generate tests procedurally based on the files in the folder
'fixtures/datastream_validator_files'. By default, this folder is empty.
The unit tests for the validator pull the name of the file (before the
extension) and use that to instantiate the correct ______DatastreamValidator
class to test that file against (e.g. Image.jpg spins up an instance of the
ImageDatastreamValidator class and checks the results).
You can test against multiple different encodings of the same filetype by giving
each file a different set of extensions, e.g. MP3.vbr.mp3 and MP3.sbr.mp3 both
test against the MP3 datastream validator, even though both are encoded
differently.
For classes that require the third parameter (e.g. the TextDatastreamValidator),
place an additional name.extension.ini file in the datastream_validator_files
folder (e.g. the Text.txt would be paired with Text.txt.ini). This .ini file
should be structured like a PHP .ini file (e.g. according to the format used by
http://php.net/parse_ini_file).The generated test will parse the .ini
file as an array and pass it on to the third parameter.
The following prefixes are currently available for use:
- Image (jpg, png, gif, and other filetypes recognized by PHPGD)
- TIFF
- JP2
- PDF
- Text (requires a configured .ini)
- WAV
- MP3
- MP4
- OGG (asserts OGG video; use an .ini with an 'audio' key to test audio only)
- MKV

277
tests/datastream_validator_tests.test

@ -0,0 +1,277 @@
<?php
/**
* @file
* Tests for things that test tests. Madness.
*/
include 'datastream_validators.inc';
/**
* A test DatastreamValidator for the DatastreamValidatorResultTestCase.
*/
class TestDatastreamValidator extends DatastreamValidator {
/**
* Assertion that adds a TRUE result.
*/
protected function assertSomethingSuccessfully() {
$this->addResult(TRUE, 'yay you did it', $this->getAssertionCall());
}
/**
* Assertion that adds a FALSE result.
*/
protected function assertSomethingFailed() {
$this->addResult(FALSE, 'boo you failed', $this->getAssertionCall());
}
}
/**
* Tests the ability of DatastreamValidators to produce correct results.
*/
class DatastreamValidatorResultTestCase extends IslandoraWebTestCase {
/**
* Returns the info for this test case.
*
* @see DrupalWebTestCase::getInfo()
*/
public static function getInfo() {
return array(
'name' => 'Datastream Validator Result Tests',
'description' => 'Unit tests for datastream validation result functionality.',
'group' => 'Islandora',
);
}
/**
* Sets up the test.
*
* @see DrupalWebTestCase::setUp()
*/
public function setUp() {
parent::setUp();
$user = $this->drupalCreateUser(array_keys(module_invoke_all('permission')));
$this->drupalLogin($user);
$object = $this->ingestConstructedObject();
$validator = new TestDatastreamValidator($object, 'DC');
$this->validator_results = $validator->getResults();
}
/**
* Generates a generic DatastreamValidatorResult and grabs its properties.
*/
public function testDatastreamValidatorResult() {
$result = new DatastreamValidatorResult(TRUE, 'true', array());
$this->assertEqual($result->getMessage(), 'true', "Result message generated correctly.", 'Islandora');
$this->assertEqual($result->getType(), TRUE, "Result type generated correctly.", 'Islandora');
$this->assertEqual($result->getCaller(), array(), "Result caller generated correctly.", 'Islandora');
}
/**
* Gets the results of TestDatastreamValidator and confirms only 2 exist.
*/
public function testTestDatastreamValidatorResultCount() {
$this->assertTrue(isset($this->validator_results[0]), "First of two expected results found.", 'Islandora');
$this->assertTrue(isset($this->validator_results[1]), "Second of two expected results found.", 'Islandora');
$this->assertFalse(isset($this->validator_results[2]), "No other unexpected results found.", 'Islandora');
}
/**
* Confirms the messages from TestDatastreamValidator.
*/
public function testTestDatastreamValidatorMessages() {
if (isset($this->validator_results[0]) && isset($this->validator_results[1])) {
$this->assertEqual($this->validator_results[0]->getMessage(), 'yay you did it', "Appropriate pass message returned.", 'Islandora');
$this->assertEqual($this->validator_results[1]->getMessage(), 'boo you failed', "Appropriate fail message returned.", 'Islandora');
}
}
/**
* Confirms the types from TestDatastreamValidator.
*/
public function testTestDatastreamValidatorTypes() {
if (isset($this->validator_results[0]) && isset($this->validator_results[1])) {
$this->assertEqual($this->validator_results[0]->getType(), TRUE, "Appropriate pass type of TRUE returned.", 'Islandora');
$this->assertEqual($this->validator_results[1]->getType(), FALSE, "Appropriate fail type of FALSE returned.", 'Islandora');
}
}
/**
* Confirms the useful information from TestDatastreamValidator.
*/
public function testTestDatastreamValidatorCallers() {
if (isset($this->validator_results[0]) && isset($this->validator_results[1])) {
// Grab the callers.
$first_caller = $this->validator_results[0]->getCaller();
$second_caller = $this->validator_results[1]->getCaller();
// Assert the 'file' key.
$this->assertTrue(substr($first_caller['file'], -48) === '/islandora/tests/datastream_validator_tests.test', "Appropriate pass caller file returned.", 'Islandora');
$this->assertTrue(substr($first_caller['file'], -48) === substr($second_caller['file'], -48), "Fail caller file matches the pass caller file.", 'Islandora');
$this->assertTrue($first_caller['function'] === 'TestDatastreamValidator->assertSomethingSuccessfully()', "Correct pass caller function returned (actual: {$first_caller['function']}; expected: TestDatastreamValidator->assertSomethingSuccessfully()).", 'Islandora');
$this->assertTrue($second_caller['function'] === 'TestDatastreamValidator->assertSomethingFailed()', "Correct fail caller function returned (actual: {$second_caller['function']}; expected: TestDatastreamValidator->assertSomethingFailed()).", 'Islandora');
$this->assertTrue($first_caller['line'] === 18, "Correct pass line number returned (actual: {$first_caller['line']}; expected: 9).", 'Islandora');
$this->assertTrue($second_caller['line'] === 25, "Correct fail line number returned (actual: {$second_caller['line']}; expected: 13).", 'Islandora');
}
}
}
/**
* Procedurally generated tests for DatastreamValidators.
*/
class PrefixDatastreamValidatorTestCase extends IslandoraWebTestCase {
/**
* The path to the datastream validator files.
*
* @var string
*/
protected $path;
/**
* Returns the info for this test case.
*
* @see DrupalWebTestCase::getInfo()
*/
public static function getInfo() {
return array(
'name' => 'Datastream File Validation Tests',
'description' => 'Tests each file in the islandora/tests/fixtures/datastream_validator_files folder against the appropriate DatastreamValidator class (see the README.md in the tests folder for details).',
'group' => 'Islandora',
);
}
/**
* Sets up the test.
*
* @see DrupalWebTestCase::setUp()
*/
public function setUp() {
parent::setUp();
$this->path = DRUPAL_ROOT . drupal_get_path('module', 'islandora') . "/tests/fixtures/datastream_validator_files/";
}
/**
* Confirms that a DatastreamValidator class exists for given filename.
*
* @param string $filename
* The file to grab the DatastreamValidator prefix from.
*
* @return bool
* TRUE if such a class exists; FALSE otherwise.
*/
protected function confirmValidatorClass($filename) {
$prefix = $this->getPrefix($filename);
if (!class_exists("{$prefix}DatastreamValidator")) {
$this->fail("No such DatastreamValidator exists for the prefix $prefix (filename: $filename).");
return FALSE;
}
return TRUE;
}
/**
* Confirms that a file exists at the given path.
*
* Bundled with lovely return values and fail messages.
*
* @param string $path
* The path to the file.
*
* @return bool
* TRUE if the file exists, FALSE otherwise.
*/
protected function confirmValidatorFile($path) {
if (!file_exists($path)) {
$this->fail("No such file exists at path $path.");
return FALSE;
}
return TRUE;
}
/**
* Gets the intended prefix from a filename.
*
* Uses the portion of the filename before the first period.
*
* @param string $filename
* The filename to get the prefix for.
*
* @return string
* The intended prefix.
*/
protected function getPrefix($filename) {
return array_shift(explode('.', $filename));
}
/**
* Create an object with a datastream generated from the given filename.
*
* @param string $filename
* The filename to use when adding a datastream.
*
* @return IslandoraFedoraObject
* The created object.
*/
protected function createObjectWithDatastream($filename) {
$prefix = $this->getPrefix($filename);
if (!$this->confirmValidatorClass($filename) && !$this->confirmValidatorFile($this->path . $filename)) {
return FALSE;
}
$datastreams = array(array(
'dsid' => $prefix,
'path' => $this->path . $filename,
'control_group' => 'M',
),
);
$object = $this->ingestConstructedObject(array(), $datastreams);
return $object;
}
/**
* Procedurally test each file in $this->path against a datastream validator.
*
* Check the README.md in this folder for details.
*/
public function testDatastreamValidators() {
// Grab everything in the validator files folder except for .ini files.
$files = array_intersect(glob("{$this->path}/*"), glob("{$this->path}/*.ini"));
foreach ($files as $file) {
$prefix = $this->getPrefix($file);
// If createObjectWithDatastream fails, we don't want to continue. We'll
// task it with returning fail messages rather than do so here.
$object = $this->createObjectWithDatastream($file);
if ($object !== FALSE) {
// Generate an appropriate validator.
$validator_name = "{$prefix}DatastreamValidator";
// If the file is paired with an .ini, use it as the third param.
if (file_exists("{$this->path}$file.ini")) {
$validator = new $validator_name($object, $prefix, parse_ini_file("{$this->path}$file.ini"));
}
else {
$validator = new $validator_name($object, $prefix);
}
// Get the results, check for fails.
$results = $validator->getResults();
$fails = FALSE;
foreach ($results as $result) {
if (!$result->getType()) {
$fails = TRUE;
$caller = $result->getCaller();
$this->fail("Failed to validate the test file $file against the assertion {$caller['function']}.");
}
}
// If there were no fails, say that the file passed validation.
if (!$fails) {
$this->pass("Test file $file validated successfully.");
}
}
}
}
}

862
tests/datastream_validators.inc

File diff suppressed because it is too large Load Diff

203
tests/islandora_web_test_case.inc

@ -216,36 +216,66 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
/** /**
* Attempts to validate an array of datastreams, generally via binary checks. * Attempts to validate an array of datastreams, generally via binary checks.
* *
* These functions exist in, and can be added to, datastream_validators.inc, * Datastream validation classes exist in, and can be added to, the file
* which is found in this folder. * 'datastream_validators.inc', which is found in this folder. Datastream
* validator classes use the naming convention 'PrefixDatastreamValidator',
* and that 'Prefix' is what this function uses to determine what class to
* instantiate.
* *
* $param AbstractObject $object * $param IslandoraFedoraObject $object
* The object to load datastreams from. * The object to load datastreams from.
* $param array $datastreams * $param array $datastreams
* An array of paired DSIDs, validate function names, and optional params. * An array of arrays that pair DSIDs, DatastreamValidator class prefixes,
* and optional params. You can check some of the existing implementations
* for examples.
*/ */
public function validateDatastreams($object, array $datastreams) { public function validateDatastreams($object, array $datastreams) {
if (!is_object($object)) { if (!is_object($object)) {
$this->fail("Failed. Object passed in is invalid.", 'Islandora'); $this->fail("Datastream validation failed; Object passed in is invalid.", 'Islandora');
return;
} }
module_load_include('inc', 'islandora', 'tests/datastream_validators'); module_load_include('inc', 'islandora', 'tests/datastream_validators');
foreach ($datastreams as $datastream) { foreach ($datastreams as $datastream) {
if (isset($object[$datastream[0]])) { // Let's give them conventional names.
$function = 'islandora_validate_' . $datastream[1] . '_datastream'; $dsid = $datastream[0];
if (function_exists($function)) { $prefix = $datastream[1];
$params = array();
if (isset($datastream[2])) { if (isset($datastream[2])) {
$results = $function($object, $datastream[0], $datastream[2]); $params = $datastream[2];
} }
// Legacy tests were created before the CamelCase conventions of the class
// system now in place. So, we need to automagically seek out prefixes
// that start with a lower-case letter and convert them to the proper
// format (rather than fixing every single legacy test).
if (ctype_lower(substr($prefix, 0, 1))) {
// Handle the case where the prefix is "image".
if ($prefix === 'image') {
$prefix = 'Image';
}
// Handle the case where the prefix is "text".
elseif ($prefix === 'text') {
$prefix = 'Text';
}
// All other cases involve just converting everything to caps.
else { else {
$results = $function($object, $datastream[0]); $prefix = strtoupper($prefix);
} }
foreach ($results as $result) {
$this->assertTrue($result[0], $result[1], 'Islandora');
} }
// Instantiate the appropriate class, and grab the results.
$class_name = "{$prefix}DatastreamValidator";
if (class_exists($class_name)) {
$validator = new $class_name($object, $dsid, $params);
foreach ($validator->getResults() as $result) {
$this->assert($result->getType(), $result->getMessage(), 'Islandora', $result->getCaller());
} }
else {
$this->fail("No {$datastream[0]} validation function exists for the {$datastream[1]} datastream.", 'Islandora');
} }
else {
$this->fail("No DatastreamValidator class was found with the name '$class_name'; are you sure the prefix given to IslandoraWebTestCase->validateDatastreams() was entered correctly, or that such a validator exists?", 'Islandora');
} }
} }
} }
@ -315,7 +345,8 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
* An array containing object information using these keys: * An array containing object information using these keys:
* 'label' - The object label; randomized if not set. * 'label' - The object label; randomized if not set.
* 'pid' - 'namespace:pid', or just 'namespace' to generate the suffix. * '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, * '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 * 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. * in $this->users; otherwise, this object will have to be manually deleted.
@ -331,8 +362,7 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
* FALSE if the object ingest failed, or the object array if successful. * FALSE if the object ingest failed, or the object array if successful.
*/ */
public function ingestConstructedObject(array $properties = array(), array $datastreams = array()) { public function ingestConstructedObject(array $properties = array(), array $datastreams = array()) {
module_load_include('inc', 'islandora', 'includes/tuque'); $tuque = islandora_get_tuque_connection($this->admin);
$tuque = new IslandoraTuque();
$repository = $tuque->repository; $repository = $tuque->repository;
if (!isset($properties['pid'])) { if (!isset($properties['pid'])) {
$properties['pid'] = "islandora"; $properties['pid'] = "islandora";
@ -355,13 +385,14 @@ class IslandoraWebTestCase extends DrupalWebTestCase {
$object->owner = $this->loggedInUser->name; $object->owner = $this->loggedInUser->name;
} }
if (isset($properties['models']) && is_array($properties['models'])) { if (isset($properties['models'])) {
foreach ($properties['models'] as $model) { try {
$object->relationships->add(FEDORA_MODEL_URI, 'hasModel', $model); $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); $repository->ingestObject($object);
@ -442,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);
}
} }

22
tests/scripts/travis_after_failure.sh

@ -0,0 +1,22 @@
#!/bin/bash
# Get the end portion of the TRAVIS_REPO_SLUG for the branch name.
IFS=/ read -a DELIMITED_SLUG <<< "$TRAVIS_REPO_SLUG"
export CURRENT_REPO=${DELIMITED_SLUG[1]}
git config user.name --global islandora-logger
git config user.email --global noreply@islandora.ca
# 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" 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 ./bin/startup.sh
cd $HOME cd $HOME
pear channel-discover pear.drush.org
pear upgrade --force Console_Getopt pear upgrade --force Console_Getopt
pear upgrade --force pear pear upgrade --force pear
pear upgrade-all
pear channel-discover pear.drush.org
pear channel-discover pear.drush.org pear channel-discover pear.drush.org
pear channel-discover pear.phpqatools.org
pear channel-discover pear.netpirates.net # "prefer-source" required due to SSL shenanigans on the Travis boxes...
pear install pear/PHP_CodeSniffer-1.4.8 composer global require --prefer-source 'squizlabs/php_codesniffer=*' 'sebastian/phpcpd=*'
pear install pear.phpunit.de/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 # Install Drush
git clone https://github.com/drush-ops/drush.git git clone https://github.com/drush-ops/drush.git
@ -34,6 +35,10 @@ phpenv rehash
drush dl --yes drupal drush dl --yes drupal
cd drupal-* cd drupal-*
drush si minimal --db-url=mysql://drupal:drupal@localhost/drupal --yes 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 & drush runserver --php-cgi=$HOME/.phpenv/shims/php-cgi localhost:8081 &>/dev/null &
ln -s $ISLANDORA_DIR sites/all/modules/islandora 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 mv sites/all/modules/islandora/tests/travis.test_config.ini sites/all/modules/islandora/tests/test_config.ini

8
theme/islandora-object.tpl.php

@ -61,13 +61,13 @@
<div class="islandora-object islandora"> <div class="islandora-object islandora">
<h2><?php print t('Details'); ?></h2> <h2><?php print t('Details'); ?></h2>
<?php if (isset($variables['islandora_thumbnail_url'])): ?>
<dl class="islandora-object-tn"> <dl class="islandora-object-tn">
<dt> <dt>
<?php if (isset($variables['islandora_thumbnail_url'])): ?> <img src="<?php print $variables['islandora_thumbnail_url']; ?>"/>
<img src="<?php print $variables['islandora_thumbnail_url']; ?>"/></dt> </dt>
<?php endif; ?>
<dd></dd>
</dl> </dl>
<?php endif; ?>
<div class="islandora-default-metadata"> <div class="islandora-default-metadata">
<?php print $description; ?> <?php print $description; ?>
<?php print $metadata; ?> <?php print $metadata; ?>

Loading…
Cancel
Save