Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: CanBeApproved Trait Added #18

Merged
merged 11 commits into from
Feb 7, 2024
184 changes: 184 additions & 0 deletions src/Scope/ApprovedScope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<?php

namespace AchyutN\LaravelHelpers\Scope;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class ApprovedScope implements Scope
{
/**
* All of the extensions to be added to the builder.
*
* @var array
*/
protected array $extensions = ['WithPending','OnlyPending','WithoutApproved','WithRejected','OnlyRejected','WithAll'];

/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model): void
{
$builder->whereNotNull($model->getQualifiedApprovedAtColumn())->whereNull($model->getQualifiedRejectedAtColumn());
}

/**
* Extend the query builder with the needed functions.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
public function extend(Builder $builder): void
{
foreach ($this->extensions as $extension) {
$this->{"add{$extension}"}($builder);
}
}

/**
* Get the "approved at" column for the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return string
*/
protected function getApprovedAtColumn(Builder $builder): string
{
if (count((array)$builder->getQuery()->joins) > 0) {
return $builder->getModel()->getQualifiedApprovedAtColumn();
}

return $builder->getModel()->getQualifiedApprovedAtColumn();
}

/**
* Get the "rejected at" column for the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return string
*/
protected function getRejectedAtColumn(Builder $builder): string
{
if (count((array)$builder->getQuery()->joins) > 0) {
return $builder->getModel()->getQualifiedRejectedAtColumn();
}

return $builder->getModel()->getQualifiedRejectedAtColumn();
}

/**
* Add the with-pending extension to the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
protected function addWithPending(Builder $builder): void
{
$builder->macro('withPending', function (Builder $builder) {

return $builder->withoutGlobalScope($this)->whereNull(
$this->getRejectedAtColumn($builder)
);
});
}

/**
* Add the without-pending extension to the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
protected function addOnlyPending(Builder $builder): void
{
$builder->macro('onlyPending', function (Builder $builder) {
$model = $builder->getModel();

$builder->withoutGlobalScope($this)->whereNull(
$model->getQualifiedApprovedAtColumn()
)->WhereNull(
$model->getQualifiedRejectedAtColumn()
);

return $builder;
});
}

/**
* Add the without-approved extension to the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
protected function addWithoutApproved(Builder $builder): void
{
$builder->macro('withoutApproved', function (Builder $builder) {
$model = $builder->getModel();

$builder->withoutGlobalScope($this)->whereNull(
$model->getQualifiedApprovedAtColumn()
);

return $builder;
});
}

/**
* Add the with-rejected extension to the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
protected function addWithRejected(Builder $builder): void
{
$builder->macro('withRejected', function (Builder $builder) {
$model = $builder->getModel();

$builder->withoutGlobalScope($this)->whereNotNull(
$model->getQualifiedRejectedAtColumn()
)->whereNull(
$model->getQualifiedApprovedAtColumn()
);

return $builder;
});
}

/**
* Add the only-rejected extension to the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
protected function addOnlyRejected(Builder $builder): void
{
$builder->macro('onlyRejected', function (Builder $builder) {
$model = $builder->getModel();

$builder->withoutGlobalScope($this)->whereNotNull(
$model->getQualifiedRejectedAtColumn()
);

return $builder;
});
}

/**
* Add the with-all extension to the builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return void
*/
protected function addWithAll(Builder $builder): void
{
$builder->macro('withAll', function (Builder $builder) {
return $builder->withoutGlobalScope($this);
});
}



}
117 changes: 117 additions & 0 deletions src/Traits/CanBeApproved.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

namespace AchyutN\LaravelHelpers\Traits;

use AchyutN\LaravelHelpers\Scope\ApprovedScope;

