diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..a7bd2a84 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,19 @@ +language: php +php: + - 5.3.3 + - 5.4 +branches: + only: + - 7.x +env: + - FEDORA_VERSION="3.5" +before_install: + - export ISLANDORA_DIR=$TRAVIS_BUILD_DIR + - $TRAVIS_BUILD_DIR/tests/scripts/travis_setup.sh + - cd $HOME/drupal-* +script: + - ant -buildfile sites/all/modules/islandora/build.xml lint + - $ISLANDORA_DIR/tests/scripts/line_endings.sh sites/all/modules/islandora + - drush dcs sites/all/modules/islandora + - phpcpd --names *.module,*.inc,*.test 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/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/breadcrumb.inc b/includes/breadcrumb.inc index dd8544a8..6fdf9e4a 100644 --- a/includes/breadcrumb.inc +++ b/includes/breadcrumb.inc @@ -25,13 +25,8 @@ * drupal_set_breadcrumb(). */ function islandora_get_breadcrumbs($object) { - $breadcrumbs = array(); - islandora_get_breadcrumbs_recursive($object->id, $breadcrumbs, $object->repository); - if (isset($breadcrumbs[0])) { - // Remove the actual object. - unset($breadcrumbs[0]); - } - $breadcrumbs = array_reverse($breadcrumbs); + $breadcrumbs = islandora_get_breadcrumbs_recursive($object->id, $object->repository); + array_pop($breadcrumbs); return $breadcrumbs; } @@ -40,30 +35,32 @@ function islandora_get_breadcrumbs($object) { * * @todo Make fully recursive... * - * @todo Could use some clean up, can't be called multiple times safely due to - * the use of static variables. - * * @param string $pid - * THe object id whose parent will be fetched for the next link. - * @param array $breadcrumbs - * The list of existing bread-crumb links in reverse order. + * The object id whose parent will be fetched for the next link. * @param FedoraRepository $repository * The fedora repository. + * @param array $context + * An associative array of context for internal use when recursing. Currently + * only used to track a single value: + * - level: The number of child-parent relationships to follow. Defaults to + * 10. + * + * @return array + * An array of links representing the breadcrumb trail, "root" first. */ -function islandora_get_breadcrumbs_recursive($pid, array &$breadcrumbs, FedoraRepository $repository) { +function islandora_get_breadcrumbs_recursive($pid, FedoraRepository $repository, array &$context = NULL) { // Before executing the query, we have a base case of accessing the top-level // collection. - static $max_level = 10; - static $level = -1; - - if (count($breadcrumbs) === 0) { - $level = $max_level; + if ($context === NULL) { + $context['level'] = 10; } $root = variable_get('islandora_repository_pid', 'islandora:root'); if ($pid == $root) { - $breadcrumbs[] = l(menu_get_active_title(), 'islandora'); - $breadcrumbs[] = l(t('Home'), ''); + return array( + l(t('Home'), ''), + l(menu_get_active_title(), 'islandora'), + ); } else { $query_string = 'select $parentObject $title $content from <#ri> @@ -82,7 +79,7 @@ function islandora_get_breadcrumbs_recursive($pid, array &$breadcrumbs, FedoraRe order by $title desc'; $results = $repository->ri->itqlQuery($query_string); - if (count($results) > 0 && $level > 0) { + if (count($results) > 0 && $context['level'] > 0) { $parent = $results[0]['parentObject']['value']; $this_title = $results[0]['title']['value']; @@ -90,16 +87,23 @@ function islandora_get_breadcrumbs_recursive($pid, array &$breadcrumbs, FedoraRe $this_title = t('-'); } - $breadcrumbs[] = l($this_title, "islandora/object/$pid"); - - $level--; - islandora_get_breadcrumbs_recursive($parent, $breadcrumbs, $repository); + $context['level']--; + return array_merge( + islandora_get_breadcrumbs_recursive($parent, $repository, $context), + array( + l($this_title, "islandora/object/$pid"), + ) + ); } else { - // Add an non-link, as we don't know how to get back to the root. - $breadcrumbs[] = '...'; - // And render the last two links and break (on the next pass). - islandora_get_breadcrumbs_recursive($root, $breadcrumbs, $repository); + // Add an non-link, as we don't know how to get back to the root, and + // render the last two links and break (on the next pass). + return array_merge( + islandora_get_breadcrumbs_recursive($root, $repository, $context), + array( + '...', + ) + ); } } } diff --git a/includes/ingest.form.inc b/includes/ingest.form.inc index 9434e9e4..db031dc0 100644 --- a/includes/ingest.form.inc +++ b/includes/ingest.form.inc @@ -35,7 +35,7 @@ function islandora_ingest_form(array $form, array &$form_state, array $configura islandora_ingest_form_init_form_state_storage($form_state, $configuration); return islandora_ingest_form_execute_step($form, $form_state); } - catch(Exception $e) { + catch (Exception $e) { drupal_set_message($e->getMessage(), 'error'); return array(array( '#markup' => l(t('Back'), 'javascript:window.history.back();', array('external' => TRUE)))); @@ -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']; } @@ -238,7 +242,7 @@ function islandora_ingest_get_approximate_steps(array $configuration) { try { islandora_ingest_form_validate_configuration($configuration); } - catch(InvalidArgumentException $e) { + catch (InvalidArgumentException $e) { // Don't log or display exception. return array(); } 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 0898db0c..c9de5e8f 100644 --- a/includes/object_properties.form.inc +++ b/includes/object_properties.form.inc @@ -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\'s account name'), + '#description' => t("The owner's account name"), '#type' => 'textfield', ), 'object_state' => array( '#title' => t('State'), '#default_value' => $object->state, '#required' => TRUE, - '#description' => t('The object\'s state (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..14a770e2 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); } /** @@ -207,7 +205,7 @@ class IslandoraFedoraApiM extends FedoraApiM { } return $ret; } - catch(Exception $e) { + catch (Exception $e) { watchdog('islandora', 'Failed to modify datastream @dsid from @pid
code: @code
message: @msg', array( '@pid' => $pid, '@dsid' => $dsid, @@ -241,7 +239,7 @@ class IslandoraFedoraApiM extends FedoraApiM { } return $ret; } - catch(Exception $e) { + catch (Exception $e) { watchdog('islandora', 'Failed to modify object: @pid
code: @code
message: @msg', array( '@pid' => $pid, '@code' => $e->getCode(), @@ -283,7 +281,7 @@ class IslandoraFedoraApiM extends FedoraApiM { return $ret; } } - catch(Exception $e) { + catch (Exception $e) { watchdog('islandora', 'Failed to purge datastream @dsid from @pid
code: @code
message: @msg', array( '@pid' => $pid, '@dsid' => $dsid, @@ -327,7 +325,7 @@ class IslandoraFedoraApiM extends FedoraApiM { return $ret; } } - catch(Exception $e) { + catch (Exception $e) { watchdog('islandora', 'Failed to purge object @pid
code: @code
message: @msg', array( '@pid' => $pid, '@code' => $e->getCode(), diff --git a/includes/utilities.inc b/includes/utilities.inc index f061f72c..ec155eb9 100644 --- a/includes/utilities.inc +++ b/includes/utilities.inc @@ -465,20 +465,44 @@ function islandora_prepare_new_object($namespace = NULL, $label = NULL, $datastr if (isset($ds['control_group']) && in_array($ds['control_group'], $groups)) { $control_group = $ds['control_group']; } - $ds_uri = FALSE; + + $as_file = FALSE; if (file_valid_uri($ds['datastream_file'])) { + // A local file with as a Drupal file/stream wrapper URI. $datastream_file = $ds['datastream_file']; - $ds_uri = TRUE; + $as_file = TRUE; + } + elseif (is_readable($ds['datastream_file'])) { + // A local file as a filesystem path. + $datastream_file = drupal_realpath($ds['datastream_file']); + $as_file = TRUE; } else { - $datastream_file = url($ds['datastream_file'], array('absolute' => TRUE)); + $scheme = parse_url($ds['datastream_file'], PHP_URL_SCHEME); + if (in_array($scheme, stream_get_wrappers())) { + // A URI which gets handled by one of the PHP-native stream wrappers. + $datastream_file = $ds['datastream_file']; + $as_file = TRUE; + } + else { + // Schema does not match available php stream wrapper. Attempt to + // set datastream_file by url for the given scheme. Https (SSL) can + // cause this to fail, and trigger an output log in watchdog. + $datastream_file = url($ds['datastream_file'], array('absolute' => TRUE)); + watchdog('islandora', 'Attempting to ingest %file in islandora_prepare_new_object(), ' . + ' but it does not appear to be readable. We will pass the path through' . + ' url(), and pass along as such.', + array('%file' => $datastream_file), + WATCHDOG_WARNING); + } } + $datastream = $object->constructDatastream($dsid, $control_group); $datastream->label = $label; $datastream->mimetype = $mimetype; switch ($control_group) { case 'M': - if ($ds_uri) { + if ($as_file) { $datastream->setContentFromFile($datastream_file); } else { @@ -490,8 +514,10 @@ function islandora_prepare_new_object($namespace = NULL, $label = NULL, $datastr $datastream->setContentFromString(file_get_contents($datastream_file)); break; } + $object->ingestDatastream($datastream); } + return $object; } @@ -505,8 +531,8 @@ function islandora_display_repository_inaccessible_message() { $text = t('Islandora configuration'); $link = l($text, 'admin/islandora/configure', array('attributes' => array('title' => $text))); $message = t('Could not connect to the repository. Please check the settings on the !link page.', - array('!link' => $link)); - drupal_set_message($message, 'error', FALSE); + array('!link' => $link)); + drupal_set_message(check_plain($message), 'error', FALSE); } /** diff --git a/islandora.api.php b/islandora.api.php index 5e976194..d1d58f4f 100644 --- a/islandora.api.php +++ b/islandora.api.php @@ -45,11 +45,24 @@ function hook_CMODEL_PID_islandora_view_object($object) { * @param FedoraObject $object * A Tuque FedoraObject being operated on. * @param array $rendered - * An arr of rendered views. + * The array of rendered views. */ function hook_islandora_view_object_alter(&$object, &$rendered) { } +/** + * Alter display output if the object has the given model. + * + * @see hook_islandora_view_object_alter() + * + * @param FedoraObject $object + * A Tuque FedoraObject being operated on. + * @param array $rendered + * The array of rendered views. + */ +function hook_CMODEL_PID_islandora_view_object_alter(&$object, &$rendered) { +} + /** * Generate an object's management display. * 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..ad9e569e 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), ); @@ -238,12 +238,13 @@ function islandora_menu() { 'access arguments' => array(FEDORA_VIEW_OBJECTS, 2), 'load arguments' => array(2), ); - $items['islandora/ingest'] = array( - 'title' => 'Add an Object', - 'page callback' => 'islandora_ingest_callback', - 'file' => 'includes/ingest.menu.inc', - '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 +287,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 +358,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. * @@ -570,7 +676,8 @@ function islandora_view_object(FedoraObject $object) { $page_number = (empty($_GET['page'])) ? '1' : $_GET['page']; $page_size = (empty($_GET['pagesize'])) ? '10' : $_GET['pagesize']; $output = array(); - foreach (islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $object->models) as $hook) { + $hooks = islandora_build_hook_list(ISLANDORA_VIEW_HOOK, $object->models); + foreach ($hooks as $hook) { // @todo Remove page number and size from this hook, implementers of the // hook should use drupal page handling directly. $temp = module_invoke_all($hook, $object, $page_number, $page_size); @@ -583,7 +690,7 @@ function islandora_view_object(FedoraObject $object) { $output = islandora_default_islandora_view_object($object); } arsort($output); - drupal_alter(ISLANDORA_VIEW_HOOK, $object, $output); + drupal_alter($hooks, $object, $output); return implode('', $output); } @@ -859,7 +966,7 @@ function islandora_delete_object(FedoraObject &$object) { $object = NULL; return TRUE; } - catch(Exception $e) { + catch (Exception $e) { // Exception message gets logged in Tuque Wrapper. return FALSE; } @@ -964,7 +1071,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/hooks.test b/tests/hooks.test index 0a667fee..3133d656 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(); } @@ -67,7 +67,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase { $object->label = "Don't Block"; $this->repository->purgeObject($object->id); } - catch(Exception $e) { + catch (Exception $e) { // Meh... Either it didn't exist or the purge failed. } } @@ -95,7 +95,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase { $this->fail('Blocked ingest should throw an Exception.'); $this->repository->purgeObject($object->id); } - catch(Exception $e) { + catch (Exception $e) { $this->pass('Ingest blocked and exception thrown.'); $this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Called "hook_islandora_object_alter" when blocking ingesting via FedoraRepository::ingestObject.'); $this->assertFalse($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_INGESTED_HOOK], 'Did not called ISLANDORA_OBJECT_INGESTED_HOOK when blocking ingesting via FedoraRepository::ingestObject.'); @@ -115,7 +115,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase { $object->label = 'block'; $this->fail('Blocked modify should throw an Exception.'); } - catch(Exception $e) { + catch (Exception $e) { $this->pass('Modify blocked and exception thrown.'); $this->assertNotEqual($object->label, 'block', 'Modification did not stick.'); $this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called "hook_islandora_object_alter" when blocking modifying via set magic functions.'); @@ -149,7 +149,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase { $this->repository->purgeObject($object->id); $this->fail('Blocked modify should throw an Exception.'); } - catch(Exception $e) { + catch (Exception $e) { $this->pass('Modify blocked and exception thrown.'); $this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called "hook_islandora_object_alter" when blocking purge via FedoraRepository::purgeObject.'); $this->assertFalse($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_PURGED_HOOK], 'Called ISLANDORA_OBJECT_PURGED_HOOK when blocking purge via FedoraRepository::purgeObject.'); @@ -191,7 +191,7 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase { $ds->label = 'block'; $this->fail('Blocked modify should throw an Exception.'); } - catch(Exception $e) { + catch (Exception $e) { $this->pass('Modify blocked and exception thrown.'); $this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called "hook_islandora_datastream_alter" when blocking modifying via set magic functions.'); $this->assertFALSE($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called ISLANDORA_DATASTREAM_MODIFIED_HOOK when blocking modifying via set magic functions.'); 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/islandora_test.info b/tests/islandora_test.info deleted file mode 100644 index c6cb57ad..00000000 --- a/tests/islandora_test.info +++ /dev/null @@ -1,6 +0,0 @@ -name = Islandora Test Module -description = Tests Hooks. Do not enable. -core = 7.x -package = Testing -hidden = TRUE -dependencies[] = islandora diff --git a/tests/islandora_test.module b/tests/islandora_test.module deleted file mode 100644 index 315b88ee..00000000 --- a/tests/islandora_test.module +++ /dev/null @@ -1,152 +0,0 @@ -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/scripts/line_endings.sh b/tests/scripts/line_endings.sh new file mode 100755 index 00000000..b72dde22 --- /dev/null +++ b/tests/scripts/line_endings.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +RETURN=0 +FILES=`find -L $1 -name "*.info" -o -name "*.txt" -o -name "*.md"` +echo "Testing for files with DOS line endings..." +for FILE in $FILES +do + file $FILE | grep CRLF + if [ $? == 0 ] + then + RETURN=1 + fi +done +exit $RETURN diff --git a/tests/scripts/travis_setup.sh b/tests/scripts/travis_setup.sh new file mode 100755 index 00000000..c0a5f0f2 --- /dev/null +++ b/tests/scripts/travis_setup.sh @@ -0,0 +1,34 @@ +#!/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 channel-discover pear.phpqatools.org +pyrus channel-discover pear.netpirates.net +pyrus install drush/drush +pyrus install pear/PHP_CodeSniffer +pyrus install pear.phpunit.de/phpcpd +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 $ISLANDORA_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/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/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"); +}