Skip to content

Commit b4aa578

Browse files
authored
Merge branch 'main' into feat-_deletedAt-attr
2 parents 4792316 + bbeaf38 commit b4aa578

120 files changed

Lines changed: 60352 additions & 8346 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/claude.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Claude
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, ready_for_review, reopened]
6+
pull_request_review:
7+
types: [submitted]
8+
issue_comment:
9+
types: [created]
10+
pull_request_review_comment:
11+
types: [created]
12+
issues:
13+
types: [opened, assigned]
14+
workflow_run:
15+
workflows: [Tests]
16+
types: [completed]
17+
18+
jobs:
19+
claude:
20+
# Caller must grant the union of every permission the callee's jobs ask
21+
# for; reusable workflows can't exceed the caller's ceiling.
22+
permissions:
23+
contents: write
24+
pull-requests: write
25+
issues: write
26+
actions: read
27+
id-token: write
28+
uses: abnegate/claude-pr-owner/.github/workflows/orchestrator.yml@7138fd26ee7317ac1f05001eafeb41d371ba58a6 # v0.6.0
29+
secrets:
30+
oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
31+
# PAT with `contents: write` on this repo. Without this, commits pushed
32+
# by the consolidator (authenticated with GITHUB_TOKEN) do not trigger
33+
# workflow_run/synchronize events, so Tests/CodeQL/Linter stay dormant
34+
# on Claude's fixes.
35+
push_token: ${{ secrets.CLAUDE_PUSH_TOKEN }}
36+
with:
37+
improvement: true
38+
healing: true
39+
bots: true
40+
comments: true

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ jobs:
88

99
steps:
1010
- name: Checkout repository
11-
uses: actions/checkout@v4
11+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1212
with:
1313
fetch-depth: 2
1414

1515
- run: git checkout HEAD^2
1616

1717
- name: Run CodeQL
1818
run: |
19-
docker run --rm -v $PWD:/app composer sh -c \
19+
docker run --rm -v $PWD:/app -w /app phpswoole/swoole:5.1.8-php8.3-alpine sh -c \
2020
"composer install --profile --ignore-platform-reqs && composer check"

.github/workflows/linter.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ jobs:
88

99
steps:
1010
- name: Checkout repository
11-
uses: actions/checkout@v4
11+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
1212
with:
1313
fetch-depth: 2
1414

1515
- run: git checkout HEAD^2
1616

1717
- name: Run Linter
1818
run: |
19-
docker run --rm -v $PWD:/app composer sh -c \
19+
docker run --rm -v $PWD:/app -w /app phpswoole/swoole:5.1.8-php8.3-alpine sh -c \
2020
"composer install --profile --ignore-platform-reqs && composer lint"

.github/workflows/tests.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ jobs:
1616
runs-on: ubuntu-latest
1717
steps:
1818
- name: Checkout repository
19-
uses: actions/checkout@v4
19+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2020

2121
- name: Set up Docker Buildx
22-
uses: docker/setup-buildx-action@v3
22+
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
2323

2424
- name: Build Docker Image
25-
uses: docker/build-push-action@v3
25+
uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1
2626
with:
2727
context: .
2828
push: false
@@ -33,7 +33,7 @@ jobs:
3333
outputs: type=docker,dest=/tmp/${{ env.IMAGE }}.tar
3434

3535
- name: Cache Docker Image
36-
uses: actions/cache@v3
36+
uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3.5.0
3737
with:
3838
key: ${{ env.CACHE_KEY }}
3939
path: /tmp/${{ env.IMAGE }}.tar
@@ -45,10 +45,10 @@ jobs:
4545

4646
steps:
4747
- name: checkout
48-
uses: actions/checkout@v4
48+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
4949

5050
- name: Load Cache
51-
uses: actions/cache@v3
51+
uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3.5.0
5252
with:
5353
key: ${{ env.CACHE_KEY }}
5454
path: /tmp/${{ env.IMAGE }}.tar
@@ -57,8 +57,7 @@ jobs:
5757
- name: Load and Start Services
5858
run: |
5959
docker load --input /tmp/${{ env.IMAGE }}.tar
60-
docker compose up -d
61-
sleep 10
60+
docker compose up -d --wait
6261
6362
- name: Run Unit Tests
6463
run: docker compose exec tests vendor/bin/phpunit /usr/src/code/tests/unit
@@ -72,24 +71,27 @@ jobs:
7271
matrix:
7372
adapter:
7473
[
74+
MongoDB,
7575
MariaDB,
7676
MySQL,
7777
Postgres,
7878
SQLite,
7979
Mirror,
8080
Pool,
81+
SharedTables/MongoDB,
8182
SharedTables/MariaDB,
8283
SharedTables/MySQL,
8384
SharedTables/Postgres,
8485
SharedTables/SQLite,
86+
Schemaless/MongoDB,
8587
]
8688

