/** * {@inheritdoc} */ protected function doSave($id, EntityInterface $entity) { $bundle = $entity->bundle(); // Generate an ID before saving, if none is available. If the ID generation // occurs earlier in the process (like on EntityInterface::create()), the // entity might be considered not new by modules that don't strictly use the // EntityInterface::isNew() method. if (empty($id)) { $id = $this->generateId(); $entity->{$this->idKey} = (string) $id; } // If the target graph is set, it has priority over the one the entity is // loaded from. If no target graph is set, use the previous one. $target_graph = $this->getGraphHandler()->getTargetGraphFromEntity($entity); $graph_uri = $this->getBundleGraphUri($bundle, $target_graph); $insert = ''; $properties = $this->mappingHandler->getEntityTypeMappedProperties($entity); $subj = '<' . (string) $id . '>'; $properties_list = "<" . implode(">, <", $properties['flat']) . ">"; foreach ($entity->toArray() as $field_name => $field) { foreach ($field as $field_item) { foreach ($field_item as $column => $value) { if (!isset($properties['by_field'][$field_name][$column])) { continue; } $pred = '<' . (string) $properties['by_field'][$field_name][$column] . '>'; if (!filter_var($value, FILTER_VALIDATE_URL) === FALSE) { $obj = '<' . $value . '>'; } else { // @todo This is most probably prone to Sparql injection..! $obj = '"""' . $value . '"""'; } $insert .= $subj . ' ' . $pred . ' ' . $obj . ' .' . "\n"; } } } // Save the bundle. $rdf_bundle_mapping = $this->mappingHandler->getRdfBundleMappedUri($entity->getEntityType()->getBundleEntityType(), $entity->bundle()); $rdf_bundle = $rdf_bundle_mapping[$entity->bundle()]; $insert .= $subj . ' ' . $this->rdfBundlePredicate . ' <' . $rdf_bundle . '> .' . "\n"; $query = <<<QUERY DELETE { GRAPH <{$graph_uri}> { <{$id}> ?field ?value } } WHERE { GRAPH <{$graph_uri}> { <{$id}> ?field ?value . FILTER (?field IN ({$properties_list})) } } QUERY; if (!$entity->isNew()) { $this->sparql->query($query); } // @todo Do in one transaction... If possible. $query = "INSERT DATA INTO <{$graph_uri}> {\n" . $insert . "\n" . '}'; $this->sparql->query($query); }
/** * {@inheritdoc} */ public function condition($property, $value = NULL, $operator = '=', $langcode = NULL) { $key = $property . '-' . $operator; $field_storage_definitions = \Drupal::service('entity.manager')->getFieldStorageDefinitions($this->entityTypeId); /* * Ok, so what is all this: * We need to convert our conditions into some sparql compatible conditions. */ $bundle = $this->entityType->getKey('bundle'); $id = $this->entityType->getKey('id'); $label = $this->entityType->getKey('label'); switch ($key) { // @todo Limit the graphs here to the set bundles. case $bundle . '-IN': $rdf_bundles = $this->mappingHandler->getBundleUriList($this->entityType->getBundleEntityType(), $value); if ($rdf_bundles) { $this->condition->condition('?entity', '?bundlepredicate', '?type'); $this->filterAdded = TRUE; $predicates = "(<" . implode(">, <", $this->entityStorage->bundlePredicate()) . ">)"; $this->filter->filter('?bundlepredicate IN ' . $predicates); $this->filter->filter('?type IN ' . $rdf_bundles); } return $this; case $bundle . '-=': $mapping = $this->mappingHandler->getRdfBundleMappedUri($this->entityType->getBundleEntityType(), $value); $bundle = $mapping[$value]; if ($bundle) { $this->condition->condition('?entity', '?bundlepredicate', SparqlArg::uri($bundle)); $predicates = "(<" . implode(">, <", $this->entityStorage->bundlePredicate()) . ">)"; $this->filter->filter('?bundlepredicate IN ' . $predicates); $this->filterAdded = TRUE; } return $this; case $id . '-IN': if ($value) { $ids_list = "(<" . implode(">, <", $value) . ">)"; if (!$this->filterAdded) { $this->condition->condition('?entity', '?bundlepredicate', '?type'); $predicates = "(<" . implode(">, <", $this->entityStorage->bundlePredicate()) . ">)"; $this->filter->filter('?bundlepredicate IN ' . $predicates); $this->filterAdded = TRUE; } $this->filter->filter('?entity IN ' . $ids_list); } return $this; case $id . '-NOT IN': case $id . '-<>': if ($value) { if (is_array($value)) { $ids_list = "(<" . implode(">, <", $value) . ">)"; } else { $ids_list = "(<" . $value . ">)"; } if (!$this->filterAdded) { $this->condition->condition('?entity', '?bundlepredicate', '?type'); $predicates = "(<" . implode(">, <", $this->entityStorage->bundlePredicate()) . ">)"; $this->filter->filter('?bundlepredicate IN ' . $predicates); $this->filterAdded = TRUE; } $this->filter->filter('!(?entity IN ' . $ids_list . ')'); } return $this; case $id . '-=': if (!$value) { return $this; } $id = '<' . $value . '>'; if (!$this->filterAdded) { $this->condition->condition('?entity', '?bundlepredicate', '?type'); $predicates = "(<" . implode(">, <", $this->entityStorage->bundlePredicate()) . ">)"; $this->filter->filter('?bundlepredicate IN ' . $predicates); $this->filterAdded = TRUE; } $this->filter->filter('?entity IN ' . SparqlArg::literal($id)); break; case $label . '-=': preg_match('/\\((.*?)\\)/', $value, $matches); $matching = array_pop($matches); if ($matching) { $ids = "(<{$matching}>)"; $this->filter->filter('?entity IN ' . $ids); } else { if (file_valid_uri($value)) { $ids = "(<{$value}>)"; $this->filter->filter('?entity IN ' . $ids); } else { $mapping = $this->mappingHandler->getEntityTypeLabelPredicates($this->entityTypeId); $label_list = "(<" . implode(">, <", array_unique(array_keys($mapping))) . ">)"; $this->condition->condition('?entity', '?label_type', '?label'); $this->filter->filter('?label_type IN ' . $label_list); $this->filter->filter('str(?label) = "' . $value . '"'); } } return $this; case $label . '-CONTAINS': $mapping = $this->mappingHandler->getEntityTypeLabelPredicates($this->entityTypeId); $label_list = "(<" . implode(">, <", array_unique(array_keys($mapping))) . ">)"; $this->condition->condition('?entity', '?label_type', '?label'); $this->filter->filter('?label_type IN ' . $label_list); if ($value) { $this->filter->filter('regex(?label, "' . $value . '", "i")'); $this->filter->filter('(lang(?label) = "" || langMatches(lang(?label), "EN"))'); } return $this; case '_field_exists-EXISTS': case '_field_exists-NOT EXISTS': $field_rdf_name = $this->getFieldRdfPropertyName($value, $field_storage_definitions); if (!UrlHelper::isValid($field_rdf_name, TRUE) === FALSE) { $field_rdf_name = SparqlArg::uri($field_rdf_name); } if ($field_rdf_name) { $this->filter('?entity ' . $field_rdf_name . ' ?c', 'FILTER ' . $operator); } return $this; } if ($operator == '=') { if (!$value) { return $this; } // @todo this code will be handled in ISAICP-2631 if (strpos($property, '.') !== FALSE) { list($field_name, $column) = explode('.', $property); } else { $field_name = $property; } $field_rdf_name = $this->getFieldRdfPropertyName($field_name, $field_storage_definitions); if (!UrlHelper::isValid($value, TRUE) === FALSE) { $value = SparqlArg::uri($value); } else { $value = SparqlArg::literal($value); } $this->condition->condition('?entity', SparqlArg::uri($field_rdf_name), $value); } return $this; }