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

Wordcheck API returning bad words with levels #1379

Merged
merged 9 commits into from
Dec 8, 2024
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
64 changes: 64 additions & 0 deletions SETUP/tests/unittests/ApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,28 @@ protected function validate_text(string $projectid, string $text): array
return $router->route($path, []);
}

protected function wordcheck(string $projectid, string $text, $languages = [], $accepted_words = []): array
{
global $request_body;

$request_body = ["text" => $text, "languages" => $languages, "accepted_words" => $accepted_words];
$_SERVER["REQUEST_METHOD"] = "PUT";
$path = "v1/projects/$projectid/wordcheck";
$router = ApiRouter::get_router();
return $router->route($path, []);
}

protected function wordcheck_report(string $projectid, string $page_name, array $accepted_words = [])
{
global $request_body;

$_SERVER["REQUEST_METHOD"] = "PUT";
$request_body = ["accepted_words" => $accepted_words];
$path = "v1/projects/$projectid/pages/$page_name/wordcheck";
$router = ApiRouter::get_router();
return $router->route($path, []);
}

//---------------------------------------------------------------------------
// tests

Expand Down Expand Up @@ -691,6 +713,48 @@ public function test_validate_text()
];
$this->assertEquals($expected, $response);
}

public function test_wordcheck_bad_words()
{
$project = $this->_create_available_project();
$response = $this->wordcheck($project->projectid, "Fort Snelling b[oe]uf a1l file");
$expected = [
"bad_words" => ["Snelling" => WC_WORLD, "b[oe]uf" => WC_WORLD, "a1l" => WC_SITE],
"messages" => [],
];
$this->assertEquals($expected, $response);
}

public function test_wordcheck_accept()
{
$project = $this->_create_available_project();
$response = $this->wordcheck($project->projectid, "Fort Snelling test\nfile", [], ["Snelling"]);
$expected = [
"bad_words" => [],
"messages" => [],
];
$this->assertEquals($expected, $response);
}

public function test_wordcheck_report()
{
global $pguser;

$pguser = $this->TEST_USERNAME;
$project = $this->_create_available_project();

// check out a page
$this->checkout($project->projectid, "P1.proj_avail");

// report wordcheck results
$accepted_words = ["Snelling", "b[oe]uf"];
$this->wordcheck_report($project->projectid, "001.png", $accepted_words);
[$result] = load_wordcheck_events($project->projectid);
$this->assertEquals("P1", $result[1]);
$this->assertEquals("001.png", $result[2]);
$this->assertEquals("ProjectTest_php", $result[3]);
$this->assertEquals($accepted_words, $result[4]);
}
}

// this mocks the function in index.php
Expand Down
91 changes: 91 additions & 0 deletions api/dp-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,61 @@ paths:
default:
$ref: '#/components/responses/UnexpectedError'

/projects/{projectid}/wordcheck:
put:
tags:
- project
description: Checks the given text for bad words, returns an array of bad words with their type and an array of messages
parameters:
- $ref: '#/components/parameters/projectid'
requestBody:
description: text, accepted words and languages
required: true
content:
application/json:
schema:
type: object
properties:
text:
type: string
accepted_words:
type: array
items:
type: string
languages:
type: array
items:
type: string
responses:
200:
description: wordcheck data
content:
application/json:
schema:
type: object
properties:
bad_words:
type: array
items:
type: object
additionalProperties:
type: integer
description: Keys are bad words, values are levels
messages:
type: array
items:
type: string
'400':
$ref: '#/components/responses/InvalidValue'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
$ref: '#/components/responses/UnexpectedError'

/projects/{projectid}/pages/{pagename}:
put:
tags:
Expand Down Expand Up @@ -1057,6 +1112,42 @@ paths:
default:
$ref: '#/components/responses/UnexpectedError'

/projects/{projectid}/pages/{pagename}/wordcheck:
put:
tags:
- project
description: Report wordcheck reults
parameters:
- $ref: '#/components/parameters/projectid'
- $ref: '#/components/parameters/pagename'
requestBody:
description: accepted words if any
required: true
content:
application/json:
schema:
type: object
properties:
accepted_words:
type: array
items:
type: string
responses:
200:
description: OK
'400':
$ref: '#/components/responses/InvalidValue'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitExceeded'
default:
$ref: '#/components/responses/UnexpectedError'

/stats/site:
get:
tags:
Expand Down
3 changes: 2 additions & 1 deletion api/v1.inc
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ $router->add_route("GET", "v1/queues/:queueid", "api_v1_queue");
$router->add_route("GET", "v1/queues/:queueid/stats", "api_v1_queue_stats");
$router->add_route("GET", "v1/queues/:queueid/projects", "api_v1_queue_projects");


