diff --git a/api/ApiRouter.inc b/api/ApiRouter.inc index eee64f293..fa91e3b9f 100644 --- a/api/ApiRouter.inc +++ b/api/ApiRouter.inc @@ -57,9 +57,8 @@ class ApiRouter * Route an API call to its specific handler. * * @param array $query_params - * @return mixed */ - public function route(string $url, array $query_params) + public function route(string $url, array $query_params): mixed { $node = $this->root; $data = []; @@ -118,8 +117,7 @@ class ApiRouter throw new InvalidAPI($path, $part, $children); } - /** @return mixed */ - public function request(bool $raw = false) + public function request(bool $raw = false): mixed { if ($raw) { return file_get_contents('php://input'); diff --git a/api/api_common.inc b/api/api_common.inc index 1380aa7ae..3774fa78c 100644 --- a/api/api_common.inc +++ b/api/api_common.inc @@ -9,7 +9,7 @@ * * @param array $query_params */ -function get_flag_value(array $query_params, string $flagname) +function get_flag_value(array $query_params, string $flagname): ?bool { if (!isset($query_params[$flagname])) { return null; diff --git a/api/exceptions.inc b/api/exceptions.inc index 4e28ace9b..5307f6c17 100644 --- a/api/exceptions.inc +++ b/api/exceptions.inc @@ -94,6 +94,7 @@ class UnexpectedError extends ApiException class InvalidAPI extends ApiException { + /** @param string[] $children */ public function __construct(string $url, ?string $part, array $children, int $code = 8) { if (is_null($part)) { @@ -114,7 +115,8 @@ class InvalidAPI extends ApiException class MethodNotAllowed extends ApiException { - public function __construct(string $url, string $invalid, array $valids, $code = 9) + /** @param string[] $valids */ + public function __construct(string $url, string $invalid, array $valids, int $code = 9) { $valid = implode(", ", $valids); $message = "API endpoint $url: Method $invalid not supported. Valid methods: $valid."; diff --git a/api/v1_docs.inc b/api/v1_docs.inc index c42210cad..330c10f00 100755 --- a/api/v1_docs.inc +++ b/api/v1_docs.inc @@ -2,7 +2,12 @@ include_once($relPath.'faq.inc'); include_once("api_common.inc"); -/** @param array $query_params */ +/** + * @param array $data + * @param array $query_params + * @return string[] + * List of document IDs + */ function api_v1_documents(string $method, array $data, array $query_params): array { global $external_faq_overrides; @@ -23,7 +28,10 @@ function api_v1_documents(string $method, array $data, array $query_params): arr return $docs; } -/** @param array $query_params */ +/** + * @param array $data + * @param array $query_params + */ function api_v1_document(string $method, array $data, array $query_params): string { $lang_code = $query_params["language_code"] ?? "en"; @@ -36,6 +44,10 @@ function api_v1_document(string $method, array $data, array $query_params): stri return $faq_url; } +/** + * @param array $data + * @return array + */ function api_v1_dictionaries(string $method, array $data): array { $dict_list = get_languages_with_dictionaries(); diff --git a/api/v1_projects.inc b/api/v1_projects.inc index 826829046..e57f111a6 100644 --- a/api/v1_projects.inc +++ b/api/v1_projects.inc @@ -22,7 +22,7 @@ include_once("api_common.inc"); * @return ?array null means 'render all fields' * @throws InvalidValue if any of the filter arguments aren't recognized */ -function get_return_fields(array $query_params, ?Project $project) +function get_return_fields(array $query_params, ?Project $project): ?array { $return_fields = array_get_as_array($query_params, "field", null); if (is_null($return_fields)) { @@ -41,8 +41,12 @@ function get_return_fields(array $query_params, ?Project $project) return $return_fields; } -/** @param array $query_params */ -function api_v1_projects(string $method, array $data, array $query_params) +/** + * @param array $data + * @param array $query_params + * @return array[] + */ +function api_v1_projects(string $method, array $data, array $query_params): array { // set which fields are queryable and their column names $valid_fields = get_project_fields_with_attr("queryable", null); @@ -164,6 +168,7 @@ function api_v1_projects(string $method, array $data, array $query_params) //--------------------------------------------------------------------------- // projects/:projectid +/** @return array */ function get_project_fields_with_attr(?string $attr, ?Project $project): array { // A list of all the fields that can be rendered by render_project_json @@ -226,13 +231,14 @@ function get_project_fields_with_attr(?string $attr, ?Project $project): array /** * Return a list of updatable project fields mapped from the API names * to the Project object names. + * @return string[] */ function get_updatable_project_fields(Project $project): array { return get_project_fields_with_attr("updatable", $project); } -function create_or_update_project(Project $project) +function create_or_update_project(Project $project): Project { // can the user use this update API at all? if (!user_is_PM()) { @@ -317,8 +323,13 @@ function create_or_update_project(Project $project) return $project; } -/** @param array $query_params */ -function api_v1_project(string $method, array $data, array $query_params) +/** + * @param 'GET'|'PUT'|'POST' $method + * @param array $data + * @param array $query_params + * @return array + */ +function api_v1_project(string $method, array $data, array $query_params): array { if ($method == "GET") { // restrict to list of desired fields, if set @@ -336,7 +347,11 @@ function api_v1_project(string $method, array $data, array $query_params) } } -function render_project_json(Project $project, ?array $return_fields = null) +/** + * @param ?string[] $return_fields + * @return array + */ +function render_project_json(Project $project, ?array $return_fields = null): array { // We want to explicitly call out the parameters we want to return so // callers can know what to expect in this version of the API. @@ -385,7 +400,11 @@ function render_project_json(Project $project, ?array $return_fields = null) //--------------------------------------------------------------------------- // projects/:projectID/artifacts/:stageid -function api_v1_project_artifacts(string $method, array $data) +/** + * @param array $data + * @return array{stage: string, name: string, url:string}[] + */ +function api_v1_project_artifacts(string $method, array $data): array { // get the project and the stage $project = $data[":projectid"]; @@ -426,7 +445,12 @@ function api_v1_project_artifacts(string $method, array $data) //--------------------------------------------------------------------------- // projects/:projectID/wordlists/:type -function api_v1_project_wordlists(string $method, array $data) +/** + * @param 'GET'|'PUT' $method + * @param array $data + * @return string|string[] + */ +function api_v1_project_wordlists(string $method, array $data): string|array { // get the project this is for and the type of word list $project = $data[":projectid"]; @@ -459,7 +483,12 @@ function api_v1_project_wordlists(string $method, array $data) //--------------------------------------------------------------------------- // projects/:projectID/holdstates -function api_v1_project_holdstates(string $method, array $data) +/** + * @param 'GET'|'PUT' $method + * @param array $data + * @return string[] + */ +function api_v1_project_holdstates(string $method, array $data): array { $project = $data[":projectid"]; @@ -499,7 +528,11 @@ function api_v1_project_holdstates(string $method, array $data) //--------------------------------------------------------------------------- // projects/:projectid/pages -function api_v1_project_pages(string $method, array $data) +/** + * @param array $data + * @return array{image: string, image_url: string, image_size: int}[] + */ +function api_v1_project_pages(string $method, array $data): array { $project = $data[":projectid"]; @@ -521,7 +554,12 @@ function api_v1_project_pages(string $method, array $data) //--------------------------------------------------------------------------- // projects/:projectid/pagedetails -function api_v1_project_pagedetails(string $method, array $data, array $query_params) +/** + * @param array $data + * @param array $query_params + * @return array[] + */ +function api_v1_project_pagedetails(string $method, array $data, array $query_params): array { // optional page round IDs (one or more) to filter down to $only_rounds = null; @@ -577,7 +615,11 @@ function api_v1_project_pagedetails(string $method, array $data, array $query_pa //--------------------------------------------------------------------------- // projects/:projectid/pages/:pagename/pagerounds/:pageroundid -function api_v1_project_page_round(string $method, array $data) +/** + * @param array $data + * @return array + */ +function api_v1_project_page_round(string $method, array $data): array { if ($data[":pageroundid"] == "OCR") { $text_column = "master_text"; @@ -622,7 +664,11 @@ function api_v1_project_page_round(string $method, array $data) return $json; } -function render_project_page_json($row) +/** + * @param array $row + * @return array{username: string, pagename: string, image_url: string, text: string, state: string} + */ +function render_project_page_json(array $row): array { return [ "username" => $row["user"], @@ -636,7 +682,11 @@ function render_project_page_json($row) //--------------------------------------------------------------------------- // projects/:projectid/transitions -function api_v1_project_transitions(string $method, array $data) +/** + * @param array $data + * @return array{timestamp: string, event_type: string, details: string[]}[] + */ +function api_v1_project_transitions(string $method, array $data): array { $sql = sprintf( " @@ -663,7 +713,11 @@ function api_v1_project_transitions(string $method, array $data) //--------------------------------------------------------------------------- // projects/difficulties -function api_v1_projects_difficulties(string $method, array $data) +/** + * @param array $data + * @return string[] + */ +function api_v1_projects_difficulties(string $method, array $data): array { $difficulties = get_project_difficulties(); return array_keys($difficulties); @@ -672,7 +726,11 @@ function api_v1_projects_difficulties(string $method, array $data) //--------------------------------------------------------------------------- // projects/genres -function api_v1_projects_genres(string $method, array $data) +/** + * @param array $data + * @return string[] + */ +function api_v1_projects_genres(string $method, array $data): array { $genres = ProjectSearchForm::genre_options(); unset($genres['']); @@ -682,7 +740,11 @@ function api_v1_projects_genres(string $method, array $data) //--------------------------------------------------------------------------- // projects/languages -function api_v1_projects_languages(string $method, array $data) +/** + * @param array $data + * @return string[] + */ +function api_v1_projects_languages(string $method, array $data): array { $languages = ProjectSearchForm::language_options(); unset($languages['']); @@ -692,7 +754,11 @@ function api_v1_projects_languages(string $method, array $data) //--------------------------------------------------------------------------- // projects/states -function api_v1_projects_states(string $method, array $data) +/** + * @param array $data + * @return string[] + */ +function api_v1_projects_states(string $method, array $data): array { $states = ProjectSearchForm::state_options(); unset($states['']); @@ -702,7 +768,11 @@ function api_v1_projects_states(string $method, array $data) //--------------------------------------------------------------------------- // projects/pagerounds -function api_v1_projects_pagerounds(string $method, array $data) +/** + * @param array $data + * @return string[] + */ +function api_v1_projects_pagerounds(string $method, array $data): array { return array_merge(["OCR"], Rounds::get_ids()); } @@ -710,8 +780,12 @@ function api_v1_projects_pagerounds(string $method, array $data) //--------------------------------------------------------------------------- // projects/charsuites -/** @param array $query_params */ -function api_v1_projects_charsuites(string $method, array $data, array $query_params) +/** + * @param array $data + * @param array $query_params + * @return array{id: string, name: string, characters: (string|null)[], enabled: bool}[] + */ +function api_v1_projects_charsuites(string $method, array $data, array $query_params): array { $enabled_filter = _get_enabled_filter($query_params); if ($enabled_filter === null) { @@ -740,8 +814,25 @@ function api_v1_projects_charsuites(string $method, array $data, array $query_pa //--------------------------------------------------------------------------- // projects/specialdays -/** @param array $query_params */ -function api_v1_projects_specialdays(string $method, array $data, array $query_params) +/** + * @param array $data + * @param array $query_params + * @return array{ + * id: string, + * name: string, + * comment: string, + * url: string, + * color: string, + * color: string, + * symbol: string, + * date_open_month: int, + * date_open_day: int, + * date_close_month: int, + * date_close_day: int, + * enabled: bool + * }[] + */ +function api_v1_projects_specialdays(string $method, array $data, array $query_params): array { $return_data = []; @@ -775,7 +866,18 @@ function api_v1_projects_specialdays(string $method, array $data, array $query_p //--------------------------------------------------------------------------- // projects/imagesources -/** @param array $query_params */ +/** + * @param array $data + * @param array $query_params + * @return array{ + * id: string, + * name: string, + * name_full: string, + * url: string, + * credit: string, + * enabled: bool + * }[] + */ function api_v1_projects_imagesources(string $method, array $data, array $query_params): array { $return_data = []; @@ -811,6 +913,10 @@ function api_v1_projects_imagesources(string $method, array $data, array $query_ //--------------------------------------------------------------------------- // projects/holdstates +/** + * @param array $data + * @return string[] + */ function api_v1_projects_holdstates(string $method, array $data): array { return Project::get_holdable_states(); @@ -826,8 +932,9 @@ function api_v1_projects_holdstates(string $method, array $data): array * - null - no enabled flag was set * - true - enabled flag was set to "true" or an empty string (for ?enabled) * - false - enabled flag was set to "false" + * @param array $query_params */ -function _get_enabled_filter($query_params) +function _get_enabled_filter(array $query_params): ?bool { return get_flag_value($query_params, "enabled"); } @@ -838,7 +945,9 @@ function _get_enabled_filter($query_params) /** * Checkout a page * + * @param array $data * @param array $query_params + * @return array */ function api_v1_project_checkout(string $method, array $data, array $query_params): array { @@ -855,6 +964,10 @@ function api_v1_project_checkout(string $method, array $data, array $query_param } } +/** + * @param array $data + * @return array{invalid_chars: array} + */ function api_v1_project_validatetext(string $method, array $data): array { $project = $data[":projectid"]; @@ -862,6 +975,10 @@ function api_v1_project_validatetext(string $method, array $data): array return ["invalid_chars" => $invalid_characters]; } +/** + * @param array $data + * @return array{bad_words: array, messages: string[]} + */ function api_v1_project_wordcheck(string $method, array $data): array { $project = $data[":projectid"]; @@ -879,6 +996,17 @@ function api_v1_project_wordcheck(string $method, array $data): array ]; } +/** + * @param array $data + * @return array{ + * name: string, + * subsets: array{ + * name: string, + * title: string, + * rows: (?string)[][][] + * }[] + * }[] + */ function api_v1_project_pickersets(string $method, array $data): array { $project = $data[":projectid"]; @@ -889,8 +1017,11 @@ function api_v1_project_pickersets(string $method, array $data): array /** * Return a page from a project * + * @param 'GET'|'PUT' $method + * @param array $data * @param array $query_params - * @return mixed + * @return ($method is 'GET' ? array{text: string, pagestate: string, saved: bool} + * : mixed) */ // TODO(jchaffraix): Refine this return once all callees have been typed. function api_v1_project_page(string $method, array $data, array $query_params) @@ -939,6 +1070,7 @@ function api_v1_project_page(string $method, array $data, array $query_params) } } +/** @param array $data */ function api_v1_project_page_format_preview(string $method, array $data): void { try { @@ -956,6 +1088,7 @@ function api_v1_project_page_format_preview(string $method, array $data): void } } +/** @param array $data */ function api_v1_project_page_report_bad(string $method, array $data): void { global $pguser, $PAGE_BADNESS_REASONS; @@ -984,6 +1117,7 @@ function api_v1_project_page_report_bad(string $method, array $data): void } } +/** @param array $data */ function api_v1_project_page_wordcheck(string $method, array $data): void { try { @@ -1052,7 +1186,7 @@ function receive_project_text_from_request_body(): string return $page_text; } -function receive_data_from_request_body(string $field) +function receive_data_from_request_body(string $field): mixed { $request_data = api_get_request_body(); return $request_data[$field] ?? null; diff --git a/api/v1_queues.inc b/api/v1_queues.inc index 9f43b3606..da6ef50d9 100644 --- a/api/v1_queues.inc +++ b/api/v1_queues.inc @@ -8,7 +8,11 @@ include_once("api_common.inc"); //--------------------------------------------------------------------------- // queues -- list queues, optionally filtered by round -/** @param array $query_params */ +/** + * @param array $data + * @param array $query_params + * @return array[] + */ function api_v1_queues(string $method, array $data, array $query_params): array { $roundid = $query_params["roundid"] ?? null; @@ -56,6 +60,11 @@ function api_v1_queues(string $method, array $data, array $query_params): array //--------------------------------------------------------------------------- // queues/:queueid -- return release queue info + +/** + * @param array $data + * @return array + */ function api_v1_queue(string $method, array $data): array { $queue = $data[":queueid"]; @@ -65,6 +74,11 @@ function api_v1_queue(string $method, array $data): array //--------------------------------------------------------------------------- // queue/:queueid/stats -- return release queue stats + +/** + * @param array $data + * @return array + */ function api_v1_queue_stats(string $method, array $data): array { $queue = $data[":queueid"]; @@ -77,7 +91,12 @@ function api_v1_queue_stats(string $method, array $data): array //--------------------------------------------------------------------------- // queue/:queueid/projects -- list projects in release queue -/** @param array $query_params */ + +/** + * @param array $data + * @param array $query_params + * @return array[] + */ function api_v1_queue_projects(string $method, array $data, array $query_params): array { $queue = $data[":queueid"]; diff --git a/api/v1_stats.inc b/api/v1_stats.inc index 639a9c454..0d6bf7d63 100644 --- a/api/v1_stats.inc +++ b/api/v1_stats.inc @@ -6,7 +6,11 @@ include_once("exceptions.inc"); //--------------------------------------------------------------------------- // stats/site -function api_v1_stats_site(string $method, array $data) +/** + * @param array $data + * @return array{server_time: string, ...} + */ +function api_v1_stats_site(string $method, array $data): array { $res = DPDatabase::query("SELECT COUNT(*) FROM users"); [$registered_users] = mysqli_fetch_row($res); @@ -35,25 +39,30 @@ function api_v1_stats_site(string $method, array $data) //--------------------------------------------------------------------------- // stats/site/projects_states -// Produces output like -// ``` -// { -// "project_new": 224, -// "project_bad": 0, -// "F1.proj_avail": 11, -// "F2.proj_avail": 7, -// "F2.proj_unavail": 2, -// "F2.proj_waiting": 1, -// ... -// "P3.proj_unavail": 1, -// "proj_post_first_available": 4, -// "proj_post_first_checked_out": 24, -// "proj_post_first_unavailable": 3, -// "proj_post_second_available": 4, -// "proj_post_second_checked_out": 2, -// "proj_delete": 46, -// }``` -function api_v1_stats_site_projects_states(string $method, array $data) + +/** + * Produces output like + * ``` + * { + * "project_new": 224, + * "project_bad": 0, + * "F1.proj_avail": 11, + * "F2.proj_avail": 7, + * "F2.proj_unavail": 2, + * "F2.proj_waiting": 1, + * ... + * "P3.proj_unavail": 1, + * "proj_post_first_available": 4, + * "proj_post_first_checked_out": 24, + * "proj_post_first_unavailable": 3, + * "proj_post_second_available": 4, + * "proj_post_second_checked_out": 2, + * "proj_delete": 46, + * }``` + * @param array $data + * @return array + */ +function api_v1_stats_site_projects_states(string $method, array $data): array { // Make sure all project state statistics are provided. $output = []; @@ -74,7 +83,11 @@ function api_v1_stats_site_projects_states(string $method, array $data) return $output; } -function api_v1_stats_site_projects_stages(string $method, array $data) +/** + * @param array $data + * @return array + */ +function api_v1_stats_site_projects_stages(string $method, array $data): array { // Make sure all project stage statistics are provided. $output = []; @@ -121,7 +134,8 @@ function api_v1_stats_site_projects_stages(string $method, array $data) //--------------------------------------------------------------------------- // stats/site/rounds -function render_round_stats($round_id) +/** @return array */ +function render_round_stats(string $round_id): array { $stats = get_site_page_tally_summary($round_id); $tallyboard = new TallyBoard($round_id, 'U'); @@ -136,7 +150,11 @@ function render_round_stats($round_id) ]; } -function api_v1_stats_site_rounds(string $method, array $data) +/** + * @param array $data + * @return array> + */ +function api_v1_stats_site_rounds(string $method, array $data): array { $return = []; foreach (Rounds::get_ids() as $round_id) { @@ -149,7 +167,11 @@ function api_v1_stats_site_rounds(string $method, array $data) //--------------------------------------------------------------------------- // stats/site/rounds/:roundid -function api_v1_stats_site_round(string $method, array $data) +/** + * @param array $data + * @return array + */ +function api_v1_stats_site_round(string $method, array $data): array { $round = $data[":roundid"]; @@ -159,7 +181,8 @@ function api_v1_stats_site_round(string $method, array $data) //--------------------------------------------------------------------------- // stats/user/:username/rounds -function render_round_user_stats(User $user, Round $round) +/** @return array */ +function render_round_user_stats(User $user, Round $round): array { if (!user_is_a_sitemanager()) { if ($user->username != User::current_username()) { @@ -184,7 +207,11 @@ function render_round_user_stats(User $user, Round $round) ]; } -function api_v1_stats_user_rounds(string $method, array $data) +/** + * @param array $data + * @return array> + */ +function api_v1_stats_user_rounds(string $method, array $data): array { $user = $data[":username"]; @@ -198,7 +225,12 @@ function api_v1_stats_user_rounds(string $method, array $data) //--------------------------------------------------------------------------- // stats/user/:username/rounds/:roundid -function api_v1_stats_user_round(string $method, array $data) + +/** + * @param array $data + * @return array + */ +function api_v1_stats_user_round(string $method, array $data): array { $user = $data[":username"]; $round = $data[":roundid"]; diff --git a/api/v1_storage.inc b/api/v1_storage.inc index 1ae99cef1..0192223c5 100644 --- a/api/v1_storage.inc +++ b/api/v1_storage.inc @@ -7,10 +7,10 @@ /** * Store/retrieve storage item (depending on the method). - * - * @return mixed + * @param 'GET'|'PUT' $method + * @param array $data */ -function api_v1_storage(string $method, array $data) +function api_v1_storage(string $method, array $data): mixed { global $pguser; @@ -33,6 +33,7 @@ function api_v1_storage(string $method, array $data) } } +/** @param array $data */ function api_v1_storage_delete(string $method, array $data): void { global $pguser; diff --git a/api/v1_validators.inc b/api/v1_validators.inc index 8f9fb9927..b492de6c9 100644 --- a/api/v1_validators.inc +++ b/api/v1_validators.inc @@ -5,6 +5,7 @@ include_once($relPath.'release_queue.inc'); //=========================================================================== // Validators +/** @param array $_data */ function validate_stage(string $stageid, array $_data): Stage { try { @@ -18,6 +19,7 @@ function validate_stage(string $stageid, array $_data): Stage } } +/** @param array $_data */ function validate_round(string $roundid, array $_data): Round { try { @@ -31,6 +33,7 @@ function validate_round(string $roundid, array $_data): Round } } +/** @param array $_data */ function validate_project(string $projectid, array $_data): Project { // validate and load the specified projectid @@ -41,6 +44,7 @@ function validate_project(string $projectid, array $_data): Project } } +/** @param array $_data */ function validate_wordlist(string $wordlist, array $_data): string { if (!in_array($wordlist, ["good", "bad"])) { @@ -49,6 +53,7 @@ function validate_wordlist(string $wordlist, array $_data): string return $wordlist; } +/** @param array $data */ function validate_page_name(string $pagename, array $data): ProjectPage { try { @@ -58,6 +63,7 @@ function validate_page_name(string $pagename, array $data): ProjectPage } } +/** @param array $_data */ function validate_page_round(string $pageround, array $_data): string { try { @@ -72,6 +78,10 @@ function validate_page_round(string $pageround, array $_data): string } } +/** + * @param array $_data + * @return array + */ function validate_release_queue(string $queueid, array $_data): array { $queue_data = fetch_queue_data((int)$queueid); @@ -91,6 +101,7 @@ function validate_document(string $document): string return $document; } +/** @param array $data */ function validate_storage_key(string $storage_key, array $data): string { if (!in_array($storage_key, SiteConfig::get()->api_storage_keys)) { diff --git a/crontab/AutoModify.inc b/crontab/AutoModify.inc index fb27e41d4..66fc470df 100644 --- a/crontab/AutoModify.inc +++ b/crontab/AutoModify.inc @@ -7,6 +7,7 @@ class AutoModify extends BackgroundJob { public bool $requires_web_context = true; + /** @var ?resource $filehandle */ private $filehandle = null; private ?string $logfile = null; diff --git a/crontab/NotifyOldPP.inc b/crontab/NotifyOldPP.inc index 3b6b57219..e7dcb1b3d 100644 --- a/crontab/NotifyOldPP.inc +++ b/crontab/NotifyOldPP.inc @@ -34,7 +34,11 @@ class NotifyOldPP extends BackgroundJob $this->stop_message = "Sent notifications to {$this->notifications_sent} users"; } - private function send_pp_reminders($PPer, $projects, $which_message) + /** + * @param array[] $projects + * @param 'first'|'second' $which_message + */ + private function send_pp_reminders(string $PPer, array $projects, string $which_message): void { global $code_url; global $pp_alert_threshold_days; diff --git a/phpstan.neon b/phpstan.neon index 366078137..fc5c5f7fc 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -26,32 +26,23 @@ parameters: # TODO(bpfoley) PHPStan level 6 errors we haven't fixed yet - identifier: missingType.return paths: - - api/api_common.inc - api/index.php - - api/v1_projects.inc - - api/v1_stats.inc - accounts/addproofer.php - accounts/login.php - credits.php - - crontab/NotifyOldPP.inc - faq/font_sample.php - faq/privacy.php - faq/prooffacehelp.php - faq/wordcheck_data.php - index.php - locale/translators/index.php - - quiz/generic/quiz_page.inc - quiz/generic/returnfeed.php - quiz/generic/wizard/checks.php - quiz/generic/wizard/messages.php - quiz/generic/wizard/output.php - quiz/generic/wizard/output_quiz.php - quiz/generic/wizard/quiz_pages.php - - quiz/small_theme.inc - stats/equilibria.php - - stats/includes/common.inc - - stats/includes/member.inc - - stats/includes/team.inc - stats/index.php - stats/misc_stats1.php - stats/pp_stage_goal.php @@ -64,7 +55,6 @@ parameters: - tools/project_manager/bad_bytes_explainer.php - tools/project_manager/clearance_check.php - tools/project_manager/diff.php - - tools/project_manager/edit_common.inc - tools/project_manager/edit_project_word_lists.php - tools/project_manager/editproject.php - tools/project_manager/external_catalog_search.php @@ -72,55 +62,38 @@ parameters: - tools/project_manager/handle_bad_page.php - tools/project_manager/manage_image_sources.php - tools/project_manager/page_detail.php - - tools/project_manager/page_operations.inc - - tools/project_manager/projectmgr.inc - tools/project_manager/projectmgr.php - tools/project_manager/remote_file_manager.php - tools/project_manager/show_good_word_suggestions_detail.php - tools/project_manager/show_image_sources.php - tools/project_manager/show_specials.php - tools/project_manager/update_illos.php - - tools/project_manager/word_freq_table.inc - tools/proofers/for_mentors.php - - tools/proofers/image_block_enh.inc - tools/proofers/images_index.php - tools/proofers/mktable.php - tools/proofers/my_projects.php - tools/proofers/my_suggestions.php - - tools/proofers/preview.inc - tools/proofers/proof_frame.php - - tools/proofers/proof_frame_enh.inc - - tools/proofers/proof_frame_std.inc - tools/proofers/review_work.php - - tools/proofers/spellcheck_text.inc - tools/set_project_event_subs.php - tools/site_admin/projects_with_odd_values.php - tools/site_search.php - tools/upload_resumable_file.php - identifier: missingType.parameter paths: - - api/exceptions.inc - api/index.php - - api/v1_projects.inc - - api/v1_stats.inc - credits.php - - crontab/NotifyOldPP.inc - faq/font_sample.php - faq/privacy.php - faq/prooffacehelp.php - faq/wordcheck_data.php - locale/translators/index.php - - quiz/generic/quiz_page.inc - quiz/generic/returnfeed.php - quiz/generic/wizard/messages.php - quiz/generic/wizard/output.php - quiz/generic/wizard/output_quiz.php - quiz/generic/wizard/quiz_pages.php - - quiz/small_theme.inc - stats/equilibria.php - - stats/includes/common.inc - - stats/includes/member.inc - - stats/includes/team.inc - stats/index.php - stats/misc_stats1.php - stats/pp_stage_goal.php @@ -131,38 +104,25 @@ parameters: - tools/project_manager/bad_bytes_explainer.php - tools/project_manager/clearance_check.php - tools/project_manager/diff.php - - tools/project_manager/edit_common.inc - tools/project_manager/edit_project_word_lists.php - tools/project_manager/editproject.php - tools/project_manager/generate_post_files.php - tools/project_manager/handle_bad_page.php - tools/project_manager/manage_image_sources.php - - tools/project_manager/page_operations.inc - tools/project_manager/projectmgr.php - tools/project_manager/show_good_word_suggestions_detail.php - tools/project_manager/update_illos.php - - tools/project_manager/word_freq_table.inc - tools/proofers/images_index.php - tools/proofers/mktable.php - tools/proofers/my_projects.php - tools/proofers/my_suggestions.php - tools/proofers/proof_frame.php - - tools/proofers/proof_frame_enh.inc - - tools/proofers/proof_frame_std.inc - tools/proofers/review_work.php - - tools/proofers/spellcheck_text.inc - tools/set_project_event_subs.php - tools/site_admin/projects_with_odd_values.php - tools/upload_resumable_file.php - identifier: missingType.iterableValue paths: - - api/exceptions.inc - - api/v1_docs.inc - - api/v1_projects.inc - - api/v1_queues.inc - - api/v1_stats.inc - - api/v1_storage.inc - - api/v1_validators.inc - credits.php - index.php - tasks.php @@ -173,16 +133,11 @@ parameters: - tools/project_manager/show_good_word_suggestions.php - tools/project_manager/show_project_possible_bad_words.php - tools/project_manager/show_project_stealth_scannos.php - - tools/project_manager/word_freq_table.inc - tools/proofers/for_mentors.php - - tools/proofers/spellcheck_text.inc - tools/site_admin/copy_pages.php - tools/site_admin/delete_pages.php - tools/site_admin/shared_postednums.php - tools/site_search.php - - identifier: missingType.property - paths: - - crontab/AutoModify.inc # Errors in third party code, and our interfaces to it - message: '#Property .* does not accept false#' diff --git a/pinc/ProofProject.inc b/pinc/ProofProject.inc index 8b60a6a5a..df2ef44f3 100644 --- a/pinc/ProofProject.inc +++ b/pinc/ProofProject.inc @@ -87,7 +87,7 @@ class ProofProjectPage extends LPage ]; } - /** @return array */ + /** @return array{text: string, pagestate: string, saved: bool} */ public function get_page_text_data(): array { return [ diff --git a/pinc/forum_interface_phpbb3.inc b/pinc/forum_interface_phpbb3.inc index 16979be67..070bdd105 100644 --- a/pinc/forum_interface_phpbb3.inc +++ b/pinc/forum_interface_phpbb3.inc @@ -549,7 +549,7 @@ function get_url_to_view_post(int $post_id): string * * If no avatar is defined, this function returns NULL. */ -function get_url_for_user_avatar(int $username): ?string +function get_url_for_user_avatar(string $username): ?string { $user_details = get_forum_user_details($username); diff --git a/quiz/generic/quiz_page.inc b/quiz/generic/quiz_page.inc index 871600299..5a832da15 100644 --- a/quiz/generic/quiz_page.inc +++ b/quiz/generic/quiz_page.inc @@ -61,7 +61,7 @@ $quiz_feedbacktext = sprintf($default_feedbacktext, $quiz_feedbackurl); // called by main.php: -function qp_round_id_for_pi_toolbox() +function qp_round_id_for_pi_toolbox(): string { global $quiz; if ($quiz->activity_type == 'proof') { @@ -77,7 +77,7 @@ function qp_round_id_for_pi_toolbox() // called by orig.php: -function qp_page_image_path() +function qp_page_image_path(): string { global $quiz_page_id; return "./images/qi_$quiz_page_id.png"; @@ -88,13 +88,13 @@ function qp_page_image_path() // called from proof.php: -function qp_initial_page_text() +function qp_initial_page_text(): string { global $initial_text; return $initial_text; } -function qp_sample_solution() +function qp_sample_solution(): string { global $solutions; return $solutions[0]; @@ -104,7 +104,7 @@ function qp_sample_solution() // called from right.php: -function qp_echo_introduction_html() +function qp_echo_introduction_html(): void { global $intro_title, $initial_instructions, $constant_message; @@ -121,7 +121,8 @@ function qp_echo_introduction_html() // called by returnfeed.php: -function qp_text_contains_anticipated_error($text, $test) +/** @param array $test */ +function qp_text_contains_anticipated_error(string $text, array $test): string { switch ($test['type']) { case "forbiddentext": @@ -245,22 +246,22 @@ function qp_text_contains_anticipated_error($text, $test) return ""; } -function in_string($needle, $haystack, $sensitive = 0) +function in_string(string $needle, string $haystack, bool $cs = false): bool { - return (str_posn($haystack, $needle, $sensitive) !== false); + return (str_posn($haystack, $needle, $cs) !== false); } /** * Find the numeric (0-based) position of * the first occurrence of $needle in $haystack. * - * The search is case-sensitive or not, depending on - * whether the value of $cs is true-ish or not (respectively). + * @param bool $cs + * Is the search is case-sensitive * - * Returns FALSE if $needle is not found. - * Be careful to distinguish FALSE from 0. + * @return false|int + * false if `$needle` is not found, and string index if it is found */ -function str_posn($haystack, $needle, $cs) +function str_posn(string $haystack, string $needle, bool $cs): false|int { if ($cs) { return strpos($haystack, $needle); @@ -269,7 +270,7 @@ function str_posn($haystack, $needle, $cs) } } -function number_of_occurrences($haystack, $needle, $cs) +function number_of_occurrences(string $haystack, string $needle, bool $cs): int { if (!$cs) { $needle = strtolower($needle); @@ -281,7 +282,7 @@ function number_of_occurrences($haystack, $needle, $cs) // ============================================================================= -function qp_echo_error_html($message_id) +function qp_echo_error_html(string $message_id): void { global $messages, $constant_message; // from the qd file global $default_challenge; // from quiz_defaults.inc @@ -350,7 +351,7 @@ function qp_echo_error_html($message_id) echo_quiz_feedback_and_links(@$message["feedbacktext"]); } -function echo_quiz_feedback_and_links($message = null) +function echo_quiz_feedback_and_links(?string $message = null): void { global $code_dir; global $quiz_feedbacktext; @@ -387,7 +388,7 @@ function echo_quiz_feedback_and_links($message = null) // ============================================================================= -function qp_choose_solution($text) +function qp_choose_solution(string $text): string { global $solutions, $criteria; @@ -429,7 +430,7 @@ function qp_choose_solution($text) * If the two texts are the same, return FALSE. * If they differ, output HTML that describes how they differ, and return TRUE. */ -function qp_compare_texts($user_text, $soln_text) +function qp_compare_texts(string $user_text, string $soln_text): bool { if ($user_text == $soln_text) { return false; @@ -449,7 +450,7 @@ function qp_compare_texts($user_text, $soln_text) return true; } -function qp_describe_difference($user_text, $soln_text) +function qp_describe_difference(string $user_text, string $soln_text): void { assert($user_text != $soln_text); @@ -520,7 +521,7 @@ function qp_describe_difference($user_text, $soln_text) // ============================================================================= -function qp_echo_solved_html() +function qp_echo_solved_html(): void { global $code_dir; global $quiz_page_id, $quiz; @@ -568,7 +569,7 @@ function qp_echo_solved_html() echo "\n"; } -function qp_exit_link($url, $text) +function qp_exit_link(string $url, string $text): string { return "
  • $text
  • "; } @@ -577,7 +578,7 @@ function qp_exit_link($url, $text) // called from hints.php: -function qp_echo_hint_html($message_id, $hint_number) +function qp_echo_hint_html(string $message_id, int $hint_number): void { global $messages; @@ -605,7 +606,7 @@ function qp_echo_hint_html($message_id, $hint_number) qp_echo_link_to_hint_if_it_exists($message_id, $hint_number + 1); } -function qp_echo_link_to_hint_if_it_exists($message_id, $hint_number) +function qp_echo_link_to_hint_if_it_exists(string $message_id, int $hint_number): void { global $quiz_page_id; global $messages, $default_hintlink; diff --git a/quiz/small_theme.inc b/quiz/small_theme.inc index 403640d4f..65e46933d 100644 --- a/quiz/small_theme.inc +++ b/quiz/small_theme.inc @@ -3,7 +3,7 @@ include_once($relPath.'html_page_common.inc'); // output_html_header() include_once($relPath.'theme.inc'); // headerbar_text_array() include_once($relPath.'faq.inc'); -function output_small_header($quiz) +function output_small_header(Quiz $quiz): void { output_html_header(''); @@ -61,7 +61,7 @@ function output_small_header($quiz) register_shutdown_function('output_small_footer'); } -function output_small_footer() +function output_small_footer(): void { echo "\n"; output_html_footer(); diff --git a/stats/includes/common.inc b/stats/includes/common.inc index 4d8723f0d..31c00cf1c 100644 --- a/stats/includes/common.inc +++ b/stats/includes/common.inc @@ -5,7 +5,7 @@ * Return a snippet of HTML that visually conveys * the change in rank between $previous_rank and $current_rank. */ -function showChangeInRank($previous_rank, $current_rank) +function format_change_in_rank(int $previous_rank, int $current_rank): string { if (empty($current_rank) || empty($previous_rank)) { // Normally, this means that the rank is zero, @@ -42,8 +42,9 @@ function showChangeInRank($previous_rank, $current_rank) return $snippet; } -function get_username_for_uid($u_id) +function get_username_for_uid(int $u_id): string { + // TODO this is fallible! $user = User::load_from_uid($u_id); return $user->username; } diff --git a/stats/includes/member.inc b/stats/includes/member.inc index be8a3bff9..b3e6a7eb5 100644 --- a/stats/includes/member.inc +++ b/stats/includes/member.inc @@ -11,7 +11,7 @@ include_once($relPath.'forum_interface.inc'); include_once($relPath.'Settings.inc'); include_once($relPath.'graph_data.inc'); -function showMbrInformation($user, $tally_name) +function showMbrInformation(User $user, ?string $tally_name): void { showMbrProfile($user); @@ -29,7 +29,7 @@ function showMbrInformation($user, $tally_name) } } -function showXmlButton($username) +function format_xml_button(string $username): string { global $code_url; @@ -40,7 +40,7 @@ function showXmlButton($username) return $xml_button; } -function showMbrProfile($user) +function showMbrProfile(User $user): void { echo "\n"; echo ""; @@ -69,7 +69,7 @@ function showMbrProfile($user) * Return a string like "Today", or "Yesterday", or "2 days ago" depending on * a timestamp */ -function days_to_now($timestamp) +function days_to_now(?int $timestamp): string { // Ensure that all calls to this function have the same base time. static $now = null; @@ -90,7 +90,7 @@ function days_to_now($timestamp) } } -function showMbrDpProfile($user) +function showMbrDpProfile(User $user): void { // Days since joined: $daysInExistenceString = days_to_now($user->date_created); @@ -117,17 +117,17 @@ function showMbrDpProfile($user) ); $t->row( _('Roles'), - showMbrRoles($user) + format_mbr_roles($user) ); $t->row( _("Stats Feed"), - showXmlButton($user->username) + format_xml_button($user->username) ); $t->end(); } -function showMbrRoles($user) +function format_mbr_roles(User $user): string { [$users_ELR_page_tallyboard, ] = get_ELR_tallyboards(); $current_P_page_tally = $users_ELR_page_tallyboard->get_current_tally($user->u_id); @@ -192,7 +192,7 @@ function showMbrRoles($user) return $mbrStatus; } -function showForumProfile($username) +function showForumProfile(string $username): void { $bb_user = get_forum_user_details($username); if (is_null($bb_user)) { @@ -354,7 +354,7 @@ function showForumProfile($username) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function showMbrAccess($user) +function showMbrAccess(User $user): void { if (!user_can_see_user_access_chart_of($user->username)) { return; @@ -369,7 +369,7 @@ function showMbrAccess($user) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function showMbrTallySelector($u_id, $tally_name) +function showMbrTallySelector(int $u_id, ?string $tally_name): void { $choices = ''; $page_tally_names = get_page_tally_names(); @@ -405,7 +405,7 @@ function showMbrTallySelector($u_id, $tally_name) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function showMbrPageStats($user, $tally_name) +function showMbrPageStats(User $user, string $tally_name): void { global $ELR_round; @@ -468,7 +468,7 @@ function showMbrPageStats($user, $tally_name) _("Highest Rank"), number_format($vitals->best_rank) . " (" . date("M. jS, Y", $vitals->best_rank_timestamp - 1) . ")" - . " " . showChangeInRank($vitals->best_rank, $vitals->current_rank) + . " " . format_change_in_rank($vitals->best_rank, $vitals->current_rank) ); $t->row( _("Best Day Ever"), @@ -483,7 +483,7 @@ function showMbrPageStats($user, $tally_name) $t->end(); } -function showMbrNeighbors($user, $tally_name) +function showMbrNeighbors(User $user, string $tally_name): void { $now = time(); @@ -534,7 +534,7 @@ function showMbrNeighbors($user, $tally_name) $t->end(); } -function showMbrTeams($user) +function showMbrTeams(User $user): void { global $code_url; @@ -576,7 +576,7 @@ function showMbrTeams($user) $t->end(); } -function showMbrHistory($user, $tally_name) +function showMbrHistory(User $user, string $tally_name): void { if (@$_GET['range'] == 'all') { $range = 'all'; diff --git a/stats/includes/team.inc b/stats/includes/team.inc index f4d40ef46..c5af8d0f6 100644 --- a/stats/includes/team.inc +++ b/stats/includes/team.inc @@ -17,7 +17,7 @@ $team_icons_url = SiteConfig::get()->dyn_url . "/teams/icon"; // Define the maximum number of teams the user can be a member of. define("MAX_USER_TEAM_MEMBERSHIP", 6); -function select_from_teams($where_body, $other_clauses = '') +function select_from_teams(string $where_body, string $other_clauses = ''): mysqli_result { [, $teams_ELR_page_tallyboard] = get_ELR_tallyboards(); [$joined_with_team_ELR_page_tallies, $team_ELR_page_tally_column] = @@ -42,7 +42,8 @@ function select_from_teams($where_body, $other_clauses = '') // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function showTeamInformation($curTeam, $tally_name) +/** @param array $curTeam */ +function showTeamInformation(array $curTeam, ?string $tally_name): void { showTeamProfile($curTeam); @@ -62,7 +63,8 @@ function showTeamInformation($curTeam, $tally_name) // ----------------------------------------------------------------------------- -function showTeamProfile($curTeam, $preview = false) +/** @param array $curTeam */ +function showTeamProfile(array $curTeam, bool $preview = false): void { global $team_avatars_url; global $code_url; @@ -199,7 +201,7 @@ function showTeamProfile($curTeam, $preview = false) echo "
    "; } -function team_get_member_count_rank($team_id) +function team_get_member_count_rank(int $team_id): ?int { $result = DPDatabase::query(" SELECT id @@ -213,11 +215,13 @@ function team_get_member_count_rank($team_id) } $i++; } + return null; } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function showTeamTallySelector($curTeam, $tally_name) +/** @param array $curTeam */ +function showTeamTallySelector(array $curTeam, ?string $tally_name): void { $team_id = $curTeam['id']; @@ -255,7 +259,8 @@ function showTeamTallySelector($curTeam, $tally_name) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function showTeamStats($curTeam, $tally_name) +/** @param array $curTeam */ +function showTeamStats(array $curTeam, ?string $tally_name): void { $teams_tallyboard = new TallyBoard($tally_name, 'T'); @@ -291,7 +296,8 @@ function showTeamStats($curTeam, $tally_name) $t->end(); } -function showTeamMbrs($curTeam, $tally_name) +/** @param array $curTeam */ +function showTeamMbrs(array $curTeam, ?string $tally_name): void { global $code_url; @@ -405,7 +411,8 @@ function showTeamMbrs($curTeam, $tally_name) $t->end(); } -function showTeamHistory($curTeam, $tally_name) +/** @param array $curTeam */ +function showTeamHistory(array $curTeam, ?string $tally_name): void { if (@$_GET['range'] == 'all') { $range = 'all'; @@ -441,7 +448,7 @@ function showTeamHistory($curTeam, $tally_name) echo ""; } -function stripAllString($ttext) +function stripAllString(string $ttext): string { return str_replace( ['[b]', '[B]', '[/b]', '[/B]', '[i]', '[I]', '[/i]', '[/I]', '[p]', '[P]', '[/p]', '[/P]', '[lb]', '[LB]'], @@ -450,7 +457,7 @@ function stripAllString($ttext) ); } -function unstripAllString($ttext) +function unstripAllString(string $ttext): string { return str_replace( ['', '', '', '', '

    ', '

    ', '
    '], @@ -459,14 +466,14 @@ function unstripAllString($ttext) ); } -function showEdit($tname, $ttext, $twebpage, $tedit, $tsid) +function showEdit(string $tname, string $ttext, string $twebpage, bool $tedit, int $tsid): void { global $teamimages; $user = User::load_current(); echo "
    "; echo ""; - if ($tedit != 1) { + if (!$tedit) { echo _("Edit Team Information"); } else { echo _("New Proofreading Team"); @@ -558,7 +565,13 @@ function showEdit($tname, $ttext, $twebpage, $tedit, $tsid) } -function uploadImages($preview, $tid, $type) +/** + * TODO: fuse $preview and $tid + * @param 'avatar'|'icon'|'both' $type + * @param ($preview is false ? int|string : null) $tid + * @return ?array{avatar: ?string, icon: ?string } + */ +function uploadImages(bool $preview, null|int|string $tid, string $type): ?array { global $team_avatars_dir, $team_icons_dir; $teamimages = [ @@ -585,18 +598,18 @@ function uploadImages($preview, $tid, $type) if (strtolower(substr($_FILES['teamavatar']['name'], -4)) == ".png" || strtolower(substr($_FILES['teamavatar']['name'], -4)) == ".jpg" || strtolower(substr($_FILES['teamavatar']['name'], -4)) == ".gif") { if ($_FILES['teamavatar']['size'] > 2097152) { echo "

    "._("The avatar uploaded is too large. Please limit the file size to 2MB or less.")."

    "; - return; + return null; } $avatarID = uniqid("avatar_").substr($_FILES['teamavatar']['name'], -4); $upload_avatar_dir = "$team_avatars_dir/$avatarID"; move_uploaded_file($_FILES['teamavatar']['tmp_name'], $upload_avatar_dir); - if ($preview != 1) { + if (!$preview) { DPDatabase::query("UPDATE user_teams SET avatar='$avatarID' WHERE id = $tid"); } $teamimages['avatar'] = $avatarID; } else { echo "

    "._("The avatar uploaded must be either a JPEG, GIF, or PNG file.")."

    "; - return; + return null; } } @@ -604,18 +617,18 @@ function uploadImages($preview, $tid, $type) if (strtolower(substr($_FILES['teamicon']['name'], -4)) == ".png" || strtolower(substr($_FILES['teamicon']['name'], -4)) == ".jpg" || strtolower(substr($_FILES['teamicon']['name'], -4)) == ".gif") { if ($_FILES['teamicon']['size'] > 1048576) { echo "

    "._("The icon uploaded is too large. Please limit the file size to 1MB or less.")."

    "; - return; + return null; } $iconID = uniqid("icon_").substr($_FILES['teamicon']['name'], -4); $upload_icon_dir = "$team_icons_dir/$iconID"; move_uploaded_file($_FILES['teamicon']['tmp_name'], $upload_icon_dir); - if ($preview != 1) { + if (!$preview) { DPDatabase::query("UPDATE user_teams SET icon='$iconID' WHERE id = $tid"); } $teamimages['icon'] = $iconID; } else { echo "

    "._("The icon uploaded must be either a JPEG, GIF, or PNG file.")."

    "; - return; + return null; } } @@ -623,7 +636,7 @@ function uploadImages($preview, $tid, $type) return $teamimages; } -function deleteImages() +function deleteImages(): void { global $team_avatars_dir, $team_icons_dir; $oneHourAgo = time() - 600; diff --git a/stats/teams/new_team.php b/stats/teams/new_team.php index 909679cf9..892875f8d 100644 --- a/stats/teams/new_team.php +++ b/stats/teams/new_team.php @@ -25,7 +25,7 @@ if (isset($_POST['mkPreview'])) { $title = sprintf(_("Preview %s"), $teamname); output_header($title, NO_STATSBAR, $theme_extra_args); - $teamimages = uploadImages(1, "", "both"); + $teamimages = uploadImages(true, null, "both"); $curTeam['id'] = 0; $curTeam['topic_id'] = 0; $curTeam['teamname'] = $teamname; @@ -37,7 +37,7 @@ $curTeam['member_count'] = 0; $curTeam['avatar'] = $teamimages['avatar']; echo "

    "; - showEdit($teamname, $text_data, $teamwebpage, 1, 0); + showEdit($teamname, $text_data, $teamwebpage, true, 0); echo "
    "; showTeamProfile($curTeam, /* $preview= */ true); echo "

    "; @@ -54,7 +54,7 @@ if (mysqli_num_rows($result) > 0 || $teamname == "") { $name = _("Create Team"); output_header($name, NO_STATSBAR); - $teamimages = uploadImages(1, "", "both"); + $teamimages = uploadImages(true, null, "both"); $curTeam['avatar'] = $teamimages['avatar']; if ($teamname == "") { echo "

    " . _("The team name must not be empty.") . "

    "; @@ -62,7 +62,7 @@ echo "

    " . _("The team name must be unique. Please make any changes and resubmit.") . "

    "; } - showEdit($teamname, $text_data, $teamwebpage, 1, 0); + showEdit($teamname, $text_data, $teamwebpage, true, 0); } else { $sql = sprintf( " @@ -91,7 +91,7 @@ ); DPDatabase::query($sql); } elseif (!empty($_FILES['teamavatar'])) { - uploadImages(0, $tid, "avatar"); + uploadImages(false, $tid, "avatar"); } if (!empty($ticon)) { $sql = sprintf( @@ -105,7 +105,7 @@ ); DPDatabase::query($sql); } elseif (!empty($_FILES['teamicon'])) { - uploadImages(0, $tid, "icon"); + uploadImages(false, $tid, "icon"); } //figure out which team to overwrite @@ -123,6 +123,6 @@ $name = _("Create a New Team"); output_header($name, NO_STATSBAR, $theme_extra_args); echo "

    "; - showEdit("", "", "", 1, 0); + showEdit("", "", "", true, 0); echo "
    "; } diff --git a/stats/teams/tedit.php b/stats/teams/tedit.php index 366eb3c5f..622f713d4 100644 --- a/stats/teams/tedit.php +++ b/stats/teams/tedit.php @@ -41,7 +41,7 @@ $edit = _("Edit"); output_header($edit . " " . $curTeam['teamname'], NO_STATSBAR, $theme_extra_args); echo "

    "; - showEdit($curTeam['teamname'], $curTeam['team_info'], $curTeam['webpage'], 0, $tid); + showEdit($curTeam['teamname'], $curTeam['team_info'], $curTeam['webpage'], false, $tid); echo "
    "; } elseif (isset($_POST['edQuit'])) { $title = _("Quit Without Saving"); @@ -50,13 +50,13 @@ } elseif (isset($_POST['edPreview'])) { $preview = _("Preview"); output_header($preview . " " . $teamname, NO_STATSBAR, $theme_extra_args); - $teamimages = uploadImages(1, $tid, "both"); + $teamimages = uploadImages(true, $tid, "both"); $curTeam['teamname'] = $teamname; $curTeam['team_info'] = $text_data; $curTeam['webpage'] = $teamwebpage; $curTeam['avatar'] = $teamimages['avatar']; echo "

    "; - showEdit($teamname, $text_data, $teamwebpage, 0, $tid); + showEdit($teamname, $text_data, $teamwebpage, false, $tid); echo "
    "; showTeamProfile($curTeam, /*$preview = */ true); echo "

    "; @@ -75,7 +75,7 @@ if (mysqli_num_rows($result) > 0 || $teamname == '') { $preview = _("Preview"); output_header($preview, NO_STATSBAR, $theme_extra_args); - $teamimages = uploadImages(1, $tid, "both"); + $teamimages = uploadImages(true, $tid, "both"); $curTeam['avatar'] = $teamimages['avatar']; if ($teamname == "") { echo "

    " . _("The team name must not be empty.") . "
    "; @@ -83,7 +83,7 @@ echo "

    " . _("The team name must be unique. Please make any changes and resubmit.") . "
    "; } - showEdit($teamname, $text_data, $teamwebpage, 0, $tid); + showEdit($teamname, $text_data, $teamwebpage, false, $tid); echo "

    "; } else { if (!empty($tavatar)) { @@ -98,7 +98,7 @@ ); DPDatabase::query($sql); } elseif (!empty($_FILES['teamavatar'])) { - uploadImages(0, $tid, "avatar"); + uploadImages(false, $tid, "avatar"); } if (!empty($ticon)) { $sql = sprintf( @@ -112,7 +112,7 @@ ); DPDatabase::query($sql); } elseif (!empty($_FILES['teamicon'])) { - uploadImages(0, $tid, "icon"); + uploadImages(false, $tid, "icon"); } $sql = sprintf( diff --git a/tools/project_manager/edit_common.inc b/tools/project_manager/edit_common.inc index e3e4c5daf..1426e77fe 100644 --- a/tools/project_manager/edit_common.inc +++ b/tools/project_manager/edit_common.inc @@ -9,14 +9,15 @@ include_once($relPath.'User.inc'); include_once($relPath.'CharSuites.inc'); include_once($relPath.'Project.inc'); // load_image_sources() -function just_echo($field_value) +function just_echo(string $field_value): void { echo html_safe($field_value); } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function text_field($field_value, $field_name, $args = []) +/** @param array{maxlength?: int, required?: bool, type?: string, min?: int} $args */ +function text_field(?string $field_value, string $field_name, array $args = []): void { $maxlength = $args["maxlength"] ?? null; $maxlength_attr = $maxlength ? "maxlength='$maxlength'" : ''; @@ -32,7 +33,8 @@ function text_field($field_value, $field_name, $args = []) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function DP_user_field($field_value, $field_name, $args = []) +/** @param array{maxlength?: int, required?: bool, type?: string, min?: int} $args */ +function DP_user_field(string $field_value, string $field_name, array $args = []): void { $required = $args["required"] ?? false; $required_attr = $required ? " required" : ""; @@ -44,7 +46,7 @@ function DP_user_field($field_value, $field_name, $args = []) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function language_list($language) +function language_list(string $language): void { $languages = Project::decode_language($language); $pri_language = $languages[0]; @@ -67,7 +69,7 @@ function language_list($language) echo "\n"; } -function echo_language_options($default) +function echo_language_options(string $default): void { $langs_with_dicts = array_flip(get_languages_with_dictionaries()); ksort($langs_with_dicts); @@ -96,7 +98,7 @@ function echo_language_options($default) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -function genre_list($genre) +function genre_list(string $genre): void { $genres = load_genre_translation_array(); echo ""; @@ -410,12 +423,12 @@ function echo_checkbox_form_start($checkbox_form) } } -function echo_checkbox_form_submit($submit_label) +function echo_checkbox_form_submit(string $submit_label): void { echo ""; } -function echo_checkbox_form_end() +function echo_checkbox_form_end(): void { echo ""; } diff --git a/tools/proofers/image_block_enh.inc b/tools/proofers/image_block_enh.inc index 8bc3e5ffd..bf75b49fa 100644 --- a/tools/proofers/image_block_enh.inc +++ b/tools/proofers/image_block_enh.inc @@ -12,7 +12,7 @@ * as percentages of its container box * (which is typically the "proofframe" of the proofing interface). */ -function ibe_get_styles() +function ibe_get_styles(): string { $user = User::load_current(); @@ -61,7 +61,7 @@ function ibe_get_styles() // ----------------------------------------------------------------------------- -function ibe_echo_block() +function ibe_echo_block(): void { echo "
    diff --git a/tools/proofers/preview.inc b/tools/proofers/preview.inc index 21457e63e..0e6d208d9 100644 --- a/tools/proofers/preview.inc +++ b/tools/proofers/preview.inc @@ -1,7 +1,7 @@ } */ -function spellcheck_text($orig_text, $projectid, $imagefile, $languages, $accepted_words) +function spellcheck_text(string $orig_text, string $projectid, string $imagefile, array $languages, array $accepted_words): array { global $puncCharacters; @@ -197,7 +197,7 @@ function spellcheck_text($orig_text, $projectid, $imagefile, $languages, $accept /** * Adds HTML code to highlight text */ -function _wrapHighlight($word, $highlightClass) +function _wrapHighlight(string $word, string $highlightClass): string { return "$word"; } @@ -205,15 +205,16 @@ function _wrapHighlight($word, $highlightClass) /** * Adds HTML code to punctuation to highlight it */ -function _wrapPunc($word) +function _wrapPunc(string $word): string { return _wrapHighlight($word, "hl-punc"); } /** * Adds HTML code to highlight words in multiple scripts + * @param array $scriptMap */ -function _wrapScriptWord($word, $scriptMap) +function _wrapScriptWord(string $word, array $scriptMap): string { global $common_unicode_scripts; @@ -233,15 +234,16 @@ function _wrapScriptWord($word, $scriptMap) /** * Adds HTML code to an accepted word to highlight it */ -function _wrapAW($word) +function _wrapAW(string $word): string { return "$word"; } /** * Adds HTML code to manage a bad word + * @return list{string, int} */ -function _wrapBadWord($word, $origLineNum, $lineIndex, $wordLen, $badWordType) +function _wrapBadWord(string $word, int $origLineNum, int $lineIndex, int $wordLen, int $badWordType): array { global $code_url; @@ -292,13 +294,14 @@ function _wrapBadWord($word, $origLineNum, $lineIndex, $wordLen, $badWordType) // -------------------------------------------- -function spellcheck_quit() +function spellcheck_quit(): string { $orig_text = $_POST['revert_text']; return str_replace("[lf]", "\r\n", $orig_text); } -function spellcheck_apply_corrections() +/** @return list{string, list{string, string}[]} */ +function spellcheck_apply_corrections(): array { $orig_text = $_POST['text_data'];