Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 103 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
- cron: '0 0 * * *'

jobs:
php-tests:
sqlite:
runs-on: ubuntu-latest

strategy:
Expand All @@ -19,7 +19,7 @@ jobs:
laravel: [12.*, 13.*]
stability: [prefer-lowest, prefer-stable]

name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }}
name: SQLite - P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }}

steps:
- name: Checkout code
Expand All @@ -39,3 +39,104 @@ jobs:

- name: Execute tests
run: vendor/bin/phpunit

mysql:
runs-on: ubuntu-latest

services:
mysql:
image: mysql:8
env:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: laravel
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping --silent"
--health-interval=10s
--health-timeout=5s
--health-retries=3

strategy:
fail-fast: true
matrix:
php: [8.5]
laravel: [13.*]
stability: [prefer-stable]

name: MySQL - P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }}

steps:
- name: Checkout code
uses: actions/checkout@v1

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, bcmath, soap, intl, gd, exif, iconv, imagick
coverage: none

- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-suggest

- name: Execute tests
run: vendor/bin/phpunit
env:
DB_CONNECTION: mysql
DB_DATABASE: laravel
DB_USERNAME: root
DB_PASSWORD: password

postgres:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:16
env:
POSTGRES_USER: root
POSTGRES_PASSWORD: password
POSTGRES_DB: laravel
ports:
- 5432:5432
options: >-
--health-cmd=pg_isready
--health-interval=10s
--health-timeout=5s
--health-retries=3

strategy:
fail-fast: true
matrix:
php: [8.5]
laravel: [13.*]
stability: [prefer-stable]

name: PostgreSQL - P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }}

steps:
- name: Checkout code
uses: actions/checkout@v1

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_pgsql, bcmath, soap, intl, gd, exif, iconv, imagick
coverage: none

- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-suggest

- name: Execute tests
run: vendor/bin/phpunit
env:
DB_CONNECTION: pgsql
DB_DATABASE: laravel
DB_USERNAME: root
DB_PASSWORD: password
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Statamic\Eloquent\Database\BaseMigration as Migration;

Expand All @@ -15,6 +16,8 @@ public function up()

public function down()
{
DB::table($this->prefix('form_submissions'))->delete();

Schema::table($this->prefix('form_submissions'), function (Blueprint $table) {
$table->dropUnique('form_submissions_id_unique');
$table->id()->change();
Expand Down
6 changes: 4 additions & 2 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
<env name="QUEUE_DRIVER" value="sync"/>
<env name="APP_URL" value="http://localhost"/>
<env name="APP_KEY" value="base64:QeU8nSJFKtBB3Y9SdxH0U4xH/1rsFd4zNfOLTeK/DUw="/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="DB_CONNECTION" value="sqlite" force="false"/>
<env name="DB_DATABASE" value=":memory:" force="false"/>
<env name="DB_USERNAME" value="" force="false"/>
<env name="DB_PASSWORD" value="" force="false"/>
</php>
</phpunit>
89 changes: 89 additions & 0 deletions src/QueriesJsonColumns.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,95 @@ public function orderBy($column, $direction = 'asc')
return $this;
}

public function whereDate($column, $operator, $value = null, $boolean = 'and')
{
if (func_num_args() === 2) {
[$value, $operator] = [$operator, '='];
}

$actualColumn = $this->column($column);

if ($this->isJsonColumnOnPostgres($actualColumn)) {
$grammar = $this->builder->getConnection()->getQueryGrammar();
$wrappedColumn = $grammar->wrap($actualColumn);

$this->builder->whereRaw(
"({$wrappedColumn})::timestamp::date {$operator} ?",
[$value],
$boolean
);

return $this;
}

return parent::whereDate($column, $operator, $value, $boolean);
}

public function whereMonth($column, $operator, $value = null, $boolean = 'and')
{
if (func_num_args() === 2) {
[$value, $operator] = [$operator, '='];
}

$actualColumn = $this->column($column);

if ($this->isJsonColumnOnPostgres($actualColumn)) {
return $this->dateBasedWhereJsonPostgres('month', $actualColumn, $operator, $value, $boolean);
}

return parent::whereMonth($column, $operator, $value, $boolean);
}

public function whereDay($column, $operator, $value = null, $boolean = 'and')
{
if (func_num_args() === 2) {
[$value, $operator] = [$operator, '='];
}

$actualColumn = $this->column($column);

if ($this->isJsonColumnOnPostgres($actualColumn)) {
return $this->dateBasedWhereJsonPostgres('day', $actualColumn, $operator, $value, $boolean);
}

return parent::whereDay($column, $operator, $value, $boolean);
}

public function whereYear($column, $operator, $value = null, $boolean = 'and')
{
if (func_num_args() === 2) {
[$value, $operator] = [$operator, '='];
}

$actualColumn = $this->column($column);

if ($this->isJsonColumnOnPostgres($actualColumn)) {
return $this->dateBasedWhereJsonPostgres('year', $actualColumn, $operator, $value, $boolean);
}

return parent::whereYear($column, $operator, $value, $boolean);
}

private function isJsonColumnOnPostgres(string $column): bool
{
return Str::contains($column, ['data->', 'meta->'])
&& str_contains(get_class($this->builder->getConnection()->getQueryGrammar()), 'PostgresGrammar');
}

private function dateBasedWhereJsonPostgres(string $type, string $column, string $operator, $value, string $boolean): static
{
$grammar = $this->builder->getConnection()->getQueryGrammar();
$wrappedColumn = $grammar->wrap($column);

$this->builder->whereRaw(
"extract({$type} from ({$wrappedColumn})::timestamp) {$operator} ?",
[$value],
$boolean
);

return $this;
}

abstract protected function getJsonCasts(): Collection;

protected function toCast(Field $field): string
Expand Down
89 changes: 89 additions & 0 deletions src/Taxonomies/TermQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,95 @@ private function applyCollectionAndTaxonomyWheres()
}
}

