diff --git a/.scripts/travis_setup.sh b/.scripts/travis_setup.sh index 3123d11f..61a75be1 100755 --- a/.scripts/travis_setup.sh +++ b/.scripts/travis_setup.sh @@ -3,16 +3,16 @@ mysql -u root -e 'create database drupal;' mysql -u root -e "GRANT ALL PRIVILEGES ON drupal.* To 'drupal'@'localhost' IDENTIFIED BY 'drupal';" # Java (Oracle) -sudo apt-get install -y software-properties-common -sudo apt-get install -y python-software-properties -sudo add-apt-repository -y ppa:webupd8team/java -sudo apt-get update -echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections -echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections -sudo apt-get install -y oracle-java8-installer -sudo update-java-alternatives -s java-8-oracle -sudo apt-get install -y oracle-java8-set-default -export JAVA_HOME=/usr/lib/jvm/java-8-oracle +#sudo apt-get install -y software-properties-common +#sudo apt-get install -y python-software-properties +#sudo add-apt-repository -y ppa:webupd8team/java +#sudo apt-get update +#echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections +#echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections +#sudo apt-get install -y oracle-java8-installer +#sudo update-java-alternatives -s java-8-oracle +#sudo apt-get install -y oracle-java8-set-default +#export JAVA_HOME=/usr/lib/jvm/java-8-oracle # phpcpd #sudo apt-get install -y phpcpd @@ -46,6 +46,7 @@ drush en -y syslog drush en -y serialization drush en -y basic_auth drush en -y rest +drush en -y simpletest drush dl rdfui --dev drush en -y rdfui @@ -71,6 +72,8 @@ cd $HOME/drupal/modules git clone https://github.com/DiegoPino/claw-jsonld.git drush en -y jsonld +drush en -y islandora + drush -y dl bootstrap drush -y en bootstrap drush -y config-set system.theme default bootstrap diff --git a/.travis.yml b/.travis.yml index b3d2ddec..5948f67c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,15 +20,17 @@ before_install: - export ISLANDORA_DIR=$TRAVIS_BUILD_DIR install: -# - $TRAVIS_BUILD_DIR/tests/scripts/travis_setup.sh + - $TRAVIS_BUILD_DIR/.scripts/travis_setup.sh - composer install - php vendor/bin/phpcs --config-set installed_paths vendor/drupal/coder/coder_sniffer script: - $ISLANDORA_DIR/.scripts/line_endings.sh . + - cd $HOME/drupal/modules/islandora - php vendor/bin/phpcs --standard=Drupal **/*.module **/*.php --ignore=tests,vendor . - php vendor/bin/phpcpd --names *.module,*.inc,*.test,*.php --exclude=vendor . + - cd $HOME/drupal; php core/scripts/run-tests.sh --php `which php` islandora notifications: irc: diff --git a/islandora/config/install/rdf.mapping.fedora_resource_type.rdf_source.yml b/islandora/config/install/rdf.mapping.fedora_resource_type.rdf_source.yml index c26306a1..6697ebc7 100644 --- a/islandora/config/install/rdf.mapping.fedora_resource_type.rdf_source.yml +++ b/islandora/config/install/rdf.mapping.fedora_resource_type.rdf_source.yml @@ -6,7 +6,7 @@ dependencies: module: - islandora id: fedora_resource_type.rdf_source -targetEntityType: fedora_resource_type +targetEntityType: fedora_resource bundle: rdf_source types: - 'schema:Thing' @@ -30,7 +30,18 @@ fieldMappings: rdf_type: properties: - 'rdf:type' + vclock: + properties: + - 'islandora:vclock' uid: properties: - 'schema:author' mapping_type: rel + fedora_has_parent: + properties: + - 'fedora:hasParent' + mapping_type: rel + ldp_contains: + properties: + - 'ldp:contains' + mapping_type: rel diff --git a/islandora/islandora.module b/islandora/islandora.module index ac28cddc..7250ef53 100644 --- a/islandora/islandora.module +++ b/islandora/islandora.module @@ -80,5 +80,6 @@ function islandora_rdf_namespaces() { 'owl' => 'http://www.w3.org/2002/07/owl#', 'ore' => 'http://www.openarchives.org/ore/terms/', 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', + 'islandora' => 'http://islandora.ca/CLAW/', ); } diff --git a/islandora/islandora.services.yml b/islandora/islandora.services.yml index 938de6ed..d1a94b40 100644 --- a/islandora/islandora.services.yml +++ b/islandora/islandora.services.yml @@ -6,3 +6,5 @@ services: tags: - { name: paramconverter } arguments: ['@entity.manager'] + islandora.eventgenerator: + class: Drupal\islandora\EventGenerator\EventGenerator diff --git a/islandora/src/Entity/FedoraResource.php b/islandora/src/Entity/FedoraResource.php index 7ae84542..ac59060a 100644 --- a/islandora/src/Entity/FedoraResource.php +++ b/islandora/src/Entity/FedoraResource.php @@ -121,6 +121,18 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac ); } + /** + * {@inheritdoc} + */ + public function preSave(EntityStorageInterface $storage) { + parent::preSave($storage); + + // Increment the vclock. + if (!$this->isNew()) { + $this->set("vclock", $this->get("vclock")->value + 1); + } + } + /** * {@inheritdoc} */ @@ -261,6 +273,13 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac return array('root'); } + /** + * {@inheritdoc} + */ + public function getVclock() { + return $this->get('vclock')->value; + } + /** * {@inheritdoc} */ @@ -283,6 +302,11 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac ->setLabel(t('UUID')) ->setDescription(t('The UUID of the Fedora resource entity.')) ->setReadOnly(TRUE); + $fields['vclock'] = BaseFieldDefinition::create('integer') + ->setLabel(t('Vector Clock')) + ->setDescription(t('Simple accumulator used for causality tracking')) + ->setDefaultValue(0) + ->setSetting('unsigned', TRUE); $fields['user_id'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Authored by')) @@ -340,7 +364,7 @@ class FedoraResource extends ContentEntityBase implements FedoraResourceInterfac ->setLabel(t('LDP Contains')) ->setDescription(t('Contains Fedora Resource.')) ->setRevisionable(TRUE) - ->setSetting('target_type', 'fedora_resource_type') + ->setSetting('target_type', 'fedora_resource') ->setSetting('handler', 'default') ->setTranslatable(TRUE) ->setDisplayOptions('view', array( diff --git a/islandora/src/EventGenerator/EventGenerator.php b/islandora/src/EventGenerator/EventGenerator.php new file mode 100644 index 00000000..e0463277 --- /dev/null +++ b/islandora/src/EventGenerator/EventGenerator.php @@ -0,0 +1,60 @@ + "https://www.w3.org/ns/activitystreams", + "type" => "Create", + "actor" => [ + "type" => "Person", + "id" => $user->toUrl()->setAbsolute()->toString(), + ], + "object" => $entity->toUrl()->setAbsolute()->toString(), + ]); + } + + /** + * {@inheritdoc} + */ + public function generateUpdateEvent(EntityInterface $entity, UserInterface $user) { + return json_encode([ + "@context" => "https://www.w3.org/ns/activitystreams", + "type" => "Update", + "actor" => [ + "type" => "Person", + "id" => $user->toUrl()->setAbsolute()->toString(), + ], + "object" => $entity->toUrl()->setAbsolute()->toString(), + ]); + } + + /** + * {@inheritdoc} + */ + public function generateDeleteEvent(EntityInterface $entity, UserInterface $user) { + return json_encode([ + "@context" => "https://www.w3.org/ns/activitystreams", + "type" => "Delete", + "actor" => [ + "type" => "Person", + "id" => $user->toUrl()->setAbsolute()->toString(), + ], + "object" => $entity->toUrl()->setAbsolute()->toString(), + ]); + } + +} diff --git a/islandora/src/EventGenerator/EventGeneratorInterface.php b/islandora/src/EventGenerator/EventGeneratorInterface.php new file mode 100644 index 00000000..766e1389 --- /dev/null +++ b/islandora/src/EventGenerator/EventGeneratorInterface.php @@ -0,0 +1,52 @@ +user = $this->drupalCreateUser(); + + // Create a test entity. + $this->entity = FedoraResource::create([ + "type" => "rdf_source", + "uid" => 1, + "name" => "Test Fixture", + "langcode" => "und", + "status" => 1, + ]); + $this->entity->save(); + + // Create the event generator so we can test it. + $this->eventGenerator = new EventGenerator(); + } + + /** + * Tests the generateCreateEvent() method. + */ + public function testGenerateCreateEvent() { + $json = $this->eventGenerator->generateCreateEvent($this->entity, $this->user); + $msg = json_decode($json, TRUE); + + $this->assertBasicStructure($msg); + $this->assertTrue($msg["type"] == "Create", "Event type is 'Create'."); + } + + /** + * Tests the generateUpdateEvent() method. + */ + public function testGenerateUpdateEvent() { + $json = $this->eventGenerator->generateUpdateEvent($this->entity, $this->user); + $msg = json_decode($json, TRUE); + + $this->assertBasicStructure($msg); + $this->assertTrue($msg["type"] == "Update", "Event type is 'Update'."); + } + + /** + * Tests the generateDeleteEvent() method. + */ + public function testGenerateDeleteEvent() { + $json = $this->eventGenerator->generateDeleteEvent($this->entity, $this->user); + $msg = json_decode($json, TRUE); + + $this->assertBasicStructure($msg); + $this->assertTrue($msg["type"] == "Delete", "Event type is 'Delete'."); + + } + + /** + * Util function for repeated checks. + * + * @param array $msg + * The message parsed as an array. + */ + protected function assertBasicStructure(array $msg) { + // Looking for @context. + $this->assertTrue(array_key_exists('@context', $msg), "Context key exists"); + $this->assertTrue($msg["@context"] == "https://www.w3.org/ns/activitystreams", "Context is activity stream."); + + // Make sure it has a type. + $this->assertTrue(array_key_exists('type', $msg), "Type key exists"); + + // Make sure the actor exists, is a person, and has a uri. + $this->assertTrue(array_key_exists('actor', $msg), "Actor key exists"); + $this->assertTrue(array_key_exists("type", $msg["actor"]), "Type key exists for actor."); + $this->assertTrue($msg["actor"]["type"] == "Person", "Actor is a person."); + $this->assertTrue(array_key_exists("id", $msg["actor"]), "Id key exists for actor."); + $this->assertTrue($msg["actor"]["id"] == $this->user->toUrl()->setAbsolute()->toString(), "Id is user's uri"); + + // Make sure the object exists and is a uri. + $this->assertTrue(array_key_exists('object', $msg), "Object key exists"); + $this->assertTrue($msg["object"] == $this->entity->toUrl()->setAbsolute()->toString(), "Object is entity uri."); + } + +} diff --git a/islandora/tests/src/Kernel/IslandoraKernelTestBase.php b/islandora/tests/src/Kernel/IslandoraKernelTestBase.php new file mode 100644 index 00000000..fb5932ab --- /dev/null +++ b/islandora/tests/src/Kernel/IslandoraKernelTestBase.php @@ -0,0 +1,48 @@ +installSchema('system', 'sequences'); + $this->installEntitySchema('user'); + $this->installConfig('filter'); + $this->installEntitySchema('fedora_resource'); + } + +} + diff --git a/islandora/tests/src/Kernel/VectorClockTest.php b/islandora/tests/src/Kernel/VectorClockTest.php new file mode 100644 index 00000000..c73df8ee --- /dev/null +++ b/islandora/tests/src/Kernel/VectorClockTest.php @@ -0,0 +1,54 @@ +entity = FedoraResource::create([ + "type" => "rdf_source", + "uid" => 1, + "name" => "Test Fixture", + "langcode" => "und", + "status" => 1, + ]); + $this->entity->save(); + + } + + /** + * Tests the basic behavior of the vector clock. + */ + public function testVectorClock() { + // Check the vclock is set to 0 when a new entity is created. + $this->assertTrue($this->entity->getVclock() == 0, "Vector clock initialized to zero."); + + // Edit the entity. + $this->entity->setName("Edited Test Fixture")->save(); + + // Check the vclock is incremented when the entity is updated. + $this->assertTrue($this->entity->getVclock() == 1, "Vector clock incremented on update."); + } + +} diff --git a/islandora_collection/config/install/field.field.fedora_resource.collection.field_description.yml b/islandora_collection/config/install/field.field.fedora_resource.collection.field_description.yml index 65faeb0b..4ddacfb7 100644 --- a/islandora_collection/config/install/field.field.fedora_resource.collection.field_description.yml +++ b/islandora_collection/config/install/field.field.fedora_resource.collection.field_description.yml @@ -7,8 +7,6 @@ dependencies: enforced: module: - islandora_collection - module: - - text id: fedora_resource.collection.field_description field_name: field_description entity_type: fedora_resource @@ -19,7 +17,5 @@ required: false translatable: false default_value: { } default_value_callback: '' -settings: - display_summary: false -field_type: text_with_summary - +settings: { } +field_type: string_long diff --git a/islandora_collection/config/install/field.storage.fedora_resource.field_description.yml b/islandora_collection/config/install/field.storage.fedora_resource.field_description.yml index e32f1bec..f3a05483 100644 --- a/islandora_collection/config/install/field.storage.fedora_resource.field_description.yml +++ b/islandora_collection/config/install/field.storage.fedora_resource.field_description.yml @@ -3,16 +3,16 @@ status: true dependencies: module: - islandora - - text enforced: module: - islandora_collection id: fedora_resource.field_description field_name: field_description entity_type: fedora_resource -type: text_with_summary -settings: { } -module: text +type: string_long +settings: + case_sensitive: false +module: core locked: false cardinality: 1 translatable: true diff --git a/islandora_collection/config/install/rdf.mapping.fedora_resource_type.collection.yml b/islandora_collection/config/install/rdf.mapping.fedora_resource_type.collection.yml index ace1ee0f..d2e102bc 100644 --- a/islandora_collection/config/install/rdf.mapping.fedora_resource_type.collection.yml +++ b/islandora_collection/config/install/rdf.mapping.fedora_resource_type.collection.yml @@ -34,6 +34,12 @@ fieldMappings: - 'schema:dateModified' datatype_callback: callable: 'Drupal\rdf\CommonDataConverter::dateIso8601Value' + rdf_type: + properties: + - 'rdf:type' + vclock: + properties: + - 'islandora:vclock' uid: properties: - 'schema:author'