. */ require_once __DIR__ . "/includes/globals.inc"; // Common datastreams define('DS_COMP_STREAM', 'DS-COMPOSITE-MODEL'); // Permissions define('FEDORA_VIEW', 'view fedora repository'); define('FEDORA_METADATA_EDIT', 'edit fedora metadata'); define('FEDORA_ADD_DS', 'add fedora datastreams'); define('FEDORA_INGEST', 'ingest fedora objects'); define('FEDORA_PURGE', 'delete fedora objects and datastreams'); define('FEDORA_MODIFY_STATE', 'modify fedora state'); define('FEDORA_MANAGE', 'manage fedora items'); // Hooks define('ISLANDORA_VIEW_HOOK', 'islandora_view_object'); define('ISLANDORA_EDIT_HOOK', 'islandora_edit_object'); define('ISLANDORA_PRE_INGEST_HOOK', 'islandora_ingest_pre_ingest'); define('ISLANDORA_POST_INGEST_HOOK', 'islandora_ingest_post_ingest'); define('ISLANDORA_PRE_PURGE_OBJECT_HOOK', 'islandora_pre_purge_object'); define('ISLANDORA_POST_PURGE_OBJECT_HOOK', 'islandora_post_purge_object'); define('ISLANDORA_INGEST_STEP_HOOK', 'islandora_ingest_steps'); define('ISLANDORA_PRE_PURGE_DATASTREAM_HOOK', 'islandora_pre_purge_datastream'); define('ISLANDORA_POST_PURGE_DATASTREAM_HOOK', 'islandora_post_purge_datastream'); define('ISLANDORA_EDIT_DATASTREAM_HOOK', 'islandora_edit_datastream'); /** * Implements hook_menu(). * * We need some standard entry points so we can have consistent urls for * different Object actions */ function islandora_menu() { $items = array(); $items['admin/islandora'] = array( 'title' => 'Islandora', 'description' => "Configure settings associated with Islandora.", 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); $items['admin/islandora/configure'] = array( 'title' => 'Configuration', 'description' => 'Configure settings for Islandora.', 'page callback' => 'drupal_get_form', 'page arguments' => array('islandora_repository_admin'), 'file' => 'admin/islandora.admin.inc', 'access arguments' => array('administer site configuration'), 'type' => MENU_NORMAL_ITEM, 'weight' => -1, ); $items['admin/islandora/solution_packs'] = array( 'title' => 'Solution packs', 'description' => 'Install content models and collections required by installed solution packs.', 'page callback' => 'islandora_solution_packs_admin', 'access arguments' => array(FEDORA_ADD_DS), 'file' => 'includes/solution_packs.inc', 'type' => MENU_NORMAL_ITEM, ); $items['islandora'] = array( 'title' => 'Islandora Repository', 'page callback' => 'islandora_view_default_object', 'type' => MENU_NORMAL_ITEM, 'access arguments' => array(FEDORA_VIEW), ); $items['islandora/object/%islandora_object'] = array( 'title' => 'Repository', 'page callback' => 'islandora_view_object', 'page arguments' => array(2), 'type' => MENU_NORMAL_ITEM, 'access callback' => 'islandora_object_access_callback', 'access arguments' => array(FEDORA_VIEW, 2), ); $items['islandora/object/%islandora_object/view'] = array( 'title' => 'View', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -1, ); $items['islandora/object/%islandora_object/view/default'] = array( 'title' => 'View', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -1, ); $items['islandora/object/%islandora_object/manage'] = array( 'title' => 'Manage', 'page callback' => 'islandora_edit_object', 'page arguments' => array(2), 'type' => MENU_LOCAL_TASK, 'access callback' => 'islandora_object_access_callback', 'access arguments' => array(FEDORA_MODIFY_STATE, 2), ); $items['islandora/object/%islandora_object/manage/datastreams'] = array( 'title' => 'Datastreams', 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); $items['islandora/object/%islandora_object/manage/properties'] = array( 'title' => 'Properties', 'page callback' => 'drupal_get_form', 'file' => 'includes/object_properties.form.inc', 'page arguments' => array('islandora_object_properties_form', 2), 'type' => MENU_LOCAL_TASK, 'access callback' => 'islandora_object_access_callback', 'access arguments' => array(FEDORA_MODIFY_STATE, 2), 'weight' => -5, ); $items['islandora/object/%islandora_object/delete'] = array( 'title' => 'Delete object', 'file' => 'includes/delete_object.form.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('islandora_delete_object_form', 2), 'type' => MENU_CALLBACK, 'access callback' => 'islandora_object_access_callback', 'access arguments' => array(FEDORA_PURGE, 2), ); $items['islandora/object/%islandora_object/manage/datastreams/add'] = array( 'title' => 'Add a datastream', 'file' => 'includes/add_datastream.form.inc', 'page callback' => 'drupal_get_form', 'page arguments' => array('islandora_add_datastream_form', 2), 'type' => MENU_LOCAL_ACTION, 'access callback' => 'islandora_object_access_callback', 'access arguments' => array(FEDORA_ADD_DS, 2) ); $items['islandora/object/%islandora_object/manage/datastreams/add/autocomplete'] = array( 'file' => 'includes/add_datastream.form.inc', 'page callback' => 'islandora_add_datastream_form_autocomplete_callback', 'page arguments' => array(2), 'type' => MENU_CALLBACK, 'access callback' => 'islandora_object_access_callback', 'access arguments' => array(FEDORA_ADD_DS, 2) ); $items['islandora/object/%islandora_object/datastream/%islandora_datastream'] = array( 'title' => 'View datastream', 'page callback' => 'islandora_view_datastream', 'page arguments' => array(4), 'type' => MENU_CALLBACK, 'file' => 'includes/datastream.inc', 'access callback' => 'islandora_object_datastream_access_callback', 'access arguments' => array(FEDORA_VIEW, 2, 4), 'load arguments' => array('%map'), ); $items['islandora/object/%islandora_object/datastream/%islandora_datastream/view'] = array( 'title' => 'View datastream', 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['islandora/object/%islandora_object/datastream/%islandora_datastream/download'] = array( 'title' => 'Download datastream', 'page callback' => 'islandora_download_datastream', 'page arguments' => array(4), 'type' => MENU_CALLBACK, 'file' => 'includes/datastream.inc', 'access callback' => 'islandora_object_datastream_access_callback', 'access arguments' => array(FEDORA_VIEW, 2, 4), 'load arguments' => array('%map'), ); $items['islandora/object/%islandora_object/datastream/%islandora_datastreams/edit'] = array( 'title' => 'Edit datastream', 'page callback' => 'islandora_edit_datastream', 'page arguments' => array(2, 4), 'type' => MENU_CALLBACK, 'file' => 'includes/datastream.inc', 'access callback' => 'islandora_object_datastream_access_callback', 'access arguments' => array(FEDORA_METADATA_EDIT, 2, 4), 'load arguments' => array('%map'), ); $items['islandora/object/%islandora_object/datastream/%islandora_datastream/delete'] = array( 'title' => 'Delete data stream', 'page callback' => 'drupal_get_form', 'page arguments' => array('islandora_delete_datastream_form', 4), 'file' => 'includes/delete_datastream.form.inc', 'type' => MENU_CALLBACK, 'access callback' => 'islandora_object_datastream_access_callback', 'access arguments' => array(FEDORA_PURGE, 2, 4), 'load arguments' => array('%map'), ); $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), ); return $items; } /** * Implements hook_admin_paths(). */ function islandora_admin_paths() { $paths = array(); $paths['islandora/object/*/manage*'] = TRUE; $paths['islandora/object/*/delete'] = TRUE; $paths['islandora/object/*/datastream/*/edit'] = TRUE; return $paths; } /** * Implements hook_theme(). */ function islandora_theme() { return array( // default object template 'islandora_default' => array( 'file' => 'theme/islandora.theme.inc', 'template' => 'theme/islandora-object', 'variables' => array('islandora_object' => NULL), ), // default edit page 'islandora_default_edit' => array( 'file' => 'theme/islandora.theme.inc', 'template' => 'theme/islandora-object-edit', 'variables' => array('islandora_object' => NULL), ), // admin table for solution pack viewer selection 'islandora_viewers_table' => array( 'file' => 'includes/solution_packs.inc', 'render element' => 'form', ), ); } /** * Implements hook_permission(). */ function islandora_permission() { return array( FEDORA_VIEW => array( 'title' => t('View repository objects and datastreams'), 'description' => t('View objects in the repository and their associated datastreams. Note: Fedora XACML security policies may override this permission.') ), FEDORA_ADD_DS => array( 'title' => t('Add datastreams to repository objects'), 'description' => t('Add datastreams to objects in the repository. Note: Fedora XACML security policies may override this position.') ), FEDORA_METADATA_EDIT => array( 'title' => t('Edit metadata'), 'description' => t('Edit metadata for objects in the repository.') ), FEDORA_INGEST => array( 'title' => t('Create new repository objects'), 'description' => t('Create new objects in the repository.') ), FEDORA_PURGE => array( 'title' => t('Permanently remove objects from the repository'), 'description' => t('Permanently remove objects from the repository.') ), FEDORA_MODIFY_STATE => array( 'title' => t('Change repository object states'), 'description' => t('Change the state of objects in the repository (e.g. from Active to Inactive).') ), FEDORA_MANAGE => array( 'title' => t('View object management tabs'), 'description' => t('View tabs that provide object management functions.') ) ); } /** * Implements hook_forms(). */ function islandora_forms($form_id) { $forms = array(); if (strpos($form_id, 'islandora_solution_pack_form_') !== FALSE) { $forms[$form_id] = array( 'callback' => 'islandora_solution_pack_form', ); } return $forms; } /** * Checks whether the user can access the given object with the given * permission. * * Checks for object existance, accessiblitly, namespace permissions, * and user permissions * * @see islandora_object_load() To find potential solutions to enable * page not found errors. * * @param string $perm * The user permission to test for. * @param FedoraObject $object * The object to test, if NULL given the object doesn't exist or is * inaccessible. * * @return boolean * TRUE if the user is allowed to access this object, FALSE otherwise. */ function islandora_object_access_callback($perm, $object = NULL) { module_load_include('inc', 'islandora', 'includes/utilities'); return user_access($perm) && is_object($object) && islandora_namespace_accessible($object->id); } /** * Checks whether the user can access the given object and datastream with * the given permission. * * Checks for object existance, accessiblitly, namespace permissions, * and user permissions * * @see islandora_object_load() To find potential solutions to enable page * not found errors. * * @param string $perm * The user permission to test for. * @param FedoraObject $object * The object to test, if NULL given the object doesn't exist or is * inaccessible. * @param FedoraDatastream $datastream * The datastream to test, if NULL given the datastream doesn't exist * or is inaccessible. * * @return boolean * TRUE if the user is allowed to access this object, FALSE otherwise. */ function islandora_object_datastream_access_callback($perm, $object = NULL, $datastream = NULL) { module_load_include('inc', 'islandora', 'includes/utilities'); return user_access($perm) && is_object($object) && islandora_namespace_accessible($object->id) && is_object($datastream); } /** * Renders the given objects manage page. * * Its possible to modify the output of this function if 'ISLANDORA_EDIT_HOOK' * is implemented in other modules. * * If no modules implement 'ISLANDORA_EDIT_HOOK' then this function returns the * default manage view. * * @param FedoraObject $object * The object to manage. * * @return string * The HTML repersentation of the manage object page. */ function islandora_edit_object(FedoraObject $object) { module_load_include('inc', 'islandora', 'includes/utilities'); $output = array(); foreach (islandora_build_hook_list(ISLANDORA_EDIT_HOOK, $object->models) as $hook) { $temp = module_invoke_all($hook, $object); if (!empty($temp)) { $output = array_merge_recursive($output, $temp); } } if (empty($output)) { // Add in the default, if we did not get any results. $output = islandora_default_islandora_edit_object($object); } arsort($output); drupal_alter(ISLANDORA_EDIT_HOOK, $object, $output); return implode('', $output); } /** * Renders the default manage object page for the given object. * * @param FedoraObject $object * The object used to render the manage object page. * * @return array * The default rendering of the object manage page, indexed at * 'Default Edit output'. */ function islandora_default_islandora_edit_object(FedoraObject $object) { $output = theme('islandora_default_edit', array('islandora_object' => $object)); return array('Default Edit output' => $output); } /** * Page callback for the path "islandora". * * Redirects to the view of the object indicated by the Drupal variable * 'islandora_repository_pid'. */ function islandora_view_default_object() { $pid = variable_get('islandora_repository_pid', 'islandora:root'); drupal_goto("islandora/object/$pid"); } /** * Renders the default view object page for the given object. * * Modules should implement ISLANDORA_VIEW_HOOK for the Fedora Content * models that their modules want to provide a view for. * * If no modules implement the hook then the default view object page * will be rendered. * * @param FedoraObject $object * The object to view. * * @return string * The html repersentation of this object. */ function islandora_view_object(FedoraObject $object) { module_load_include('inc', 'islandora', 'includes/breadcrumb'); module_load_include('inc', 'islandora', 'includes/utilities'); drupal_set_breadcrumb(islandora_get_breadcrumbs($object)); // Optional pager parameters $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) { // @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); if (!empty($temp)) { $output = array_merge_recursive($output, $temp); } } if (empty($output)) { // No results, use the default view. $output = islandora_default_islandora_view_object($object); } arsort($output); drupal_alter(ISLANDORA_VIEW_HOOK, $object, $output); return implode('', $output); } /** * Renders the default view object page for the given object. * * @param FedoraObject $object * The object used to render the view object page. * * @return array * The default rendering of the object view page, indexed at 'Default output'. */ function islandora_default_islandora_view_object($object) { $output = theme('islandora_default', array('islandora_object' => $object)); return array('Default output' => $output); } /** * A helper function to get a connection and return an object for objects * specified in the menu path as '%islandora_object'. * * This should only be used by the Drupal menu wildcard system! * * When this function returns FALSE the Drupal menu system will issues a * "page not found" error, when this function returns NULL, the access function * is expected to check for the given object and return false generating a * "accesss denied" error. * * This will currently display a message if the repository is inaccessable, * ideally this would redirect to another page in such a case, * as the access function will not be aware of this fact and will trigger * the display of the "access denied" page. * * @todo When the repository down this should return a 500 error or a * site offline notice. Currently only displays a message. * * @param string $object_id * The pid of an object in the menu path identified by '%islandora_object'. * * @return FedoraObject * If the given object id exists in the repository then this returns a * FedoraObject. * If no object was found it returns FALSE which triggers * drupal_page_not_found(). * If the object was inaccessible then NULL is returned, and the * access callback is expected to catch that case, triggering * drupal_access_denied(). */ function islandora_object_load($object_id) { static $object = NULL, $load_failed = FALSE; // Assume inaccessible. if ($load_failed || isset($object)) { return $object; } $object = islandora_get_object_by_id($object_id); // Either NULL or FALSE. if (!isset($object)) { module_load_include('inc', 'islandora', 'includes/utilities'); if (islandora_describe_repository() === FALSE) { drupal_set_message(t('The repository is not availible please contact the administrator.'), 'error'); } $load_failed = TRUE; } return $object; } /** * A helper function to get an datastream specified as '%islandora_datastream' * for the object specified in the menu path as '%islandora_object'. * * This should only be used by the Drupal menu wildcard system! * * The following settings are required for any menu paths which intent to use * this auto loader. * * @code * 'load arguments' => array('%map'), * @endcode * * Its up to the access callbacks and menu callbacks to trigger * drupal_access_denied() when appropriate. * * @param string $datastream_id * The dsid of the datastream specified as '%islandora_datastream' to fetch * from the given object in the menu path identified by '%islandora_object'. * * @return FedoraDatastream * If the given datastream ID exists then this returns a FedoraDatastream * object, otherwise it returns NULL which triggers drupal_page_not_found(). */ function islandora_datastream_load($datastream_id, $map) { static $datastream = NULL, $load_failed = FALSE; if ($load_failed || isset($datastream)) { return $datastream; } foreach ($map as $element) { $is_fedora_object = is_object($element) && strtolower(get_class($element)) == 'fedoraobject'; if ($is_fedora_object && isset($element[$datastream_id])) { $datastream = $element[$datastream_id]; return $datastream; } } $load_failed = TRUE; return $datastream; } /** * Content model, collection view and collection policy datastreams may now * optionally define a version number in their top-level XML element as an * attribute, as in: * content); } elseif (!empty($datastream_file)) { $doc = simplexml_load_file($datastream_file); } if (!empty($doc) && $version = (int)$doc->attributes()->version) { $return = $version; } return $return; } /** * Implements hook_islandora_required_objects(). */ function islandora_islandora_required_objects() { $module_path = drupal_get_path('module', 'islandora'); return array( 'islandora' => array( 'title' => 'Islandora', 'objects' => array( array( 'pid' => 'islandora:root', 'label' => 'Top-level collection', 'cmodel' => 'islandora:collectionCModel', 'datastreams' => array( array( 'dsid' => 'COLLECTION_POLICY', 'label' => 'Collection policy', 'mimetype' => 'text/xml', 'control_group' => 'X', 'datastream_file' => "$module_path/xml/islandora_collection_policy.xml", ), array( 'dsid' => 'TN', 'label' => 'Thumbnail', 'mimetype' => 'image/png', 'control_group' => 'M', 'datastream_file' => "$module_path/images/folder.png", ), ), ), ), ), ); } /** * Implements islandora_undeleteable_datastreams(). */ function islandora_islandora_undeletable_datastreams(array $models) { return array('DC'); }