diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..0c5fe32a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: php +php: + - 5.3.3 + - 5.4 +branches: + only: + - 7.x +env: + - FEDORA_VERSION="3.5" +before_install: + - $TRAVIS_BUILD_DIR/tests/travis_setup.sh + - cd $HOME/drupal-* +script: + - ant -buildfile sites/all/modules/islandora/build.xml lint + - drush dcs sites/all/modules/islandora + - drush test-run --uri=http://localhost:8081 Islandora diff --git a/README.txt b/README.md similarity index 85% rename from README.txt rename to README.md index ce276d7b..fd2663b7 100644 --- a/README.txt +++ b/README.md @@ -1,16 +1,10 @@ -CONTENTS OF THIS FILE ---------------------- - - * summary - * requirements - * installation - * configuration - * customization - * troubleshooting - * faq - * contact - * sponsors +BUILD STATUS +------------ +Current build status: +[![Build Status](https://travis-ci.org/Islandora/islandora.png?branch=7.x)](https://travis-ci.org/Islandora/islandora) +CI Server: +http://jenkins.discoverygarden.ca SUMMARY ------- diff --git a/build.xml b/build.xml index 854d3a0a..273f8ca8 100644 --- a/build.xml +++ b/build.xml @@ -1,110 +1,84 @@ - + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - + + + - - - - - - + + + + + + + + + + - - - - - - - + + + + + - - - - - - - - + + + + + - - - - - - - - + + + + + - - - - - - - - - - + + + + + - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - + + + + + diff --git a/build/Doxyfile b/build/Doxyfile index 1d4e3693..f41dc285 100644 --- a/build/Doxyfile +++ b/build/Doxyfile @@ -27,6 +27,9 @@ DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = Islandora 7.x +# Put the git hash here using sed before generating the documentation. +PROJECT_NUMBER = + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location diff --git a/css/islandora.objects.css b/css/islandora.objects.css new file mode 100644 index 00000000..5e03d3f7 --- /dev/null +++ b/css/islandora.objects.css @@ -0,0 +1,39 @@ +/** + * @file + * Styles for rendering grids/lists of objects. + */ +.islandora-objects-display-switch { + float: right; +} +.islandora-objects-grid-item { + display: inline-block; + width: 20%; + min-width: 100px; + min-height: 180px; + display: -moz-inline-stack; + display: inline-block; + vertical-align: top; + margin: 1.5em 1.84%; + zoom: 1; + *display: inline; + _height: 180px; +} +.islandora-objects-list-item { + padding-bottom: 1.5em; + border-bottom: 1px solid #ddd; +} +.islandora-objects-list-item .islandora-object-thumb { + clear: left; + float: left; + padding: 3px 0 0; + text-align: center; + width: 100px; +} +.islandora-objects-list-item .islandora-object-caption, .islandora-objects-list-item .islandora-object-description { + margin: 0 0 0 130px; + padding-top: 2px; + padding-bottom: 2px; +} +.islandora-object-thumb img { + width: 100%; +} diff --git a/includes/add_datastream.form.inc b/includes/add_datastream.form.inc index fa94148f..d19d5757 100644 --- a/includes/add_datastream.form.inc +++ b/includes/add_datastream.form.inc @@ -39,7 +39,7 @@ function islandora_add_datastream_form(array $form, array &$form_state, FedoraOb '#collapsed' => FALSE, 'dsid' => array( '#title' => 'Datastream ID', - '#description' => t("An ID for this stream that is unique to this object. Must start with a letter and contain only alphanumeric characters and dashes and underscores. Datastreams that are defined by the content model don't currently exist: @unused_dsids.", array('@unused_dsids' => $unused_datastreams)), + '#description' => t("An ID for this stream that is unique to this object. Must start with a letter and contain only alphanumeric characters, dashes and underscores. The following datastreams are defined by this content model but don't currently exist: @unused_dsids.", array('@unused_dsids' => $unused_datastreams)), ), '#type' => 'textfield', '#size' => 64, @@ -57,7 +57,7 @@ function islandora_add_datastream_form(array $form, array &$form_state, FedoraOb '#required' => TRUE, '#size' => 64, '#maxlength' => 64, - '#description' => t('A Human readable label'), + '#description' => t('A human-readable label'), '#type' => 'textfield', '#element_validate' => array('islandora_add_datastream_form_field_does_not_contain_a_forward_slash'), ), diff --git a/includes/admin.form.inc b/includes/admin.form.inc index d3bccd5a..a1f22652 100644 --- a/includes/admin.form.inc +++ b/includes/admin.form.inc @@ -146,7 +146,7 @@ function islandora_repository_admin(array $form, array &$form_state) { '#type' => 'textfield', '#title' => t('PID namespaces allowed in this Drupal install'), '#default_value' => variable_get('islandora_pids_allowed', 'default: demo: changeme: ilives: islandora-book: books: newspapers: '), - '#description' => t('A space separated list of PID namespaces that users are permitted to access from this Drupal installation.
This could be more than a simple namespace ie demo:mydemos.
islandora: is reserved and is always allowed.'), + '#description' => t('A list of PID namespaces, separated by spaces, that users are permitted to access from this Drupal installation.
This could be more than a simple namespace, e.g. demo:mydemos.
The namespace islandora: is reserved, and is always allowed.'), '#weight' => 0, ); } diff --git a/includes/ingest.form.inc b/includes/ingest.form.inc index 9434e9e4..0f8e843e 100644 --- a/includes/ingest.form.inc +++ b/includes/ingest.form.inc @@ -96,15 +96,18 @@ function islandora_ingest_form_init_form_state_storage(array &$form_state, array */ function islandora_ingest_form_prepare_new_object(array $configuration) { module_load_include('inc', 'islandora', 'includes/utilities'); - // ID is more specific than namespace so it will take precedence. - $id = isset($configuration['namespace']) ? $configuration['namespace'] : 'islandora'; - $id = isset($configuration['id']) ? $configuration['id'] : $id; - $label = isset($configuration['label']) ? $configuration['label'] : 'New Object'; - $relationship_map = function($o) { - return array('relationship' => 'isMemberOfCollection', 'pid' => $o); - }; - $relationships = empty($configuration['collections']) ? array() : array_map($relationship_map, $configuration['collections']); - return islandora_prepare_new_object($id, $label, array(), array(), $relationships); + if (empty($configuration['object'])) { + // ID is more specific than namespace so it will take precedence. + $id = isset($configuration['namespace']) ? $configuration['namespace'] : 'islandora'; + $id = isset($configuration['id']) ? $configuration['id'] : $id; + $label = isset($configuration['label']) ? $configuration['label'] : 'New Object'; + $relationship_map = function($o) { + return array('relationship' => 'isMemberOfCollection', 'pid' => $o); + }; + $relationships = empty($configuration['collections']) ? array() : array_map($relationship_map, $configuration['collections']); + return islandora_prepare_new_object($id, $label, array(), array(), $relationships); + } + return $configuration['object']; } /** @@ -144,7 +147,8 @@ function islandora_ingest_form_get_step(array &$form_state, $step_id = NULL) { function islandora_ingest_form_get_current_step_id(array &$form_state) { if (empty($form_state['islandora']['step_id'])) { $steps = islandora_ingest_form_get_steps($form_state); - return array_shift(array_keys($steps)); + $keys = array_keys($steps); + return array_shift($keys); } return $form_state['islandora']['step_id']; } diff --git a/includes/ingest.menu.inc b/includes/ingest.menu.inc deleted file mode 100644 index a6f79891..00000000 --- a/includes/ingest.menu.inc +++ /dev/null @@ -1,49 +0,0 @@ -'; - // Redirect back to referer or top level collection. - drupal_goto($redirect); - } -} - -/** - * Fetches the ingest configuration from the $_GET parameters. - * - * Generic parameters as accepted by all ingest processes, other modules may - * add to this list. - * id -> The pid of the object to create. optional. - * models -> Comma delimited list of all the content models the created object - * should have. - * collections -> Comma delimited list of all the collections the created - * object should belong to. - * - * @return array - * The configuration options used to build the multi-paged ingest process. - */ -function islandora_ingest_get_configuration() { - $configuration = $_GET; - unset($configuration['q']); - $convert_to_array_keys = array_intersect(array('models', 'collections'), array_keys($configuration)); - foreach ($convert_to_array_keys as $key) { - $configuration[$key] = explode(',', $configuration[$key]); - } - return $configuration; -} diff --git a/includes/object_properties.form.inc b/includes/object_properties.form.inc index 29875d28..c9de5e8f 100644 --- a/includes/object_properties.form.inc +++ b/includes/object_properties.form.inc @@ -30,7 +30,7 @@ function islandora_object_properties_form(array $form, array &$form_state, Fedor '#title' => t('Item Label'), '#default_value' => $object->label, '#required' => 'TRUE', - '#description' => t('A Human readable label'), + '#description' => t('A human-readable label'), // Double the normal length. '#size' => 120, // Max length for a Fedora Label. @@ -43,14 +43,14 @@ function islandora_object_properties_form(array $form, array &$form_state, Fedor '#title' => t('Owner'), '#default_value' => $object->owner, '#required' => FALSE, - '#description' => t('The owner id'), + '#description' => t("The owner's account name"), '#type' => 'textfield', ), 'object_state' => array( '#title' => t('State'), '#default_value' => $object->state, '#required' => TRUE, - '#description' => t('The items state one of active, inactive or deleted'), + '#description' => t("The object's state (active, inactive or deleted)"), '#type' => 'select', '#options' => array('A' => 'Active', 'I' => 'Inactive', 'D' => 'Deleted'), ), diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc index 8bd3c3e6..4d989e9f 100644 --- a/includes/tuque_wrapper.inc +++ b/includes/tuque_wrapper.inc @@ -35,22 +35,20 @@ $islandora_module_path = drupal_get_path('module', 'islandora'); * Allow modules to alter an object before a mutable event occurs. */ function islandora_alter_object(AbstractFedoraObject $object, array &$context) { - $types = array('islandora_object'); - foreach ($object->models as $model) { - $types[] = "{$model}_islandora_object"; - } - drupal_alter($types, $object, $context); + module_load_include('inc', 'islandora', 'includes/utilities'); + drupal_alter(islandora_build_hook_list('islandora_object', $object->models), $object, $context); } /** * Allow modules to alter a datastream before a mutable event occurs. */ function islandora_alter_datastream(AbstractFedoraObject $object, AbstractDatastream $datastream, array &$context) { - $types = array('islandora_datastream'); + module_load_include('inc', 'islandora', 'includes/utilities'); + $types = array(); foreach ($object->models as $model) { - $types[] = "{$model}_{$datastream->id}_islandora_datastream"; + $types[] = "{$model}_{$datastream->id}"; } - drupal_alter($types, $object, $datastream, $context); + drupal_alter(islandora_build_hook_list('islandora_datastream', $types), $object, $datastream, $context); } /** diff --git a/islandora.install b/islandora.install index 9a1825b5..caff7d75 100644 --- a/islandora.install +++ b/islandora.install @@ -10,13 +10,14 @@ */ function islandora_requirements($phase) { $requirements = array(); - // Ensure translations don't break at install time + + // Ensure translations don't break at install time. $t = get_t(); if (!class_exists('XSLTProcessor', FALSE)) { $requirements['islandora_xsltprocessor']['title'] = $t('Islandora XSLTProcessor Prerequisite'); $requirements['islandora_xsltprocessor']['value'] = $t('Not installed'); - $link = l($t('PHP XSL extension'), 'http://us2.php.net/manual/en/book.xsl.php', array('attributes' => array('target'=>'_blank'))); + $link = l($t('PHP XSL extension'), 'http://us2.php.net/manual/en/book.xsl.php', array('attributes' => array('target' => '_blank'))); $requirements['islandora_xsltprocessor']['description'] = $t('The !xsllink is required. Check your installed PHP extensions and php.ini file.', array('!xsllink' => $link)); $requirements['islandora_xsltprocessor']['severity'] = REQUIREMENT_ERROR; } diff --git a/islandora.module b/islandora.module index 94aedbe0..64c81628 100644 --- a/islandora.module +++ b/islandora.module @@ -120,7 +120,7 @@ function islandora_menu() { FEDORA_METADATA_EDIT, FEDORA_ADD_DS, FEDORA_PURGE, - FEDORA_INGEST + FEDORA_INGEST, ), 2), ); @@ -245,6 +245,14 @@ function islandora_menu() { 'type' => MENU_SUGGESTED_ITEM, 'access arguments' => array(FEDORA_INGEST), ); + $items['islandora/object/%islandora_object/download_clip'] = array( + 'page callback' => 'islandora_download_clip', + 'page arguments' => array(2), + 'type' => MENU_CALLBACK, + 'access callback' => 'islandora_object_access_callback', + 'access arguments' => array(FEDORA_VIEW_OBJECTS, 2), + 'load arguments' => array(2), + ); return $items; } @@ -286,6 +294,29 @@ function islandora_theme() { 'file' => 'theme/theme.inc', 'variables' => array('object' => NULL, 'content' => array()), ), + // Render a bunch of objects as either a grid or a list. + 'islandora_objects' => array( + 'file' => 'theme/theme.inc', + 'template' => 'theme/islandora-objects', + 'variables' => array( + 'objects' => NULL, + 'display' => NULL, + 'page_size' => 20, + 'limit' => 10, + ), + ), + // Render a bunch of objects as a grid. + 'islandora_objects_grid' => array( + 'file' => 'theme/theme.inc', + 'template' => 'theme/islandora-objects-grid', + 'variables' => array('objects' => NULL), + ), + // Render a bunch of objects as a list. + 'islandora_objects_list' => array( + 'file' => 'theme/theme.inc', + 'template' => 'theme/islandora-objects-list', + 'variables' => array('objects' => NULL), + ), ); } @@ -334,6 +365,88 @@ function islandora_forms($form_id) { return $forms; } +/** + * Checks whether the user can access the given object. + * + * Checks for repository access, object/datastream existance, namespace access, + * user permissions, content models. + * + * Will check the given user or the user repersented by the GET token parameter, + * failing that it will use the global user. + * + * @global $user + * + * @param mixed $object + * The FedoraObject or FedoraDatastream to test for accessibility, if NULL + * is given the object is assumed to not exist or be inaccessible. + * @param array $permissions + * The required user permissions. + * @param array $content_models + * The required content models. + * @param bool $access_any + * (optional) TRUE to grant access if any single requirement is met from both + * the permissions and content models parameters. FALSE if all requirements + * must be met from both the permissions and content model parameters. + * @param object $account + * (optional) The account to check, if not given check the GET parameters for + * a token to restore the user. If no GET parameter is present use currently + * logged in user. + * + * @return bool + * TRUE if the user is allowed to access this object/datastream, FALSE + * otherwise. + */ +function islandora_user_access($object, array $permissions, $content_models = array(), $access_any = TRUE, $account = NULL) { + module_load_include('inc', 'islandora', 'includes/utilities'); + $is_repository_accessible = &drupal_static(__FUNCTION__); + // If the repository is inaccessible then access always fails. + if (!isset($is_repository_accessible)) { + $is_repository_accessible = islandora_describe_repository(); + if (!$is_repository_accessible) { + // Only display the inaccessible message once. + islandora_display_repository_inaccessible_message(); + return FALSE; + } + } + if (!$is_repository_accessible || !is_object($object)) { + return FALSE; + } + // Determine the user account to test against. + if (!isset($account)) { + $token = filter_input(INPUT_GET, 'token', FILTER_SANITIZE_STRING); + if ($token) { + module_load_include('inc', 'islandora', 'includes/authtokens'); + $user = islandora_validate_object_token($object->id, $datastream->id, $token); + if ($user) { + $account = user_load($user->uid); + } + } + else { + global $user; + $account = $user; + } + } + // Determine what has been passed as $object. + if (is_subclass_of($object, 'FedoraObject')) { + $object = $object; + } + elseif (is_subclass_of($object, 'FedoraDatastream')) { + $datastream = $object; + $object = $datastream->parent; + } + // Check for access. + $accessible_namespace = islandora_namespace_accessible($object->id); + if ($access_any) { + $has_required_permissions = islandora_user_access_any($permissions, $account); + $has_required_content_models = empty($content_models) ? TRUE : count(array_intersect($object->models, $content_models)) > 0; + } + else { + $has_required_permissions = islandora_user_access_all($permissions, $account); + $has_required_content_models = count(array_diff($content_models, $object->models)) == 0; + } + return $accessible_namespace && $has_required_permissions && $has_required_content_models; +} + /** * Checks whether the user can access the given object. * @@ -964,7 +1077,29 @@ function islandora_entity_property_info() { * @return array * A renderable array. */ -function islandora_print_object(FedoraObject $object) { +function islandora_print_object(AbstractObject $object) { drupal_set_title($object->label); return theme('islandora_object_print', array('object' => $object)); } + +/** + * Menu callback downloads the given clip. + */ +function islandora_download_clip(AbstractObject $object) { + if (isset($_GET['clip'])) { + $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on'; + $http_protocol = $is_https ? 'https' : 'http'; + $url = $http_protocol . '://' . $_SERVER['HTTP_HOST'] . $_GET['clip']; + $filename = $object->label; + header("Content-Disposition: attachment; filename=\"{$filename}.jpg\""); + header("Content-type: image/jpeg"); + header("Content-Transfer-Encoding: binary"); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_URL, $url); + $response = curl_exec($ch); + curl_close($ch); + } + exit(); +} diff --git a/tests/README.txt b/tests/README.txt index 797d788b..c03004ae 100644 --- a/tests/README.txt +++ b/tests/README.txt @@ -1,3 +1,4 @@ You can define your own configurations specific to your enviroment by copying default.test_config.ini to test_config.ini, making your changes in the copied -file. \ No newline at end of file +file. These test need write access to the system's $FEDORA_HOME/server/config +directory as well as the filter-drupal.xml file. \ No newline at end of file diff --git a/tests/hooks.test b/tests/hooks.test index 0a667fee..bc3020f3 100644 --- a/tests/hooks.test +++ b/tests/hooks.test @@ -32,7 +32,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase { * @see IslandoraWebTestCase::setUp() */ public function setUp() { - parent::setUp('islandora_hooks_test', 'devel'); + parent::setUp('islandora_hooks_test'); $this->repository = $this->admin->repository; $this->purgeTestObjects(); } diff --git a/tests/islandora_hooks_test.info b/tests/islandora_hooks_test.info new file mode 100644 index 00000000..9d211978 --- /dev/null +++ b/tests/islandora_hooks_test.info @@ -0,0 +1,7 @@ +name = Islandora Hook testing +description = Tests Hooks. Do not enable. +core = 7.x +package = Testing +hidden = TRUE +dependencies[] = islandora +files[] = islandora_hooks_test.module diff --git a/tests/islandora_hooks_test.module b/tests/islandora_hooks_test.module new file mode 100644 index 00000000..315b88ee --- /dev/null +++ b/tests/islandora_hooks_test.module @@ -0,0 +1,152 @@ +id == 'test:testIngestedObjectHook') { + $_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK] = TRUE; + if ($object->label == 'block') { + $context['block'] = TRUE; + } + } + break; + + case 'modify': + if ($object->id == 'test:testModifiedObjectHook') { + $_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK] = TRUE; + if (isset($context['params']['label']) && $context['params']['label'] == 'block') { + $context['block'] = TRUE; + } + } + elseif ($object->id == 'test:testPurgedObjectHook') { + $_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = TRUE; + if (isset($context['params']['label']) && $context['params']['label'] == 'block') { + $context['block'] = TRUE; + } + elseif (isset($context['params']['label']) && $context['params']['label'] == 'delete') { + $context['delete'] = TRUE; + } + } + break; + + case 'purge': + if ($object->id == 'test:testPurgedObjectHook') { + $_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK] = TRUE; + if ($object->label == 'block') { + $context['block'] = TRUE; + } + elseif ($object->label == 'delete') { + $context['delete'] = TRUE; + } + } + break; + } +} + +/** + * Implements hook_islandora_object_alter(). + */ +function islandora_hooks_test_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context) { + switch ($context['action']) { + case 'ingest': + if ($object->id == 'test:testIngestedDatastreamHook') { + $_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = TRUE; + if ($datastream->label == 'block') { + $context['block'] = TRUE; + } + } + break; + + case 'modify': + if ($object->id == 'test:testModifiedDatastreamHook') { + $_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = TRUE; + if (isset($context['params']['dsLabel']) && $context['params']['dsLabel'] == 'block') { + $context['block'] = TRUE; + } + } + elseif ($object->id == 'test:testPurgedDatastreamHook') { + $_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_PURGED_HOOK] = TRUE; + if (isset($context['params']['dsLabel']) && $context['params']['dsLabel'] == 'block') { + $context['block'] = TRUE; + } + elseif (isset($context['params']['dsLabel']) && $context['params']['dsLabel'] == 'delete') { + $context['delete'] = TRUE; + } + } + break; + + case 'purge': + if ($object->id == 'test:testPurgedDatastreamHook') { + $_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_PURGED_HOOK] = TRUE; + if ($datastream->label == 'block') { + $context['block'] = TRUE; + } + elseif ($datastream->label == 'delete') { + $context['delete'] = TRUE; + } + } + break; + } +} + +/** + * Implements hook_islandora_object_ingested(). + */ +function islandora_hooks_test_islandora_object_ingested(FedoraObject $object) { + if ($object->id == 'test:testIngestedObjectHook') { + $_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK] = TRUE; + } +} + +/** + * Implements hook_islandora_object_modified(). + */ +function islandora_hooks_test_islandora_object_modified(FedoraObject $object) { + if ($object->id == 'test:testModifiedObjectHook') { + $_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = TRUE; + } +} + +/** + * Implements hook_islandora_object_purged(). + */ +function islandora_hooks_test_islandora_object_purged($pid) { + if ($pid == 'test:testPurgedObjectHook') { + $_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK] = TRUE; + } +} + +/** + * Implements hook_islandora_datastream_ingested(). + */ +function islandora_hooks_test_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream) { + if ($object->id == 'test:testIngestedDatastreamHook' && $datastream->id == "TEST") { + $_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_INGESTED_HOOK] = TRUE; + } +} + +/** + * Implements hook_islandora_datastream_modified(). + */ +function islandora_hooks_test_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream) { + if ($object->id == 'test:testModifiedDatastreamHook' && $datastream->id == "TEST") { + $_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = TRUE; + } +} + +/** + * Implements hook_islandora_datastream_purged(). + */ +function islandora_hooks_test_islandora_datastream_purged(FedoraObject $object, $dsid) { + if ($object->id == 'test:testPurgedDatastreamHook' && $dsid == "TEST") { + $_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_PURGED_HOOK] = TRUE; + } +} diff --git a/tests/islandora_manage_permissions.test b/tests/islandora_manage_permissions.test index 76f43a6d..72aebd89 100644 --- a/tests/islandora_manage_permissions.test +++ b/tests/islandora_manage_permissions.test @@ -1,7 +1,17 @@ 'Islandora Manage Permissions', @@ -10,69 +20,117 @@ class IslandoraPermissionsTestCase extends IslandoraWebTestCase { ); } + /** + * Prepares enviroment for testing. + * + * @see IslandoraWebTestCase::setUp() + */ public function setUp() { parent::setUp(array('islandora')); } + /** + * Test manage permissions. + */ public function testManagePermissions() { - - - // permission FEDORA_VIEW_OBJECTS - // create a user with permission + // Test permission FEDORA_VIEW_OBJECTS. + // Create a user with permission. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); - // log the user in + // Log the user in. $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertNoLink('Manage', 'Manage tab is not on current page.'); - - - // permission FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES + + // Test permission FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_MANAGE_PROPERTIES)); - // log the user in $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertLink('Manage', 0, 'Manage tab is on current page.'); $this->clickLink(t('Manage')); $this->assertLink('Properties', 0, 'Properties tab is on current page.'); $this->assertNoLink('Datastreams', 'Datastreams tab is not on current page.'); - $this->assertNoLink('Collection','Collection tab is not on current page.'); + $this->assertNoLink('Collection', 'Collection tab is not on current page.'); - - // permission FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS + // Test permission FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_ADD_DS)); - // log the user in $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertLink('Manage', 0, 'Manage tab is on current page.'); $this->clickLink(t('Manage')); $this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.'); $this->assertNoLink('Properties', 'Properties tab is not on current page.'); - $this->assertNoLink('Collection','Collection tab is not on current page.'); - - - // permission FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT + $this->assertNoLink('Collection', 'Collection tab is not on current page.'); + + // Test permission FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_METADATA_EDIT)); - // log the user in - $this->drupalLogin($user); + $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertLink('Manage', 0, 'Manage tab is on current page.'); $this->clickLink(t('Manage')); $this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.'); $this->assertNoLink('Properties', 'Properties tab is not on current page.'); - $this->assertNoLink('Collection','Collection tab is not on current page.'); - - - // permission FEDORA_VIEW_OBJECTS, FEDORA_PURGE + $this->assertNoLink('Collection', 'Collection tab is not on current page.'); + + // Test permission FEDORA_VIEW_OBJECTS, FEDORA_PURGE. $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE)); - // log the user in $this->drupalLogin($user); $this->clickLink(t('Islandora Repository')); $this->assertLink('Manage', 0, 'Manage tab is on current page.'); $this->clickLink(t('Manage')); $this->assertLink('Datastreams', 0, 'Datastreams tab is on current page.'); $this->assertNoLink('Properties', 'Properties tab is not on current page.'); - $this->assertNoLink('Collection','Collection tab is not on current page.'); - + $this->assertNoLink('Collection', 'Collection tab is not on current page.'); } - } \ No newline at end of file + /** + * Test generic access functions. + * + * Note that we can't test with the Global user as SimpleTest doesn't support + * it. Therefore we can't test the authtoken support. + */ + public function testAccessFunctions() { + $object = islandora_object_load(variable_get('islandora_repository_pid', 'islandora:root')); + // Test islandora_user_access(); + // Test no object/permissions. + $ret = islandora_user_access(NULL, array()); + $this->assertFalse($ret, 'User access denied when no object/permissions are provided.'); + // Test with object no permissions. + $ret = islandora_user_access($object, array()); + $this->assertFalse($ret, 'User access denied when no permissions are provided.'); + // Test access with matching permission. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user); + $this->assertTrue($ret, 'User access granted when permissions match.'); + // Test access with matching permission but access any is FALSE. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array(), FALSE, $user); + $this->assertFalse($ret, 'User access denied for matching permission but with access any set to FALSE.'); + // Test access with non-matching permission. + $user = $this->drupalCreateUser(array(FEDORA_PURGE)); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user); + $this->assertFalse($ret, 'User access denied when permissions did not match.'); + // Test access with both permissions and content model. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); + $model = $object->models; + $model = reset($model); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array($model), TRUE, $user); + $this->assertTrue($ret, 'User access granted for matching permission and model.'); + // Test access with matching permissions and non-matching content model. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS)); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS), array('islandora:obviouslyNotACModel'), TRUE, $user); + $this->assertFalse($ret, 'User access denied for matching permission and non-matching model.'); + // Test access with all matching permissions and one matching model but + // access any is FALSE. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE)); + $model = $object->models; + $model = reset($model); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array($model, 'islandora:obviouslyNotACModel'), FALSE, $user); + $this->assertFalse($ret, 'User access denied for all matching permissions and one matching model but with access any set to FALSE.'); + $ret = islandora_user_access($object, array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE), array($model), FALSE, $user); + $this->assertTrue($ret, 'User access granted for all matching permissions and matching models with access any set to FALSE.'); + // Test passing in a Datastream. + $user = $this->drupalCreateUser(array(FEDORA_VIEW_OBJECTS, FEDORA_PURGE)); + $ret = islandora_user_access($object['DC'], array(FEDORA_VIEW_OBJECTS), array(), TRUE, $user); + $this->assertTrue($ret, 'User access granted for matching permissions, with a datastream given instead of an object.'); + } +} diff --git a/tests/travis.test_config.ini b/tests/travis.test_config.ini new file mode 100644 index 00000000..61d63713 --- /dev/null +++ b/tests/travis.test_config.ini @@ -0,0 +1,6 @@ +[fedora] +fedora_url = "http://localhost:8080/fedora" +use_drupal_filter = TRUE +drupal_filter_file = "/home/travis/islandora_tomcat/fedora/server/config/filter-drupal.xml" +admin_user = "fedoraAdmin" +admin_pass = "fedoraAdmin" diff --git a/tests/travis_setup.sh b/tests/travis_setup.sh new file mode 100755 index 00000000..abbaccd2 --- /dev/null +++ b/tests/travis_setup.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +mysql -u root -e 'create database drupal;' +mysql -u root -e "create database fedora;" +mysql -u root -e "GRANT ALL PRIVILEGES ON fedora.* To 'fedora'@'localhost' IDENTIFIED BY 'fedora';" +mysql -u root -e "GRANT ALL PRIVILEGES ON drupal.* To 'drupal'@'localhost' IDENTIFIED BY 'drupal';" +cd $HOME +git clone git://github.com/Islandora/tuque.git +git clone -b $FEDORA_VERSION git://github.com/Islandora/islandora_tomcat.git +cd islandora_tomcat +export CATALINA_HOME='.' +./bin/startup.sh +cd $HOME +pyrus channel-discover pear.drush.org +pyrus install drush/drush +pyrus install pear/PHP_CodeSniffer +phpenv rehash +drush dl --yes drupal +cd drupal-* +drush si standard --db-url=mysql://drupal:drupal@localhost/drupal --yes +drush runserver --php-cgi=$HOME/.phpenv/shims/php-cgi localhost:8081 &>/dev/null & +ln -s $TRAVIS_BUILD_DIR sites/all/modules/islandora +mv sites/all/modules/islandora/tests/travis.test_config.ini sites/all/modules/islandora/tests/test_config.ini +mkdir sites/all/libraries +ln -s $HOME/tuque sites/all/libraries/tuque +drush dl --yes coder +drush en --yes coder_review +drush en --yes simpletest +drush en --user=1 --yes islandora +drush cc all +sleep 4 diff --git a/tests/web_test_case.inc b/tests/web_test_case.inc index a513de43..8a5b9a00 100644 --- a/tests/web_test_case.inc +++ b/tests/web_test_case.inc @@ -18,6 +18,11 @@ class IslandoraWebTestCase extends DrupalWebTestCase { // Always enable islandora. $args[] = 'islandora'; parent::setUp($args); + + // Its possible test are running before class autoloading. + module_load_include('inc', 'islandora', 'includes/tuque'); + module_load_include('inc', 'islandora', 'includes/tuque_wrapper'); + $this->configuration = $this->getTestConfiguration(); if ($this->configuration['use_drupal_filter']) { $this->backUpDrupalFilter(); diff --git a/theme/islandora-objects-grid.tpl.php b/theme/islandora-objects-grid.tpl.php new file mode 100644 index 00000000..e6d7e140 --- /dev/null +++ b/theme/islandora-objects-grid.tpl.php @@ -0,0 +1,17 @@ + +
+ +
+
+
+
+
+
+ +
diff --git a/theme/islandora-objects-list.tpl.php b/theme/islandora-objects-list.tpl.php new file mode 100644 index 00000000..67f5f02d --- /dev/null +++ b/theme/islandora-objects-list.tpl.php @@ -0,0 +1,29 @@ + +
+ + + +
+
+
+ +
+
+ + + +
+
+ +
+
+
+ + +
diff --git a/theme/islandora-objects.tpl.php b/theme/islandora-objects.tpl.php new file mode 100644 index 00000000..f1893ef6 --- /dev/null +++ b/theme/islandora-objects.tpl.php @@ -0,0 +1,21 @@ + +
+ + $display_links, + 'attributes' => array('class' => array('links', 'inline')), + ) + ); + ?> + + + + +
diff --git a/theme/theme.inc b/theme/theme.inc index 87e44fc1..7c43deef 100644 --- a/theme/theme.inc +++ b/theme/theme.inc @@ -157,3 +157,64 @@ function islandora_preprocess_islandora_object_print(array &$variables) { function theme_islandora_object_print(array &$variables) { return drupal_render($variables['content']); } + +/** + * Implements hook_preprocess_theme(). + */ +function islandora_preprocess_islandora_objects(array &$variables) { + module_load_include('inc', 'islandora_paged_content', 'includes/utilities'); + $display = (empty($_GET['display'])) ? 'grid' : $_GET['display']; + $grid_display = $display == 'grid'; + $list_display = !$grid_display; + $query_params = drupal_get_query_parameters($_GET); + $variables['display_links'] = array( + array( + 'title' => t('Grid view'), + 'href' => url($_GET['q'], array('absolute' => TRUE)), + 'attributes' => array( + 'class' => $grid_display ? 'active' : '', + ), + 'query' => array('display' => 'grid') + $query_params, + ), + array( + 'title' => t('List view'), + 'href' => url($_GET['q'], array('absolute' => TRUE)), + 'attributes' => array( + 'class' => $list_display ? 'active' : '', + ), + 'query' => array('display' => 'list') + $query_params, + ), + ); + // Pager. + $objects = $variables['objects']; + $limit = $variables['limit']; + $page_size = $variables['page_size']; + $page = pager_default_initialize(count($objects), $limit); + $objects = array_slice($objects, $page * $limit, $limit); + $variables['pager'] = theme('pager', array('quantity' => 10)); + // Content. + $map_objects = function($o) { + $o = islandora_object_load($o); + $url = "islandora/object/{$o->id}"; + $link_options = array('html' => TRUE, 'attributes' => array('title' => $o->label)); + $img = theme_image(array('path' => url("$url/datastream/TN/view"), 'attributes' => array())); + $description = NULL; + $dc = DublinCore::importFromXMLString($o['DC']->content); + if ($dc) { + $dc = $dc->asArray(); + $description = $dc['dc:description']['value']; + } + return array( + 'label' => $o->label, + 'class' => drupal_strtolower(preg_replace('/[^A-Za-z0-9]/', '-', $o->id)), + 'link' => l($o->label, $url, $link_options), + 'thumb' => l($img, $url, $link_options), + 'description' => $description, + ); + }; + $objects = array_map($map_objects, $objects); + $theme = $grid_display ? 'islandora_objects_grid' : 'islandora_objects_list'; + $variables['content'] = theme($theme, array('objects' => $objects)); + $module_path = drupal_get_path('module', 'islandora'); + drupal_add_css("$module_path/css/islandora.objects.css"); +}