trait CanBeApproved
{
/**
* Boot the approve trait for a model.
*
* @return void
*/
public static function bootCanBeApproved(): void
{
static::addGlobalScope(new ApprovedScope());
}

/**
* Initialize approve trait for an instance.
*
* @return void
*/

public function initializeCanBeApproved(): void
{
if (!isset($this->casts[$this->getApprovedAtColumn()])) {
$this->casts[$this->getApprovedAtColumn()] = 'datetime';
}
if (!isset($this->casts[$this->getRejectedAtColumn()])) {
$this->casts[$this->getRejectedAtColumn()] = 'datetime';
}

}

/**
* Get the name of the "approved at" column.
*
* @return string
*/
public function getApprovedAtColumn(): string
{
return defined(static::class . '::APPROVED_AT') ? static::APPROVED_AT : 'approved_at';
}

/**
* Get the name of the "rejected at" column.
*
* @return string
*/
public function getRejectedAtColumn(): string
{
return defined(static::class . '::REJECTED_AT') ? static::REJECTED_AT : 'rejected_at';
}


/**
* Get the fully qualified "approved at" column.
*
* @return string
*/
public function getQualifiedApprovedAtColumn(): string
{
return $this->qualifyColumn($this->getApprovedAtColumn());
}

/**
* Get the fully qualified "rejected at" column.
*
* @return string
*/
public function getQualifiedRejectedAtColumn(): string
{
return $this->qualifyColumn($this->getRejectedAtColumn());
}

/**
* Approve the model.
*
* @return bool
*/
public function setApproved(): bool
{
$this->{$this->getApprovedAtColumn()} = $this->freshTimestamp();
$this->{$this->getRejectedAtColumn()} = null;
return $this->save();
}

/**
* Reject the model.
*
* @return bool
*/

public function setRejected(): bool
{
$this->{$this->getRejectedAtColumn()} = $this->freshTimestamp();
$this->{$this->getApprovedAtColumn()} = null;

return $this->save();
}

/**
* Set the model as pending.
*
* @return bool
*/
public function setPending(): bool
{
$this->{$this->getRejectedAtColumn()} = null;
$this->{$this->getApprovedAtColumn()} = null;

return $this->save();
}


}
70 changes: 70 additions & 0 deletions tests/ApproveActiveTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace AchyutN\LaravelHelpers\Tests;


use AchyutN\LaravelHelpers\Tests\Models\ApproveActive;

class ApproveActiveTest extends BaseTestCase
{

public function test_change_to_approved()
{
$approve_active = ApproveActive::factory()->create();
$approve_active->setApproved();
$this->assertFalse($approve_active->approved_at == null);
$this->assertTrue($approve_active->rejected_at == null);
}

public function test_active_count()
{
ApproveActive::factory(10)->create(['rejected_at' => now()]);
$this->assertEquals(0, ApproveActive::count());
}

public function test_active_and_approved_count()
{
ApproveActive::factory(10)->create(['approved_at' => now()]);
$this->assertEquals(10, ApproveActive::count());
}

public function test_active_and_pending_count()
{
ApproveActive::factory(10)->create();
$this->assertEquals(0, ApproveActive::count());
}

public function test_active_and_rejected_count()
{
ApproveActive::factory(10)->create(['rejected_at' => now()]);
$this->assertEquals(0, ApproveActive::count());
}

public function test_inactive_and_approved_count()
{
ApproveActive::factory(10)->create(['approved_at' => now(), 'inactive_at' => now()]);
$this->assertEquals(0, ApproveActive::count());
}

public function test_active_and_change_to_approved()
{
$approve_active = ApproveActive::factory()->create();
$approve_active->setApproved();
$this->assertEquals(1, ApproveActive::count());
}

public function test_inactive_and_change_to_approved()
{
$approve_active = ApproveActive::factory()->create(['inactive_at'=>now()]);
$approve_active->setApproved();
$this->assertEquals(0, ApproveActive::count());
}

public function test_approved_and_change_to_active()
{
$approve_active = ApproveActive::factory()->create(['approved_at'=>now(),'inactive_at'=>now()]);
$approve_active->setActive();
$this->assertEquals(1, ApproveActive::count());
}

}
Loading
Loading