public function whereDate($column, $operator, $value = null, $boolean = 'and')
{
if (func_num_args() === 2) {
[$value, $operator] = [$operator, '='];
}

$actualColumn = $this->column($column);

if ($this->isJsonColumnOnPostgres($actualColumn)) {
$grammar = $this->builder->getConnection()->getQueryGrammar();
$wrappedColumn = $grammar->wrap($actualColumn);

$this->builder->whereRaw(
"({$wrappedColumn})::timestamp::date {$operator} ?",
[$value],
$boolean
);

return $this;
}

return parent::whereDate($column, $operator, $value, $boolean);
}

public function whereMonth($column, $operator, $value = null, $boolean = 'and')
{
if (func_num_args() === 2) {
[$value, $operator] = [$operator, '='];
}

$actualColumn = $this->column($column);

if ($this->isJsonColumnOnPostgres($actualColumn)) {
return $this->dateBasedWhereJsonPostgres('month', $actualColumn, $operator, $value, $boolean);
}

return parent::whereMonth($column, $operator, $value, $boolean);
}

public function whereDay($column, $operator, $value = null, $boolean = 'and')
{
if (func_num_args() === 2) {
[$value, $operator] = [$operator, '='];
}

$actualColumn = $this->column($column);

if ($this->isJsonColumnOnPostgres($actualColumn)) {
return $this->dateBasedWhereJsonPostgres('day', $actualColumn, $operator, $value, $boolean);
}

return parent::whereDay($column, $operator, $value, $boolean);
}

public function whereYear($column, $operator, $value = null, $boolean = 'and')
{
if (func_num_args() === 2) {
[$value, $operator] = [$operator, '='];
}

$actualColumn = $this->column($column);

if ($this->isJsonColumnOnPostgres($actualColumn)) {
return $this->dateBasedWhereJsonPostgres('year', $actualColumn, $operator, $value, $boolean);
}

return parent::whereYear($column, $operator, $value, $boolean);
}

private function isJsonColumnOnPostgres(string $column): bool
{
return Str::contains($column, 'data->')
&& str_contains(get_class($this->builder->getConnection()->getQueryGrammar()), 'PostgresGrammar');
}

private function dateBasedWhereJsonPostgres(string $type, string $column, string $operator, $value, string $boolean): static
{
$grammar = $this->builder->getConnection()->getQueryGrammar();
$wrappedColumn = $grammar->wrap($column);

$this->builder->whereRaw(
"extract({$type} from ({$wrappedColumn})::timestamp) {$operator} ?",
[$value],
$boolean
);

return $this;
}

public function with($relations, $callback = null)
{
return $this;
Expand Down
4 changes: 3 additions & 1 deletion tests/Assets/AssetContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ public function calling_folders_uses_eloquent_asset_container_contents()

$queryExecuted = false;
\DB::listen(function (QueryExecuted $query) use (&$queryExecuted) {
$queryExecuted = str_contains($query->sql, 'select distinct "folder" from "assets_meta"');
if (str_contains($query->sql, 'select distinct') && str_contains($query->sql, 'folder') && str_contains($query->sql, 'assets_meta')) {
$queryExecuted = true;
}
});

$this->container->folders();
Expand Down
2 changes: 1 addition & 1 deletion tests/Assets/AssetTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function it_loads_from_an_existing_model_outside_the_query_builder()
$this->assertSame('test.jpg', $asset->basename());
$this->assertSame('test', $asset->filename());
$this->assertSame('jpg', $asset->extension());
$this->assertSame(['width' => 100, 'height' => 100, 'data' => ['focus' => '50-50-1']], $asset->meta());
$this->assertEquals(['width' => 100, 'height' => 100, 'data' => ['focus' => '50-50-1']], $asset->meta());
}

#[Test]
Expand Down
8 changes: 4 additions & 4 deletions tests/Commands/ExportEntriesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function it_exports_entries()
{
Collection::make('pages')->title('Pages')->save();
EntryModel::create([
'id' => 'abc-123',
'id' => 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'collection' => 'pages',
'slug' => 'foo',
'site' => 'en',
Expand All @@ -68,16 +68,16 @@ public function it_exports_localized_entries()

Collection::make('pages')->title('Pages')->save();
EntryModel::create([
'id' => 'origin-id',
'id' => 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
'collection' => 'pages',
'slug' => 'foo',
'site' => 'en',
'data' => ['title' => 'Foo'],
'published' => true,
]);
EntryModel::create([
'id' => 'localized-id',
'origin_id' => 'origin-id',
'id' => 'c3d4e5f6-a7b8-9012-cdef-123456789012',
'origin_id' => 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
'collection' => 'pages',
'slug' => 'foo',
'site' => 'fr',
Expand Down
Loading
Loading