diff --git a/src/Database/Adapter/SQL.php b/src/Database/Adapter/SQL.php index 31bc7e6a3..08e70e790 100644 --- a/src/Database/Adapter/SQL.php +++ b/src/Database/Adapter/SQL.php @@ -393,6 +393,12 @@ public function getDocument(string $collection, string $id, array $queries = [], unset($document['_permissions']); } + $document['main::$permissions'] = json_decode($document['main::$permissions'], true); + + if ($this->sharedTables) { + $document['main::$tenant'] = $document['main::$tenant'] === null ? null : (int)$document['main::$tenant']; + } + return new Document($document); } @@ -1674,6 +1680,32 @@ public function getTenantQuery( return "{$condition} ({$alias}{$dot}_tenant IN ({$bindings}) {$orIsNull})"; } + /** + * Get the SQL projection given the selected attributes + * + * @param array $selects + * @return string + * @throws Exception + */ + protected function addHiddenAttribute(array $selects): string + { + $alias = Query::DEFAULT_ALIAS; + + $strings = []; + + $strings[] = $alias.'._uid as '.$this->quote($alias.'::$id'); + $strings[] = $alias.'._id as '.$this->quote($alias.'::$sequence'); + $strings[] = $alias.'._permissions as '.$this->quote($alias.'::$permissions'); + $strings[] = $alias.'._createdAt as '.$this->quote($alias.'::$createdAt'); + $strings[] = $alias.'._updatedAt as '.$this->quote($alias.'::$updatedAt'); + + if ($this->sharedTables) { + $strings[] = $alias.'._tenant as '.$this->quote($alias.'::$tenant'); + } + + return ', '.implode(', ', $strings); + } + /** * Get the SQL projection given the selected attributes * @@ -1685,28 +1717,17 @@ public function getTenantQuery( protected function getAttributeProjection(array $selections, string $prefix): mixed { if (empty($selections) || \in_array('*', $selections)) { - return "{$this->quote($prefix)}.*"; + return "{$this->quote($prefix)}.* {$this->addHiddenAttribute($selections)}"; } - $internalKeys = [ - '$id', - '$sequence', - '$permissions', - '$createdAt', - '$updatedAt', - ]; - - $selections = \array_diff($selections, [...$internalKeys, '$collection']); - - foreach ($internalKeys as $internalKey) { - $selections[] = $this->getInternalKeyForAttribute($internalKey); - } + $selections = array_diff($selections, ['$collection']); foreach ($selections as &$selection) { + $selection = $this->getInternalKeyForAttribute($selection); $selection = "{$this->quote($prefix)}.{$this->quote($this->filter($selection))}"; } - return \implode(',', $selections); + return \implode(',', $selections).$this->addHiddenAttribute($selections); } protected function getInternalKeyForAttribute(string $attribute): string diff --git a/src/Database/Database.php b/src/Database/Database.php index 6ed45aa99..01e9edd92 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -526,6 +526,25 @@ public function silent(callable $callback, ?array $listeners = null): mixed } } + /** + * Check if attribute is internal + * + * @param string $attribute + * @return bool + */ + public static function isInternalAttribute(string $attribute): bool + { + if (str_contains($attribute, '$')) { + foreach (Database::INTERNAL_ATTRIBUTES as $attr) { + if (str_contains($attribute, $attr['$id'])) { + return true; + } + } + } + + return false; + } + /** * Get getConnection Id * @@ -3277,7 +3296,7 @@ public function getDocument(string $collection, string $id, array $queries = [], if ($collection->getId() !== self::METADATA) { if (!$validator->isValid([ ...$collection->getRead(), - ...($documentSecurity ? $document->getRead() : []) + ...($documentSecurity ? $document->getRead('main::$permissions') : []) ])) { return new Document(); } @@ -3294,17 +3313,17 @@ public function getDocument(string $collection, string $id, array $queries = [], $queries, $forUpdate ); - if ($document->isEmpty()) { return $document; } $document->setAttribute('$collection', $collection->getId()); + $document->setAttribute('main::$collection', $collection->getId()); if ($collection->getId() !== self::METADATA) { if (!$validator->isValid([ ...$collection->getRead(), - ...($documentSecurity ? $document->getRead() : []) + ...($documentSecurity ? $document->getRead('main::$permissions') : []) ])) { return new Document(); } @@ -3335,6 +3354,9 @@ public function getDocument(string $collection, string $id, array $queries = [], $this->trigger(self::EVENT_DOCUMENT_READ, $document); + $document->setAttribute('main::$createdAt', DateTime::formatTz($document->getAttribute('main::$createdAt'))); + $document->setAttribute('main::$updatedAt', DateTime::formatTz($document->getAttribute('main::$updatedAt'))); + return $document; } @@ -3667,6 +3689,16 @@ public function createDocument(string $collection, Document $document): Document $this->trigger(self::EVENT_DOCUMENT_CREATE, $document); + $document->setAttribute('main::$id', $document->getId()); + $document->setAttribute('main::$sequence', $document->getSequence()); + $document->setAttribute('main::$permissions', $document->getPermissions()); + $document->setAttribute('main::$createdAt', $document->getCreatedAt()); + $document->setAttribute('main::$updatedAt', $document->getUpdatedAt()); + $document->setAttribute('main::$collection', $document->getCollection()); + if ($this->adapter->getSharedTables()) { + $document->setAttribute('main::$tenant', $document->getTenant()); + } + return $document; } @@ -3989,7 +4021,7 @@ private function relateDocuments( if ($related->isEmpty()) { // If the related document doesn't exist, create it, inheriting permissions if none are set - if (!isset($relation['$permissions'])) { + if (!isset($relation['$permissions'])) { // todo: Should this be main::$permissions $relation->setAttribute('$permissions', $document->getPermissions()); } @@ -4143,8 +4175,14 @@ public function updateDocument(string $collection, string $id, Document $documen $relationships[$relationship->getAttribute('key')] = $relationship; } + $alias = Query::DEFAULT_ALIAS; + // Compare if the document has any changes foreach ($document as $key => $value) { + if (str_starts_with($key, $alias.'::') && Database::isInternalAttribute($key)){ + continue; + } + // Skip the nested documents as they will be checked later in recursions. if (\array_key_exists($key, $relationships)) { // No need to compare nested documents more than max depth. @@ -4288,6 +4326,16 @@ public function updateDocument(string $collection, string $id, Document $documen $this->trigger(self::EVENT_DOCUMENT_UPDATE, $document); + $document->setAttribute('main::$id', $document->getId()); + $document->setAttribute('main::$sequence', $document->getSequence()); + $document->setAttribute('main::$permissions', $document->getPermissions()); + $document->setAttribute('main::$createdAt', $document->getCreatedAt()); + $document->setAttribute('main::$updatedAt', $document->getUpdatedAt()); + $document->setAttribute('main::$collection', $document->getCollection()); + if ($this->adapter->getSharedTables()) { + $document->setAttribute('main::$tenant', $document->getTenant()); + } + return $document; } @@ -4588,6 +4636,7 @@ private function updateDocumentRelationships(Document $collection, Document $old $related->getId(), $related->setAttribute($twoWayKey, $document->getId()) )); + break; case 'object': if ($value instanceof Document) { @@ -4606,7 +4655,7 @@ private function updateDocumentRelationships(Document $collection, Document $old $this->relationshipWriteStack[] = $relatedCollection->getId(); if ($related->isEmpty()) { - if (!isset($value['$permissions'])) { + if (!isset($value['$permissions'])) {// todo check if should be main::$permissions $value->setAttribute('$permissions', $document->getAttribute('$permissions')); } $related = $this->createDocument( @@ -4695,7 +4744,7 @@ private function updateDocumentRelationships(Document $collection, Document $old ); if ($related->isEmpty()) { - if (!isset($relation['$permissions'])) { + if (!isset($relation['$permissions'])) { // todo check if should be main::$permissions $relation->setAttribute('$permissions', $document->getAttribute('$permissions')); } $this->createDocument( @@ -4735,7 +4784,7 @@ private function updateDocumentRelationships(Document $collection, Document $old ); if ($related->isEmpty()) { - if (!isset($value['$permissions'])) { + if (!isset($value['$permissions'])) { // todo check if should be main::$permissions $value->setAttribute('$permissions', $document->getAttribute('$permissions')); } $this->createDocument( @@ -4808,7 +4857,7 @@ private function updateDocumentRelationships(Document $collection, Document $old $related = $this->getDocument($relatedCollection->getId(), $relation->getId(), [Query::select(['$id'])]); if ($related->isEmpty()) { - if (!isset($value['$permissions'])) { + if (!isset($value['$permissions'])) {// todo check if should be main::$permissions $relation->setAttribute('$permissions', $document->getAttribute('$permissions')); } $related = $this->createDocument( @@ -6085,6 +6134,9 @@ public function find(string $collection, array $queries = [], string $forPermiss if (!$node->isEmpty()) { $node->setAttribute('$collection', $collection->getId()); + $node->setAttribute('main::$collection', $collection->getId()); + $node->setAttribute('main::$createdAt', DateTime::formatTz($node->getAttribute('main::$createdAt'))); + $node->setAttribute('main::$updatedAt', DateTime::formatTz($node->getAttribute('main::$updatedAt'))); } } @@ -6298,6 +6350,21 @@ public static function addFilter(string $name, callable $encode, callable $decod */ public function encode(Document $collection, Document $document): Document { + /** + * When iterating over an ArrayObject, foreach uses an internal iterator (like Iterator), and modifying the object during iteration doesn’t affect the iterator immediately. + */ + $keysToRemove = []; + + foreach ($document as $key => $value) { + if (strpos($key, '::$') !== false) { + $keysToRemove[] = $key; + } + } + + foreach ($keysToRemove as $key) { + unset($document[$key]); + } + $attributes = $collection->getAttribute('attributes', []); $internalAttributes = \array_filter(Database::INTERNAL_ATTRIBUTES, function ($attribute) { @@ -6586,12 +6653,12 @@ private function validateSelections(Document $collection, array $queries): array $selections = \array_merge($selections, $relationshipSelections); - $selections[] = '$id'; - $selections[] = '$sequence'; - $selections[] = '$collection'; - $selections[] = '$createdAt'; - $selections[] = '$updatedAt'; - $selections[] = '$permissions'; +// $selections[] = '$id'; +// $selections[] = '$sequence'; +// $selections[] = '$collection'; +// $selections[] = '$createdAt'; +// $selections[] = '$updatedAt'; +// $selections[] = '$permissions'; return \array_values(\array_unique($selections)); } diff --git a/src/Database/Document.php b/src/Database/Document.php index 2ed634f46..a8819cf25 100644 --- a/src/Database/Document.php +++ b/src/Database/Document.php @@ -80,17 +80,17 @@ public function getCollection(): string /** * @return array */ - public function getPermissions(): array + public function getPermissions(string $attribute = '$permissions'): array { - return \array_values(\array_unique($this->getAttribute('$permissions', []))); + return \array_values(\array_unique($this->getAttribute($attribute, []))); } /** * @return array */ - public function getRead(): array + public function getRead(string $attribute = '$permissions'): array { - return $this->getPermissionsByType(Database::PERMISSION_READ); + return $this->getPermissionsByType(Database::PERMISSION_READ, $attribute); } /** @@ -132,11 +132,11 @@ public function getWrite(): array /** * @return array */ - public function getPermissionsByType(string $type): array + public function getPermissionsByType(string $type, string $attribute = '$permissions'): array { $typePermissions = []; - foreach ($this->getPermissions() as $permission) { + foreach ($this->getPermissions($attribute) as $permission) { if (!\str_starts_with($permission, $type)) { continue; } @@ -183,13 +183,8 @@ public function getAttributes(): array { $attributes = []; - $internalKeys = \array_map( - fn ($attr) => $attr['$id'], - Database::INTERNAL_ATTRIBUTES - ); - foreach ($this as $attribute => $value) { - if (\in_array($attribute, $internalKeys)) { + if (Database::isInternalAttribute($attribute)){ continue; } diff --git a/tests/e2e/Adapter/Scopes/DocumentTests.php b/tests/e2e/Adapter/Scopes/DocumentTests.php index 3fdbb87d7..51d1deb29 100644 --- a/tests/e2e/Adapter/Scopes/DocumentTests.php +++ b/tests/e2e/Adapter/Scopes/DocumentTests.php @@ -743,6 +743,7 @@ public function testUpsertDocumentsAttributeMismatch(): void ]); $this->assertEquals(1, $docs); + $this->assertEquals('first', $existingDocument->getAttribute('first')); $this->assertEquals(null, $existingDocument->getAttribute('last')); $this->assertEquals('second', $newDocument->getAttribute('first')); @@ -1128,26 +1129,38 @@ public function testGetDocumentSelect(Document $document): Document $this->assertArrayNotHasKey('boolean', $document->getAttributes()); $this->assertArrayNotHasKey('colors', $document->getAttributes()); $this->assertArrayNotHasKey('with-dash', $document->getAttributes()); - $this->assertArrayHasKey('$id', $document); - $this->assertArrayHasKey('$sequence', $document); - $this->assertArrayHasKey('$createdAt', $document); - $this->assertArrayHasKey('$updatedAt', $document); - $this->assertArrayHasKey('$permissions', $document); - $this->assertArrayHasKey('$collection', $document); + $this->assertArrayNotHasKey('$id', $document); + $this->assertArrayNotHasKey('$sequence', $document); + $this->assertArrayNotHasKey('$createdAt', $document); + $this->assertArrayNotHasKey('$updatedAt', $document); + $this->assertArrayNotHasKey('$permissions', $document); + //$this->assertArrayNotHasKey('$collection', $document); + $this->assertArrayHasKey('main::$id', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); + $this->assertArrayHasKey('main::$collection', $document); $document = $database->getDocument('documents', $documentId, [ Query::select(['string', 'integer_signed', '$id']), ]); - $this->assertArrayHasKey('$id', $document); - $this->assertArrayHasKey('$sequence', $document); - $this->assertArrayHasKey('$createdAt', $document); - $this->assertArrayHasKey('$updatedAt', $document); - $this->assertArrayHasKey('$permissions', $document); - $this->assertArrayHasKey('$collection', $document); $this->assertArrayHasKey('string', $document); $this->assertArrayHasKey('integer_signed', $document); + $this->assertArrayHasKey('$id', $document); + $this->assertArrayNotHasKey('$sequence', $document); + $this->assertArrayNotHasKey('$createdAt', $document); + $this->assertArrayNotHasKey('$updatedAt', $document); + $this->assertArrayNotHasKey('$permissions', $document); + //$this->assertArrayNotHasKey('$collection', $document); $this->assertArrayNotHasKey('float', $document); + $this->assertArrayHasKey('main::$id', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); + $this->assertArrayHasKey('main::$collection', $document); return $document; } @@ -2805,12 +2818,18 @@ public function testFindSelect(): void $this->assertArrayNotHasKey('director', $document); $this->assertArrayNotHasKey('price', $document); $this->assertArrayNotHasKey('active', $document); - $this->assertArrayHasKey('$id', $document); - $this->assertArrayHasKey('$sequence', $document); - $this->assertArrayHasKey('$collection', $document); - $this->assertArrayHasKey('$createdAt', $document); - $this->assertArrayHasKey('$updatedAt', $document); - $this->assertArrayHasKey('$permissions', $document); + $this->assertArrayNotHasKey('$id', $document); + $this->assertArrayNotHasKey('$sequence', $document); + //$this->assertArrayNotHasKey('$collection', $document); + $this->assertArrayNotHasKey('$createdAt', $document); + $this->assertArrayNotHasKey('$updatedAt', $document); + $this->assertArrayNotHasKey('$permissions', $document); + $this->assertArrayHasKey('main::$id', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$collection', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); } $documents = $database->find('movies', [ @@ -2824,11 +2843,17 @@ public function testFindSelect(): void $this->assertArrayNotHasKey('price', $document); $this->assertArrayNotHasKey('active', $document); $this->assertArrayHasKey('$id', $document); - $this->assertArrayHasKey('$sequence', $document); - $this->assertArrayHasKey('$collection', $document); - $this->assertArrayHasKey('$createdAt', $document); - $this->assertArrayHasKey('$updatedAt', $document); - $this->assertArrayHasKey('$permissions', $document); + $this->assertArrayNotHasKey('$sequence', $document); + //$this->assertArrayNotHasKey('$collection', $document); + $this->assertArrayNotHasKey('$createdAt', $document); + $this->assertArrayNotHasKey('$updatedAt', $document); + $this->assertArrayNotHasKey('$permissions', $document); + $this->assertArrayHasKey('main::$id', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$collection', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); } $documents = $database->find('movies', [ @@ -2841,12 +2866,18 @@ public function testFindSelect(): void $this->assertArrayNotHasKey('director', $document); $this->assertArrayNotHasKey('price', $document); $this->assertArrayNotHasKey('active', $document); - $this->assertArrayHasKey('$id', $document); + $this->assertArrayNotHasKey('$id', $document); $this->assertArrayHasKey('$sequence', $document); - $this->assertArrayHasKey('$collection', $document); - $this->assertArrayHasKey('$createdAt', $document); - $this->assertArrayHasKey('$updatedAt', $document); - $this->assertArrayHasKey('$permissions', $document); + //$this->assertArrayNotHasKey('$collection', $document); + $this->assertArrayNotHasKey('$createdAt', $document); + $this->assertArrayNotHasKey('$updatedAt', $document); + $this->assertArrayNotHasKey('$permissions', $document); + $this->assertArrayHasKey('main::$id', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$collection', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); } $documents = $database->find('movies', [ @@ -2859,12 +2890,17 @@ public function testFindSelect(): void $this->assertArrayNotHasKey('director', $document); $this->assertArrayNotHasKey('price', $document); $this->assertArrayNotHasKey('active', $document); - $this->assertArrayHasKey('$id', $document); - $this->assertArrayHasKey('$sequence', $document); + $this->assertArrayNotHasKey('$id', $document); + $this->assertArrayNotHasKey('$sequence', $document); $this->assertArrayHasKey('$collection', $document); - $this->assertArrayHasKey('$createdAt', $document); - $this->assertArrayHasKey('$updatedAt', $document); - $this->assertArrayHasKey('$permissions', $document); + $this->assertArrayNotHasKey('$createdAt', $document); + $this->assertArrayNotHasKey('$updatedAt', $document); + $this->assertArrayNotHasKey('$permissions', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$collection', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); } $documents = $database->find('movies', [ @@ -2877,12 +2913,17 @@ public function testFindSelect(): void $this->assertArrayNotHasKey('director', $document); $this->assertArrayNotHasKey('price', $document); $this->assertArrayNotHasKey('active', $document); - $this->assertArrayHasKey('$id', $document); - $this->assertArrayHasKey('$sequence', $document); - $this->assertArrayHasKey('$collection', $document); + $this->assertArrayNotHasKey('$id', $document); + $this->assertArrayNotHasKey('$sequence', $document); + // $this->assertArrayNotHasKey('$collection', $document); $this->assertArrayHasKey('$createdAt', $document); - $this->assertArrayHasKey('$updatedAt', $document); - $this->assertArrayHasKey('$permissions', $document); + $this->assertArrayNotHasKey('$updatedAt', $document); + $this->assertArrayNotHasKey('$permissions', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$collection', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); } $documents = $database->find('movies', [ @@ -2895,12 +2936,17 @@ public function testFindSelect(): void $this->assertArrayNotHasKey('director', $document); $this->assertArrayNotHasKey('price', $document); $this->assertArrayNotHasKey('active', $document); - $this->assertArrayHasKey('$id', $document); - $this->assertArrayHasKey('$sequence', $document); - $this->assertArrayHasKey('$collection', $document); - $this->assertArrayHasKey('$createdAt', $document); + $this->assertArrayNotHasKey('$id', $document); + $this->assertArrayNotHasKey('$sequence', $document); + // $this->assertArrayNotHasKey('$collection', $document); + $this->assertArrayNotHasKey('$createdAt', $document); $this->assertArrayHasKey('$updatedAt', $document); - $this->assertArrayHasKey('$permissions', $document); + $this->assertArrayNotHasKey('$permissions', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$collection', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); } $documents = $database->find('movies', [ @@ -2913,12 +2959,17 @@ public function testFindSelect(): void $this->assertArrayNotHasKey('director', $document); $this->assertArrayNotHasKey('price', $document); $this->assertArrayNotHasKey('active', $document); - $this->assertArrayHasKey('$id', $document); - $this->assertArrayHasKey('$sequence', $document); - $this->assertArrayHasKey('$collection', $document); - $this->assertArrayHasKey('$createdAt', $document); - $this->assertArrayHasKey('$updatedAt', $document); + $this->assertArrayNotHasKey('$id', $document); + $this->assertArrayNotHasKey('$sequence', $document); + //$this->assertArrayNotHasKey('$collection', $document); + $this->assertArrayNotHasKey('$createdAt', $document); + $this->assertArrayNotHasKey('$updatedAt', $document); $this->assertArrayHasKey('$permissions', $document); + $this->assertArrayHasKey('main::$sequence', $document); + $this->assertArrayHasKey('main::$collection', $document); + $this->assertArrayHasKey('main::$createdAt', $document); + $this->assertArrayHasKey('main::$updatedAt', $document); + $this->assertArrayHasKey('main::$permissions', $document); } } diff --git a/tests/e2e/Adapter/Scopes/RelationshipTests.php b/tests/e2e/Adapter/Scopes/RelationshipTests.php index f7623db49..cb0482055 100644 --- a/tests/e2e/Adapter/Scopes/RelationshipTests.php +++ b/tests/e2e/Adapter/Scopes/RelationshipTests.php @@ -969,7 +969,7 @@ public function testSelectRelationshipAttributes(): void // Select some parent attributes, some child attributes $make = $database->findOne('make', [ - Query::select(['name', 'models.name']), + Query::select(['name', 'models.name', '*']), ]); if ($make->isEmpty()) { @@ -988,6 +988,11 @@ public function testSelectRelationshipAttributes(): void $this->assertArrayHasKey('$collection', $make); $this->assertArrayHasKey('$createdAt', $make); $this->assertArrayHasKey('$updatedAt', $make); + $this->assertArrayHasKey('main::$id', $make); + $this->assertArrayHasKey('main::$sequence', $make); + $this->assertArrayHasKey('main::$collection', $make); + $this->assertArrayHasKey('main::$createdAt', $make); + $this->assertArrayHasKey('main::$updatedAt', $make); // Select internal attributes $make = $database->findOne('make', [ @@ -1000,11 +1005,16 @@ public function testSelectRelationshipAttributes(): void $this->assertArrayHasKey('name', $make); $this->assertArrayHasKey('$id', $make); - $this->assertArrayHasKey('$sequence', $make); - $this->assertArrayHasKey('$collection', $make); - $this->assertArrayHasKey('$createdAt', $make); - $this->assertArrayHasKey('$updatedAt', $make); - $this->assertArrayHasKey('$permissions', $make); + $this->assertArrayNotHasKey('$sequence', $make); + //$this->assertArrayNotHasKey('$collection', $make); + $this->assertArrayNotHasKey('$createdAt', $make); + $this->assertArrayNotHasKey('$updatedAt', $make); + $this->assertArrayNotHasKey('$permissions', $make); + $this->assertArrayHasKey('main::$id', $make); + $this->assertArrayHasKey('main::$sequence', $make); + $this->assertArrayHasKey('main::$collection', $make); + $this->assertArrayHasKey('main::$createdAt', $make); + $this->assertArrayHasKey('main::$updatedAt', $make); $make = $database->findOne('make', [ Query::select(['name', '$sequence']), @@ -1015,12 +1025,17 @@ public function testSelectRelationshipAttributes(): void } $this->assertArrayHasKey('name', $make); - $this->assertArrayHasKey('$id', $make); + $this->assertArrayNotHasKey('$id', $make); $this->assertArrayHasKey('$sequence', $make); - $this->assertArrayHasKey('$collection', $make); - $this->assertArrayHasKey('$createdAt', $make); - $this->assertArrayHasKey('$updatedAt', $make); - $this->assertArrayHasKey('$permissions', $make); + //$this->assertArrayHasKey('$collection', $make); + $this->assertArrayNotHasKey('$createdAt', $make); + $this->assertArrayNotHasKey('$updatedAt', $make); + $this->assertArrayNotHasKey('$permissions', $make); + $this->assertArrayHasKey('main::$id', $make); + $this->assertArrayHasKey('main::$sequence', $make); + $this->assertArrayHasKey('main::$collection', $make); + $this->assertArrayHasKey('main::$createdAt', $make); + $this->assertArrayHasKey('main::$updatedAt', $make); $make = $database->findOne('make', [ Query::select(['name', '$collection']), @@ -1031,12 +1046,17 @@ public function testSelectRelationshipAttributes(): void } $this->assertArrayHasKey('name', $make); - $this->assertArrayHasKey('$id', $make); - $this->assertArrayHasKey('$sequence', $make); + $this->assertArrayNotHasKey('$id', $make); + $this->assertArrayNotHasKey('$sequence', $make); $this->assertArrayHasKey('$collection', $make); - $this->assertArrayHasKey('$createdAt', $make); - $this->assertArrayHasKey('$updatedAt', $make); - $this->assertArrayHasKey('$permissions', $make); + $this->assertArrayNotHasKey('$createdAt', $make); + $this->assertArrayNotHasKey('$updatedAt', $make); + $this->assertArrayNotHasKey('$permissions', $make); + $this->assertArrayHasKey('main::$id', $make); + $this->assertArrayHasKey('main::$sequence', $make); + $this->assertArrayHasKey('main::$collection', $make); + $this->assertArrayHasKey('main::$createdAt', $make); + $this->assertArrayHasKey('main::$updatedAt', $make); $make = $database->findOne('make', [ Query::select(['name', '$createdAt']), @@ -1047,12 +1067,17 @@ public function testSelectRelationshipAttributes(): void } $this->assertArrayHasKey('name', $make); - $this->assertArrayHasKey('$id', $make); - $this->assertArrayHasKey('$sequence', $make); - $this->assertArrayHasKey('$collection', $make); + $this->assertArrayNotHasKey('$id', $make); + $this->assertArrayNotHasKey('$sequence', $make); + //$this->assertArrayHasKey('$collection', $make); $this->assertArrayHasKey('$createdAt', $make); - $this->assertArrayHasKey('$updatedAt', $make); - $this->assertArrayHasKey('$permissions', $make); + $this->assertArrayNotHasKey('$updatedAt', $make); + $this->assertArrayNotHasKey('$permissions', $make); + $this->assertArrayHasKey('main::$id', $make); + $this->assertArrayHasKey('main::$sequence', $make); + $this->assertArrayHasKey('main::$collection', $make); + $this->assertArrayHasKey('main::$createdAt', $make); + $this->assertArrayHasKey('main::$updatedAt', $make); $make = $database->findOne('make', [ Query::select(['name', '$updatedAt']), @@ -1063,12 +1088,17 @@ public function testSelectRelationshipAttributes(): void } $this->assertArrayHasKey('name', $make); - $this->assertArrayHasKey('$id', $make); - $this->assertArrayHasKey('$sequence', $make); - $this->assertArrayHasKey('$collection', $make); - $this->assertArrayHasKey('$createdAt', $make); + $this->assertArrayNotHasKey('$id', $make); + $this->assertArrayNotHasKey('$sequence', $make); + //$this->assertArrayHasKey('$collection', $make); + $this->assertArrayNotHasKey('$createdAt', $make); $this->assertArrayHasKey('$updatedAt', $make); - $this->assertArrayHasKey('$permissions', $make); + $this->assertArrayNotHasKey('$permissions', $make); + $this->assertArrayHasKey('main::$id', $make); + $this->assertArrayHasKey('main::$sequence', $make); + $this->assertArrayHasKey('main::$collection', $make); + $this->assertArrayHasKey('main::$createdAt', $make); + $this->assertArrayHasKey('main::$updatedAt', $make); $make = $database->findOne('make', [ Query::select(['name', '$permissions']), @@ -1079,12 +1109,17 @@ public function testSelectRelationshipAttributes(): void } $this->assertArrayHasKey('name', $make); - $this->assertArrayHasKey('$id', $make); - $this->assertArrayHasKey('$sequence', $make); - $this->assertArrayHasKey('$collection', $make); - $this->assertArrayHasKey('$createdAt', $make); - $this->assertArrayHasKey('$updatedAt', $make); + $this->assertArrayNotHasKey('$id', $make); + $this->assertArrayNotHasKey('$sequence', $make); + // $this->assertArrayHasKey('$collection', $make); + $this->assertArrayNotHasKey('$createdAt', $make); + $this->assertArrayNotHasKey('$updatedAt', $make); $this->assertArrayHasKey('$permissions', $make); + $this->assertArrayHasKey('main::$id', $make); + $this->assertArrayHasKey('main::$sequence', $make); + $this->assertArrayHasKey('main::$collection', $make); + $this->assertArrayHasKey('main::$createdAt', $make); + $this->assertArrayHasKey('main::$updatedAt', $make); // Select all parent attributes, some child attributes $make = $database->findOne('make', [