Skip to content

Commit ce0d10a

Browse files
committed
Tidying up.
1 parent 3b52290 commit ce0d10a

File tree

2 files changed

+53
-177
lines changed

2 files changed

+53
-177
lines changed

ISSUES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,4 @@ Hooks with `@param` tags where types are not valid PHP docblock types.
6767

6868
- `block_editor_rest_api_preload_paths` — $preload_paths: `(string` (wp-includes/block-editor.php)
6969
- `block_editor_rest_api_preload_paths` — $preload_paths: `string[])[]` (wp-includes/block-editor.php)
70+

scripts/generate-issues.sh

Lines changed: 52 additions & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -1,215 +1,90 @@
11
#!/bin/bash
22

33
# Generate a markdown document listing all hook data issues
4-
# Uses the npm show:* scripts to gather data
54

65
OUTPUT_FILE="ISSUES.md"
76

7+
# Helper function to run a jq query on both actions and filters, combine and dedupe results
8+
run_check() {
9+
local query="$1"
10+
local actions_result filters_result
11+
actions_result=$(jq -r "$query" hooks/actions.json 2>/dev/null)
12+
filters_result=$(jq -r "$query" hooks/filters.json 2>/dev/null)
13+
echo -e "${actions_result}\n${filters_result}" | grep -v '^$' | sort -u
14+
}
15+
16+
# Helper function to write a section to the output file
17+
write_section() {
18+
local title="$1"
19+
local description="$2"
20+
local empty_message="$3"
21+
local results="$4"
22+
23+
echo "## $title" >> "$OUTPUT_FILE"
24+
echo "" >> "$OUTPUT_FILE"
25+
if [ -n "$description" ]; then
26+
echo "$description" >> "$OUTPUT_FILE"
27+
echo "" >> "$OUTPUT_FILE"
28+
fi
29+
if [ -n "$results" ]; then
30+
echo "$results" >> "$OUTPUT_FILE"
31+
else
32+
echo "_${empty_message}_" >> "$OUTPUT_FILE"
33+
fi
34+
echo "" >> "$OUTPUT_FILE"
35+
}
36+
837
echo "# WordPress Hooks Data Issues" > "$OUTPUT_FILE"
938
echo "" >> "$OUTPUT_FILE"
1039
echo "This document lists known data quality issues in the hooks JSON files." >> "$OUTPUT_FILE"
1140
echo "" >> "$OUTPUT_FILE"
1241

1342
# Duplicate Actions
14-
echo "## Duplicate Actions" >> "$OUTPUT_FILE"
15-
echo "" >> "$OUTPUT_FILE"
16-
17-
DUPLICATE_ACTIONS=$(jq -r '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1) | .key] | .[]' hooks/actions.json)
18-
19-
if [ -n "$DUPLICATE_ACTIONS" ]; then
20-
echo "$DUPLICATE_ACTIONS" | while read -r name; do
21-
echo "- \`$name\`" >> "$OUTPUT_FILE"
22-
done
23-
else
24-
echo "_No duplicate actions._" >> "$OUTPUT_FILE"
25-
fi
26-
27-
echo "" >> "$OUTPUT_FILE"
43+
DUPLICATE_ACTIONS=$(jq -r '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1) | .key] | .[] | "- `\(.)`"' hooks/actions.json)
44+
write_section "Duplicate Actions" "" "No duplicate actions." "$DUPLICATE_ACTIONS"
2845

2946
# Duplicate Filters
30-
echo "## Duplicate Filters" >> "$OUTPUT_FILE"
31-
echo "" >> "$OUTPUT_FILE"
32-
33-
DUPLICATE_FILTERS=$(jq -r '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1) | .key] | .[]' hooks/filters.json)
34-
35-
if [ -n "$DUPLICATE_FILTERS" ]; then
36-
echo "$DUPLICATE_FILTERS" | while read -r name; do
37-
echo "- \`$name\`" >> "$OUTPUT_FILE"
38-
done
39-
else
40-
echo "_No duplicate filters._" >> "$OUTPUT_FILE"
41-
fi
42-
43-
echo "" >> "$OUTPUT_FILE"
47+
DUPLICATE_FILTERS=$(jq -r '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1) | .key] | .[] | "- `\(.)`"' hooks/filters.json)
48+
write_section "Duplicate Filters" "" "No duplicate filters." "$DUPLICATE_FILTERS"
4449

