Browse Source

Resolve issue with recursing. Curse you, PHP!

pull/524/head
Adam Vessey 10 years ago
parent
commit
29978b7a1e
  1. 76
      includes/tuque_wrapper.inc
  2. 4
      tests/hooks.test
  3. 8
      tests/islandora_hooks_test.module

76
includes/tuque_wrapper.inc

@ -144,6 +144,41 @@ 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);
// 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.
*
@ -373,6 +408,41 @@ 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);
// 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.
*
@ -383,10 +453,8 @@ class IslandoraFedoraDatastream extends FedoraDatastream {
protected function modifyDatastream(array $args) {
try {
parent::modifyDatastream($args);
// XXX: Reload datastream from parent.
$datastream = $this->parent[$this->id];
islandora_invoke_datastream_hooks(ISLANDORA_DATASTREAM_MODIFIED_HOOK, $this->parent->models, $this->id, $this->parent, $datastream);
if ($datastream->state == 'D') {
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);
}
}

4
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 {

8
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;
}
}
}

Loading…
Cancel
Save