diff --git a/.travis.yml b/.travis.yml index 84b226d0..7107e787 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: php php: - 5.3.3 - 5.4 + - 5.5 branches: only: - /^7.x/ @@ -26,3 +27,5 @@ script: - drush test-run --uri=http://localhost:8081 Islandora after_failure: - $ISLANDORA_DIR/tests/scripts/travis_after_failure.sh +notifications: + irc: "irc.freenode.org#islandora" diff --git a/includes/admin.form.inc b/includes/admin.form.inc index 69f09fd2..42612ea0 100644 --- a/includes/admin.form.inc +++ b/includes/admin.form.inc @@ -61,6 +61,13 @@ function islandora_repository_admin(array $form, array &$form_state) { '#description' => t('HTTP caching can reduce network traffic, by allowing clients to used cached copies.'), '#default_value' => variable_get('islandora_use_datastream_cache_headers', TRUE), ), + 'islandora_defer_derivatives_on_ingest' => array( + '#type' => 'checkbox', + '#title' => t('Defer derivative generation during ingest'), + '#description' => t('Prevent derivatives from running during ingest, + useful if derivatives are to be created by an external service.'), + '#default_value' => variable_get('islandora_defer_derivatives_on_ingest', FALSE), + ), ), 'islandora_namespace' => array( '#type' => 'fieldset', diff --git a/includes/datastream.inc b/includes/datastream.inc index ba2872c2..edc0026b 100644 --- a/includes/datastream.inc +++ b/includes/datastream.inc @@ -30,6 +30,7 @@ function islandora_download_datastream(AbstractDatastream $datastream) { * The version of the datastream to display */ function islandora_view_datastream(AbstractDatastream $datastream, $download = FALSE, $version = NULL) { + module_load_include('inc', 'islandora', 'includes/mimetype.utils'); // XXX: Certain features of the Devel module rely on the use of "shutdown // handlers", such as query logging... The problem is that they might blindly // add additional output which will break things if what is actually being @@ -45,16 +46,13 @@ function islandora_view_datastream(AbstractDatastream $datastream, $download = F return drupal_not_found(); } } - header('Content-type: ' . $datastream->mimetype); if ($datastream->controlGroup == 'M' || $datastream->controlGroup == 'X') { header('Content-length: ' . $datastream->size); } if ($download) { // Browsers will not append all extensions. - $mime_detect = new MimeDetect(); - $extension = '.' . $mime_detect->getExtension($datastream->mimetype); - + $extension = '.' . islandora_get_extension_for_mimetype($datastream->mimetype); // Prevent adding on a duplicate extension. $label = $datastream->label; $extension_length = strlen($extension); @@ -65,7 +63,6 @@ function islandora_view_datastream(AbstractDatastream $datastream, $download = F if ($duplicate_extension_position === FALSE) { $filename .= $extension; } - header("Content-Disposition: attachment; filename=\"$filename\""); } @@ -290,42 +287,6 @@ function islandora_datastream_get_url(AbstractDatastream $datastream, $type = 'd } } -/** - * Gets the delete link. - * - * @param AbstractDatastream $datastream - * The datastream to generated the url to. - * - * @return string - * Markup containing the link to the confirm form to delete the datastream. - */ -function islandora_datastream_get_delete_link(AbstractDatastream $datastream) { - $message = islandora_deprecated('7.x-1.2', 'Use the "islandora_datastream_delete_link" theme implementation.'); - trigger_error(filter_xss($message), E_USER_DEPRECATED); - - return theme('islandora_datastream_delete_link', array( - 'datastream' => $datastream, - )); -} - -/** - * Gets the edit link. - * - * @param AbstractDatastream $datastream - * The datastream to generated the url to. - * - * @return string - * Markup containing the link to edit the datastream. - */ -function islandora_datastream_edit_get_link(AbstractDatastream $datastream) { - $message = islandora_deprecated('7.x-1.2', 'Use the "islandora_datastream_edit_link" theme implementation.'); - trigger_error(filter_xss($message), E_USER_DEPRECATED); - - return theme('islandora_datastream_edit_link', array( - 'datastream' => $datastream, - )); -} - /** * Display the edit datastream page. * @@ -373,44 +334,6 @@ function islandora_edit_datastream_registry_render(array $edit_registry) { ); } -/** - * Get markup for a download link. - * - * @param AbstractDatastream $datastream - * The datastream for which to generate a link. - * - * @return string - * Either the link markup if the user has access or an empty string if the - * user is not allowed to see the given datastream. - */ -function islandora_datastream_get_download_link(AbstractDatastream $datastream) { - $message = islandora_deprecated('7.x-1.2', 'Use the "islandora_datastream_download_link" theme implementation.'); - trigger_error(filter_xss($message), E_USER_DEPRECATED); - - return theme('islandora_datastream_download_link', array( - 'datastream' => $datastream, - )); -} - -/** - * Get markup for a view link. - * - * @param AbstractDatastream $datastream - * The datastream for which to generate a link. - * - * @return string - * Either the link markup if the user has access or a string containing the - * datastream ID if the user is not allowed to see the given datastream. - */ -function islandora_datastream_get_view_link(AbstractDatastream $datastream) { - $message = islandora_deprecated('7.x-1.2', 'Use the "islandora_datastream_view_link" theme implementation.'); - trigger_error(filter_xss($message), E_USER_DEPRECATED); - - return theme('islandora_datastream_view_link', array( - 'datastream' => $datastream, - )); -} - /** * Set the headers for the chunking of our content. * diff --git a/includes/datastream.version.inc b/includes/datastream.version.inc index f245830c..e97640d4 100644 --- a/includes/datastream.version.inc +++ b/includes/datastream.version.inc @@ -275,22 +275,23 @@ function islandora_get_object_extensions(AbstractObject $object) { function islandora_datastream_version_replace_form($form, &$form_state, AbstractDatastream $datastream) { module_load_include('inc', 'islandora', 'includes/content_model'); module_load_include('inc', 'islandora', 'includes/utilities'); + module_load_include('inc', 'islandora', 'includes/mimetype.utils'); $object = islandora_object_load($datastream->parent->id); $form_state['object_id'] = $object->id; $form_state['dsid'] = $datastream->id; $form_state['object'] = $object; - $extensions = islandora_get_object_extensions($object); - $mime_detect = new MimeDetect(); - $ext = array(); - if (isset($extensions[$datastream->id])) { - foreach ($extensions[$datastream->id]['mime'] as $key => $value) { - $str = $mime_detect->getExtension($value); - array_push($ext, $str); - } + $datastream_mime_map = islandora_get_object_extensions($object); + $current_mime = $datastream->mimetype; + $mimes = $datastream_mime_map[$datastream->id]['mime']; + if (!in_array($current_mime, $mimes)) { + $mimes[] = $current_mime; + } + $extensions = array(); + foreach ($mimes as $mime) { + $extensions = array_merge($extensions, islandora_get_extensions_for_mimetype($mime)); } - $comma = count($ext) > 1 ? "," : ""; - $ext = array(implode($comma, $ext)); + $valid_extensions = implode(' ', $extensions); $upload_size = min((int) ini_get('post_max_size'), (int) ini_get('upload_max_filesize')); return array( 'dsid_fieldset' => array( @@ -314,7 +315,7 @@ function islandora_datastream_version_replace_form($form, &$form_state, Abstract '#description' => t('Select a file to upload.
Files must be less than @size MB.', array('@size' => $upload_size)), '#upload_location' => 'temporary://', '#upload_validators' => array( - 'file_validate_extensions' => $ext, + 'file_validate_extensions' => array($valid_extensions), // Assume its specified in MB. 'file_validate_size' => array($upload_size * 1024 * 1024), ), diff --git a/includes/derivatives.inc b/includes/derivatives.inc index 72d61235..7248f03f 100644 --- a/includes/derivatives.inc +++ b/includes/derivatives.inc @@ -4,6 +4,9 @@ * Defines functions used when constructing derivatives. */ +// Relations. +define('ISLANDORA_DEFER_DERIVATIVES_FLAG', 'deferDerivatives'); + /** * Decides which derivative function to call and runs it. * @@ -245,3 +248,39 @@ function islandora_filter_derivatives($hooks, $options, AbstractObject $object) $hooks = array_filter($hooks, $filter_function); return $hooks; } + +/** + * Set the defer derivatives flag on an object. + */ +function islandora_set_defer_derivatives_flag(AbstractObject $object) { + $object->relationships->add( + ISLANDORA_RELS_EXT_URI, + ISLANDORA_DEFER_DERIVATIVES_FLAG, + 'true', + RELS_TYPE_PLAIN_LITERAL + ); +} + +/** + * Get the defer derivatives flag on an object. + */ +function islandora_get_defer_derivatives_flag(AbstractObject $object) { + return $object->relationships->get( + ISLANDORA_RELS_EXT_URI, + ISLANDORA_DEFER_DERIVATIVES_FLAG, + 'true', + RELS_TYPE_PLAIN_LITERAL + ); +} + +/** + * Remove the defer derivatives flag on an object. + */ +function islandora_remove_defer_derivatives_flag(AbstractObject $object) { + $object->relationships->remove( + ISLANDORA_RELS_EXT_URI, + ISLANDORA_DEFER_DERIVATIVES_FLAG, + 'true', + RELS_TYPE_PLAIN_LITERAL + ); +} diff --git a/includes/ingest.form.inc b/includes/ingest.form.inc index f7979063..b5a4740d 100644 --- a/includes/ingest.form.inc +++ b/includes/ingest.form.inc @@ -706,7 +706,11 @@ function islandora_ingest_form_ingest_button(array &$form_state) { $validate_callback = $form_id . '_validate'; $validate = function_exists($validate_callback) ? array($validate_callback) : NULL; $submit_callback = $form_id . '_submit'; - $submit = function_exists($submit_callback) ? array($submit_callback, 'islandora_ingest_form_submit') : array('islandora_ingest_form_submit'); + $submit = function_exists($submit_callback) ? array( + $submit_callback, + 'islandora_ingest_form_pre_submit', + 'islandora_ingest_form_submit', + ) : array('islandora_ingest_form_pre_submit', 'islandora_ingest_form_submit'); return array( '#type' => 'submit', '#name' => 'ingest', diff --git a/includes/mime_detect.inc b/includes/mime_detect.inc index c1be1b92..da2c69f3 100644 --- a/includes/mime_detect.inc +++ b/includes/mime_detect.inc @@ -132,8 +132,8 @@ class MimeDetect { 'wbxml' => 'application/vnd.wap.wbxml', 'xht' => 'application/xhtml+xml', 'xhtml' => 'application/xhtml+xml', - 'xsl' => 'text/xml', - 'xml' => 'text/xml', + 'xsl' => 'text/xsl', + 'xslt' => 'text/xsl', 'csv' => 'text/csv', 'tsv' => 'text/tab-separated-values', 'txt' => 'text/plain', @@ -191,6 +191,8 @@ class MimeDetect { "xyz" => "chemical/x-xyz", // PDB. "pdb" => "chemical/x-pdb", + // ChemDraw CDX. + 'cdx' => 'chemical/x-cdx', // ChemDraw 3D. "c3d" => "chemical/x-chem3d", // ChemDraw file. @@ -202,23 +204,17 @@ class MimeDetect { // GAMESS Input. "inp" => "chemical/x-gamess-input", // GAMESS Output. - "gam" => "chemical/x-gamess-input", - // General output file. - "out" => "application/octet-stream", + "gam" => "chemical/x-gamess-output", // Gaussian Cube. "cub" => "chemical/x-gaussian-cube", // Gaussian 98/03 Cartesian Input. "gau" => "chemical/x-gaussian-input", - // Corel Multimedia Manager v6 Album. - "gal" => "application/octet-stream", // JCAMP Spectroscopic Data Exchange Format. "jdx" => "chemical/x-jcamp-dx", // OpenDX Grid. "dx" => "chemical/x-jcamp-dx", // MOPAC Cartesian. "mop" => "chemical/x-mopac-input", - // General Input File. - "in" => "application/octet-stream", // Compressed formats: // (note: http://svn.cleancode.org/svn/email/trunk/mime.types) "tgz" => "application/x-gzip", @@ -228,6 +224,8 @@ class MimeDetect { "zip" => "application/x-zip", // others: 'bin' => 'application/octet-stream', + // Web Archives: + "warc" => "application/warc", ); protected $protectedFileExtensions; protected $extensionExceptions = array( diff --git a/includes/mimetype.utils.inc b/includes/mimetype.utils.inc new file mode 100644 index 00000000..1a20859d --- /dev/null +++ b/includes/mimetype.utils.inc @@ -0,0 +1,60 @@ + t('Regenerating all derivatives for @label', array('@label' => $object->label)), 'operations' => islandora_do_batch_derivatives($object, array('force' => TRUE)), @@ -117,6 +118,7 @@ function islandora_regenerate_object_derivatives_batch(AbstractObject $object) { */ function islandora_regenerate_datastream_derivative_batch(AbstractDatastream $datastream) { module_load_include('inc', 'islandora', 'includes/derivatives'); + islandora_remove_defer_derivatives_flag($datastream->parent); return array( 'title' => t('Regenerating derivatives for the @dsid datastream', array('@dsid' => $datastream->id)), 'operations' => islandora_do_batch_derivatives($datastream->parent, array( diff --git a/includes/tuque_wrapper.inc b/includes/tuque_wrapper.inc index 573d7c62..2f4ea1df 100644 --- a/includes/tuque_wrapper.inc +++ b/includes/tuque_wrapper.inc @@ -144,6 +144,46 @@ class IslandoraFedoraObject extends FedoraObject { protected $fedoraDatastreamClass = 'IslandoraFedoraDatastream'; protected $fedoraRelsExtClass = 'IslandoraFedoraRelsExt'; + /** + * Magical magic, to allow recursive modifications. + * + * So... Magic functions in PHP are not re-entrant... Meaning that if you + * have something which tries to call __set on an object anywhere later in + * the callstack after it has already been called, it will not call the + * magic method again; instead, it will set the property on the object + * proper. Here, we detect the property being set on the object proper, and + * restore the magic functionality as long as it keeps getting set... + * + * Not necessary to try to account for this in Tuque proper, as Tuque itself + * does not have a mechanism to trigger modifications resulting from other + * modifications. + * + * @param string $name + * The name of the property being set. + * @param mixed $value + * The value to which the property should be set. + */ + public function __set($name, $value) { + parent::__set($name, $value); + + // Recursion only matters for magic properties... "Plain" properties cannot + // call other code in order to start recursing, and in fact we would get + // stuck looping with a "plain" property. + if ($this->propertyIsMagical($name)) { + // XXX: Due to the structure of the code, we cannot use property_exists() + // (because many of the properties are declared in the class, and the + // magic triggers due them being NULLed), nor can we use isset() (because + // it is implemented as another magic function...). + $vars = get_object_vars($this); + while (isset($vars[$name])) { + $new_value = $this->$name; + unset($this->$name); + parent::__set($name, $new_value); + $vars = get_object_vars($this); + } + } + } + /** * Ingest the given datastream. * @@ -173,6 +213,30 @@ class IslandoraFedoraObject extends FedoraObject { throw $e; } } + + /** + * Inherits. + * + * Calls parent and invokes object modified and deleted(/purged) hooks. + * + * @see FedoraObject::modifyObject() + */ + protected function modifyObject($params) { + try { + parent::modifyObject($params); + islandora_invoke_object_hooks(ISLANDORA_OBJECT_MODIFIED_HOOK, $this->models, $this); + if ($this->state == 'D') { + islandora_invoke_object_hooks(ISLANDORA_OBJECT_PURGED_HOOK, $this->models, $this->id); + } + } + catch (Exception $e) { + watchdog('islandora', 'Failed to modify object: @pid
code: @code
message: @msg', array( + '@pid' => $this->id, + '@code' => $e->getCode(), + '@msg' => $e->getMessage()), WATCHDOG_ERROR); + throw $e; + } + } } class IslandoraRepositoryConnection extends RepositoryConnection {} @@ -219,25 +283,10 @@ class IslandoraFedoraApiM extends FedoraApiM { if (isset($params['lastModifiedDate'])) { $params['lastModifiedDate'] = (string) $object[$dsid]->createdDate; } - try { - if ($context['block']) { - throw new Exception('Modify Datastream was blocked.'); - } - $ret = parent::modifyDatastream($pid, $dsid, $params); - islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_MODIFIED_HOOK, $object->models, $dsid, $object, $datastream); - if (isset($params['dsState']) && $params['dsState'] == 'D') { - islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_PURGED_HOOK, $object->models, $dsid, $object, $dsid); - } - return $ret; - } - catch (Exception $e) { - watchdog('islandora', 'Failed to modify datastream @dsid from @pid
code: @code
message: @msg', array( - '@pid' => $pid, - '@dsid' => $dsid, - '@code' => $e->getCode(), - '@msg' => $e->getMessage()), WATCHDOG_ERROR); - throw $e; + if ($context['block']) { + throw new Exception('Modify Datastream was blocked.'); } + return parent::modifyDatastream($pid, $dsid, $params); } /** @@ -254,24 +303,10 @@ class IslandoraFedoraApiM extends FedoraApiM { ); islandora_alter_object($object, $context); $params = $context['params']; - try { - if ($context['block']) { - throw new Exception('Modify Object was blocked.'); - } - $ret = parent::modifyObject($pid, $params); - islandora_invoke_object_hooks(ISLANDORA_OBJECT_MODIFIED_HOOK, $object->models, $object); - if (isset($params['state']) && $params['state'] == 'D') { - islandora_invoke_object_hooks(ISLANDORA_OBJECT_PURGED_HOOK, $object->models, $object->id); - } - return $ret; - } - catch (Exception $e) { - watchdog('islandora', 'Failed to modify object: @pid
code: @code
message: @msg', array( - '@pid' => $pid, - '@code' => $e->getCode(), - '@msg' => $e->getMessage()), WATCHDOG_ERROR); - throw $e; + if ($context['block']) { + throw new Exception('Modify Object was blocked.'); } + return parent::modifyObject($pid, $params); } /** @@ -377,6 +412,71 @@ class IslandoraNewFedoraDatastream extends NewFedoraDatastream { class IslandoraFedoraDatastream extends FedoraDatastream { protected $fedoraRelsIntClass = 'IslandoraFedoraRelsInt'; protected $fedoraDatastreamVersionClass = 'IslandoraFedoraDatastreamVersion'; + + /** + * Magical magic, to allow recursive modifications. + * + * So... Magic functions in PHP are not re-entrant... Meaning that if you + * have something which tries to call __set on an object anywhere later in + * the callstack after it has already been called, it will not call the + * magic method again; instead, it will set the property on the object + * proper. Here, we detect the property being set on the object proper, and + * restore the magic functionality as long as it keeps getting set... + * + * Not necessary to try to account for this in Tuque proper, as Tuque itself + * does not have a mechanism to trigger modifications resulting from other + * modifications. + * + * @param string $name + * The name of the property being set. + * @param mixed $value + * The value to which the property should be set. + */ + public function __set($name, $value) { + parent::__set($name, $value); + + // Recursion only matters for magic properties... "Plain" properties cannot + // call other code in order to start recursing, and in fact we would get + // stuck looping with a "plain" property. + if ($this->propertyIsMagical($name)) { + // XXX: Due to the structure of the code, we cannot use property_exists() + // (because many of the properties are declared in the class, and the + // magic triggers due them being NULLed), nor can we use isset() (because + // it is implemented as another magic function...). + $vars = get_object_vars($this); + while (isset($vars[$name])) { + $new_value = $this->$name; + unset($this->$name); + parent::__set($name, $new_value); + $vars = get_object_vars($this); + } + } + } + + /** + * Inherits. + * + * Calls parent and invokes modified and purged hooks. + * + * @see FedoraDatastream::modifyDatastream() + */ + protected function modifyDatastream(array $args) { + try { + parent::modifyDatastream($args); + islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_MODIFIED_HOOK, $this->parent->models, $this->id, $this->parent, $this); + if ($this->state == 'D') { + islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_PURGED_HOOK, $this->parent->models, $this->id, $this->parent, $this->id); + } + } + catch (Exception $e) { + watchdog('islandora', 'Failed to modify datastream @dsid from @pid
code: @code
message: @msg', array( + '@pid' => $this->parent->id, + '@dsid' => $this->id, + '@code' => $e->getCode(), + '@msg' => $e->getMessage()), WATCHDOG_ERROR); + throw $e; + } + } } class IslandoraFedoraDatastreamVersion extends FedoraDatastreamVersion { diff --git a/includes/utilities.inc b/includes/utilities.inc index fd6c1c3e..26633df5 100644 --- a/includes/utilities.inc +++ b/includes/utilities.inc @@ -30,16 +30,16 @@ function islandora_convert_bytes_to_human_readable($bytes, $precision = 2) { return $bytes . ' B'; } elseif (($bytes >= $kilobyte) && ($bytes < $megabyte)) { - return round($bytes / $kilobyte, $precision) . ' KB'; + return round($bytes / $kilobyte, $precision) . ' KiB'; } elseif (($bytes >= $megabyte) && ($bytes < $gigabyte)) { - return round($bytes / $megabyte, $precision) . ' MB'; + return round($bytes / $megabyte, $precision) . ' MiB'; } elseif (($bytes >= $gigabyte) && ($bytes < $terabyte)) { - return round($bytes / $gigabyte, $precision) . ' GB'; + return round($bytes / $gigabyte, $precision) . ' GiB'; } elseif ($bytes >= $terabyte) { - return round($bytes / $terabyte, $precision) . ' TB'; + return round($bytes / $terabyte, $precision) . ' TiB'; } else { return $bytes . ' B'; @@ -445,8 +445,9 @@ function islandora_get_datastreams_requirements_from_content_model(AbstractObjec /** * Prepare an ingestable object. * - * @param string $namespace - * The namespace in which the PID for the new object will be created. + * @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 @@ -471,10 +472,10 @@ function islandora_get_datastreams_requirements_from_content_model(AbstractObjec * @return NewFedoraObject * An ingestable NewFedoraObject. */ -function islandora_prepare_new_object($namespace = NULL, $label = NULL, $datastreams = array(), $content_models = array(), $relationships = array()) { +function islandora_prepare_new_object($name_source = 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 = 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) { @@ -648,54 +649,6 @@ function islandora_system_settings_form_default_value($name, $default_value, arr 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. * diff --git a/islandora.install b/islandora.install index f37894e9..12c92009 100644 --- a/islandora.install +++ b/islandora.install @@ -46,6 +46,7 @@ function islandora_uninstall() { // Add new variables to clean up. $variables = array( 'islandora_ds_replace_exclude_enforced', + 'islandora_defer_derivatives_on_ingest', ); array_walk($variables, 'variable_del'); } diff --git a/islandora.module b/islandora.module index fd40790b..b692438e 100644 --- a/islandora.module +++ b/islandora.module @@ -142,9 +142,11 @@ function islandora_menu() { 'access arguments' => array(ISLANDORA_VIEW_OBJECTS, 2), ); $items['islandora/object/%islandora_object/print_object'] = array( + 'title' => 'Print Object', + 'weight' => 20, 'page callback' => 'islandora_printer_object', 'page arguments' => array(2), - 'type' => MENU_NORMAL_ITEM, + 'type' => MENU_LOCAL_TASK, 'access callback' => 'islandora_object_access', 'access arguments' => array(ISLANDORA_VIEW_OBJECTS, 2), ); @@ -1024,17 +1026,6 @@ function islandora_view_object(AbstractObject $object) { module_load_include('inc', 'islandora', 'includes/breadcrumb'); module_load_include('inc', 'islandora', 'includes/utilities'); - // Add the print button via JavaScript. - $path = drupal_get_path('module', 'islandora'); - drupal_add_js(array( - 'islandora' => array( - 'print_img' => $path . '/images/print-icon.png'), - ), array( - 'type' => 'setting')); - - drupal_add_js(array('islandora' => array('print_link' => 'islandora/object/' . $object->id . '/print_object')), array('type' => 'setting')); - drupal_add_js($path . '/js/add_print.js'); - drupal_set_title($object->label); drupal_set_breadcrumb(islandora_get_breadcrumbs($object)); @@ -1573,9 +1564,12 @@ function islandora_entity_property_info() { */ function islandora_download_clip(AbstractObject $object) { if (isset($_GET['clip'])) { - $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on'; - $http_protocol = $is_https ? 'https' : 'http'; - $url = $http_protocol . '://' . $_SERVER['HTTP_HOST'] . $_GET['clip']; + $url = $_GET['clip']; + if (!preg_match('/^https?:\/\//', $url)) { + $is_https = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on'; + $http_protocol = $is_https ? 'https' : 'http'; + $url = $http_protocol . '://' . $_SERVER['HTTP_HOST'] . $url; + } $filename = $object->label; header("Content-Disposition: attachment; filename=\"{$filename}.jpg\""); header("Content-type: image/jpeg"); @@ -1599,6 +1593,7 @@ function islandora_download_clip(AbstractObject $object) { function islandora_file_mimetype_mapping_alter(&$mapping) { $mime_detect = new MimeDetect(); $types = $mime_detect->getMimeTypes(); + $diff = array_diff_key($types, $mapping['extensions']); foreach ($diff as $ext => $mime) { $mapping['mimetypes'][] = $mime; @@ -1728,6 +1723,10 @@ function islandora_islandora_basic_collection_get_query_filters() { */ function islandora_islandora_object_ingested(AbstractObject $object) { module_load_include('inc', 'islandora', 'includes/derivatives'); + // Defer derivatives if necessary. + if (islandora_get_defer_derivatives_flag($object)) { + return; + } islandora_run_derivatives($object, NULL); } @@ -1739,6 +1738,10 @@ function islandora_islandora_object_ingested(AbstractObject $object) { */ function islandora_islandora_datastream_ingested(AbstractObject $object, AbstractDatastream $datastream) { module_load_include('inc', 'islandora', 'includes/derivatives'); + // Defer derivatives if necessary. + if (islandora_get_defer_derivatives_flag($object)) { + return; + } islandora_run_derivatives($object, $datastream->id); } @@ -1910,3 +1913,64 @@ function islandora_find_package($package_name) { } return $found && user_access('administer site configuration'); } + +/** + * Helper function for ingest steps and batches. + * + * When batches within batches are triggered within ingest steps + * the submit handler becomes out of scope. When it becomes time to execute the + * submit the function cannot be found and fails. This pre-submit is to + * get around this problem. + * + * @see https://www.drupal.org/node/2300367 + * + * @see https://www.drupal.org/node/1300928 + */ +function islandora_ingest_form_pre_submit($form, &$form_state) { + module_load_include('inc', 'islandora', 'includes/ingest.form'); +} + +/** + * Implements hook_menu_local_tasks_alter(). + */ +function islandora_menu_local_tasks_alter(&$data, $router_item, $root_path) { + if (strpos($root_path, 'islandora/object/%') === 0) { + if (isset($data['tabs'][0]['output'])) { + foreach ($data['tabs'][0]['output'] as $key => &$tab) { + if ($tab['#link']['path'] == 'islandora/object/%/print_object') { + if ($root_path == 'islandora/object/%') { + $islandora_path = drupal_get_path('module', 'islandora'); + $tab['#theme'] = 'link'; + $tab['#text'] = theme('image', array( + 'path' => "$islandora_path/images/print-icon.png", + 'alt' => t('Print Object'), + 'attributes' => array( + 'id' => 'print_btn', + ), + )); + $tab['#path'] = "{$router_item['href']}/print_object"; + $tab['#options'] = array( + 'attributes' => array(), + 'html' => TRUE, + ); + } + else { + unset($data['tabs'][0]['output'][$key]); + break; + } + } + } + } + } +} + +/** + * Implements hook_islandora_object_alter(). + */ +function islandora_islandora_object_alter(AbstractObject $object, array &$context) { + // Prevent derivative creation during ingest if var is set. + if ($context['action'] == 'ingest' && variable_get('islandora_defer_derivatives_on_ingest', FALSE)) { + module_load_include('inc', 'islandora', 'includes/derivatives'); + islandora_set_defer_derivatives_flag($object); + } +} diff --git a/js/add_print.js b/js/add_print.js deleted file mode 100644 index 0059ed88..00000000 --- a/js/add_print.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file -* JavaScript file responsable for the print button behaviour. -* -* The print button is added automatically to every view, as metadata -* can be printed from every object. -* -*/ -(function ($) { - $(document).ready(function() { - $('.tabs .primary').append(''); - $('#print_btn').css("cursor","pointer"); - $('#print_btn').click(function() { - window.location=Drupal.settings.basePath + Drupal.settings.islandora.print_link; - }); - }); -})(jQuery); - diff --git a/tests/hooks.test b/tests/hooks.test index d08c537b..b8846c52 100644 --- a/tests/hooks.test +++ b/tests/hooks.test @@ -109,9 +109,11 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase { $this->repository->ingestObject($object); $_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE; $_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK] = FALSE; + $_SESSION['islandora_hooks']['iteration'][ISLANDORA_OBJECT_MODIFIED_HOOK] = 0; $object->label = "New Label!"; $this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called "hook_islandora_object_alter" when modifying via set magic functions.'); $this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK], 'Called ISLANDORA_OBJECT_MODIFIED_HOOK when modifying via set magic functions.'); + $this->assertEqual('New Label! + 3', $object->label, 'Re-entered ISLANDORA_OBJECT_MODIFIED_HOOK when modifying via set magic functions.'); // Test blocking the modification. try { @@ -191,10 +193,12 @@ class IslandoraHooksTestCase extends IslandoraWebTestCase { $ds = $object->constructDatastream('TEST'); $object->ingestDatastream($ds); $_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE; + $_SESSION['islandora_hooks']['iteration'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = 0; $_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = FALSE; $ds->label = "New Label!"; $this->assert($_SESSION['islandora_hooks']['alter'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called "hook_islandora_datastream_alter" when modifying via set magic functions.'); $this->assert($_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK], 'Called ISLANDORA_DATASTREAM_MODIFIED_HOOK when modifying via set magic functions.'); + $this->assertEqual('New Label! + 3', $ds->label, 'Re-entered ISLANDORA_DATASTREAM_MODIFIED_HOOK when modifying via set magic functions.'); // Test blocking modifying. try { diff --git a/tests/islandora_hooks_test.module b/tests/islandora_hooks_test.module index a6b8a5b6..cceb4dbc 100644 --- a/tests/islandora_hooks_test.module +++ b/tests/islandora_hooks_test.module @@ -112,6 +112,10 @@ function islandora_hooks_test_islandora_object_ingested(AbstractObject $object) function islandora_hooks_test_islandora_object_modified(AbstractObject $object) { if ($object->id == 'test:testModifiedObjectHook') { $_SESSION['islandora_hooks']['hook'][ISLANDORA_OBJECT_MODIFIED_HOOK] = TRUE; + if ($_SESSION['islandora_hooks']['iteration'][ISLANDORA_OBJECT_MODIFIED_HOOK]++ < 3) { + $new_label = 'New Label! + ' . $_SESSION['islandora_hooks']['iteration'][ISLANDORA_OBJECT_MODIFIED_HOOK]; + $object->label = $new_label; + } } } @@ -139,6 +143,10 @@ function islandora_hooks_test_islandora_datastream_ingested(AbstractObject $obje function islandora_hooks_test_islandora_datastream_modified(AbstractObject $object, AbstractDatastream $datastream) { if ($object->id == 'test:testModifiedDatastreamHook' && $datastream->id == "TEST") { $_SESSION['islandora_hooks']['hook'][ISLANDORA_DATASTREAM_MODIFIED_HOOK] = TRUE; + if ($_SESSION['islandora_hooks']['iteration'][ISLANDORA_DATASTREAM_MODIFIED_HOOK]++ < 3) { + $new_label = 'New Label! + ' . $_SESSION['islandora_hooks']['iteration'][ISLANDORA_DATASTREAM_MODIFIED_HOOK]; + $datastream->label = $new_label; + } } } diff --git a/tests/scripts/travis_setup.sh b/tests/scripts/travis_setup.sh index 336087ed..5a8c78ef 100755 --- a/tests/scripts/travis_setup.sh +++ b/tests/scripts/travis_setup.sh @@ -1,14 +1,13 @@ #!/bin/bash - mysql -u root -e 'create database drupal;' mysql -u root -e "create database fedora;" mysql -u root -e "GRANT ALL PRIVILEGES ON fedora.* To 'fedora'@'localhost' IDENTIFIED BY 'fedora';" mysql -u root -e "GRANT ALL PRIVILEGES ON drupal.* To 'drupal'@'localhost' IDENTIFIED BY 'drupal';" cd $HOME git clone git://github.com/Islandora/tuque.git -git clone -b $FEDORA_VERSION git://github.com/Islandora/islandora_tomcat.git +wget http://alpha.library.yorku.ca/islandora_tomcat.$FEDORA_VERSION.tar.gz +tar xf islandora_tomcat.$FEDORA_VERSION.tar.gz cd islandora_tomcat -git fsck export CATALINA_HOME='.' export JAVA_OPTS="-Xms1024m -Xmx1024m -XX:MaxPermSize=512m -XX:+CMSClassUnloadingEnabled -Djavax.net.ssl.trustStore=$CATALINA_HOME/fedora/server/truststore -Djavax.net.ssl.trustStorePassword=tomcat" ./bin/startup.sh @@ -18,29 +17,23 @@ pear upgrade --force Console_Getopt pear upgrade --force pear pear channel-discover pear.drush.org -# "prefer-source" required due to SSL shenanigans on the Travis boxes... -composer global require --prefer-source 'squizlabs/php_codesniffer=*' 'sebastian/phpcpd=*' -# Because we can't add to the PATH here and this file is used in many repos, -# let's just throw symlinks in. -find $HOME/.composer/vendor/bin -executable \! -type d -exec sudo ln -s {} /usr/local/sbin/ \; +wget http://alpha.library.yorku.ca/drush-6.3.tar.gz +tar xf drush-6.3.tar.gz +sudo mv drush-6.3 /opt/ +sudo ln -s /opt/drush-6.3/drush /usr/bin/drush + +wget http://alpha.library.yorku.ca/PHP_CodeSniffer-1.5.4.tgz +pear install PHP_CodeSniffer-1.5.4.tgz -# Install Drush -git clone https://github.com/drush-ops/drush.git -pushd drush -git checkout 5.9.0 -chmod +x drush -popd -sudo ln -s $HOME/drush/drush /usr/local/sbin +wget http://alpha.library.yorku.ca/phpcpd.phar +sudo mv phpcpd.phar /usr/local/bin/phpcpd +sudo chmod +x /usr/local/bin/phpcpd phpenv rehash drush dl --yes drupal cd drupal-* drush si minimal --db-url=mysql://drupal:drupal@localhost/drupal --yes -# Needs to make things from Composer be available (PHP CS, primarily) -sudo chmod a+w sites/default/settings.php -echo "include_once '$HOME/.composer/vendor/autoload.php';" >> sites/default/settings.php -sudo chmod a-w sites/default/settings.php -drush runserver --php-cgi=$HOME/.phpenv/shims/php-cgi localhost:8081 &>/dev/null & +drush runserver --php-cgi=$HOME/.phpenv/shims/php-cgi localhost:8081 &>/tmp/drush_webserver.log & ln -s $ISLANDORA_DIR sites/all/modules/islandora mv sites/all/modules/islandora/tests/travis.test_config.ini sites/all/modules/islandora/tests/test_config.ini mkdir sites/all/libraries diff --git a/theme/islandora-dublin-core-display.tpl.php b/theme/islandora-dublin-core-display.tpl.php index 52c80607..4badc619 100644 --- a/theme/islandora-dublin-core-display.tpl.php +++ b/theme/islandora-dublin-core-display.tpl.php @@ -20,7 +20,7 @@
$value): ?> -
+
diff --git a/theme/theme.inc b/theme/theme.inc index c81a918d..884025b4 100644 --- a/theme/theme.inc +++ b/theme/theme.inc @@ -203,7 +203,6 @@ function theme_islandora_object_print(array &$variables) { * Implements hook_preprocess_theme(). */ function islandora_preprocess_islandora_objects(array &$variables) { - module_load_include('inc', 'islandora_paged_content', 'includes/utilities'); $display = (empty($_GET['display'])) ? 'grid' : $_GET['display']; $grid_display = $display == 'grid'; $list_display = !$grid_display; @@ -276,7 +275,7 @@ function islandora_preprocess_islandora_objects(array &$variables) { */ function theme_islandora_datastream_download_link(array $vars) { $datastream = $vars['datastream']; - module_load_include('inc', 'islandora', 'includes/utilities'); + module_load_include('inc', 'islandora', 'includes/datastream'); $label = t('download'); return islandora_datastream_access(ISLANDORA_VIEW_OBJECTS, $datastream) ?