4550
# Missing @since Tags
46-
echo "## Missing @since Tags" >> "$OUTPUT_FILE"
47-
echo "" >> "$OUTPUT_FILE"
48-
49-
MISSING_SINCE_ACTIONS=$(jq -r '.hooks[] | select(.doc.tags | map(.name) | contains(["since"]) | not) | "- `\(.name)` (\(.file))"' hooks/actions.json)
50-
MISSING_SINCE_FILTERS=$(jq -r '.hooks[] | select(.doc.tags | map(.name) | contains(["since"]) | not) | "- `\(.name)` (\(.file))"' hooks/filters.json)
51-
52-
MISSING_SINCE=$(echo -e "${MISSING_SINCE_ACTIONS}\n${MISSING_SINCE_FILTERS}" | grep -v '^$' | sort)
53-
54-
if [ -n "$MISSING_SINCE" ]; then
55-
echo "$MISSING_SINCE" >> "$OUTPUT_FILE"
56-
else
57-
echo "_No hooks with missing @since tags._" >> "$OUTPUT_FILE"
58-
fi
59-
60-
echo "" >> "$OUTPUT_FILE"
51+
MISSING_SINCE=$(run_check '.hooks[] | select(.doc.tags | map(.name) | contains(["since"]) | not) | "- `\(.name)` (\(.file))"')
52+
write_section "Missing @since Tags" "" "No hooks with missing @since tags." "$MISSING_SINCE"
6153

6254
# Empty Descriptions
63-
echo "## Empty Descriptions" >> "$OUTPUT_FILE"
64-
echo "" >> "$OUTPUT_FILE"
65-
66-
EMPTY_DESC_ACTIONS=$(jq -r '.hooks[] | select(.doc.description == "" or .doc.description == null) | "- `\(.name)` (\(.file))"' hooks/actions.json)
67-
EMPTY_DESC_FILTERS=$(jq -r '.hooks[] | select(.doc.description == "" or .doc.description == null) | "- `\(.name)` (\(.file))"' hooks/filters.json)
68-
69-
EMPTY_DESC=$(echo -e "${EMPTY_DESC_ACTIONS}\n${EMPTY_DESC_FILTERS}" | grep -v '^$' | sort)
70-
71-
if [ -n "$EMPTY_DESC" ]; then
72-
echo "$EMPTY_DESC" >> "$OUTPUT_FILE"
73-
else
74-
echo "_No hooks with empty descriptions._" >> "$OUTPUT_FILE"
75-
fi
76-
77-
echo "" >> "$OUTPUT_FILE"
55+
EMPTY_DESC=$(run_check '.hooks[] | select(.doc.description == "" or .doc.description == null) | "- `\(.name)` (\(.file))"')
56+
write_section "Empty Descriptions" "" "No hooks with empty descriptions." "$EMPTY_DESC"
7857

7958
# Empty Variables
80-
echo "## Empty Variables" >> "$OUTPUT_FILE"
81-
echo "" >> "$OUTPUT_FILE"
82-
echo "Hooks with \`@param\` tags that have an empty variable name." >> "$OUTPUT_FILE"
83-
echo "" >> "$OUTPUT_FILE"
84-
85-
EMPTY_VARS_ACTIONS=$(jq -r '.hooks[] | select(.doc.tags[] | select(.name == "param" and .variable == "")) | "- `\(.name)` (\(.file))"' hooks/actions.json 2>/dev/null | sort -u)
86-
EMPTY_VARS_FILTERS=$(jq -r '.hooks[] | select(.doc.tags[] | select(.name == "param" and .variable == "")) | "- `\(.name)` (\(.file))"' hooks/filters.json 2>/dev/null | sort -u)
87-
88-
EMPTY_VARS=$(echo -e "${EMPTY_VARS_ACTIONS}\n${EMPTY_VARS_FILTERS}" | grep -v '^$' | sort -u)
89-
90-
if [ -n "$EMPTY_VARS" ]; then
91-
echo "$EMPTY_VARS" >> "$OUTPUT_FILE"
92-
else
93-
echo "_No hooks with empty variables._" >> "$OUTPUT_FILE"
94-
fi
95-
96-
echo "" >> "$OUTPUT_FILE"
59+
EMPTY_VARS=$(run_check '.hooks[] | select(.doc.tags[] | select(.name == "param" and .variable == "")) | "- `\(.name)` (\(.file))"')
60+
write_section "Empty Variables" "Hooks with \`@param\` tags that have an empty variable name." "No hooks with empty variables." "$EMPTY_VARS"
9761

