Skip to content

Commit

Permalink
feat: support platform assignment
Browse files Browse the repository at this point in the history
* feat: wip

* feat: add support filters

* chore(l10n): update pot file

* feat: add tests

* chore(l10n): update pot file

* fix: use `do_action` for better semantics

* fix: use returned value from hook instead

* feat: call a new action to notify others that insstitutions were deleted

* chore(l10n): update pot file

---------

Co-authored-by: GitHub Actions <[email protected]>
  • Loading branch information
fdalcin and actions-user authored Nov 28, 2024
1 parent e8849f6 commit efb9f0e
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 20 deletions.
41 changes: 21 additions & 20 deletions languages/pressbooks-multi-institution.pot
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2024-10-09T14:54:43+00:00\n"
"POT-Creation-Date: 2024-11-28T18:16:38+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.11.0\n"
"X-Domain: pressbooks-multi-institution\n"
Expand Down Expand Up @@ -39,7 +39,18 @@ msgstr ""
msgid "https://pressbooks.org"
msgstr ""

#: src/Bootstrap.php:80
#: src/Bootstrap.php:97
#: src/Traits/OverridesBulkActions.php:14
#: src/Views/AssignUsersTable.php:74
#: src/Views/BaseInstitutionList.php:108
#: src/Views/InstitutionsTotals.php:33
#: resources/views/assign/index.blade.php:58
#: resources/views/partials/filters/institutions/content.blade.php:14
#: resources/views/table/institution.blade.php:1
msgid "Unassigned"
msgstr ""

#: src/Bootstrap.php:138
msgid "Are you sure you want to delete the selected institutions?"
msgstr ""

Expand Down Expand Up @@ -73,32 +84,32 @@ msgid_plural "Users updated."
msgstr[0] ""
msgstr[1] ""

#: src/Controllers/InstitutionsController.php:101
#: src/Controllers/InstitutionsController.php:103
msgid "Action completed."
msgstr ""

#: src/Controllers/InstitutionsController.php:126
#: src/Controllers/InstitutionsController.php:128
msgid "The form is invalid."
msgstr ""

#: src/Controllers/InstitutionsController.php:172
#: src/Controllers/InstitutionsController.php:174
msgid "Institution has been added."
msgstr ""

#: src/Controllers/InstitutionsController.php:173
#: src/Controllers/InstitutionsController.php:175
msgid "Institution has been updated."
msgstr ""

#: src/Controllers/InstitutionsController.php:200
#: src/Controllers/InstitutionsController.php:202
msgid "The name field is required."
msgstr ""

#: src/Controllers/InstitutionsController.php:210
#: src/Controllers/InstitutionsController.php:212
msgid "The book limit field should be numeric."
msgstr ""

#: src/Services/InstitutionStatsService.php:39
#: src/Services/MenuManager.php:165
#: src/Services/MenuManager.php:167
msgid "%s Stats"
msgstr ""

Expand All @@ -122,24 +133,14 @@ msgstr ""
msgid "Edit Institution"
msgstr ""

#: src/Services/MenuManager.php:117
#: src/Services/MenuManager.php:119
msgid "Administer Institution"
msgstr ""

#: src/Services/PermissionsManager.php:95
msgid "Sorry, you are not allowed to access this page."
msgstr ""

#: src/Traits/OverridesBulkActions.php:14
#: src/Views/AssignUsersTable.php:74
#: src/Views/BaseInstitutionList.php:108
#: src/Views/InstitutionsTotals.php:33
#: resources/views/assign/index.blade.php:58
#: resources/views/partials/filters/institutions/content.blade.php:14
#: resources/views/table/institution.blade.php:1
msgid "Unassigned"
msgstr ""

#: src/Views/AssignBooksTable.php:33
msgid "Cover"
msgstr ""
Expand Down
58 changes: 58 additions & 0 deletions src/Bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

namespace PressbooksMultiInstitution;