8789
steps:
8890
- name: checkout
89-
uses: actions/checkout@v4
91+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
9092

9193
- name: Load Cache
92-
uses: actions/cache@v3
94+
uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c # v3.5.0
9395
with:
9496
key: ${{ env.CACHE_KEY }}
9597
path: /tmp/${{ env.IMAGE }}.tar
@@ -98,9 +100,7 @@ jobs:
98100
- name: Load and Start Services
99101
run: |
100102
docker load --input /tmp/${{ env.IMAGE }}.tar
101-
docker compose up -d
102-
sleep 10
103+
docker compose up -d --wait
103104
104105
- name: Run Tests
105106
run: docker compose exec -T tests vendor/bin/phpunit /usr/src/code/tests/e2e/Adapter/${{matrix.adapter}}Test.php --debug
106-

Dockerfile

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,17 @@ RUN composer install \
1212
--no-scripts \
1313
--prefer-dist
1414

15-
FROM php:8.3.19-cli-alpine3.21 AS compile
16-
17-
ENV PHP_REDIS_VERSION="6.0.2" \
18-
PHP_SWOOLE_VERSION="v5.1.7" \
19-
PHP_XDEBUG_VERSION="3.4.2"
15+
FROM php:8.4.18-cli-alpine3.22 AS compile
2016

17+
ENV PHP_REDIS_VERSION="6.3.0" \
18+
PHP_SWOOLE_VERSION="v6.1.6" \
19+
PHP_XDEBUG_VERSION="3.4.2" \
20+
PHP_MONGODB_VERSION="2.1.1"
2121
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
2222