$router->add_route("PUT", "v1/projects/:projectid/checkout", "api_v1_project_checkout");
$router->add_route("PUT", "v1/projects/:projectid/validatetext", "api_v1_project_validatetext");
$router->add_route("PUT", "v1/projects/:projectid/wordcheck", "api_v1_project_wordcheck");
$router->add_route("PUT", "v1/projects/:projectid/pages/:pagename", "api_v1_project_page");
$router->add_route("GET", "v1/projects/:projectid/pages/:pagename", "api_v1_project_page");
$router->add_route("PUT", "v1/projects/:projectid/pages/:pagename/wordcheck", "api_v1_project_page_wordcheck");

$router->add_route("GET", "v1/stats/site", "api_v1_stats_site");
$router->add_route("GET", "v1/stats/site/projects/stages", "api_v1_stats_site_projects_stages");
Expand Down
82 changes: 63 additions & 19 deletions api/v1_projects.inc
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,23 @@ function api_v1_project_validatetext($method, $data, array $query_params)
return $text_checker->analyse(receive_project_text_from_request_body('text'), $data[":projectid"]);
}

function api_v1_project_wordcheck($method, $data, array $query_params)
{
$project = $data[":projectid"];
$accepted_words = receive_data_from_request_body("accepted_words") ?? [];
$languages = receive_data_from_request_body("languages") ?? [];
if (!$languages) {
$languages = $project->languages;
}

$text = receive_project_text_from_request_body();
[$bad_words, $languages, $messages] = get_bad_word_levels_for_project_text($text, $project->projectid, $languages, $accepted_words);
return [
"bad_words" => $bad_words,
"messages" => $messages,
];
}

function api_v1_project_page(string $method, array $data, array $query_params)
{
global $pguser;
Expand All @@ -817,23 +834,9 @@ function api_v1_project_page(string $method, array $data, array $query_params)
$proof_project = new ProofProject($project);

$page_state = $query_params['pagestate'] ?? null;
if (null === $page_state) {
throw new InvalidValue("No page state found in request.");
}
if (!in_array($page_state, Rounds::get_page_states())) {
throw new InvalidValue(sprintf("%s is not a valid page state", $page_state));
}
if ($page_state != $project_page->page_state) {
$err = sprintf(
_('Page "%1$s" is not in state "%2$s"; it is now in state "%3$s".'),
$project_page->page_name,
$page_state,
$project_page->page_state
);
throw new ProjectPageInconsistentStateException($err);
}

validate_page_state($project_page, $page_state);
$proof_project_page = new ProofProjectPage($proof_project, $project_page);

$page_action = $query_params['pageaction'] ?? null;
switch ($page_action) {
case null:
Expand All @@ -858,6 +861,23 @@ function api_v1_project_page(string $method, array $data, array $query_params)
}
}

function api_v1_project_page_wordcheck(string $method, array $data, array $query_params): void
{
try {
$project = $data[":projectid"];
$proof_project = new ProofProject($project);

$project_page = $data[":pagename"];
$proof_project_page = new ProofProjectPage($proof_project, $project_page);

$proof_project_page->wc_report(receive_data_from_request_body("accepted_words") ?? []);
} catch (ProjectException $exception) {
throw new NotFoundError($exception->getMessage(), $exception->getCode());
} catch (UserAccessException $exception) {
throw new ForbiddenError($exception->getMessage(), $exception->getCode());
}
}

function validate_project_state($project, $state)
{
if (null === $state) {
Expand All @@ -877,12 +897,36 @@ function validate_project_state($project, $state)
}
}

function receive_project_text_from_request_body($field): string
function validate_page_state($project_page, $page_state)
{
$request_data = api_get_request_body();
$page_text = $request_data[$field] ?? null;
if (null === $page_state) {
throw new InvalidValue("No page state found in request.");
}
if (!in_array($page_state, Rounds::get_page_states())) {
throw new InvalidValue(sprintf("%s is not a valid page state", $page_state));
}
if ($page_state != $project_page->page_state) {
$err = sprintf(
_('Page "%1$s" is not in state "%2$s"; it is now in state "%3$s".'),
$project_page->page_name,
$page_state,
$project_page->page_state
);
throw new ProjectPageInconsistentStateException($err);
}
}

function receive_project_text_from_request_body(): string
{
$page_text = receive_data_from_request_body("text");
if (null === $page_text) {
throw new InvalidValue("There is no text");
}
return $page_text;
}

function receive_data_from_request_body($field)
{
$request_data = api_get_request_body();
return $request_data[$field] ?? null;
}
21 changes: 21 additions & 0 deletions pinc/ProofProject.inc
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,27 @@ class ProofProjectPage extends LPage
"saved" => $this->can_be_reverted_to_last_save(),
];
}

public function wc_report(array $accepted_words): void
{
global $pguser;

_Page_require(
$this->projectid,
$this->imagefile,
[$this->round->page_out_state, $this->round->page_temp_state],
$this->round->user_column_name,
$pguser,
'report'
);
save_wordcheck_event(
$this->projectid,
$this->round->id,
$this->imagefile,
$pguser,
$accepted_words
);
}
}

class ProofProject
Expand Down