use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\Builder;
use Kucrut\Vite;
use Pressbooks\Container;
use PressbooksMultiInstitution\Actions\AssignBookToInstitution;
use PressbooksMultiInstitution\Actions\AssignUserToInstitution;
use PressbooksMultiInstitution\Actions\InstitutionalManagerDashboard;
use PressbooksMultiInstitution\Models\Institution;
use PressbooksMultiInstitution\Services\InstitutionStatsService;
use PressbooksMultiInstitution\Services\MenuManager;
use PressbooksMultiInstitution\Services\PermissionsManager;
Expand Down Expand Up @@ -40,6 +43,8 @@ public function setUp(): void

Container::getInstance()->singleton(BookList::class, fn () => new BookList(app('db')));
Container::getInstance()->singleton(UserList::class, fn () => new UserList(app('db')));

$this->registerInstitutionHooks();
}

private function registerActions(): void
Expand Down Expand Up @@ -71,6 +76,59 @@ private function registerBlade(): void
);
}

private function registerInstitutionHooks(): void
{
add_filter(
hook_name: 'pressbooks_get_institution_by_id',
callback: function (mixed $default, string|int $id) {
$institution = Institution::query()->find($id);

return $institution?->id ?? $default;
},
accepted_args: 2
);

add_filter(
hook_name: 'pressbooks_get_institution_dropdown',
callback: function (array $default) {
return Institution::query()
->orderBy('name')
->pluck('name', 'id')
->prepend(__('Unassigned', 'pressbooks-multi-institution'), 0)
->toArray();
},
);

add_filter(
hook_name: 'pressbooks_append_institution_to_query',
callback: function (EloquentBuilder $query, string $columnToCompare, string $search = '', string $order = '', string $direction = ''): EloquentBuilder {
$query
->addSelect([
'institution' => Institution::query()
->select('name')
->whereColumn('id', '=', $columnToCompare)
])
->when($search, function (EloquentBuilder $query, string $value) use ($columnToCompare) {
$query->orWhereExists(function (Builder $query) use ($value, $columnToCompare) {
$query
->selectRaw(1)
->from('institutions')
->whereColumn('id', '=', $columnToCompare)
->where('name', 'like', "%{$value}%");
});
})
->when($order === 'institution', function (EloquentBuilder $query) use ($direction) {
$query
->orderByRaw($direction === 'asc' ? 'institution IS NOT NULL' : 'institution IS NULL')
->orderBy('institution', $direction);
});

return $query;
},
accepted_args: 5
);
}

private function enqueueScripts(): void
{
add_action('admin_enqueue_scripts', function ($page) {
Expand Down
2 changes: 2 additions & 0 deletions src/Controllers/InstitutionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public function processBulkActions(): array
default => null,
};

do_action('pressbooks_multi_institution_deleted_institution', $items);

apply_filters('pb_institutional_after_delete', [], $institutionalManagerIds);

return [
Expand Down
2 changes: 2 additions & 0 deletions src/Services/MenuManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public function registerMenus(): void
echo app(AssignBooksController::class)->index();
}
);

do_action('pressbooks_multi_institution_add_menu', $this->slug);
}

/**
Expand Down
201 changes: 201 additions & 0 deletions tests/Feature/BootstrapTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
<?php

namespace Tests\Feature;

use PressbooksMultiInstitution\Models\Institution;
use Tests\TestCase;
use Tests\Traits\CreatesModels;

class BootstrapTest extends TestCase
{
use CreatesModels;

/**
* @test
*/
public function it_registers_get_institution_dropdown_hook(): void
{
global $wp_filter;

$this->assertArrayHasKey('pressbooks_get_institution_dropdown', $wp_filter);
}

/**
* @test
*/
public function it_registers_get_institution_by_id_hook(): void
{
global $wp_filter;

$this->assertArrayHasKey('pressbooks_get_institution_by_id', $wp_filter);
}


/**
* @test
*/
public function it_registers_append_institution_to_query_hook(): void
{
global $wp_filter;

$this->assertArrayHasKey('pressbooks_append_institution_to_query', $wp_filter);
}