9862
# Invalid Variable Names
99-
echo "## Invalid Variable Names" >> "$OUTPUT_FILE"
100-
echo "" >> "$OUTPUT_FILE"
101-
echo "Hooks with \`@param\` tags where the variable is not a valid PHP variable name." >> "$OUTPUT_FILE"
102-
echo "" >> "$OUTPUT_FILE"
103-
10463
# Valid variable names match $[a-zA-Z_][a-zA-Z0-9_]* but not $this
105-
INVALID_VAR_NAMES_ACTIONS=$(jq -r '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and .variable != "" and .variable != null and ((.variable | test("^\\$[a-zA-Z_][a-zA-Z0-9_]*$") | not) or .variable == "$this")) | "- `\($name)` — \(.variable) (\($file))"' hooks/actions.json 2>/dev/null | sort -u)
106-
INVALID_VAR_NAMES_FILTERS=$(jq -r '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and .variable != "" and .variable != null and ((.variable | test("^\\$[a-zA-Z_][a-zA-Z0-9_]*$") | not) or .variable == "$this")) | "- `\($name)` — \(.variable) (\($file))"' hooks/filters.json 2>/dev/null | sort -u)
107-
108-
INVALID_VAR_NAMES=$(echo -e "${INVALID_VAR_NAMES_ACTIONS}\n${INVALID_VAR_NAMES_FILTERS}" | grep -v '^$' | sort -u)
109-
110-
if [ -n "$INVALID_VAR_NAMES" ]; then
111-
echo "$INVALID_VAR_NAMES" >> "$OUTPUT_FILE"
112-
else
113-
echo "_No hooks with invalid variable names._" >> "$OUTPUT_FILE"
114-
fi
115-
116-
echo "" >> "$OUTPUT_FILE"
64+
INVALID_VAR_NAMES=$(run_check '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and .variable != "" and .variable != null and ((.variable | test("^\\$[a-zA-Z_][a-zA-Z0-9_]*$") | not) or .variable == "$this")) | "- `\($name)` — \(.variable) (\($file))"')
65+
write_section "Invalid Variable Names" "Hooks with \`@param\` tags where the variable is not a valid PHP variable name." "No hooks with invalid variable names." "$INVALID_VAR_NAMES"
11766

11867
# Empty Param Descriptions
119-
echo "## Empty Param Descriptions" >> "$OUTPUT_FILE"
120-
echo "" >> "$OUTPUT_FILE"
121-
echo "Hooks with \`@param\` tags that have an empty description." >> "$OUTPUT_FILE"
122-
echo "" >> "$OUTPUT_FILE"
123-
124-
EMPTY_PARAM_DESC_ACTIONS=$(jq -r '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and (.content == "" or .content == null)) | "- `\($name)` — \(.variable) (\($file))"' hooks/actions.json 2>/dev/null | sort -u)
125-
EMPTY_PARAM_DESC_FILTERS=$(jq -r '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and (.content == "" or .content == null)) | "- `\($name)` — \(.variable) (\($file))"' hooks/filters.json 2>/dev/null | sort -u)
126-
127-
EMPTY_PARAM_DESC=$(echo -e "${EMPTY_PARAM_DESC_ACTIONS}\n${EMPTY_PARAM_DESC_FILTERS}" | grep -v '^$' | sort -u)
128-
129-
if [ -n "$EMPTY_PARAM_DESC" ]; then
130-
echo "$EMPTY_PARAM_DESC" >> "$OUTPUT_FILE"
131-
else
132-
echo "_No hooks with empty param descriptions._" >> "$OUTPUT_FILE"
133-
fi
134-
135-
echo "" >> "$OUTPUT_FILE"
68+
EMPTY_PARAM_DESC=$(run_check '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and (.content == "" or .content == null)) | "- `\($name)` — \(.variable) (\($file))"')
69+
write_section "Empty Param Descriptions" "Hooks with \`@param\` tags that have an empty description." "No hooks with empty param descriptions." "$EMPTY_PARAM_DESC"
13670