23-
RUN \
24-
apk update \
25-
&& apk add --no-cache \
26-
postgresql-libs \
27-
postgresql-dev \
23+
RUN apk update && apk add --no-cache \
24+
libpq \
25+
libpq-dev \
2826
make \
2927
automake \
3028
autoconf \
@@ -35,9 +33,20 @@ RUN \
3533
linux-headers \
3634
docker-cli \
3735
docker-cli-compose \
38-
&& docker-php-ext-install opcache pgsql pdo_mysql pdo_pgsql \
39-
&& apk del postgresql-dev \
40-
&& rm -rf /var/cache/apk/*
36+
&& (pecl install mongodb-$PHP_MONGODB_VERSION \
37+
|| (git clone --depth 1 --branch $PHP_MONGODB_VERSION --recurse-submodules https://github.com/mongodb/mongo-php-driver.git /tmp/mongodb \
38+
&& cd /tmp/mongodb \
39+
&& git submodule update --init --recursive \
40+
&& phpize \
41+
&& ./configure \
42+
&& make \
43+
&& make install \
44+
&& cd / \
45+
&& rm -rf /tmp/mongodb)) \
46+
&& docker-php-ext-enable mongodb \
47+
&& docker-php-ext-install opcache pgsql pdo_mysql pdo_pgsql \
48+
&& apk del libpq-dev \
49+
&& rm -rf /var/cache/apk/*
4150

4251
# Redis Extension
4352
FROM compile AS redis
@@ -96,10 +105,10 @@ RUN echo "opcache.enable_cli=1" >> $PHP_INI_DIR/php.ini
96105
RUN echo "memory_limit=1024M" >> $PHP_INI_DIR/php.ini
97106

98107
COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor
99-
COPY --from=swoole /usr/local/lib/php/extensions/no-debug-non-zts-20230831/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
100-
COPY --from=redis /usr/local/lib/php/extensions/no-debug-non-zts-20230831/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
101-
COPY --from=pcov /usr/local/lib/php/extensions/no-debug-non-zts-20230831/pcov.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
102-
COPY --from=xdebug /usr/local/lib/php/extensions/no-debug-non-zts-20230831/xdebug.so /usr/local/lib/php/extensions/no-debug-non-zts-20230831/
108+
COPY --from=swoole /usr/local/lib/php/extensions/no-debug-non-zts-20240924/swoole.so /usr/local/lib/php/extensions/no-debug-non-zts-20240924/
109+
COPY --from=redis /usr/local/lib/php/extensions/no-debug-non-zts-20240924/redis.so /usr/local/lib/php/extensions/no-debug-non-zts-20240924/
110+
COPY --from=pcov /usr/local/lib/php/extensions/no-debug-non-zts-20240924/pcov.so /usr/local/lib/php/extensions/no-debug-non-zts-20240924/
111+
COPY --from=xdebug /usr/local/lib/php/extensions/no-debug-non-zts-20240924/xdebug.so /usr/local/lib/php/extensions/no-debug-non-zts-20240924/
103112

104113
COPY ./bin /usr/src/code/bin
105114
COPY ./src /usr/src/code/src
@@ -109,6 +118,6 @@ COPY ./dev /usr/src/code/dev
109118
RUN if [ "$DEBUG" = "true" ]; then cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini; fi
110119
RUN if [ "$DEBUG" = "true" ]; then mkdir -p /tmp/xdebug; fi
111120
RUN if [ "$DEBUG" = "false" ]; then rm -rf /usr/src/code/dev; fi
112-
RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so; fi
121+
RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20240924/xdebug.so; fi
113122

114123
CMD [ "tail", "-f", "/dev/null" ]

README.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,48 @@ A list of the utopia/php concepts and their relevant equivalent using the differ
2626
- **Document** - A simple JSON object that will be stored in one of the utopia/database collections. For SQL-based adapters, this will be equivalent to a row. For a No-SQL adapter, this will equivalent to a native document.
2727
- **Attribute** - A simple document attribute. For SQL-based adapters, this will be equivalent to a column. For a No-SQL adapter, this will equivalent to a native document field.
2828
- **Index** - A simple collection index used to improve the performance of your database queries.
29-
- **Permissions** - Using permissions, you can decide which roles have read, create, update and delete access for a specific document. The special attribute `$permissions` is used to store permission metadata for each document in the collection. A permission role can be any string you want. You can use `Authorization::setRole()` to delegate new roles to your users, once obtained a new role a user would gain read, create, update or delete access to a relevant document.
29+
- **Permissions** - Using permissions, you can decide which roles have read, create, update and delete access for a specific document. The special attribute `$permissions` is used to store permission metadata for each document in the collection. A permission role can be any string you want. You can use `$authorization->addRole()` to delegate new roles to your users, once obtained a new role a user would gain read, create, update or delete access to a relevant document.
3030

3131
### Filters
3232

3333
Attribute filters are functions that manipulate attributes before saving them to the database and after retrieving them from the database. You can add filters using the `Database::addFilter($name, $encode, $decode)` where `$name` is the name of the filter that we can add later to attribute `filters` array. `$encode` and `$decode` are the functions used to encode and decode the attribute, respectively. There are also instance-level filters that can only be defined while constructing the `Database` instance. Instance level filters override the static filters if they have the same name.
3434

35+
### Custom Document Types
36+
37+
The database library supports mapping custom document classes to specific collections, enabling a domain-driven design approach. This allows you to create collection-specific classes (like `User`, `Post`, `Product`) that extend the base `Document` class with custom methods and business logic.
38+
39+
```php
40+
// Define a custom document class
41+
class User extends Document
42+
{
43+
public function getEmail(): string
44+
{
45+
return $this->getAttribute('email', '');
46+
}
47+
48+
public function isAdmin(): bool
49+
{
50+
return $this->getAttribute('role') === 'admin';
51+
}
52+
}
53+
54+
// Register the custom type
55+
$database->setDocumentType('users', User::class);
56+
57+
// Now all documents from 'users' collection are User instances
58+
$user = $database->getDocument('users', 'user123');
59+
$email = $user->getEmail(); // Use custom methods
60+
if ($user->isAdmin()) {
61+
// Domain logic
62+
}
63+
```
64+
65+
**Benefits:**
66+
- ✅ Domain-driven design with business logic in domain objects
67+
- ✅ Type safety with IDE autocomplete for custom methods
68+
- ✅ Code organization and encapsulation
69+
- ✅ Fully backwards compatible
70+
3571
### Reserved Attributes
3672

3773
- `$id` - the document unique ID, you can set your own custom ID or a random UID will be generated by the library.

bin/cli.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require_once '/usr/src/code/vendor/autoload.php';
44

55
use Utopia\CLI\CLI;
6+
use Utopia\Console;
67

78
ini_set('memory_limit', '-1');
89

@@ -11,5 +12,14 @@
1112
include 'tasks/load.php';
1213
include 'tasks/index.php';
1314
include 'tasks/query.php';
15+
include 'tasks/relationships.php';
16+
include 'tasks/operators.php';
17+
18+
$cli
19+
->error()
20+
->inject('error')
21+
->action(function ($error) {
22+
Console::error($error->getMessage());
23+
});
1424

1525
$cli->run();

bin/operators

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
php /usr/src/code/bin/cli.php operators "$@"

bin/relationships

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
php /usr/src/code/bin/cli.php relationships "$@"

0 commit comments

Comments
 (0)