You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1019 lines
32 KiB
1019 lines
32 KiB
<?php |
|
|
|
/** |
|
* @file |
|
* Utility functions. |
|
* |
|
* @todo this file should be broken out into other files. |
|
*/ |
|
|
|
/** |
|
* Convert bytes to human readable format. |
|
* |
|
* XXX: Shouldn't Drupal's format_size() be preferred? |
|
* |
|
* @param int $bytes |
|
* Size in bytes to convert |
|
* @param int $precision |
|
* The amount of decimal precision to show. |
|
* |
|
* @return string |
|
* Human readable size. |
|
*/ |
|
function islandora_convert_bytes_to_human_readable($bytes, $precision = 2) { |
|
$kilobyte = 1024; |
|
$megabyte = $kilobyte * 1024; |
|
$gigabyte = $megabyte * 1024; |
|
$terabyte = $gigabyte * 1024; |
|
|
|
if (($bytes >= 0) && ($bytes < $kilobyte)) { |
|
return $bytes . ' B'; |
|
} |
|
elseif (($bytes >= $kilobyte) && ($bytes < $megabyte)) { |
|
return round($bytes / $kilobyte, $precision) . ' KB'; |
|
} |
|
elseif (($bytes >= $megabyte) && ($bytes < $gigabyte)) { |
|
return round($bytes / $megabyte, $precision) . ' MB'; |
|
} |
|
elseif (($bytes >= $gigabyte) && ($bytes < $terabyte)) { |
|
return round($bytes / $gigabyte, $precision) . ' GB'; |
|
} |
|
elseif ($bytes >= $terabyte) { |
|
return round($bytes / $terabyte, $precision) . ' TB'; |
|
} |
|
else { |
|
return $bytes . ' B'; |
|
} |
|
} |
|
|
|
function islandora_temp_file_entry($file_name, $file_uri) { |
|
// Check for this file in the file managed table. |
|
$list = db_select('file_managed', 'c') |
|
->fields('c') |
|
->condition('uri', $file_uri, "=") |
|
->execute(); |
|
$data = $list->fetchObject(); |
|
|
|
dsm($data, "existing: "); |
|
|
|
if (!$data) { |
|
$file = new stdClass(); |
|
$file->uri = $file_uri; |
|
$file->filename = $file_name; |
|
// Temporary. |
|
$file->status = 0; |
|
|
|
dsm($file, "file in islandora_temp_file_entry"); |
|
// Save the temp file to be cleaned up later via cron. |
|
file_save($file); |
|
} |
|
} |
|
/** |
|
* Creates a label for control group symbols. |
|
*/ |
|
function islandora_control_group_to_human_readable($control_group) { |
|
switch ($control_group) { |
|
case 'M': |
|
return '<b>M</b>anaged'; |
|
|
|
case 'X': |
|
return 'Inline <b>X</b>ML'; |
|
|
|
case 'R': |
|
return '<b>R</b>edirect'; |
|
|
|
case 'E': |
|
return '<b>E</b>xternally Referenced'; |
|
|
|
default: |
|
return $control_group; |
|
} |
|
} |
|
|
|
/** |
|
* Checks if the given pid is valid. |
|
* |
|
* @param string $pid |
|
* The object id to check. |
|
* |
|
* @return bool |
|
* TRUE if valid, FALSE otherwise. |
|
*/ |
|
function islandora_is_valid_pid($pid) { |
|
return drupal_strlen(trim($pid)) <= 64 && preg_match('/^([A-Za-z0-9]|-|\.)+:(([A-Za-z0-9])|-|\.|~|_|(%[0-9A-F]{2}))+$/', trim($pid)); |
|
} |
|
|
|
/** |
|
* Checks if the given namespace is valid. |
|
* |
|
* @param string $namespace |
|
* The namespace to check without the ":" character. |
|
* |
|
* @return bool |
|
* TRUE if valid, FALSE otherwise. |
|
*/ |
|
function islandora_is_valid_namespace($namespace) { |
|
return drupal_strlen(trim($namespace)) <= 64 && preg_match('/^([A-Za-z0-9]|-|\.)+$/', trim($namespace)); |
|
} |
|
|
|
/** |
|
* Checks if the given datastream id is valid. |
|
* |
|
* @param string $dsid |
|
* The datastream id to check. |
|
* |
|
* @return bool |
|
* TRUE if valid, FALSE otherwise. |
|
*/ |
|
function islandora_is_valid_dsid($dsid) { |
|
return drupal_strlen(trim($dsid)) <= 64 && preg_match('/^[a-zA-Z0-9\_\-\.]+$/', trim($dsid)); |
|
} |
|
|
|
/** |
|
* Helper function to describe a Fedora repository. |
|
* |
|
* Can be used to check if Fedora is available. |
|
* |
|
* @param string $url |
|
* A url to a Fedora repository, if NULL the default is used. |
|
* |
|
* @return array |
|
* Returns an array describing the repository. Returns FALSE if Fedora is down |
|
* or if the url is incorrect. |
|
*/ |
|
function islandora_describe_repository($url = NULL) { |
|
$url = isset($url) ? $url : variable_get('islandora_base_url', 'http://localhost:8080/fedora'); |
|
$connection = islandora_get_tuque_connection(); |
|
if ($connection) { |
|
try { |
|
$info = $connection->api->a->describeRepository(); |
|
return $info; |
|
} |
|
catch (RepositoryException $e) { |
|
return FALSE; |
|
} |
|
} |
|
return FALSE; |
|
} |
|
|
|
/** |
|
* Build and invoke a list of hooks by combining the given hook and refinements. |
|
* |
|
* The given hook will be called as MODULE_HOOK, and for each hook refinement |
|
* as MODULE_REFINEMENT_HOOK. Any additional arguments passed to this function |
|
* will be passed as arguments to module_invoke_all(). |
|
* |
|
* @see islandora_build_hook_list() |
|
* |
|
* @param string $hook |
|
* A hook to call. |
|
* @param array $refinements |
|
* An array of strings, that will be escaped and concatinated with the given |
|
* hook. This will most likely be PIDs/DSIDs/Labels etc. We often refine our |
|
* hooks using an objects model. |
|
* @param array $args |
|
* Any arguments to pass onto module_invoke_all(). |
|
* |
|
* @return array |
|
* The merged results from all the hooks. |
|
*/ |
|
function islandora_invoke_hook_list($hook, array $refinements, array $args) { |
|
$return = array(); |
|
foreach (islandora_build_hook_list($hook, $refinements) as $hook) { |
|
array_unshift($args, $hook); |
|
$result = call_user_func_array('module_invoke_all', $args); |
|
$return = array_merge_recursive($return, $result); |
|
array_shift($args); |
|
} |
|
return $return; |
|
} |
|
|
|
/** |
|
* Build a list of all the hooks to call. |
|
* |
|
* Concatenates each hook $refinement (escaped) to the hook name, for calling |
|
* with module_invoke_all(). |
|
* |
|
* Any non-valid PHP function characters in the given refinements are |
|
* converted to "_" characters. |
|
* |
|
* @param string $hook |
|
* The base hook to concatenate. |
|
* @param array $refinements |
|
* An array of strings, that will be escaped and concatinated with the given |
|
* hook. This will most likely be PIDs/DSIDs/Labels etc. We often refine our |
|
* hooks using an objects model. |
|
* |
|
* @return array |
|
* An array with each refinement escaped and concatenated with the base hook |
|
* name, in addition to the base hook name. |
|
*/ |
|
function islandora_build_hook_list($hook, $refinements = array()) { |
|
$refinements = array_unique($refinements); |
|
$hooks = array($hook); |
|
foreach ($refinements as $refinement) { |
|
$refinement = preg_replace('/[^a-zA-Z0-9_]/', '_', $refinement); |
|
$hooks[] = "{$refinement}_{$hook}"; |
|
} |
|
return $hooks; |
|
} |
|
|
|
/** |
|
* Escape a Fedora PID to be valid inside of a PHP function name. |
|
* |
|
* Originally intended to allow inclusion of a PID in a module_invoke_all() |
|
* call. |
|
*/ |
|
function islandora_escape_pid_for_function($pid) { |
|
// Apparently, case doesn't matter for function calls in PHP, so let's not |
|
// really worry about changing the case. |
|
return str_replace( |
|
// Any PID characters which are not valid in the name of a PHP function. |
|
array( |
|
':', |
|
'-', |
|
), |
|
'_', |
|
$pid |
|
); |
|
} |
|
|
|
/** |
|
* Gets the namespace of the given id. |
|
* |
|
* @param string $id |
|
* Either a PID or namespace to check for accessibility. Any string like those |
|
* below are fine. |
|
* |
|
* @code |
|
* 'islandora', |
|
* 'islandora:', |
|
* 'islandora:1234', |
|
* @endcode |
|
* |
|
* @return string |
|
* The namespace portion of the given string. |
|
*/ |
|
function islandora_get_namespace($id) { |
|
$matches = array(); |
|
preg_match('/^([^:]*)/', $id, $matches); |
|
return $matches[0]; |
|
} |
|
|
|
/** |
|
* Checks the given namespace/PID is/has an accessible namespace. |
|
* |
|
* Accessible is defined by the "islandora_pids_allowed" variable. |
|
* |
|
* @param string $id |
|
* Either a PID or namespace to check for accessibility. Any string like those |
|
* below are fine. |
|
* |
|
* @code |
|
* 'islandora', |
|
* 'islandora:', |
|
* 'islandora:1234', |
|
* @endcode |
|
* |
|
* @return bool |
|
* TRUE if accessible, FALSE otherwise. |
|
*/ |
|
function islandora_namespace_accessible($id) { |
|
if (variable_get('islandora_namespace_restriction_enforced', FALSE)) { |
|
$namespace = islandora_get_namespace($id); |
|
$allowed_namespaces = islandora_get_allowed_namespaces(); |
|
return in_array($namespace, $allowed_namespaces); |
|
} |
|
return TRUE; |
|
} |
|
|
|
/** |
|
* Gets any objects that the given object has a parent relationship with. |
|
* |
|
* Parent relationships are defined as (isMemberOf, isMemberOfCollection). |
|
* |
|
* This function gets its info from the RELS-EXT directly rather than through an |
|
* risearch. |
|
* |
|
* @param AbstractObject $object |
|
* The object whose parents will be returned. |
|
* |
|
* @return array |
|
* An array of FedoraObject's that the given object has a |
|
* (isMemberOf, isMemberOfCollection) relationship with. |
|
*/ |
|
function islandora_get_parents_from_rels_ext(AbstractObject $object) { |
|
try { |
|
$collections = array_merge( |
|
$object->relationships->get(FEDORA_RELS_EXT_URI, 'isMemberOfCollection'), |
|
$object->relationships->get(FEDORA_RELS_EXT_URI, 'isMemberOf')); |
|
} |
|
catch (RepositoryException $e) { |
|
// @todo some logging would be nice, not sure what this throws. |
|
return array(); |
|
} |
|
$map = function($o) { |
|
return islandora_object_load($o['object']['value']); |
|
}; |
|
$collections = array_map($map, $collections); |
|
return array_filter($collections); |
|
} |
|
|
|
/** |
|
* Gets the datastreams requirments that are missing. |
|
* |
|
* @param AbstractObject $object |
|
* The object which models will be used to determine what datastreams it |
|
* should have. |
|
* |
|
* @return array |
|
* The DS-COMPOSITE-MODEL defined datastreams that are required for the given |
|
* object, but not already present. |
|
*/ |
|
function islandora_get_missing_datastreams_requirements(AbstractObject $object) { |
|
module_load_include('inc', 'islandora', 'includes/utilities'); |
|
$datastreams = islandora_get_datastreams_requirements($object); |
|
foreach ($datastreams as $dsid => $requirements) { |
|
if (isset($object[$dsid])) { |
|
unset($datastreams[$dsid]); |
|
} |
|
} |
|
return $datastreams; |
|
} |
|
|
|
/** |
|
* Gets the required datastreams for the given object. |
|
* |
|
* Checks the object's content model's for which datastream are expected to be |
|
* used with this object, as defined by the DS-COMPOSITE-MODEL datastreams. |
|
* |
|
* For duplicate datastreams in the models, the first model defines the |
|
* datastreams attributes regardless of what other models define. |
|
* This should be undefined behavior according to the documentation. |
|
* |
|
* @link https://wiki.duraspace.org/display/FEDORA34/Fedora+Digital+Object+Model#FedoraDigitalObjectModel-ContentModelObjectCMODEL @endlink |
|
* |
|
* @see islandora_get_required_datastreams_from_content_model() |
|
* |
|
* @param AbstractObject $object |
|
* The object which models will be used to determine what datastreams it |
|
* should have. |
|
* |
|
* @return array |
|
* The DS-COMPOSITE-MODEL defined datastreams that are required for the given |
|
* object. |
|
*/ |
|
function islandora_get_datastreams_requirements(AbstractObject $object) { |
|
return islandora_get_datastreams_requirements_from_models($object->models); |
|
} |
|
|
|
/** |
|
* Get the list of which datastreams are valid in the given set of models. |
|
* |
|
* @param array $models |
|
* An array of content models PIDs from which to parse the DS-COMPOSITE-MODEL |
|
* stream. |
|
* |
|
* @return array |
|
* An associative array of associative arrays, merged from calls to |
|
* islandora_get_datastreams_requirements_from_content_model(). |
|
*/ |
|
function islandora_get_datastreams_requirements_from_models(array $models) { |
|
$dsids = array(); |
|
foreach ($models as $model_pid) { |
|
$model = islandora_object_load($model_pid); |
|
if (isset($model) && $model) { |
|
$dsids += islandora_get_datastreams_requirements_from_content_model($model); |
|
} |
|
} |
|
// The AUDIT Datastream can not really be added, so it can't really be |
|
// missing. |
|
unset($dsids['AUDIT']); |
|
return $dsids; |
|
} |
|
|
|
/** |
|
* Checks the given content model for which datastreams are required. |
|
* |
|
* As defined by it's DS-COMPOSITE-MODEL datastream. |
|
* |
|
* @todo Add support for fetching the schema information. |
|
* |
|
* @param AbstractObject $object |
|
* The content model whose DS-COMPOSITE-MODEL datastream will be used to |
|
* determine what datastreams are required. |
|
* |
|
* @return array |
|
* An associative array mapping datastream IDs to associative arrays |
|
* containing the values parsed from the DS-COMPOSITE-MODEL on the given |
|
* object--of the form: |
|
* - DSID: A datastream ID being described. |
|
* - "id": A string containing ID of the datastream. |
|
* - "mime": A array containing MIME-types the stream may have. |
|
* - "optional": A boolean indicating if the given stream is optional. |
|
*/ |
|
function islandora_get_datastreams_requirements_from_content_model(AbstractObject $object) { |
|
if (empty($object[ISLANDORA_DS_COMP_STREAM]) || !islandora_datastream_access(ISLANDORA_VIEW_OBJECTS, $object[ISLANDORA_DS_COMP_STREAM])) { |
|
return array(); |
|
} |
|
$xml = new SimpleXMLElement($object[ISLANDORA_DS_COMP_STREAM]->content); |
|
foreach ($xml->dsTypeModel as $ds) { |
|
$dsid = (string) $ds['ID']; |
|
$optional = strtolower((string) $ds['optional']); |
|
$mime = array(); |
|
foreach ($ds->form as $form) { |
|
$mime[] = (string) $form['MIME']; |
|
} |
|
$dsids[$dsid] = array( |
|
'id' => $dsid, |
|
'mime' => $mime, |
|
'optional' => ($optional == 'true') ? TRUE : FALSE, |
|
); |
|
} |
|
return $dsids; |
|
} |
|
|
|
/** |
|
* Prepare an ingestable object. |
|
* |
|
* @param string $namespace |
|
* The namespace in which the PID for the new object will be created. |
|
* @param string $label |
|
* An optional label to apply to the object. |
|
* @param array $datastreams |
|
* A array of datastreams to add, where each datastream definition is an |
|
* associative array containing: |
|
* - dsid: The datastream ID. |
|
* - label: An optional label for the datastream. |
|
* - mimetype: A MIMEtype for the datastream; defaults to text/xml. |
|
* - control_group: One of X, M, R and E; defaults to M. |
|
* - datastream_file: A web-accessible path, for which we try to get an |
|
* absolute path using url(). |
|
* @param array $content_models |
|
* An array of content model PIDs to which the new object should subscribe. |
|
* @param array $relationships |
|
* An array of relationships, where each relationship is an associative array |
|
* containing: |
|
* - relationship: The predicate for the relationship, from the Fedora |
|
* RELS-EXT namespace. |
|
* - pid: The object for the relationship, to which we are creating the |
|
* relationhsip. |
|
* |
|
* @return NewFedoraObject |
|
* An ingestable NewFedoraObject. |
|
*/ |
|
function islandora_prepare_new_object($namespace = NULL, $label = NULL, $datastreams = array(), $content_models = array(), $relationships = array()) { |
|
global $user; |
|
$tuque = islandora_get_tuque_connection(); |
|
$object = isset($namespace) ? $tuque->repository->constructObject($namespace) : new IslandoraNewFedoraObject(NULL, $tuque->repository); |
|
$object->owner = isset($user->name) ? $user->name : $object->owner; |
|
$object->label = isset($label) ? $label : $object->label; |
|
foreach ($content_models as $content_model) { |
|
$object->relationships->add(FEDORA_MODEL_URI, 'hasModel', $content_model); |
|
} |
|
foreach ($relationships as $relationship) { |
|
$object->relationships->add(FEDORA_RELS_EXT_URI, $relationship['relationship'], $relationship['pid']); |
|
} |
|
foreach ($datastreams as $ds) { |
|
$dsid = $ds['dsid']; |
|
$label = isset($ds['label']) ? $ds['label'] : ''; |
|
$mimetype = isset($ds['mimetype']) ? $ds['mimetype'] : 'text/xml'; |
|
// Default 'Managed' |
|
$control_group = 'M'; |
|
$groups = array('X', 'M', 'R', 'E'); |
|
if (isset($ds['control_group']) && in_array($ds['control_group'], $groups)) { |
|
$control_group = $ds['control_group']; |
|
} |
|
|
|
$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']; |
|
$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 { |
|
$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 ($as_file) { |
|
$datastream->setContentFromFile($datastream_file); |
|
} |
|
else { |
|
$datastream->setContentFromUrl($datastream_file); |
|
} |
|
break; |
|
|
|
case 'X': |
|
$datastream->setContentFromString(file_get_contents($datastream_file)); |
|
break; |
|
} |
|
|
|
$object->ingestDatastream($datastream); |
|
} |
|
|
|
return $object; |
|
} |
|
|
|
/** |
|
* Displays the repository is inaccessible message. |
|
* |
|
* Use anywhere we want to ensure a consitent error message when the repository |
|
* is not accessible. |
|
*/ |
|
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(filter_xss($message), 'error', FALSE); |
|
|
|
} |
|
|
|
/** |
|
* Create a message stating if the given executable is available. |
|
* |
|
* If the both the version and required version are given then only if the |
|
* version is equal to or greater than the required version the executable |
|
* will be considered correct. |
|
* |
|
* @param string $path |
|
* The absolute path to an executable to check for availability. |
|
* @param string $version |
|
* The version of exectuable. |
|
* @param string $required_version |
|
* The required version of exectuable. |
|
* |
|
* @return string |
|
* A message in html detailing if the given executable is accessible. |
|
*/ |
|
function islandora_executable_available_message($path, $version = NULL, $required_version = NULL) { |
|
$available = is_executable($path); |
|
if ($available) { |
|
$image = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())); |
|
$message = t('Executable found at @path', array('@path' => $path)); |
|
if ($version) { |
|
$message .= t('<br/>Version: @version', array('@version' => $version)); |
|
} |
|
if ($required_version) { |
|
$message .= t('<br/>Required Version: @version', array('@version' => $required_version)); |
|
if (version_compare($version, $required_version) < 0) { |
|
$image = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())); |
|
} |
|
} |
|
} |
|
else { |
|
$image = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())); |
|
$message = t('Unable to locate executable at @path', array('@path' => $path)); |
|
} |
|
return $image . $message; |
|
} |
|
|
|
/** |
|
* Create a message stating if the given directory exists. |
|
* |
|
* @param string $path |
|
* The absolute path to an executable to check for availability. |
|
* |
|
* @return string |
|
* A message in HTML detailing if the given directory is exists. |
|
*/ |
|
function islandora_directory_exists_message($path) { |
|
$available = is_dir($path); |
|
if ($available) { |
|
$image = theme_image(array('path' => 'misc/watchdog-ok.png', 'attributes' => array())); |
|
$message = t('Directory found at @path', array('@path' => $path)); |
|
} |
|
else { |
|
$image = theme_image(array('path' => 'misc/watchdog-error.png', 'attributes' => array())); |
|
$message = t('Unable to locate directory at @path', array('@path' => $path)); |
|
} |
|
return $image . $message; |
|
} |
|
|
|
/** |
|
* Gets the default value for the given system_settings_form() element. |
|
* |
|
* Checks the $form_state for the default value if not it checks |
|
* variable_get(). Assumes #tree is FALSE. This is only really required |
|
* for elements that utilize AJAX, as their value can change before the |
|
* submit actually takes place. |
|
* |
|
* @param string $name |
|
* The name of the system settings form element. |
|
* @param mixed $default_value |
|
* The default value for the system settings form element. |
|
* @param array $form_state |
|
* The Drupal form state. |
|
* |
|
* @return mixed |
|
* The default value for use in a the system_settings_form(). |
|
*/ |
|
function islandora_system_settings_form_default_value($name, $default_value, array &$form_state) { |
|
return isset($form_state['values'][$name]) ? $form_state['values'][$name] : variable_get($name, $default_value); |
|
} |
|
|
|
/** |
|
* Returns basic information about DS-COMPOSITE-MODEL. |
|
* |
|
* @deprecated |
|
* The pre-existing--and more flexible-- |
|
* islandora_get_datastreams_requirements_from_content_model() should be |
|
* preferred, as it addresses the case where a stream can be allowed to have |
|
* one of a set of mimetypes (this functions appears to only return the last |
|
* declared mimetype for a given datastream). |
|
* |
|
* @param string $pid |
|
* The PID of content model containing DS_COMP stream. |
|
* |
|
* @return array |
|
* An associative array mapping datastream IDs to an associative array |
|
* representing the parsed DS-COMPOSITE-MODEL of the form: |
|
* - DSID: A string containing the datastream ID. |
|
* - "mimetype": A string containing the last mimetype declared for the |
|
* given datastream ID. |
|
* - "optional": An optional boolean indicating that the given datastream |
|
* is optional. |
|
*/ |
|
function islandora_get_comp_ds_mappings($pid) { |
|
$message = islandora_deprecated('7.x-1.2', t('Refactor to use the more flexible islandora_get_datastreams_requirements_from_content_model().')); |
|
trigger_error(filter_xss($message), E_USER_DEPRECATED); |
|
|
|
$cm_object = islandora_object_load($pid); |
|
if (!isset($cm_object) || !isset($cm_object['DS-COMPOSITE-MODEL'])) { |
|
return FALSE; |
|
} |
|
$datastream = $cm_object['DS-COMPOSITE-MODEL']; |
|
$ds_comp_stream = $datastream->content; |
|
$sxml = new SimpleXMLElement($ds_comp_stream); |
|
$mappings = array(); |
|
foreach ($sxml->dsTypeModel as $ds) { |
|
$dsid = (string) $ds['ID']; |
|
$optional = (string) $ds['optional']; |
|
foreach ($ds->form as $form) { |
|
$mime = (string) $form['MIME']; |
|
if ($optional) { |
|
$mappings[$dsid]['optional'] = $optional; |
|
} |
|
$mappings[$dsid]['mimetype'] = $mime; |
|
} |
|
} |
|
return $mappings; |
|
} |
|
|
|
/** |
|
* Checks that the given/current account has all the given permissions. |
|
* |
|
* @param array $perms |
|
* The permissions to check. |
|
* @param mixed $account |
|
* (optional) The account to check, if not given use currently logged in user. |
|
* |
|
* @return bool |
|
* TRUE if the account has all the given permissions, FALSE otherwise. |
|
*/ |
|
function islandora_user_access_all(array $perms, $account = NULL) { |
|
$message = islandora_deprecated('7.x-1.2', 'Roll your own code or use islandora_user_access().'); |
|
trigger_error(filter_xss($message), E_USER_DEPRECATED); |
|
|
|
foreach ($perms as $perm) { |
|
if (!user_access($perm, $account)) { |
|
return FALSE; |
|
} |
|
} |
|
return TRUE; |
|
} |
|
|
|
/** |
|
* Checks that the given/current account has at one of the given permissions. |
|
* |
|
* @param array $perms |
|
* The permissions to check. |
|
* @param mixed $account |
|
* (optional) The account to check, if not given use currently logged in user. |
|
* |
|
* @return bool |
|
* TRUE if the account has at least one of the given permissions, FALSE |
|
* otherwise. |
|
*/ |
|
function islandora_user_access_any(array $perms, $account = NULL) { |
|
$message = islandora_deprecated('7.x-1.2', 'Roll your own code or use islandora_user_access().'); |
|
trigger_error(filter_xss($message), E_USER_DEPRECATED); |
|
|
|
foreach ($perms as $perm) { |
|
if (user_access($perm, $account)) { |
|
return TRUE; |
|
} |
|
} |
|
return FALSE; |
|
} |
|
|
|
/** |
|
* Gets the list of allowed namespaces as defined by 'islandora_pids_allowed'. |
|
* |
|
* @return array |
|
* The list of namespaces striped of trailing ":" characters. |
|
*/ |
|
function islandora_get_allowed_namespaces() { |
|
$matches = array(); |
|
$allowed_namespaces = variable_get('islandora_pids_allowed', 'default: demo: changeme: islandora:'); |
|
preg_match_all('/([A-Za-z0-9-\.]+):/', $allowed_namespaces, $matches); |
|
$accessible_namespaces = $matches[1]; |
|
// Ensure that the "islandora" namespace is explicitly allowed |
|
// no matter what happens. |
|
if (!in_array('islandora', $accessible_namespaces)) { |
|
$accessible_namespaces[] = 'islandora'; |
|
} |
|
return $accessible_namespaces; |
|
} |
|
|
|
/** |
|
* Gets a list of all existing content models. |
|
* |
|
* If 'islandora_namespace_restriction_enforced' is set to true only return |
|
* content models in the allowed namespace. |
|
* |
|
* @param bool $ignore_system_namespace |
|
* Ignore content models in the 'fedora-system' namespace. |
|
* |
|
* @return array |
|
* An associative array of all existing content models. |
|
* - pid: The PID of the content model object. |
|
* - pid: The PID of the content model object. |
|
* - label: The label of the content model object. |
|
*/ |
|
function islandora_get_content_models($ignore_system_namespace = TRUE) { |
|
module_load_include('inc', 'islandora', 'includes/utilities'); |
|
$tuque = islandora_get_tuque_connection(); |
|
$query = "PREFIX fm: <" . FEDORA_MODEL_URI . "> |
|
PREFIX fr: <" . FEDORA_RELS_EXT_URI . "> |
|
SELECT ?object ?label |
|
FROM <#ri> |
|
WHERE { |
|
{?object fm:hasModel <info:fedora/fedora-system:ContentModel-3.0>; |
|
fm:state fm:Active |
|
} |
|
UNION{ |
|
?object fr:isMemberOfCollection <info:fedora/islandora:ContentModelsCollection>; |
|
fm:state fm:Active |
|
} |
|
OPTIONAL{ |
|
?object fm:label ?label |
|
} |
|
}"; |
|
$content_models = array(); |
|
$results = $tuque->repository->ri->sparqlQuery($query, 'unlimited'); |
|
foreach ($results as $result) { |
|
$content_model = $result['object']['value']; |
|
$label = $result['label']['value']; |
|
$namespace = islandora_get_namespace($content_model); |
|
$ignore = $ignore_system_namespace && $namespace == 'fedora-system'; |
|
$ignore |= !islandora_namespace_accessible($namespace); |
|
if (!$ignore) { |
|
$content_models[$content_model] = array('pid' => $content_model, 'label' => $label); |
|
} |
|
} |
|
return $content_models; |
|
} |
|
|
|
/** |
|
* Returns Drupal tableselect element allowing selection of Content Models. |
|
* |
|
* @param string $drupal_variable |
|
* the name of the Drupal variable holding selected content models |
|
* Content models held in this variable will appear at the top of |
|
* the displayed list |
|
* @param array $default_values_array |
|
* default values to display if $drupal_variable is unset |
|
* |
|
* @return array |
|
* Drupal form element allowing content model selection |
|
*/ |
|
function islandora_content_model_select_table_form_element($drupal_variable, $default_values_array = array('')) { |
|
$defaults = array(); |
|
$rows = array(); |
|
$content_models = array(); |
|
$options = islandora_get_content_models(TRUE); |
|
foreach ($options as $option) { |
|
$content_models[$option['pid']] = $option['label']; |
|
} |
|
|
|
$selected = array_values(variable_get($drupal_variable, $default_values_array)); |
|
$comparator = function ($a, $b) use ($selected) { |
|
$a_val = $b_val = 0; |
|
if (in_array($a, $selected)) { |
|
$a_val = 1; |
|
} |
|
if (in_array($b, $selected)) { |
|
$b_val = 1; |
|
} |
|
return $b_val - $a_val; |
|
}; |
|
uksort($content_models, $comparator); |
|
foreach ($content_models as $pid => $label) { |
|
$rows[$pid] = array( |
|
'pid' => $pid, |
|
'title' => $label, |
|
); |
|
$defaults[$pid] = in_array($pid, $selected); |
|
} |
|
$header = array( |
|
'pid' => array('data' => t('PID')), |
|
'title' => array('data' => t('Content Model')), |
|
); |
|
// Build and return table element. |
|
$element = array( |
|
'#type' => 'tableselect', |
|
'#header' => $header, |
|
'#options' => $rows, |
|
'#default_value' => $defaults, |
|
'#empty' => t("There are no content models in this Fedora Repository."), |
|
); |
|
|
|
return $element; |
|
} |
|
|
|
/** |
|
* Convience function for generating a E_USER_DEPRECATED message. |
|
* |
|
* To utilitize this function pass the results to trigger_error() like so: |
|
* |
|
* @code |
|
* $message = islandora_deprecated('7.x-1.1', t('Use more cowbell.')) |
|
* trigger_error(filter_xss($message), E_USER_DEPRECATED) |
|
* @endcode |
|
* |
|
* @param string $release |
|
* The release the calling function was depreciated in. |
|
* @param string $solution |
|
* A message describing an alternative solution to the deprecated function. |
|
* It's assumed to be already passed though the t() function. |
|
* |
|
* @return string |
|
* The deprecated message. |
|
*/ |
|
function islandora_deprecated($release, $solution = NULL) { |
|
$bt = debug_backtrace(); |
|
assert($bt[0]['function'] == __FUNCTION__); |
|
$function = $bt[1]['function']; |
|
$message = t('@function() has been deprecated. As of @release, please update your code before the next release.', array( |
|
'@function' => $function, |
|
'@release' => $release, |
|
)); |
|
if (isset($solution)) { |
|
$message .= "<br/>\n" . $solution; |
|
} |
|
return $message; |
|
} |
|
|
|
/** |
|
* Transform recursively-merged array of strings to renderable arrays. |
|
* |
|
* Renderable arrays are passed-through as-is. |
|
* |
|
* Previously, functions/hooks like islandora_view_object would return an |
|
* associative array with string values containing markup. These values were |
|
* then imploded into one large piece of markup. Here, we transform this older |
|
* structure which was generated into a renderable array, because renderable |
|
* arrays are awesome! |
|
* |
|
* @param array $markup_array |
|
* An associative array of which the values are either a string or an array |
|
* of strings, which we transform to renderable markup elements (by |
|
* reference). |
|
*/ |
|
function islandora_as_renderable_array(&$markup_array) { |
|
foreach ($markup_array as &$value) { |
|
if (!is_array($value)) { |
|
// Not a renderable array, just a string. Let's convert it to a |
|
// renderable '#markup' element. |
|
$value = array('#markup' => $value); |
|
} |
|
elseif (!isset($value['#type']) && !isset($value['#markup'])) { |
|
// A simple array--possibly the result of a recursive merge? Let's |
|
// look at each, to possibly convert them to a renderable '#markup' |
|
// elements. |
|
foreach ($value as &$inner) { |
|
if (!is_array($inner)) { |
|
// If it is an array at this level, we can assume that it is a |
|
// renderable array. If it is not an array, convert to a renderable |
|
// '#markup' element. |
|
$inner = array('#markup' => $inner); |
|
} |
|
} |
|
unset($inner); |
|
} |
|
} |
|
unset($value); |
|
} |
|
|
|
/** |
|
* Sanitizes an input string to be valid XML. |
|
* |
|
* @param string $input |
|
* An input string. |
|
* @param string $replacement |
|
* What we are replacing invalid characters with, defaults to ''. |
|
* |
|
* @return string |
|
* The sanitized string. |
|
*/ |
|
function islandora_sanitize_input_for_valid_xml($input, $replacement = '') { |
|
$input = preg_replace('/[^\x9\xA\xD\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u', $replacement, $input); |
|
return $input; |
|
} |
|
|
|
/** |
|
* Page callback for session status messages to be sent to drupal_set_message(). |
|
* |
|
* @return array |
|
* Render array containing markup. |
|
*/ |
|
function islandora_event_status() { |
|
$results = FALSE; |
|
if (isset($_SESSION['islandora_event_messages'])) { |
|
foreach ($_SESSION['islandora_event_messages'] as $message) { |
|
drupal_set_message($message['message'], $message['severity']); |
|
$results = TRUE; |
|
} |
|
unset($_SESSION['islandora_event_messages']); |
|
} |
|
$text = ($results) ? t('The status messages above will be deleted after viewing this page.') : t('No messages to display.'); |
|
return array('#markup' => $text); |
|
} |
|
|
|
/** |
|
* Scales the given image. |
|
* |
|
* @param object $file |
|
* The image file to scale. |
|
* @param int $width |
|
* The width to scale the derived image to. |
|
* @param int $height |
|
* The height to scale the derived image to. |
|
* |
|
* @return bool |
|
* TRUE if successful, FALSE otherwise. |
|
*/ |
|
function islandora_scale_thumbnail($file, $width, $height) { |
|
$real_path = drupal_realpath($file->uri); |
|
$image = image_load($real_path); |
|
try { |
|
if (!empty($image)) { |
|
$scale = image_scale($image, $width, $height, TRUE); |
|
if ($scale) { |
|
return image_save($image); |
|
} |
|
} |
|
} |
|
catch (exception $e) { |
|
drupal_set_message(t( |
|
"Islandora failed to scale image with message: '@message'", |
|
array("@message" => $e->getMessage()))); |
|
watchdog( |
|
'islandora', |
|
'Islandora failed to scale image.<br/> With stack: @trace', |
|
array('@trace' => $e->getTraceAsString()), |
|
WATCHDOG_ERROR |
|
); |
|
} |
|
return FALSE; |
|
} |
|
|
|
/** |
|
* Determines if the server operating system is Windows. |
|
* |
|
* @return bool |
|
* TRUE if Windows, FALSE otherwise. |
|
*/ |
|
function islandora_deployed_on_windows() { |
|
// Determine if PHP is currently running on Windows. |
|
if (strpos(strtolower(php_uname('s')), 'windows') !== FALSE) { |
|
return TRUE; |
|
} |
|
return FALSE; |
|
}
|
|
|