13771
# Missing Original Since
138-
echo "## Missing Original Since" >> "$OUTPUT_FILE"
139-
echo "" >> "$OUTPUT_FILE"
140-
echo "Hooks where all \`@since\` tags have descriptions, indicating the original version is missing." >> "$OUTPUT_FILE"
141-
echo "" >> "$OUTPUT_FILE"
142-
14372
# Exclude hooks with @since MU (3.0.0) as this indicates the original multisite version
144-
MISSING_ORIG_SINCE_ACTIONS=$(jq -r '.hooks[] | select((.doc.tags | map(select(.name == "since" and .description == "MU (3.0.0)")) | length == 0) and (.doc.tags | map(select(.name == "since")) | length > 0) and (.doc.tags | map(select(.name == "since" and (.description == null or .description == ""))) | length == 0)) | "- `\(.name)` (\(.file))"' hooks/actions.json 2>/dev/null | sort -u)
145-
MISSING_ORIG_SINCE_FILTERS=$(jq -r '.hooks[] | select((.doc.tags | map(select(.name == "since" and .description == "MU (3.0.0)")) | length == 0) and (.doc.tags | map(select(.name == "since")) | length > 0) and (.doc.tags | map(select(.name == "since" and (.description == null or .description == ""))) | length == 0)) | "- `\(.name)` (\(.file))"' hooks/filters.json 2>/dev/null | sort -u)
146-
147-
MISSING_ORIG_SINCE=$(echo -e "${MISSING_ORIG_SINCE_ACTIONS}\n${MISSING_ORIG_SINCE_FILTERS}" | grep -v '^$' | sort -u)
148-
149-
if [ -n "$MISSING_ORIG_SINCE" ]; then
150-
echo "$MISSING_ORIG_SINCE" >> "$OUTPUT_FILE"
151-
else
152-
echo "_No hooks with missing original since version._" >> "$OUTPUT_FILE"
153-
fi
154-
155-
echo "" >> "$OUTPUT_FILE"
73+
MISSING_ORIG_SINCE=$(run_check '.hooks[] | select((.doc.tags | map(select(.name == "since" and .description == "MU (3.0.0)")) | length == 0) and (.doc.tags | map(select(.name == "since")) | length > 0) and (.doc.tags | map(select(.name == "since" and (.description == null or .description == ""))) | length == 0)) | "- `\(.name)` (\(.file))"')
74+
write_section "Missing Original Since" "Hooks where all \`@since\` tags have descriptions, indicating the original version is missing." "No hooks with missing original since version." "$MISSING_ORIG_SINCE"
15675

15776
# Param Count Mismatches
158-
echo "## Param Count Mismatches" >> "$OUTPUT_FILE"
159-
echo "" >> "$OUTPUT_FILE"
160-
echo "Hooks where the number of \`@param\` tags does not match the \`args\` count." >> "$OUTPUT_FILE"
161-
echo "" >> "$OUTPUT_FILE"
162-
16377
# Exclude action_reference and filter_reference types as they use ref_array functions which always report args as 1
164-
PARAM_MISMATCH_ACTIONS=$(jq -r '.hooks[] | select(.type != "action_reference" and .type != "filter_reference") | select(.args != ([.doc.tags[] | select(.name == "param")] | length)) | "- `\(.name)` — args: \(.args), params: \([.doc.tags[] | select(.name == "param")] | length) (\(.file))"' hooks/actions.json)
165-
PARAM_MISMATCH_FILTERS=$(jq -r '.hooks[] | select(.type != "action_reference" and .type != "filter_reference") | select(.args != ([.doc.tags[] | select(.name == "param")] | length)) | "- `\(.name)` — args: \(.args), params: \([.doc.tags[] | select(.name == "param")] | length) (\(.file))"' hooks/filters.json)
166-
167-
PARAM_MISMATCH=$(echo -e "${PARAM_MISMATCH_ACTIONS}\n${PARAM_MISMATCH_FILTERS}" | grep -v '^$' | sort)
168-
169-
if [ -n "$PARAM_MISMATCH" ]; then
170-
echo "$PARAM_MISMATCH" >> "$OUTPUT_FILE"
171-
else
172-
echo "_No hooks with param count mismatches._" >> "$OUTPUT_FILE"
173-
fi
174-
175-
echo "" >> "$OUTPUT_FILE"
78+
PARAM_MISMATCH=$(run_check '.hooks[] | select(.type != "action_reference" and .type != "filter_reference") | select(.args != ([.doc.tags[] | select(.name == "param")] | length)) | "- `\(.name)` — args: \(.args), params: \([.doc.tags[] | select(.name == "param")] | length) (\(.file))"')
79+
write_section "Param Count Mismatches" "Hooks where the number of \`@param\` tags does not match the \`args\` count." "No hooks with param count mismatches." "$PARAM_MISMATCH"
17680

