Configured wedocs new package system#250
Conversation
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
WalkthroughAdds a new dynamic Table of Contents block (editor, frontend, styles, server render), refactors DocsGrid PHP rendering with guarded functions and echoes, removes several built assets and built block metadata, updates build/dev deps and PostCSS formatting, disables the Frontend template_include hook, switches truncation to mb_substr for multibyte safety, and applies a broad formatting/whitespace normalization across many files. ChangesMain functional changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (4)
package.json(1 hunks)src/blocks/DocsGrid/render.php(1 hunks)webpack.config.js(1 hunks)wedocs.php(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/blocks/DocsGrid/render.php (2)
src/blocks/DocsGrid/edit.js (1)
attributes(20-48)src/blocks/DocsGrid/save.js (1)
attributes(4-16)
🪛 PHPMD (2.15.0)
src/blocks/DocsGrid/render.php
182-182: Avoid unused local variables such as '$total_pages'. (undefined)
(UnusedLocalVariable)
227-227: Avoid unused local variables such as '$total_articles'. (undefined)
(UnusedLocalVariable)
| return ob_get_clean(); | ||
| } | ||
| echo render_wedocs_docs_grid($attributes); | ||
| } |
There was a problem hiding this comment.
Return the rendered markup instead of echoing
When a block.json uses the render file, WordPress expects that file to return the HTML string. Echoing here causes the metadata loader to return 1, which results in broken front-end output. Replace the echo with a return so the block renders correctly.
- echo render_wedocs_docs_grid($attributes);
+ return render_wedocs_docs_grid($attributes);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return ob_get_clean(); | |
| } | |
| echo render_wedocs_docs_grid($attributes); | |
| } | |
| return ob_get_clean(); | |
| } | |
| return render_wedocs_docs_grid($attributes); | |
| } |
🤖 Prompt for AI Agents
In src/blocks/DocsGrid/render.php around lines 321 to 324, the file currently
echoes the rendered markup which causes WordPress to return 1 from the render
file; replace the final echo call with a return so the function returns the HTML
string (i.e., change echo render_wedocs_docs_grid($attributes); to return
render_wedocs_docs_grid($attributes);) and ensure no additional output is sent
after the return.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
wedocs.php (2)
176-188: Apply WordPress coding standards for spacing around control structures.The control structures don't follow WordPress coding standards for spacing. WordPress requires spaces after opening parentheses and before closing parentheses.
Apply this diff to align with WordPress coding standards:
public function register_blocks() { $block_lists = [ WEDOCS_PATH . '/assets/build/blocks/DocsGrid', ]; - foreach ($block_lists as $block) { - if (file_exists($block . '/block.json')) { + foreach ( $block_lists as $block ) { + if ( file_exists( $block . '/block.json' ) ) { // Register the DocsGrid block - register_block_type($block); + register_block_type( $block ); } } }
184-184: Update comment to reflect generic block registration.The comment specifically mentions "DocsGrid block" but this code is inside a loop that can register multiple block types. Consider making the comment more generic to match the actual functionality.
Apply this diff:
- // Register the DocsGrid block + // Register the block register_block_type($block);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (2)
package.json(1 hunks)wedocs.php(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- package.json
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
src/blocks/TableOfContents/render.php (1)
74-95: Inline style building is fine; consider null-coalescing to avoid empty style attr.Current get_block_wrapper_attributes handles null, but you can skip style when no styles exist.
- 'style' => !empty($inline_styles) ? implode('; ', $inline_styles) : null + // Only set 'style' when we actually have styles. + ...( ! empty( $inline_styles ) ? [ 'style' => implode( '; ', $inline_styles ) ] : [] )src/blocks/TableOfContents/style.scss (1)
58-76: Add visible focus styles for keyboard navigation.Improve accessibility by styling focus-visible on links.
a { text-decoration: none; color: var(--toc-link-color, inherit); display: inline-block; transition: color 0.2s ease; + &:focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; + } &:hover { color: var(--toc-link-hover-color, currentColor); text-decoration: underline; }Optionally honor reduced motion:
html.smooth-scroll { - scroll-behavior: smooth; + scroll-behavior: smooth; + @media (prefers-reduced-motion: reduce) { + scroll-behavior: auto; + } }Also applies to: 138-141
src/blocks/TableOfContents/edit.js (1)
279-381: Avoid __experimental APIs where stable equivalents exist; mirror final ID strategy in preview.
- Prefer stable ToolsPanel components when your target WP version allows, to reduce churn.
- For consistency, preview numbering/indent is fine; optionally use the same slugify ID strategy used in view/SSR to keep anchors consistent in editor previews.
Please confirm your minimum WP version. If ≥ 6.3, you can replace __experimentalToolsPanel and related with their stable counterparts.
Also applies to: 128-144
wedocs.php (1)
176-189: Apply the suggested refactor to improve maintainability and handle incomplete builds.The verification reveals that
TableOfContentsis not yet built inassets/build/blocks/(onlyDocsGridexists), while the hard-coded array tries to register both. Thefile_exists()guard masks this incomplete build. The suggested refactor addresses this:
- Using
glob()auto-discovers only built blocks, preventing drift from hard-coded lists- Adding
function_exists('register_block_type')guards against older WordPress versions- Future blocks will be automatically registered without code changes
The review comment suggestions are sound and should be applied.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
includes/Frontend.php(1 hunks)src/blocks/TableOfContents/block.json(1 hunks)src/blocks/TableOfContents/edit.js(1 hunks)src/blocks/TableOfContents/editor.scss(1 hunks)src/blocks/TableOfContents/index.js(1 hunks)src/blocks/TableOfContents/render.php(1 hunks)src/blocks/TableOfContents/save.js(1 hunks)src/blocks/TableOfContents/style.scss(1 hunks)src/blocks/TableOfContents/view.js(1 hunks)src/blocks/index.js(1 hunks)wedocs.php(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- includes/Frontend.php
- src/blocks/TableOfContents/save.js
- src/blocks/index.js
🧰 Additional context used
🧬 Code graph analysis (3)
src/blocks/TableOfContents/render.php (2)
src/blocks/TableOfContents/edit.js (2)
attributes(55-70)headings(72-72)src/blocks/TableOfContents/view.js (13)
content(159-159)headings(55-55)headings(174-177)level(104-104)text(105-105)id(106-106)id(175-175)html(95-95)counters(100-100)i(113-113)i(129-129)indent(122-122)numbers(128-128)
src/blocks/TableOfContents/index.js (1)
src/blocks/TableOfContents/edit.js (1)
Edit(54-409)
src/blocks/TableOfContents/edit.js (1)
src/blocks/TableOfContents/view.js (14)
headings(55-55)headings(174-177)supportedHeadings(42-42)showHierarchy(43-43)showNumbering(44-44)counters(100-100)i(113-113)i(129-129)indent(122-122)numberText(125-125)level(104-104)tocTitle(12-12)collapsibleOnMobile(16-16)smoothScroll(15-15)
🔇 Additional comments (5)
src/blocks/TableOfContents/editor.scss (1)
6-27: LGTM for editor styles.Scoped, minimal, and safe for editor. No blocking issues.
src/blocks/TableOfContents/index.js (1)
29-34: Registration pattern is correct.Dynamic block wired via block.json + Edit; no save() needed. Good.
src/blocks/TableOfContents/block.json (3)
106-106: Verify textdomain matches project convention.Line 106 specifies textdomain as
"dynamic-table-of-contents-block-wp", but the AI summary indicates it should be"wedocs". Ensure this matches your project's localization and textdomain configuration to avoid translation/i18n issues.
84-92: Verify color attribute defaults are handled safely in frontend code.The color attributes (
titleColor,linkColor,linkHoverColor) lack default values (lines 85, 88, 91). Confirm that the frontend rendering code, view script, and render.php handler gracefully manageundefinedornullvalues for these attributes to prevent styling breakage.
107-111: Verify asset file paths and naming match build output.Asset paths reference
index.css,style-index.css,index.js,view.js, andrender.php. Confirm these file names align with your webpack/build configuration to ensure assets are correctly located and bundled.
There was a problem hiding this comment.
Actionable comments posted: 15
♻️ Duplicate comments (1)
src/blocks/TableOfContents/render.php (1)
188-189:⚠️ Potential issue | 🟠 Major | ⚡ Quick winH6 numbering path is still incomplete.
Line 188 initializes counters only up to 5, but Line 200 allows level 6 and Line 207 increments
$counters[$level]. This can cause undefined index and wrong numbering forh6.Also applies to: 207-210
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/blocks/TableOfContents/render.php` around lines 188 - 189, The counters array only includes keys 1..5 so h6 will cause undefined index when $level === 6; update the $counters initialization to include key 6 (e.g. [1=>0,...,6=>0]) and ensure any logic that references $counters[$level] (the increment/reset code around where $global_counter is used) properly supports level 6 as well so numbering and resets behave the same for h6 as for other levels.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@includes/Ajax.php`:
- Around line 40-42: The hide_pro_notice AJAX handler is registered for
unauthenticated users and updates user meta without any nonce or capability
checks; modify the registration and handler (the add_action calls and the
hide_pro_notice method) to require a valid nonce and authenticated user: remove
or stop using the nopriv hook (or keep it only if you add explicit checks),
verify the nonce with check_ajax_referer (or wp_verify_nonce) at the start of
hide_pro_notice, ensure the user is logged in (is_user_logged_in /
wp_get_current_user) and optionally check a capability with current_user_can
before calling update_user_meta, and return proper AJAX responses
(wp_send_json_success/wp_send_json_error) instead of silent updates. Ensure any
incoming data is sanitized and that update_user_meta is only reached after these
checks.
In `@includes/API/API.php`:
- Around line 221-233: The route schema declares docIds and status nested under
the "data" object but update_docs_status reads them from the request root,
causing empty $doc_ids; update update_docs_status to pull the payload from the
"data" key (e.g. obtain $data = $request->get_param('data') or
$request->get_json_params()['data'] and then read docIds and status from $data)
and use those values when building $doc_ids and $status (adjust the logic in the
update_docs_status handler around the current 354-367 logic that reads request
params), or alternatively change the route schema to match the current
root-level reading—ensure the same source is used in the route schema and in
update_docs_status.
- Around line 784-785: The post-type check in get_doc is comparing the
controller property $this->post_type instead of the actual post's type; update
the validation in the get_doc flow to check $post->post_type === 'docs'
(alongside the existing empty($post) and empty($post->ID) checks) so non-doc
posts are rejected—locate the conditional that currently uses $this->post_type
and replace it to validate $post->post_type.
In `@includes/Assets.php`:
- Around line 52-56: The wp_register_style call registering 'wedocs-app-style'
is passing the version string into the $deps slot (third arg) instead of an
array and omitting the $ver (fourth arg); update the wp_register_style
invocation(s) that use $react_dependencies['version'] (and the analogous
registration around the other stylesheet) to pass an array of dependencies as
the third parameter (e.g. [] or $react_dependencies['dependencies']) and pass
the version string as the fourth parameter so cache-busting works correctly;
locate the calls by the handle 'wedocs-app-style' and the other similar
registration near the other stylesheet/handle and swap the args accordingly.
In `@includes/Frontend.php`:
- Around line 38-40: The commented-out add_filter call removed the plugin's
template fallback for docs pages; re-enable the template_include hook by
restoring the add_filter( 'template_include', [ $this, 'template_loader' ], 20 )
line in the Frontend class (or, if the behavior is intentional, add a clear
comment and update README/changelog to document that template_loader will no
longer run and themes must provide single-docs.php), ensuring the
template_loader method is executed so plugin templates are used as a fallback
for docs pages.
- Around line 71-72: Guard the unconditional require of WEDOCS_PATH .
'/assets/build/store.asset.php' so it doesn't fatal when missing: check
file_exists(...) before requiring and only set $store_dependencies from the
required file when present; otherwise use a safe default (e.g. ['dependencies'
=> [], 'version' => null]) and still call wp_register_script('wedocs-store-js',
WEDOCS_ASSETS . '/build/store.js', $store_dependencies['dependencies'],
$store_dependencies['version'], true). Update the block in Frontend.php where
$store_dependencies is assigned and where wp_register_script is invoked to use
this guarded logic.
In `@includes/functions.php`:
- Around line 578-581: The function wedocs_apply_extracted_content uses strlen
and substr which can break multibyte characters; change it to use mb_strlen and
mb_substr (specifying UTF-8) in wedocs_apply_extracted_content so length checks
and truncation are multibyte-safe, and optionally provide a fallback to the
single-byte functions if mbstring is not available.
- Around line 589-593: The function wedocs_convert_utc_to_est uses the fixed
'EST' zone which ignores DST and leads to incorrect comparisons; update it to
convert UTC to the IANA zone 'America/New_York' (e.g., use new
DateTimeZone('America/New_York')) in wedocs_convert_utc_to_est so the
DateTime->setTimezone call is DST-aware and returns the correct Eastern time
string for promotion windows.
In `@readme.md`:
- Line 7: The version badge text "PLUGIN_VERSION-V2.1.7" in the README is stale;
update the badge to reflect the current release version referenced elsewhere
(replace the literal "V2.1.7" in the badge string with the current version),
e.g., update the PLUGIN_VERSION badge token used in the markdown line that
contains PLUGIN_VERSION-V2.1.7 so it matches the project's release metadata or
uses a dynamic variable if available.
In `@readme.txt`:
- Around line 111-124: The changelog headings contain unbalanced bold markers
and parentheses (e.g., "v2.1.14 (22nd Oct, 2025**)", "v2.1.13 (3rd Oct,
2025**)", "v2.1.12 (25th July, 2025**") so fix each heading by properly closing
the bold and parentheses (for example change to "**v2.1.14 (22nd Oct, 2025)**"
etc.), ensure consistent heading formatting across "v2.1.14", "v2.1.13", and
"v2.1.12" entries, and scan nearby headings like "v2.1.11 (28th Apr, 2025)" to
confirm all Markdown bold and parentheses are balanced.
In `@src/blocks/DocsGrid/render.php`:
- Around line 39-40: The render invocation is incorrectly placed inside the
function_exists guard for render_wedocs_docs_grid so repeated includes can
define the function once and then skip executing the renderer; keep the function
definition guard (if(!function_exists('render_wedocs_docs_grid')) { function
render_wedocs_docs_grid(...) { ... } }) but move any call to
render_wedocs_docs_grid($attributes) out of that guard (or ensure the call is
run unconditionally after the guard), so the function remains protected from
redeclaration while the render call always executes on each include.
In `@src/blocks/TableOfContents/render.php`:
- Around line 131-133: The current preg_match using
'/<div[^>]*class=["\'][^"\']*entry-content[^"\']*["\'][^>]*>(.*?)<\/div>/is'
(operating on $content and storing into $entry_match) is unsafe for nested
markup and can truncate content; replace this regex-based extraction with a
proper HTML parse: use DOMDocument/DOMXPath to load $content, locate the element
that contains the "entry-content" class, and extract its inner HTML into
$content (with a safe fallback to the original $content if not found); ensure
you suppress/clear libxml errors and handle character encoding when using
DOMDocument so the new logic is used instead of preg_match.
In `@src/blocks/TableOfContents/style.scss`:
- Line 71: The SCSS uses the keyword casing "currentColor" which violates the
stylelint value-keyword-case rule; in src/blocks/TableOfContents/style.scss
locate the declaration that sets border-left: 3px solid currentColor and change
the keyword to lowercase "currentcolor" so the property becomes border-left: 3px
solid currentcolor, ensuring consistency with stylelint-config-standard-scss.
In `@src/components/DocListing/QuickEditModal.js`:
- Around line 34-38: The selector passed to useSelect reads sectionId but the
dependency array is empty, causing stale results; update the useSelect call in
QuickEditModal.js so the dependency array includes sectionId (or the parsed
integer, e.g. parseInt(sectionId)) so that
select(docStore).getSectionArticles(parseInt(sectionId)) is re-run when
sectionId changes; reference the useSelect call, the getSectionArticles selector
on docStore, and the sectionId variable when making this change.
- Around line 123-133: The current useEffect handlers for updating newArticle
and formError use stale closures by spreading newArticle/formError directly;
change them to functional state updates so you merge into the latest state: use
setNewArticle(prev => ({ ...prev, parent: sectionId })) and setFormError(prev =>
({ ...prev, sectionId: false })) in the first effect, and in the second effect
use setNewArticle(prev => ({ ...prev, menu_order: articles?.length })); update
the effects that reference setNewArticle and setFormError accordingly to avoid
overwriting concurrent user edits.
---
Duplicate comments:
In `@src/blocks/TableOfContents/render.php`:
- Around line 188-189: The counters array only includes keys 1..5 so h6 will
cause undefined index when $level === 6; update the $counters initialization to
include key 6 (e.g. [1=>0,...,6=>0]) and ensure any logic that references
$counters[$level] (the increment/reset code around where $global_counter is
used) properly supports level 6 as well so numbering and resets behave the same
for h6 as for other levels.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: b41e5789-b7b4-4957-97c4-bee77395a4ea
⛔ Files ignored due to path filters (13)
assets/build/5f4138884ca3828fa2ff.svgis excluded by!**/*.svgassets/build/fonts/wedocs.0e4fd4b5.ttfis excluded by!**/*.ttfassets/build/fonts/wedocs.29ec52e7.woffis excluded by!**/*.woffassets/build/images/avatar-four.5b164b46.jpgis excluded by!**/*.jpgassets/build/images/avatar-one.d65f1350.jpgis excluded by!**/*.jpgassets/build/images/avatar-three.af590ffb.jpgis excluded by!**/*.jpgassets/build/images/avatar-two.15349c81.jpgis excluded by!**/*.jpgassets/build/images/pro-badge.aa003c10.pngis excluded by!**/*.pngassets/build/images/slider-1.b05d3c91.jpgis excluded by!**/*.jpgassets/build/images/slider-2.f7822c31.jpgis excluded by!**/*.jpgassets/build/images/slider-3.ab3b7f94.jpgis excluded by!**/*.jpgassets/build/images/slider-4.501d8d95.jpgis excluded by!**/*.jpgpackage-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (102)
.gitignore.svnignoreappsero.jsonassets/build/block.asset.phpassets/build/block.jsassets/build/blocks/DocsGrid/block.jsonassets/build/blocks/DocsGrid/render.phpassets/build/frontend.asset.phpassets/build/frontend.cssassets/build/frontend.jsassets/build/index.asset.phpassets/build/index.cssassets/build/index.jsassets/build/print.asset.phpassets/build/print.cssassets/build/print.jsassets/build/store.asset.phpassets/build/store.jsassets/build/style-block.cssassets/js/frontend.jsincludes/API/API.phpincludes/API/SettingsApi.phpincludes/Admin.phpincludes/Admin/Admin.phpincludes/Admin/Promotion.phpincludes/Ajax.phpincludes/Assets.phpincludes/Capability.phpincludes/Frontend.phpincludes/Post_Types.phpincludes/Shortcode.phpincludes/Upgrader/Abstracts/UpgradeHandler.phpincludes/Upgrader/Upgrades/Upgrades.phpincludes/Upgrader/Upgrades/V_2_0_2.phpincludes/functions.phplanguages/wedocs.potpackage.jsonpostcss.config.jsreadme.mdreadme.txtsrc/assets/less/responsive.lesssrc/blocks/DocsGrid/StyleControls.jssrc/blocks/DocsGrid/block.jsonsrc/blocks/DocsGrid/edit.jssrc/blocks/DocsGrid/index.jssrc/blocks/DocsGrid/render.phpsrc/blocks/DocsGrid/save.jssrc/blocks/DocsGrid/style.scsssrc/blocks/Search/edit.jssrc/blocks/Search/index.jssrc/blocks/Search/save.jssrc/blocks/TableOfContents/block.jsonsrc/blocks/TableOfContents/edit.jssrc/blocks/TableOfContents/editor.scsssrc/blocks/TableOfContents/index.jssrc/blocks/TableOfContents/render.phpsrc/blocks/TableOfContents/save.jssrc/blocks/TableOfContents/style.scsssrc/blocks/TableOfContents/view.jssrc/blocks/index.jssrc/components/AddArticleModal.jssrc/components/AddDocModal.jssrc/components/AddSectionModal.jssrc/components/App.jssrc/components/ConfirmationModal.jssrc/components/DocActions.jssrc/components/DocListing/ArticleChildrens.jssrc/components/DocListing/DocSections.jssrc/components/DocListing/QuickEditModal.jssrc/components/DocListing/SectionArticles.jssrc/components/DraggableDocs.jssrc/components/Migrations/Modals/MigrationContentMappingModal.jssrc/components/Migrations/Modals/MigrationProgressModal.jssrc/components/Migrations/Modals/MigrationSelectionModal.jssrc/components/MultiSelectBox.jssrc/components/PermissionSettingsDemo/PrivacySettings.jssrc/components/ProPreviews/PermissionSettings.jssrc/components/ProPreviews/SocialShareSettings.jssrc/components/ProPreviews/common/UpgradeButton.jssrc/components/ProPreviews/common/UpgradePopup.jssrc/components/ProPreviews/common/UpgradeTooltip.jssrc/components/ProPreviews/index.jssrc/components/RestrictionModal.jssrc/components/Settings/GeneralSettings.jssrc/components/Settings/Menu.jssrc/components/Settings/index.jssrc/data/docs/actions.jssrc/data/docs/controls.jssrc/data/docs/resolvers.jssrc/data/docs/selectors.jssrc/data/settings/controls.jssrc/data/settings/reducer.jssrc/index.jssrc/utils/helper.jstailwind.config.jstemplates/content-modal.phptemplates/doc-search-form.phptemplates/docs-sidebar.phptemplates/shortcode.phptemplates/single-docs.phpwebpack.config.jswedocs.php
💤 Files with no reviewable changes (12)
- assets/build/store.js
- assets/build/frontend.css
- assets/build/blocks/DocsGrid/block.json
- assets/build/block.asset.php
- assets/build/style-block.css
- assets/build/frontend.asset.php
- assets/build/blocks/DocsGrid/render.php
- assets/build/block.js
- assets/build/store.asset.php
- assets/build/print.css
- assets/build/index.asset.php
- assets/build/print.asset.php
✅ Files skipped from review due to trivial changes (31)
- .gitignore
- appsero.json
- postcss.config.js
- src/blocks/Search/index.js
- src/blocks/DocsGrid/save.js
- src/blocks/DocsGrid/index.js
- src/blocks/index.js
- src/blocks/DocsGrid/block.json
- includes/Upgrader/Upgrades/Upgrades.php
- src/components/App.js
- .svnignore
- includes/Shortcode.php
- includes/API/SettingsApi.php
- src/components/DocListing/ArticleChildrens.js
- includes/Admin/Admin.php
- src/blocks/TableOfContents/save.js
- includes/Upgrader/Abstracts/UpgradeHandler.php
- includes/Admin/Promotion.php
- src/components/DocActions.js
- src/assets/less/responsive.less
- src/components/AddSectionModal.js
- src/components/DocListing/DocSections.js
- assets/js/frontend.js
- src/blocks/Search/save.js
- src/blocks/DocsGrid/StyleControls.js
- src/blocks/DocsGrid/style.scss
- src/blocks/DocsGrid/edit.js
- src/components/AddDocModal.js
- src/blocks/Search/edit.js
- src/components/ConfirmationModal.js
- src/components/AddArticleModal.js
🚧 Files skipped from review as they are similar to previous changes (6)
- src/blocks/TableOfContents/editor.scss
- src/blocks/TableOfContents/index.js
- src/blocks/TableOfContents/block.json
- src/blocks/TableOfContents/view.js
- package.json
- src/blocks/TableOfContents/edit.js
| add_action( 'wp_ajax_hide_wedocs_pro_notice', [ $this, 'hide_pro_notice' ] ); | ||
| add_action( 'wp_ajax_nopriv_hide_wedocs_pro_notice', [ $this, 'hide_pro_notice' ] ); | ||
| } |
There was a problem hiding this comment.
hide_pro_notice is exposed without nonce/authz protections.
Line 40–42 registers a nopriv action and Line 230–233 updates user meta with no nonce/capability checks. This enables CSRF-style state changes and unnecessary anonymous access to a state-changing endpoint.
Also applies to: 230-233
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@includes/Ajax.php` around lines 40 - 42, The hide_pro_notice AJAX handler is
registered for unauthenticated users and updates user meta without any nonce or
capability checks; modify the registration and handler (the add_action calls and
the hide_pro_notice method) to require a valid nonce and authenticated user:
remove or stop using the nopriv hook (or keep it only if you add explicit
checks), verify the nonce with check_ajax_referer (or wp_verify_nonce) at the
start of hide_pro_notice, ensure the user is logged in (is_user_logged_in /
wp_get_current_user) and optionally check a capability with current_user_can
before calling update_user_meta, and return proper AJAX responses
(wp_send_json_success/wp_send_json_error) instead of silent updates. Ensure any
incoming data is sanitized and that update_user_meta is only reached after these
checks.
| 'data' => array( | ||
| 'type' => 'object', | ||
| 'description' => esc_html__( 'Collective documents object', 'wedocs' ), | ||
| 'properties' => array( | ||
| 'docIds' => array( | ||
| 'type' => 'object', | ||
| ), | ||
| 'status' => array( | ||
| 'type' => 'string', | ||
| ), | ||
| ), | ||
| ), | ||
| ], |
There was a problem hiding this comment.
update_docs_status reads a different payload shape than the route schema.
Route args define docIds/status under data (Line 221+), but Line 356/366 read them from request root. This can result in empty $doc_ids and no updates.
Also applies to: 354-367
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@includes/API/API.php` around lines 221 - 233, The route schema declares
docIds and status nested under the "data" object but update_docs_status reads
them from the request root, causing empty $doc_ids; update update_docs_status to
pull the payload from the "data" key (e.g. obtain $data =
$request->get_param('data') or $request->get_json_params()['data'] and then read
docIds and status from $data) and use those values when building $doc_ids and
$status (adjust the logic in the update_docs_status handler around the current
354-367 logic that reads request params), or alternatively change the route
schema to match the current root-level reading—ensure the same source is used in
the route schema and in update_docs_status.
| if ( empty( $post ) || empty( $post->ID ) || 'docs' !== $this->post_type ) { | ||
| return $error; |
There was a problem hiding this comment.
get_doc post-type validation checks the wrong value.
Line 784 compares 'docs' with $this->post_type (always true for this controller) instead of validating $post->post_type, so non-doc posts can pass.
Proposed fix
- if ( empty( $post ) || empty( $post->ID ) || 'docs' !== $this->post_type ) {
+ if ( empty( $post ) || empty( $post->ID ) || $post->post_type !== $this->post_type ) {
return $error;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if ( empty( $post ) || empty( $post->ID ) || 'docs' !== $this->post_type ) { | |
| return $error; | |
| if ( empty( $post ) || empty( $post->ID ) || $post->post_type !== $this->post_type ) { | |
| return $error; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@includes/API/API.php` around lines 784 - 785, The post-type check in get_doc
is comparing the controller property $this->post_type instead of the actual
post's type; update the validation in the get_doc flow to check $post->post_type
=== 'docs' (alongside the existing empty($post) and empty($post->ID) checks) so
non-doc posts are rejected—locate the conditional that currently uses
$this->post_type and replace it to validate $post->post_type.
| wp_register_style( | ||
| 'wedocs-app-style', | ||
| $assets_url . '/build/index.css', | ||
| $react_dependencies['version'], | ||
| ); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "Assets.php" -type fRepository: weDevsOfficial/wedocs-plugin
Length of output: 94
🏁 Script executed:
cat -n includes/Assets.php | sed -n '40,90p'Repository: weDevsOfficial/wedocs-plugin
Length of output: 2392
🌐 Web query:
WordPress wp_register_style function arguments $deps $ver
💡 Result:
The wp_register_style function in WordPress is used to register a CSS stylesheet for later use [1][2]. The $deps and $ver arguments are optional parameters that provide control over dependency management and cache busting [1][3]. $deps (array) This optional parameter accepts an array of registered stylesheet handles that the current stylesheet depends on [1][4]. WordPress will ensure that all stylesheets listed in this array are enqueued before the current stylesheet [2][5]. The default value is an empty array (array) [1][2]. $ver (string|bool|null) This optional parameter specifies the version number of the stylesheet, which is appended to the URL as a query string (e.g.,?ver=1.0) for cache busting purposes [1][2]. - If set to a string (e.g., '1.0'), that specific version is used [6][2]. - If set to false (the default), the current installed WordPress version is automatically added [1][3]. - If set to null, no version query string is added to the URL [1][4]. The full function signature is: wp_register_style( string $handle, string|false $src, string[] $deps = array, string|bool|null $ver = false, string $media = 'all') [1][4]
Citations:
- 1: https://developer.wordpress.org/reference/functions/wp_register_style/
- 2: https://wp-kama.com/function/wp_register_style
- 3: https://typeerror.org/docs/wordpress/functions/wp_register_style
- 4: https://docs.classicpress.net/reference/functions/wp_register_style/
- 5: https://codex.wordpress.org/Class_Reference/WP_Styles
- 6: https://wpturbo.dev/functions/wp_register_style/
Fix wp_register_style argument order (version is currently passed as dependencies).
Both registrations pass the version string in the $deps position (3rd argument), which should be an array of dependencies. This prevents the stylesheet from registering properly with the correct version for cache-busting. The 4th argument ($ver) is missing entirely, causing WordPress to append its own version instead.
Suggested fix
wp_register_style(
'wedocs-app-style',
$assets_url . '/build/index.css',
- $react_dependencies['version'],
+ array(),
+ $react_dependencies['version']
);
wp_register_style(
'wedocs-block-style',
$assets_url . '/build/style-block.css',
- $block_dependencies['version']
+ array(),
+ $block_dependencies['version']
);Also applies to: 80-84
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@includes/Assets.php` around lines 52 - 56, The wp_register_style call
registering 'wedocs-app-style' is passing the version string into the $deps slot
(third arg) instead of an array and omitting the $ver (fourth arg); update the
wp_register_style invocation(s) that use $react_dependencies['version'] (and the
analogous registration around the other stylesheet) to pass an array of
dependencies as the third parameter (e.g. [] or
$react_dependencies['dependencies']) and pass the version string as the fourth
parameter so cache-busting works correctly; locate the calls by the handle
'wedocs-app-style' and the other similar registration near the other
stylesheet/handle and swap the args accordingly.
| // override the theme template | ||
| // add_filter( 'template_include', [ $this, 'template_loader' ], 20 ); | ||
There was a problem hiding this comment.
Re-enable template_include hook or document intentional behavior change.
Disabling this hook removes plugin template fallback for docs pages and can break rendering on themes without single-docs.php.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@includes/Frontend.php` around lines 38 - 40, The commented-out add_filter
call removed the plugin's template fallback for docs pages; re-enable the
template_include hook by restoring the add_filter( 'template_include', [ $this,
'template_loader' ], 20 ) line in the Frontend class (or, if the behavior is
intentional, add a clear comment and update README/changelog to document that
template_loader will no longer run and themes must provide single-docs.php),
ensuring the template_loader method is executed so plugin templates are used as
a fallback for docs pages.
| if(!function_exists( 'render_wedocs_docs_grid' )){ | ||
| function render_wedocs_docs_grid($attributes) { |
There was a problem hiding this comment.
Render call is incorrectly coupled to function_exists guard.
Because Line 323 is inside the guard, subsequent includes (same request) can skip rendering entirely once the function is already defined.
Proposed fix
if(!function_exists( 'render_wedocs_docs_grid' )){
function render_wedocs_docs_grid($attributes) {
...
return ob_get_clean();
}
- echo render_wedocs_docs_grid($attributes);
}
+echo render_wedocs_docs_grid($attributes);Also applies to: 323-324
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/blocks/DocsGrid/render.php` around lines 39 - 40, The render invocation
is incorrectly placed inside the function_exists guard for
render_wedocs_docs_grid so repeated includes can define the function once and
then skip executing the renderer; keep the function definition guard
(if(!function_exists('render_wedocs_docs_grid')) { function
render_wedocs_docs_grid(...) { ... } }) but move any call to
render_wedocs_docs_grid($attributes) out of that guard (or ensure the call is
run unconditionally after the guard), so the function remains protected from
redeclaration while the render call always executes on each include.
| if (preg_match('/<div[^>]*class=["\'][^"\']*entry-content[^"\']*["\'][^>]*>(.*?)<\/div>/is', $content, $entry_match)) { | ||
| $content = $entry_match[1]; | ||
| } |
There was a problem hiding this comment.
entry-content regex extraction is structurally unsafe and can truncate content.
Line 131 matches only until the first </div>, so nested markup inside .entry-content can cut off later headings and produce incomplete TOC output.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/blocks/TableOfContents/render.php` around lines 131 - 133, The current
preg_match using
'/<div[^>]*class=["\'][^"\']*entry-content[^"\']*["\'][^>]*>(.*?)<\/div>/is'
(operating on $content and storing into $entry_match) is unsafe for nested
markup and can truncate content; replace this regex-based extraction with a
proper HTML parse: use DOMDocument/DOMXPath to load $content, locate the element
that contains the "entry-content" class, and extract its inner HTML into
$content (with a safe fallback to the original $content if not found); ensure
you suppress/clear libxml errors and handle character encoding when using
DOMDocument so the new logic is used instead of preg_match.
|
|
||
| &.active { | ||
| font-weight: 600; | ||
| border-left: 3px solid currentColor; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check if the file exists and view the context around line 71
cat -n src/blocks/TableOfContents/style.scss | sed -n '65,80p'Repository: weDevsOfficial/wedocs-plugin
Length of output: 497
🏁 Script executed:
# Look for stylelint configuration in the repository
find . -name ".stylelintrc*" -o -name "stylelint.config.*" 2>/dev/null | head -20Repository: weDevsOfficial/wedocs-plugin
Length of output: 92
🏁 Script executed:
# Also check if stylelint is configured in package.json
cat package.json | grep -A 20 -B 2 "stylelint"Repository: weDevsOfficial/wedocs-plugin
Length of output: 54
🏁 Script executed:
# Read the stylelint configuration
cat .stylelintrc.jsonRepository: weDevsOfficial/wedocs-plugin
Length of output: 1432
🏁 Script executed:
# Check if value-keyword-case is mentioned anywhere in the config
cat .stylelintrc.json | grep -i "value-keyword"Repository: weDevsOfficial/wedocs-plugin
Length of output: 54
🌐 Web query:
stylelint value-keyword-case rule currentColor default behavior
💡 Result:
The default behavior of the Stylelint value-keyword-case rule regarding currentColor is to expect the lowercase form, currentcolor [1][2]. While historically some SVG-related keywords were expected to be camelCase, Stylelint updated its default behavior to align with modern CSS specifications, which treat CSS keywords as case-insensitive and generally favor lowercase [3][4]. Consequently, if you use the primary option "lower" (which is standard in many configurations), Stylelint will flag currentColor as a problem and expect currentcolor [1][2]. If you specifically require the camelCase version (currentColor), you can enable the secondary option camelCaseSvgKeywords by setting it to true in your Stylelint configuration [1][2]: { "rules": { "value-keyword-case": ["lower", { "camelCaseSvgKeywords": true }] } } When camelCaseSvgKeywords is set to true, the rule will accept currentColor as valid [1][2]. The default value for this option is false [1][2].
Citations:
- 1: https://github.com/stylelint/stylelint/blob/main/lib/rules/value-keyword-case/README.md
- 2: https://stylelint.io/user-guide/rules/value-keyword-case/
- 3: value-keyword-case for currentColor in non SVG CSS is breaking code stylelint/stylelint#5863
- 4: Add camelCaseSvgKeywords to value-keyword-case and set default to false stylelint/stylelint#4884
Use the keyword casing expected by the configured linter.
currentColor should be currentcolor to satisfy the value-keyword-case rule configured in stylelint-config-standard-scss.
🧰 Tools
🪛 Stylelint (17.11.0)
[error] 71-71: Expected "currentColor" to be "currentcolor" (value-keyword-case)
(value-keyword-case)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/blocks/TableOfContents/style.scss` at line 71, The SCSS uses the keyword
casing "currentColor" which violates the stylelint value-keyword-case rule; in
src/blocks/TableOfContents/style.scss locate the declaration that sets
border-left: 3px solid currentColor and change the keyword to lowercase
"currentcolor" so the property becomes border-left: 3px solid currentcolor,
ensuring consistency with stylelint-config-standard-scss.
| const articles = useSelect( | ||
| ( select ) => | ||
| select( docStore ).getSectionArticles( parseInt( sectionId ) ), | ||
| [] | ||
| ); |
There was a problem hiding this comment.
useSelect is missing sectionId dependency and can return stale article lists.
Line 34–38 uses sectionId inside the selector but passes [] dependencies, so section switches may not rebind the selector argument correctly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/DocListing/QuickEditModal.js` around lines 34 - 38, The
selector passed to useSelect reads sectionId but the dependency array is empty,
causing stale results; update the useSelect call in QuickEditModal.js so the
dependency array includes sectionId (or the parsed integer, e.g.
parseInt(sectionId)) so that
select(docStore).getSectionArticles(parseInt(sectionId)) is re-run when
sectionId changes; reference the useSelect call, the getSectionArticles selector
on docStore, and the sectionId variable when making this change.
| useEffect( () => { | ||
| setNewArticle( { | ||
| ...newArticle, | ||
| parent: sectionId, | ||
| } ); | ||
| setFormError( { ...formError, sectionId: false } ); | ||
| }, [ sectionId ] ); | ||
| useEffect( () => { | ||
| setNewArticle( { ...newArticle, menu_order: articles?.length } ); | ||
| }, [ articles ] ); |
There was a problem hiding this comment.
Avoid stale state merges in the useEffect updates.
Line 123–133 spreads newArticle/formError from stale closures, which can overwrite more recent user edits. Use functional state updates.
Proposed fix
- useEffect( () => {
- setNewArticle( {
- ...newArticle,
- parent: sectionId,
- } );
- setFormError( { ...formError, sectionId: false } );
- }, [ sectionId ] );
+ useEffect( () => {
+ setNewArticle( (prev) => ( { ...prev, parent: sectionId } ) );
+ setFormError( (prev) => ( { ...prev, sectionId: false } ) );
+ }, [ sectionId ] );
- useEffect( () => {
- setNewArticle( { ...newArticle, menu_order: articles?.length } );
- }, [ articles ] );
+ useEffect( () => {
+ setNewArticle( (prev) => ( { ...prev, menu_order: articles?.length } ) );
+ }, [ articles ] );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| useEffect( () => { | |
| setNewArticle( { | |
| ...newArticle, | |
| parent: sectionId, | |
| } ); | |
| setFormError( { ...formError, sectionId: false } ); | |
| }, [ sectionId ] ); | |
| useEffect( () => { | |
| setNewArticle( { ...newArticle, menu_order: articles?.length } ); | |
| }, [ articles ] ); | |
| useEffect( () => { | |
| setNewArticle( (prev) => ( { ...prev, parent: sectionId } ) ); | |
| setFormError( (prev) => ( { ...prev, sectionId: false } ) ); | |
| }, [ sectionId ] ); | |
| useEffect( () => { | |
| setNewArticle( (prev) => ( { ...prev, menu_order: articles?.length } ) ); | |
| }, [ articles ] ); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/DocListing/QuickEditModal.js` around lines 123 - 133, The
current useEffect handlers for updating newArticle and formError use stale
closures by spreading newArticle/formError directly; change them to functional
state updates so you merge into the latest state: use setNewArticle(prev => ({
...prev, parent: sectionId })) and setFormError(prev => ({ ...prev, sectionId:
false })) in the first effect, and in the second effect use setNewArticle(prev
=> ({ ...prev, menu_order: articles?.length })); update the effects that
reference setNewArticle and setFormError accordingly to avoid overwriting
concurrent user edits.
Summary by CodeRabbit
New Features
Refactor
Chores