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