17781
# Empty Param Types
178-
echo "## Empty Param Types" >> "$OUTPUT_FILE"
179-
echo "" >> "$OUTPUT_FILE"
180-
echo "Hooks with \`@param\` tags that have empty or missing type arrays." >> "$OUTPUT_FILE"
181-
echo "" >> "$OUTPUT_FILE"
182-
183-
EMPTY_PARAM_TYPES_ACTIONS=$(jq -r '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and (.types == null or .types == [] or (.types | length == 0))) | "- `\($name)` — \(.variable) (\($file))"' hooks/actions.json 2>/dev/null | sort -u)
184-
EMPTY_PARAM_TYPES_FILTERS=$(jq -r '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and (.types == null or .types == [] or (.types | length == 0))) | "- `\($name)` — \(.variable) (\($file))"' hooks/filters.json 2>/dev/null | sort -u)
185-
186-
EMPTY_PARAM_TYPES=$(echo -e "${EMPTY_PARAM_TYPES_ACTIONS}\n${EMPTY_PARAM_TYPES_FILTERS}" | grep -v '^$' | sort -u)
187-
188-
if [ -n "$EMPTY_PARAM_TYPES" ]; then
189-
echo "$EMPTY_PARAM_TYPES" >> "$OUTPUT_FILE"
190-
else
191-
echo "_No hooks with empty param types._" >> "$OUTPUT_FILE"
192-
fi
193-
194-
echo "" >> "$OUTPUT_FILE"
82+
EMPTY_PARAM_TYPES=$(run_check '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param" and (.types == null or .types == [] or (.types | length == 0))) | "- `\($name)` — \(.variable) (\($file))"')
83+
write_section "Empty Param Types" "Hooks with \`@param\` tags that have empty or missing type arrays." "No hooks with empty param types." "$EMPTY_PARAM_TYPES"
19584

19685
# Invalid Param Types
197-
echo "## Invalid Param Types" >> "$OUTPUT_FILE"
198-
echo "" >> "$OUTPUT_FILE"
199-
echo "Hooks with \`@param\` tags where types are not valid PHP docblock types." >> "$OUTPUT_FILE"
200-
echo "" >> "$OUTPUT_FILE"
201-
20286
# Valid types: primitives, class names (with optional leading backslash), array modifiers [], generic syntax like array<type>
203-
# This regex matches: word chars, backslashes, [], <>, commas, spaces (for generics), pipes, parentheses, $this
204-
INVALID_TYPES_ACTIONS=$(jq -r '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param") | .variable as $var | .types[]? | select(test("^[a-zA-Z_\\\\][a-zA-Z0-9_\\\\]*(<[^>]+>)?(\\[\\])*$") | not) | "- `\($name)` — \($var): `\(.)` (\($file))"' hooks/actions.json 2>/dev/null | sort -u)
205-
INVALID_TYPES_FILTERS=$(jq -r '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param") | .variable as $var | .types[]? | select(test("^[a-zA-Z_\\\\][a-zA-Z0-9_\\\\]*(<[^>]+>)?(\\[\\])*$") | not) | "- `\($name)` — \($var): `\(.)` (\($file))"' hooks/filters.json 2>/dev/null | sort -u)
206-
207-
INVALID_TYPES=$(echo -e "${INVALID_TYPES_ACTIONS}\n${INVALID_TYPES_FILTERS}" | grep -v '^$' | sort -u)
208-
209-
if [ -n "$INVALID_TYPES" ]; then
210-
echo "$INVALID_TYPES" >> "$OUTPUT_FILE"
211-
else
212-
echo "_No hooks with invalid param types._" >> "$OUTPUT_FILE"
213-
fi
87+
INVALID_TYPES=$(run_check '.hooks[] | .name as $name | .file as $file | .doc.tags[] | select(.name == "param") | .variable as $var | .types[]? | select(test("^[a-zA-Z_\\\\][a-zA-Z0-9_\\\\]*(<[^>]+>)?(\\[\\])*$") | not) | "- `\($name)` — \($var): `\(.)` (\($file))"')
88+
write_section "Invalid Param Types" "Hooks with \`@param\` tags where types are not valid PHP docblock types." "No hooks with invalid param types." "$INVALID_TYPES"
21489

21590
echo "Generated $OUTPUT_FILE"

0 commit comments

Comments
 (0)