public function fetchRelatedObjectIdsOfEntity(MySQLi $mySQLi, Entity $otherEntity) { $queryContext = new QueryContext(array(), NULL); $scope = Scope::parseValue(Scope::VALUE_C_REF . Scope::VALUE_A_REF . Scope::VALUE_O_REF); $fetchedObjectIds = array(); if ($otherEntity->isObjectEntity()) { $fetchedObjectRefs = array(); $this->fetchRelatedObjectRefsOfEntity($mySQLi, $otherEntity, $queryContext, $scope, $fetchedObjectRefs); foreach ($fetchedObjectRefs as $fetchedObjectRef) { $fetchedObjectIds[] = $fetchedObjectRef->id; } } else { $fetchedObjectIds[] = 0; } return $fetchedObjectIds; }
public function __construct(Entity $fkEntity, array $fkColumnNameToEntityMap, $ownerEntity) { $this->fkEntity = $fkEntity; $this->fkColumnNames = array(); $this->relatedEntities = array(); if ($fkEntity->isObjectEntity() or count($fkColumnNameToEntityMap) < 2) { $this->relatedEntities[] = $fkEntity; } foreach ($fkColumnNameToEntityMap as $fkColumnName => $toEntity) { $this->fkColumnNames[$toEntity->getId()] = $fkColumnName; $this->relatedEntities[] = $toEntity; } if (count($this->relatedEntities) < 2) { throw new Exception("Cannot create a Relationship between less than two entities."); } if ($ownerEntity != NULL and array_search($ownerEntity, $this->relatedEntities) === FALSE) { throw new Exception("Owner-entity '" . $ownerEntity->getName() . "' must be either NULL, '" . $this->getOneEntity()->getName() . "' or '" . $this->getOtherEntity()->getName() . "'."); } $this->ownerEntity = $ownerEntity; }
private function insertOrUpdate(Schema $schema, Entity $entity, $id, array $propertyValues, Audit $audit) { $mustInsert = $id == NULL; $mySQLi = $schema->getMySQLi(); $entityName = $entity->getName(); $stateIdColumnName = $entity->getStateIdColumnName(); // Create a state object if the given entity supports states. $stateId = NULL; if ($stateIdColumnName != NULL) { $queryString = "INSERT INTO " . DbConstants::TABLE_STATE . " (id_created) VALUES(" . $audit->getId() . ")"; $queryResult = $mySQLi->query($queryString); if (!$queryResult) { throw new Exception("Error creating state for new object of '{$entityName}'" . " - {$mySQLi->error}\n<!--\n{$queryString}\n-->"); } $stateId = $mySQLi->insert_id; // Statefull entities must always be inserted. $mustInsert = TRUE; // If no id was given... if ($id == NULL) { // ...then use the (auto-incremented) stateId as id. $id = $stateId; } } // Prepare the input parameters for the insert-query. $columnNames = array(); $types = ''; $values = array(); // Add the object-id if applicable. if ($entity->isObjectEntity()) { // Ensure that primary key properties are not specified explicitly. foreach ($propertyValues as $propertyName => $value) { if ($entity->getProperty($propertyName)->getKeyIndicator() == Property::KEY_PRIMARY) { throw new Exception("Property '{$propertyName}' of '{$entityName}' is a primary key and cannot be changed."); } } // Add the object-id. $columnNames[] = $entity->getObjectIdColumnName(); $types .= 'i'; $values[] = $id; } // Add the state-info if applicable. if ($stateIdColumnName != NULL) { $columnNames[] = $stateIdColumnName; $types .= 'i'; $values[] = $stateId; } $blobs = array(); foreach ($propertyValues as $columnName => $value) { $property = $entity->getProperty($columnName); $columnNames[] = $property->getName(); $typeIndicator = $property->getTypeIndicator(); switch ($typeIndicator) { case Property::TYPE_TEXT: case Property::TYPE_TIMESTAMP: $types .= 's'; break; case Property::TYPE_BINARY: $types .= 'b'; $blobs[count($values)] = $value; $value = NULL; break; case Property::TYPE_DOUBLE: $types .= 'd'; break; case Property::TYPE_INTEGER: $types .= 'i'; break; default: throw new Exception("Unknown type indicator '{$typeIndicator}'."); } $values[] = $value; } // Compose the query string... $queryString = NULL; if ($mustInsert) { $queryString = "INSERT INTO {$entityName} (" . implode(',', $columnNames) . ") VALUES("; for ($i = 0; $i < count($columnNames); $i++) { $queryString .= '?,'; } // Remove the last comma. $queryString = substr($queryString, 0, strlen($queryString) - 1); $queryString .= ")"; } else { $queryString = "UPDATE {$entityName} SET "; foreach ($columnNames as $columnName) { $queryString .= "{$columnName}=?,"; } // Remove the last comma. $queryString = substr($queryString, 0, strlen($queryString) - 1); if ($entity->isObjectEntity()) { $queryString .= " WHERE " . $entity->getObjectIdColumnName() . " = " . $id; } } // ...and prepare the query. $stmt = $mySQLi->prepare($queryString); if ($stmt === FALSE) { throw new Exception("Error creating prepared statement to insert '{$entityName}' - " . "{$mySQLi->error}\n<!--\n{$queryString}\n-->"); } // Don't throw exceptions before closing the prepared statement. $exception = NULL; // Fill-in the parameters. $bindParams = array(&$types); for ($i = 0; $i < count($values); $i++) { $bindParams[] =& $values[$i]; } call_user_func_array(array($stmt, "bind_param"), $bindParams); foreach ($blobs as $index => $value) { $stmt->send_long_data($index, base64_decode($value)); } // Execute the query. $queryResult = $stmt->execute(); if (!$queryResult) { $formattedPropertyValues = array(); foreach ($propertyValues as $columnName => $value) { $formattedPropertyValues[] = "{$columnName}={$value}"; } $exception = new Exception("Error " . ($mustInsert ? 'inserting' : 'updating') . " object '{$entityName}' - {$mySQLi->error}\n<!-- " . implode(', ', $formattedPropertyValues) . " -->"); } else { if ($id == NULL) { $id = $mySQLi->insert_id; } } // Close the prepared statement before throwing any exception. $stmt->close(); if ($exception != NULL) { throw $exception; } return $id; }