/**
* @test
*/
public function it_retrieves_a_dropdown_list_of_institutions(): void
{
$first = $this->createInstitution([
'name' => 'Fake Institution',
]);

$second = $this->createInstitution([
'name' => 'Another Fake Institution',
]);

$response = apply_filters('pressbooks_get_institution_dropdown', []);

$this->assertEquals([
0 => 'Unassigned',
$second->id => $second->name,
$first->id => $first->name,
], $response);
}

/**
* @test
*/
public function it_retrieves_an_empty_dropdown_list_of_institutions_when_no_institutions_are_registered(): void
{
$response = apply_filters('pressbooks_get_institution_dropdown', []);

$this->assertEquals([
0 => 'Unassigned',
], $response);
}

/**
* @test
*/
public function it_retrieves_the_institution_id(): void
{
$institution = $this->createInstitution([
'name' => 'Fake Institution',
]);

$id = apply_filters('pressbooks_get_institution_by_id', null, $institution->id);

$this->assertEquals($institution->id, $id);
}

/**
* @test
*/
public function it_returns_default_value_if_institution_does_not_exist(): void
{
$id = apply_filters('pressbooks_get_institution_by_id', null, 999);

$this->assertNull($id);
}

/**
* @test
*/
public function it_appends_institution_subquery_to_query(): void
{
$query = Institution::query();

$columnToCompare = 'column_name';

$this->assertStringNotContainsString('select `name` from `wptests_institutions` where `id` = `column_name`', $query->toSql());

$query = apply_filters('pressbooks_append_institution_to_query', $query, $columnToCompare);

$this->assertStringContainsString('select `name` from `wptests_institutions` where `id` = `column_name`', $query->toSql());
}

/**
* @test
*/
public function it_appends_exists_clause_when_searching(): void
{
$query = Institution::query();

$columnToCompare = 'column_name';

$searchValue = 'foo';

$this->assertStringNotContainsString('exists (select 1 from `wptests_institutions` where `id` = `column_name` and `name` like ?)', $query->toSql());

$this->assertEmpty($query->getBindings());

$query = apply_filters('pressbooks_append_institution_to_query', $query, $columnToCompare, $searchValue);

$this->assertStringContainsString('exists (select 1 from `wptests_institutions` where `id` = `column_name` and `name` like ?)', $query->toSql());

$this->assertEquals([
'%foo%'
], $query->getBindings());
}

/**
* @test
*/
public function it_appends_order_by_clause_ascending_when_sorting_by_institution(): void
{
$query = Institution::query();

$columnToCompare = 'column_name';

$sort = 'institution';

$direction = 'asc';

$this->assertStringNotContainsString('order by institution IS NOT NULL, `institution` asc', $query->toSql());

$query = apply_filters('pressbooks_append_institution_to_query', $query, $columnToCompare, '', $sort, $direction);

$this->assertStringContainsString('order by institution IS NOT NULL, `institution` asc', $query->toSql());
}

/**
* @test
*/
public function it_appends_order_by_clause_descending_when_sorting_by_institution(): void
{
$query = Institution::query();

$columnToCompare = 'column_name';

$sort = 'institution';

$direction = 'desc';

$this->assertStringNotContainsString('order by institution IS NULL, `institution` desc', $query->toSql());

$query = apply_filters('pressbooks_append_institution_to_query', $query, $columnToCompare, '', $sort, $direction);

$this->assertStringContainsString('order by institution IS NULL, `institution` desc', $query->toSql());
}

/**
* @test
*/
public function it_does_not_append_order_by_clause_when_sorting_by_a_different_field(): void
{
$query = Institution::query();

$columnToCompare = 'column_name';

$sort = 'foo';

$direction = 'asc';

$this->assertStringNotContainsString('order by', $query->toSql());

$query = apply_filters('pressbooks_append_institution_to_query', $query, $columnToCompare, '', $sort, $direction);

$this->assertStringNotContainsString('order by', $query->toSql());
}
}

0 comments on commit efb9f0e

Please sign in to comment.