<?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) . ' KiB';
}
elseif (($bytes >= $megabyte) & & ($bytes < $gigabyte)) {
return round($bytes / $megabyte, $precision) . ' MiB';
}
elseif (($bytes >= $gigabyte) & & ($bytes < $terabyte)) {
return round($bytes / $gigabyte, $precision) . ' GiB';
}
elseif ($bytes >= $terabyte) {
return round($bytes / $terabyte, $precision) . ' TiB';
}
else {
return $bytes . ' B';
}
}
/**
* Add a file as managed if is not already.
*
* @param string $file_uri
* The given file URI location.
*
* @return object
* The file, as returned from file_save().
*/
function islandora_temp_file_entry($file_uri, $mime = NULL) {
$query = new EntityFieldQuery();
$result = $query
->entityCondition('entity_type', 'file')
->propertyCondition('uri', $file_uri)
->execute();
if (isset($result['file'])) {
$fid = current($result['file'])->fid;
$file = file_load($fid);
}
else {
$file = new stdClass();
$file->uri = $file_uri;
$file->filename = drupal_basename($file_uri);
if (isset($mime)) {
$file->filemime = $mime;
}
else {
$file->filemime = file_get_mimetype($file_uri);
}
}
$file->status = 0;
return 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 '< strong > M< / strong > anaged';
case 'X':
return 'Inline < strong > X< / strong > ML';
case 'R':
return '< strong > R< / strong > edirect';
case 'E':
return '< strong > E< / strong > 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;
}
/**
Created hooks and implemented them as part of the tuque wrapper classes.
hook_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_CMODEL_PID_DSID_islandora_datastream_altezr(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_islandora_object_ingested(FedoraObject $object)
hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object)
hook_islandora_object_modified(FedoraObject $object)
hook_CMODEL_PID_islandora_object_modified(FedoraObject $object)
hook_islandora_object_purged($pid)
hook_CMODEL_PID_islandora_object_purged($pid)
hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_purged(FedoraObject $object, $dsid)
hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid)
Also updated the testing scripts to support different configurations, as well
wrote tests for all the implemented hooks. This requires the latest version
of Tuque so be sure to update.
12 years ago
* 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().
*
* @param string $hook
* A hook to call.
Created hooks and implemented them as part of the tuque wrapper classes.
hook_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_CMODEL_PID_DSID_islandora_datastream_altezr(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_islandora_object_ingested(FedoraObject $object)
hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object)
hook_islandora_object_modified(FedoraObject $object)
hook_CMODEL_PID_islandora_object_modified(FedoraObject $object)
hook_islandora_object_purged($pid)
hook_CMODEL_PID_islandora_object_purged($pid)
hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_purged(FedoraObject $object, $dsid)
hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid)
Also updated the testing scripts to support different configurations, as well
wrote tests for all the implemented hooks. This requires the latest version
of Tuque so be sure to update.
12 years ago
* @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
Created hooks and implemented them as part of the tuque wrapper classes.
hook_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_CMODEL_PID_DSID_islandora_datastream_altezr(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_islandora_object_ingested(FedoraObject $object)
hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object)
hook_islandora_object_modified(FedoraObject $object)
hook_CMODEL_PID_islandora_object_modified(FedoraObject $object)
hook_islandora_object_purged($pid)
hook_CMODEL_PID_islandora_object_purged($pid)
hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_purged(FedoraObject $object, $dsid)
hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid)
Also updated the testing scripts to support different configurations, as well
wrote tests for all the implemented hooks. This requires the latest version
of Tuque so be sure to update.
12 years ago
* The merged results from all the hooks.
*
* @see islandora_build_hook_list()
*/
Created hooks and implemented them as part of the tuque wrapper classes.
hook_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_CMODEL_PID_DSID_islandora_datastream_altezr(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_islandora_object_ingested(FedoraObject $object)
hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object)
hook_islandora_object_modified(FedoraObject $object)
hook_CMODEL_PID_islandora_object_modified(FedoraObject $object)
hook_islandora_object_purged($pid)
hook_CMODEL_PID_islandora_object_purged($pid)
hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_purged(FedoraObject $object, $dsid)
hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid)
Also updated the testing scripts to support different configurations, as well
wrote tests for all the implemented hooks. This requires the latest version
of Tuque so be sure to update.
12 years ago
function islandora_invoke_hook_list($hook, array $refinements, array $args) {
$return = array();
foreach (islandora_build_hook_list($hook, $refinements) as $refined_hook) {
array_unshift($args, $refined_hook);
Created hooks and implemented them as part of the tuque wrapper classes.
hook_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_CMODEL_PID_DSID_islandora_datastream_altezr(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_islandora_object_ingested(FedoraObject $object)
hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object)
hook_islandora_object_modified(FedoraObject $object)
hook_CMODEL_PID_islandora_object_modified(FedoraObject $object)
hook_islandora_object_purged($pid)
hook_CMODEL_PID_islandora_object_purged($pid)
hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_purged(FedoraObject $object, $dsid)
hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid)
Also updated the testing scripts to support different configurations, as well
wrote tests for all the implemented hooks. This requires the latest version
of Tuque so be sure to update.
12 years ago
$result = call_user_func_array('module_invoke_all', $args);
$return = array_merge_recursive($return, $result);
array_shift($args);
}
if (module_exists('rules')) {
$event_info = rules_get_event_info($hook);
if (isset($event_info['module'])) {
$parameters = $event_info['variables'];
$rule_args = array_slice($args, 0, count($parameters));
array_unshift($rule_args, $hook);
$result = call_user_func_array('rules_invoke_event', $rule_args);
}
}
Created hooks and implemented them as part of the tuque wrapper classes.
hook_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_CMODEL_PID_DSID_islandora_datastream_altezr(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_islandora_object_ingested(FedoraObject $object)
hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object)
hook_islandora_object_modified(FedoraObject $object)
hook_CMODEL_PID_islandora_object_modified(FedoraObject $object)
hook_islandora_object_purged($pid)
hook_CMODEL_PID_islandora_object_purged($pid)
hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_purged(FedoraObject $object, $dsid)
hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid)
Also updated the testing scripts to support different configurations, as well
wrote tests for all the implemented hooks. This requires the latest version
of Tuque so be sure to update.
12 years ago
return $return;
}
Created hooks and implemented them as part of the tuque wrapper classes.
hook_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_CMODEL_PID_DSID_islandora_datastream_altezr(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_islandora_object_ingested(FedoraObject $object)
hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object)
hook_islandora_object_modified(FedoraObject $object)
hook_CMODEL_PID_islandora_object_modified(FedoraObject $object)
hook_islandora_object_purged($pid)
hook_CMODEL_PID_islandora_object_purged($pid)
hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_purged(FedoraObject $object, $dsid)
hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid)
Also updated the testing scripts to support different configurations, as well
wrote tests for all the implemented hooks. This requires the latest version
of Tuque so be sure to update.
12 years ago
/**
* 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, array $refinements = array()) {
Created hooks and implemented them as part of the tuque wrapper classes.
hook_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_CMODEL_PID_islandora_object_alter(AbstractFedoraObject $object, array &$context)
hook_islandora_datastream_alter(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_CMODEL_PID_DSID_islandora_datastream_altezr(AbstractFedoraObject $object, AbstractFedoraDatastream $datastream, array &$context)
hook_islandora_object_ingested(FedoraObject $object)
hook_CMODEL_PID_islandora_object_ingested(FedoraObject $object)
hook_islandora_object_modified(FedoraObject $object)
hook_CMODEL_PID_islandora_object_modified(FedoraObject $object)
hook_islandora_object_purged($pid)
hook_CMODEL_PID_islandora_object_purged($pid)
hook_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_DSID_islandora_datastream_ingested(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_CMODEL_PID_islandora_datastream_modified(FedoraObject $object, FedoraDatastream $datastream)
hook_islandora_datastream_purged(FedoraObject $object, $dsid)
hook_CMODEL_PID_islandora_datastream_purged(FedoraObject $object, $dsid)
Also updated the testing scripts to support different configurations, as well
wrote tests for all the implemented hooks. This requires the latest version
of Tuque so be sure to update.
12 years ago
$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 $name_source
* Either a pid or 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($name_source = NULL,
$label = NULL,
array $datastreams = array(),
array $content_models = array(),
array $relationships = array()) {
global $user;
$tuque = islandora_get_tuque_connection();
$object = isset($name_source) ? $tuque->repository->constructObject($name_source) : 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);
}
/**
* 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, array $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(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;
}
/**
* Build the edit registry for a given datastream.
*
* @param AbstractDatastream $datastream
* The datastream being edited.
*
* @return array
* The built edit registry array.
*/
function islandora_build_datastream_edit_registry(AbstractDatastream $datastream) {
$edit_registry = module_invoke_all(ISLANDORA_EDIT_DATASTREAM_REGISTRY_HOOK, $datastream->parent, $datastream);
$context = array(
'object' => $datastream->parent,
'datastream' => $datastream,
'original_edit_registry' => $edit_registry,
);
drupal_alter(ISLANDORA_EDIT_DATASTREAM_REGISTRY_HOOK, $edit_registry, $context);
return $edit_registry;
}