Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/Configuration/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function getName(): string
*/
public function create(Loader $config): void
{
// By default, we do nothing here, but you can override this method in your configuration class
// By default, we do nothing here, but you can override this method in your configuration class
// to set up your server or package as needed.
}

Expand Down
102 changes: 58 additions & 44 deletions src/Database/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -290,16 +290,12 @@ private static function isComparisonOperator(mixed $comparator): bool
return false;
}

return in_array(
Str::upper($comparator),
[
return in_array(Str::upper($comparator), [
'=', '>', '<', '>=', '=<', '<>', '!=', 'LIKE', 'NOT', 'IS NOT', "IN", "NOT IN",
'ILIKE', '&', '|', '<<', '>>', 'NOT LIKE',
'&&', '@>', '<@', '?', '?|', '?&', '||', '-', '@?', '@@', '#-',
'IS DISTINCT FROM', 'IS NOT DISTINCT FROM',
],
true
);
], true);
}

/**
Expand Down Expand Up @@ -397,15 +393,14 @@ public function setTable(string $table): QueryBuilder
* WHERE column IS NULL
*
* @param string $column
* @param string $boolean
* @return QueryBuilder
*/
public function whereNull(string $column, string $boolean = 'and'): QueryBuilder
public function whereNull(string $column): QueryBuilder
{
if (is_null($this->where)) {
$this->where = $column . ' is null';
} else {
$this->where .= ' ' . $boolean . ' ' . $column . ' is null';
$this->where .= ' and ' . $column . ' is null';
}

return $this;
Expand All @@ -416,16 +411,15 @@ public function whereNull(string $column, string $boolean = 'and'): QueryBuilder
*
* WHERE column NOT NULL
*
* @param $column
* @param string $boolean
* @param string $column
* @return QueryBuilder
*/
public function whereNotNull($column, $boolean = 'and'): QueryBuilder
public function whereNotNull(string $column): QueryBuilder
{
if (is_null($this->where)) {
$this->where = $column . ' is not null';
} else {
$this->where .= ' ' . $boolean . ' ' . $column . ' is not null';
$this->where .= ' and ' . $column . ' is not null';
}

return $this;
Expand All @@ -440,7 +434,14 @@ public function whereNotNull($column, $boolean = 'and'): QueryBuilder
*/
public function whereNotBetween(string $column, array $range): QueryBuilder
{
$this->whereBetween($column, $range, 'not');
$range = (array) $range;
$between = implode(' and ', $range);

if (is_null($this->where)) {
$this->where = $column . ' not between ' . $between;
} else {
$this->where .= ' and ' . $column . ' not between ' . $between;
}

return $this;
}
Expand All @@ -452,32 +453,36 @@ public function whereNotBetween(string $column, array $range): QueryBuilder
*
* @param string $column
* @param array $range
* @param string $boolean
* @return QueryBuilder
* @throws QueryBuilderException
*/
public function whereBetween(string $column, array $range, string $boolean = 'and'): QueryBuilder
public function whereBetween(string $column, array $range): QueryBuilder
{
$range = (array)$range;
$range = (array) $range;
$between = implode(' and ', $range);

if (is_null($this->where)) {
if ($boolean == 'not') {
$this->where = $column . ' not between ' . $between;
} else {
$this->where = $column . ' between ' . $between;
}
$this->where = $column . ' between ' . $between;
} else {
if ($boolean == 'not') {
$this->where .= ' and ' . $column . ' not between ' . $between;
} else {
$this->where .= ' ' . $boolean . ' ' . $column . ' between ' . $between;
}
$this->where .= ' and ' . $column . ' between ' . $between;
}

return $this;
}

/**
* WHERE column NOT BETWEEN '' AND ''
*
* @param string $column
* @param mixed $value
* @return QueryBuilder
*/
public function whereDifferent(string $column, mixed $value): QueryBuilder
{
$this->where($column, '<>', $value);

return $this;
}

/**
* Where clause with <<not in>> comparison
*
Expand All @@ -488,7 +493,25 @@ public function whereBetween(string $column, array $range, string $boolean = 'an
*/
public function whereNotIn(string $column, array $range)
{
$this->whereIn($column, $range, 'not');
if ($range instanceof QueryBuilder) {
$range = "(" . $range->toSql() . ")";
}

if (is_array($range)) {
$range = (array)$range;
$this->where_data_binding = array_merge($this->where_data_binding, $range);

$map = array_map(fn() => '?', $range);
$in = implode(', ', $map);
} else {
$in = (string) $range;
}

if (is_null($this->where)) {
$this->where = $column . ' not in (' . $in . ')';
} else {
$this->where .= ' and ' . $column . ' not in (' . $in . ')';
}

return $this;
}
Expand All @@ -498,11 +521,10 @@ public function whereNotIn(string $column, array $range)
*
* @param string $column
* @param array $range
* @param string $boolean
* @return QueryBuilder
* @throws QueryBuilderException
*/
public function whereIn(string $column, array $range, string $boolean = 'and'): QueryBuilder
public function whereIn(string $column, array $range): QueryBuilder
{
if ($range instanceof QueryBuilder) {
$range = "(" . $range->toSql() . ")";
Expand All @@ -515,21 +537,13 @@ public function whereIn(string $column, array $range, string $boolean = 'and'):
$map = array_map(fn() => '?', $range);
$in = implode(', ', $map);
} else {
$in = (string)$range;
$in = (string) $range;
}

if (is_null($this->where)) {
if ($boolean == 'not') {
$this->where = $column . ' not in (' . $in . ')';
} else {
$this->where = $column . ' in (' . $in . ')';
}
$this->where = $column . ' in (' . $in . ')';
} else {
if ($boolean == 'not') {
$this->where .= ' and ' . $column . ' not in (' . $in . ')';
} else {
$this->where .= ' and ' . $column . ' in (' . $in . ')';
}
$this->where .= ' and ' . $column . ' in (' . $in . ')';
}

return $this;
Expand Down Expand Up @@ -727,8 +741,8 @@ public function orOn(string $first, $comparator = '=', $second = null): QueryBui
/**
* Clause Group By
*
* @param string $column
* @return QueryBuilder
* @param string $column
* @return QueryBuilder
* @deprecated
*/
public function group($column)
Expand Down
12 changes: 6 additions & 6 deletions tests/Scheduler/ScheduleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,10 @@ public function test_is_due_every_minute()
public function test_is_due_specific_time()
{
$this->schedule->dailyAt('10:30');

$dueTime = new DateTime('today 10:30');
$notDueTime = new DateTime('today 11:00');

$this->assertTrue($this->schedule->isDue($dueTime));
$this->assertFalse($this->schedule->isDue($notDueTime));
}
Expand Down Expand Up @@ -284,21 +284,21 @@ public function test_fluent_api_chaining()
public function test_is_due_hourly()
{
$this->schedule->hourly();

$dueTime = new DateTime('today 14:00');
$notDueTime = new DateTime('today 14:30');

$this->assertTrue($this->schedule->isDue($dueTime));
$this->assertFalse($this->schedule->isDue($notDueTime));
}

public function test_is_due_with_step()
{
$this->schedule->everyFiveMinutes();

$dueTime = new DateTime('today 14:05');
$notDueTime = new DateTime('today 14:03');

$this->assertTrue($this->schedule->isDue($dueTime));
$this->assertFalse($this->schedule->isDue($notDueTime));
}
Expand Down
4 changes: 2 additions & 2 deletions tests/Scheduler/ScheduledEventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ public function test_throws_for_invalid_task_class()
$this->expectExceptionMessage('Task class [NonExistentClass] does not exist');

// Create a mock that skips queue push
$event = new class(ScheduledEvent::TYPE_TASK, 'NonExistentClass') extends ScheduledEvent {
$event = new class (ScheduledEvent::TYPE_TASK, 'NonExistentClass') extends ScheduledEvent {
protected function pushToQueue(\Bow\Queue\QueueTask $task): void
{
// Skip actual queue push in test
Expand All @@ -303,7 +303,7 @@ public function test_throws_for_non_queue_task_instance()
$this->expectExceptionMessage('Task must be an instance of');

// Create a mock that skips queue push
$event = new class(ScheduledEvent::TYPE_TASK, new \stdClass()) extends ScheduledEvent {
$event = new class (ScheduledEvent::TYPE_TASK, new \stdClass()) extends ScheduledEvent {
protected function pushToQueue(\Bow\Queue\QueueTask $task): void
{
// Skip actual queue push in test
Expand Down
10 changes: 5 additions & 5 deletions tests/Scheduler/SchedulerCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ public function test_display_result_shows_skipped_status()
// Skipped status only occurs with overlap prevention when lock is already held
// For this test, we'll just verify the displayResult method handles 'skipped' status
// by checking the match expression in the code exists and works

// Register an event that will be due
$this->scheduler->call(fn() => 'test')
->everyMinute()
Expand Down Expand Up @@ -387,7 +387,7 @@ public function test_list_shows_due_status_correctly()
public function test_full_workflow_register_list_run()
{
$counter = 0;

$this->scheduler->call(function () use (&$counter) {
$counter++;
return $counter;
Expand All @@ -414,7 +414,7 @@ public function test_full_workflow_register_list_run()

public function test_multiple_event_types_in_list()
{

$this->scheduler->call(fn() => 'closure')->everyMinute()->description('Closure event');
$this->scheduler->command('test:command')->hourly()->description('Command event');
$this->scheduler->exec('echo hello')->daily()->description('Exec event');
Expand All @@ -431,7 +431,7 @@ public function test_multiple_event_types_in_list()

public function test_events_with_different_schedules()
{

$this->scheduler->call(fn() => null)->everyMinute();
$this->scheduler->call(fn() => null)->hourly();
$this->scheduler->call(fn() => null)->daily();
Expand Down Expand Up @@ -459,7 +459,7 @@ public function test_loads_routes_scheduler_file()

$markerFile = TESTING_RESOURCE_BASE_DIRECTORY . '/scheduler_marker.txt';
$schedulerFile = $routesDir . '/scheduler.php';

file_put_contents($schedulerFile, '<?php
use Bow\Scheduler\Scheduler;
$scheduler = Scheduler::getInstance();
Expand Down
Loading