Preview/Smartylint#95
Conversation
…findings across error and warning severities
WalkthroughThis pull request introduces six new Smarty template files for an e-commerce application. The templates comprise a complete page layout system (header, footer), product presentation pages (product listing and detail views), a checkout flow, and an email order confirmation template, with features including dynamic content rendering, conditional logic, form handling, and pagination. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 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 docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c3f99b44e2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| </select> | ||
| </label> | ||
|
|
||
| {if $shipping_method == "express"} |
There was a problem hiding this comment.
Close the checkout shipping condition block
The {if $shipping_method == "express"} block opened here is never closed, so Smarty cannot correctly match block delimiters when compiling this template. In practice, rendering the checkout page will fail with an unclosed-tag parse error instead of showing the form.
Useful? React with 👍 / 👎.
|
|
||
| {if $products} | ||
| <ul class="products"> | ||
| {foreach $products as $product} |
There was a problem hiding this comment.
Close the products loop before ending the list
This {foreach $products as $product} is not followed by a matching {/foreach} before </ul>, which leaves Smarty block structure invalid. As a result, the product listing template will fail to compile/render whenever this page is requested.
Useful? React with 👍 / 👎.
| {include file=meta.tpl} | ||
| {include file="styles.tpl" theme=$current_theme} | ||
|
|
||
| <link rel="canonical" href="https://demoapp.example.com/{$canonical_path}> |
There was a problem hiding this comment.
Terminate the canonical link href quote
The href attribute starts with a double quote but never closes it, so browsers can treat following markup as part of the same attribute value and misparse the document head/body structure. This can break metadata and page layout parsing on product pages that include this header.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 13
🧹 Nitpick comments (6)
smartylint/header.tpl (1)
1-1: Remove empty top-level Smarty comment.Line 1 is an empty comment block and can be removed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@smartylint/header.tpl` at line 1, Remove the empty top-level Smarty comment "{* *}" from header.tpl; locate the top of the template (the "{* *}" token) and delete that empty comment block so the file no longer begins with a redundant Smarty comment.smartylint/email_order.tpl (1)
34-34: Remove unnecessary empty comment block.Line 34 is an empty Smarty comment and adds noise.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@smartylint/email_order.tpl` at line 34, Remove the extraneous empty Smarty comment "{* *}" from the template (smartylint/email_order.tpl) to eliminate noise; simply delete that comment token so the template content remains unchanged and no blank comment blocks are left in the file.smartylint/product_detail.tpl (1)
6-6: Migrate deprecated@defaultmodifier usage.Line 6, Line 12, and Line 37 use
@default; switch todefaultto avoid deprecated behavior.🔧 Proposed fix
-<img src="{$Image.url}" alt="{$Image.alt|@default:""}"> +<img src="{$Image.url|escape:'url'}" alt="{$Image.alt|default:""|escape}"> -<p class="sku">SKU: {$Product.sku|@default:"n/a"}</p> +<p class="sku">SKU: {$Product.sku|default:"n/a"|escape}</p> -<time>{$Review.created_at|@default:"recently"}</time> +<time>{$Review.created_at|default:"recently"|escape}</time>Also applies to: 12-12, 37-37
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@smartylint/product_detail.tpl` at line 6, Three template expressions use the deprecated Smarty modifier `@default` (e.g., the img alt attribute expression "{$Image.alt|@default:""}" and the other occurrences on lines referenced); replace each "@default" modifier with the non-deprecated "default" modifier (e.g., "{$Image.alt|default:""}") so the template uses default instead of `@default`; update all occurrences (Image.alt and the two other template variables referenced) consistently to ensure no deprecated modifiers remain.smartylint/footer.tpl (2)
6-18: Remove no-op wrapper/empty blocks or implement their body.Line 6-18 contains
{if true}and empty{if}/{foreach}blocks. They increase template noise and can mask unfinished logic.Would you like me to draft concrete footer/newsletter/social markup for these placeholders?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@smartylint/footer.tpl` around lines 6 - 18, Remove the no-op template wrappers or implement their intended content: delete the redundant `{if true}` ... `{/if}` wrapper around the static links (or convert it to a meaningful condition), implement the `{if $show_newsletter}` block to render the newsletter signup markup when true, and populate the `{foreach $social_links as $link}` loop to output each social link (e.g., anchor tags using `$link` properties) instead of leaving them empty; refer to the `{if true}`, `{if $show_newsletter}`, and `{foreach $social_links as $link}` blocks to locate and fix these placeholders.
22-22: Replace deprecated@defaultmodifier usage.Line 22 uses
@default, which is deprecated in Smarty lint rules and should be migrated.🔧 Proposed fix
-<p>Build {$build_id|@default:"dev"}</p> +<p>Build {$build_id|default:"dev"}</p>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@smartylint/footer.tpl` at line 22, Replace the deprecated Smarty modifier usage {$build_id|@default:"dev"} by using the supported modifier name; locate the template reference to the build_id variable (the expression containing `@default` in footer.tpl) and change the modifier from "@default" to "default" so the expression reads the variable with a fallback of "dev".smartylint/checkout.tpl (1)
37-37: Prefer strict/boolean condition checks for template conditionals.Line 37 and Line 40 use loose
==comparisons. Tighten these conditions to avoid coercion surprises.Also applies to: 40-40
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@smartylint/checkout.tpl` at line 37, Replace loose comparisons in the template conditionals: change instances of {if $shipping_method == "express"} (and the similar occurrence at the other location) to use a strict comparison like {if $shipping_method === "express"} (or the Smarty "eq" operator if your engine prefers: {if $shipping_method eq "express"}) so the check is not subject to type coercion; update both occurrences referencing $shipping_method in this file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@smartylint/checkout.tpl`:
- Around line 37-43: The template opens an if block with `{if $shipping_method
== "express"}` but never closes it, causing a parse error; close that outer
conditional by adding a matching `{/if}` after the express-related content
(before the existing `{if $promo_code == "WELCOME10"}` block or before
`</fieldset>` as appropriate) so the `{if $shipping_method == "express"}` block
is properly terminated and the nested promo `{if $promo_code == "WELCOME10"}`
remains valid.
- Around line 22-52: The checkout form that posts to "/checkout/place-order" is
missing a CSRF token; add a hidden input for the CSRF token (e.g., <input
type="hidden" name="csrf_token" ...>) into the <form
action="/checkout/place-order" method="post"> in the template (checkout.tpl) and
ensure the server-side handler that processes /checkout/place-order validates
that token, or alternatively confirm global/request-level CSRF middleware is
enabled for that route so submissions from the Card/Payment fields are
protected.
- Around line 14-17: The template renders unescaped runtime data — update the
cart item and buyer/coupon renderings to use Smarty escaping: apply
{$line.name|escape:'html'} and {$line.quantity|escape:'html'} (and
{$line.subtotal|escape:'html'} after formatting) for HTML text contexts, and use
{$buyerField|escape:'quotes'} and {$couponValue|escape:'quotes'} for values
placed in attributes; ensure you add the |escape modifier to each occurrence
referenced (e.g., {$line.name}, {$line.quantity}, {$line.subtotal}, buyer field
variables, and coupon value) so text contexts use 'html' escaping and attribute
contexts use 'quotes' escaping.
In `@smartylint/email_order.tpl`:
- Around line 22-25: Remove the deprecated {php} block and move the logic to
Smarty-safe constructs: either assign the tracking value from PHP controller
(e.g., compute $tracking = isset($order['tracking_number']) ?
$order['tracking_number'] : 'pending' and $smarty->assign('tracking',
$tracking)) or use Smarty template features directly (use
{$order.tracking_number|default:'pending'} to render the value). Replace the
{php} block that references $order['tracking_number'] and $tracking with a plain
template line that outputs the tracking label and the Smarty variable (e.g.,
"Tracking: " followed by the Smarty expression) so the template is Smarty 4
compatible and secure.
In `@smartylint/footer.tpl`:
- Line 32: The include statement in footer.tpl uses an unquoted filename
({include file=tracking.tpl}); update it to use quoted filename syntax to match
the codebase pattern by changing the include to use single (or consistent)
quotes around tracking.tpl (e.g. {include file='tracking.tpl'}) so it aligns
with the other includes in this template.
- Around line 25-28: Change the loose string comparison {if $debug == "true"} to
a boolean check {if $debug} and escape the payload when rendering by replacing
{$debug_payload} with an escaped version like
{$debug_payload|escape:'html':'UTF-8'} (or {$debug_payload|escape:'html'} if
UTF-8 is implicit) inside the <pre class="debug">; this hardens the condition
and prevents XSS by ensuring the debug payload is HTML-escaped.
In `@smartylint/header.tpl`:
- Line 12: The canonical link tag in header.tpl is missing the closing quote for
the href attribute; update the <link rel="canonical"...> line so the href value
ends with a double quote after {$canonical_path} (i.e., ensure the attribute
reads href="https://demoapp.example.com/{$canonical_path}"), preserving the
existing template variable and surrounding markup to restore valid HTML and
prevent DOM parsing errors.
- Around line 6-7: Template outputs are rendering unescaped dynamic variables
(e.g., {$page_title}, {$meta_description}, {$page_class} and other runtime
variables in this template) which opens XSS risks; update every occurrence that
injects user-controlled or dynamic data into HTML text or attributes to use
Smarty's escape modifier (for example use |escape:'htmlall') so values are
correctly escaped in HTML contexts, and apply this consistently to all instances
mentioned (lines showing {$page_title}, {$meta_description}, {$page_class} and
the other dynamic variables in the file).
- Line 9: The Smarty include on header.tpl uses an unquoted parameter ({include
file=meta.tpl}) which causes parser ambiguity; update the include invocation in
header.tpl to use quoted filename syntax (e.g., change the include call
referencing meta.tpl to use "meta.tpl") so it matches the correct usage
elsewhere in the template and avoids parsing errors.
In `@smartylint/product_detail.tpl`:
- Around line 20-27: The add-to-cart form that posts to "/cart/add" is missing a
CSRF token hidden input; update the form (the <form action="/cart/add" ...>
block that contains inputs product_id and qty and the submit button) to include
a hidden field named "csrf_token" with the template variable value (e.g.,
{$csrf_token}) so the server can validate the token on POST; ensure the hidden
input appears inside the same form alongside the existing product_id and qty
inputs.
- Around line 11-17: Escape all dynamic template outputs and fix deprecated
modifier usage: update occurrences of {$Product.name},
{$Product.sku|@default:"n/a"}, {$Product.price|string_format:"%.2f"},
{$Product.long_description} and any {$Review.body} or similar variables to use
the Smarty escaping filter (e.g., |escape or |htmlspecialchars) and change the
deprecated `@default` modifier to the Smarty 3+ syntax (|default) or wrap with
{if} checks; keep numeric formatting (string_format) but pipe escape after
formatting where appropriate. Also ensure the checkout form includes an explicit
CSRF token hidden field (or verify/instrument framework CSRF middleware) so the
form submission includes the token for server-side validation.
In `@smartylint/product_list.tpl`:
- Around line 12-29: The template opens a {foreach $products as $product} loop
but never closes it, causing a parse error; close the loop by inserting the
matching {/foreach} before the closing </ul> so the list of <li
class="product-card"> elements is properly wrapped and the conditional {if
$product.on_sale} and button remain inside the loop.
- Around line 4-8: Escape all user-controlled Smarty template variables and
quote attribute values to prevent XSS and broken markup: wrap occurrences of
{$category_name}, {$result_count}, {$search_query}, all {$product.*} fields
(e.g., {$product.id}, {$product.slug}, {$product.image_url}, {$product.name},
{$product.short_description}, {$product.discount_label}) with the Smarty |escape
modifier (e.g., {$variable|escape}) and ensure the data-name attribute uses a
quoted, escaped value (e.g., data-name="{$product.name|escape}"); update every
instance in product_list.tpl where these variables are output (including in
URLs, attributes, and text nodes) so all dynamic output is escaped and
attributes are quoted.
---
Nitpick comments:
In `@smartylint/checkout.tpl`:
- Line 37: Replace loose comparisons in the template conditionals: change
instances of {if $shipping_method == "express"} (and the similar occurrence at
the other location) to use a strict comparison like {if $shipping_method ===
"express"} (or the Smarty "eq" operator if your engine prefers: {if
$shipping_method eq "express"}) so the check is not subject to type coercion;
update both occurrences referencing $shipping_method in this file.
In `@smartylint/email_order.tpl`:
- Line 34: Remove the extraneous empty Smarty comment "{* *}" from the template
(smartylint/email_order.tpl) to eliminate noise; simply delete that comment
token so the template content remains unchanged and no blank comment blocks are
left in the file.
In `@smartylint/footer.tpl`:
- Around line 6-18: Remove the no-op template wrappers or implement their
intended content: delete the redundant `{if true}` ... `{/if}` wrapper around
the static links (or convert it to a meaningful condition), implement the `{if
$show_newsletter}` block to render the newsletter signup markup when true, and
populate the `{foreach $social_links as $link}` loop to output each social link
(e.g., anchor tags using `$link` properties) instead of leaving them empty;
refer to the `{if true}`, `{if $show_newsletter}`, and `{foreach $social_links
as $link}` blocks to locate and fix these placeholders.
- Line 22: Replace the deprecated Smarty modifier usage
{$build_id|@default:"dev"} by using the supported modifier name; locate the
template reference to the build_id variable (the expression containing `@default`
in footer.tpl) and change the modifier from "@default" to "default" so the
expression reads the variable with a fallback of "dev".
In `@smartylint/header.tpl`:
- Line 1: Remove the empty top-level Smarty comment "{* *}" from header.tpl;
locate the top of the template (the "{* *}" token) and delete that empty comment
block so the file no longer begins with a redundant Smarty comment.
In `@smartylint/product_detail.tpl`:
- Line 6: Three template expressions use the deprecated Smarty modifier `@default`
(e.g., the img alt attribute expression "{$Image.alt|@default:""}" and the other
occurrences on lines referenced); replace each "@default" modifier with the
non-deprecated "default" modifier (e.g., "{$Image.alt|default:""}") so the
template uses default instead of `@default`; update all occurrences (Image.alt and
the two other template variables referenced) consistently to ensure no
deprecated modifiers remain.
🪄 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: Central YAML (base), Repository UI (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: 209ce2f8-f05e-42c1-ad0d-c37b982c4b96
📒 Files selected for processing (6)
smartylint/checkout.tplsmartylint/email_order.tplsmartylint/footer.tplsmartylint/header.tplsmartylint/product_detail.tplsmartylint/product_list.tpl
| <td>{$line.name}</td> | ||
| <td>{$line.quantity}</td> | ||
| <td>{$line.subtotal|string_format:"%.2f"}</td> | ||
| </tr> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "checkout.tpl" -type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 103
🏁 Script executed:
cat -n ./smartylint/checkout.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 2589
🏁 Script executed:
# Check for Smarty configuration or security settings
find . -name "*.php" -o -name "*.conf*" -o -name "*.config*" | head -20 | xargs grep -l "smarty\|escape\|auto_escape" 2>/dev/null || trueRepository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check if there's any PHP configuration that might set auto-escaping
find . -type f \( -name "*.php" -o -name "*.conf" -o -name "*.config" \) -exec grep -l "escape" {} \; 2>/dev/null | head -10Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Look for PHP files that might initialize Smarty or this template
find . -name "*.php" -type f | head -20Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check the directory structure
ls -la ./smartylint/Repository: coderabbitai/coderabbit-pr-review
Length of output: 570
Add HTML escaping to cart items, buyer fields, and coupon value.
Lines 14-17, 25-27, 38, and 48 render runtime data without escaping. In HTML text contexts (lines 14-17, 38), use {$variable|escape:'html'}. In HTML attribute contexts (lines 25-27, 48), use {$variable|escape:'quotes'} to prevent attribute injection and XSS attacks.
Also applies to: 25-27, 38-38, 48-48
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/checkout.tpl` around lines 14 - 17, The template renders unescaped
runtime data — update the cart item and buyer/coupon renderings to use Smarty
escaping: apply {$line.name|escape:'html'} and {$line.quantity|escape:'html'}
(and {$line.subtotal|escape:'html'} after formatting) for HTML text contexts,
and use {$buyerField|escape:'quotes'} and {$couponValue|escape:'quotes'} for
values placed in attributes; ensure you add the |escape modifier to each
occurrence referenced (e.g., {$line.name}, {$line.quantity}, {$line.subtotal},
buyer field variables, and coupon value) so text contexts use 'html' escaping
and attribute contexts use 'quotes' escaping.
| <form action="/checkout/place-order" method="post"> | ||
| <fieldset> | ||
| <legend>Shipping</legend> | ||
| <label>Full name <input type="text" name="name" value="{$buyer.name}"></label> | ||
| <label>Address <input type="text" name="address" value="{$buyer.address}"></label> | ||
| <label>City <input type="text" name="city" value="{$buyer.city}"></label> | ||
|
|
||
| <label> | ||
| Method | ||
| <select name="shipping_method"> | ||
| <option value="standard">Standard</option> | ||
| <option value="express">Express</option> | ||
| </select> | ||
| </label> | ||
|
|
||
| {if $shipping_method == "express"} | ||
| <p class="note">Express delivery adds {$express_fee|string_format:"%.2f"}.</p> | ||
|
|
||
| {if $promo_code == "WELCOME10"} | ||
| <p class="note">Promo applied: 10% off.</p> | ||
| {/if} | ||
| </fieldset> | ||
|
|
||
| <fieldset> | ||
| <legend>Payment</legend> | ||
| <label>Card number <input type="text" name="card"></label> | ||
| <label>Coupon <input type="text" name="coupon" value="{$applied_coupon}"></label> | ||
| </fieldset> | ||
|
|
||
| <button type="submit">Place order</button> | ||
| </form> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find and read the actual checkout.tpl file
find . -name "checkout.tpl" -type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 103
🏁 Script executed:
# Search for CSRF-related patterns in the codebase
rg -i "csrf" --type-list | head -20Repository: coderabbitai/coderabbit-pr-review
Length of output: 467
🏁 Script executed:
# Look for token-related patterns in templates and code
rg -i "token|_token" -t smarty -t php -t js | head -30Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check the codebase structure to understand the framework
ls -laRepository: coderabbitai/coderabbit-pr-review
Length of output: 356
🏁 Script executed:
# Read the actual checkout.tpl file
cat -n ./smartylint/checkout.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 2589
🏁 Script executed:
# Search for CSRF patterns in the codebase
rg -i "csrf" .Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Search for token patterns in the codebase
rg -i "_token|csrf_token|token" .Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check for middleware or security-related files
find . -name "*.php" -o -name "*.py" -o -name "*.js" | grep -i "middleware\|config\|security"Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Look for form helpers or template functions that might add CSRF tokens
rg -i "form|csrf" --type smarty .Repository: coderabbitai/coderabbit-pr-review
Length of output: 950
🏁 Script executed:
# Check all template files for CSRF patterns
find ./smartylint -name "*.tpl" -exec grep -l "csrf\|token\|_token" {} \;Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check if there are any PHP, Python, or configuration files outside smartylint
find . -type f \( -name "*.php" -o -name "*.py" -o -name "*.js" -o -name "*.conf" -o -name "*.config" \) ! -path "./.git/*"Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Specifically check the product_detail.tpl form for comparison
cat -n ./smartylint/product_detail.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 2132
Add CSRF token to the checkout form or verify CSRF middleware protection.
The POST form submitting sensitive payment and order data (lines 22-52) contains no CSRF token. Either include a hidden CSRF token field in the form, or confirm that request-level CSRF validation middleware is enforced for the /checkout/place-order endpoint.
🧰 Tools
🪛 smarty-lint (0.3.3)
[warn] 37-37: Use "===" instead of "==".
(eqeqeq)
[warn] 40-40: Use "===" instead of "==".
(eqeqeq)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/checkout.tpl` around lines 22 - 52, The checkout form that posts
to "/checkout/place-order" is missing a CSRF token; add a hidden input for the
CSRF token (e.g., <input type="hidden" name="csrf_token" ...>) into the <form
action="/checkout/place-order" method="post"> in the template (checkout.tpl) and
ensure the server-side handler that processes /checkout/place-order validates
that token, or alternatively confirm global/request-level CSRF middleware is
enabled for that route so submissions from the Card/Payment fields are
protected.
| {if $shipping_method == "express"} | ||
| <p class="note">Express delivery adds {$express_fee|string_format:"%.2f"}.</p> | ||
|
|
||
| {if $promo_code == "WELCOME10"} | ||
| <p class="note">Promo applied: 10% off.</p> | ||
| {/if} | ||
| </fieldset> |
There was a problem hiding this comment.
Close the outer shipping {if} block.
Line 37 opens an if block that is never closed. This is a template parse error and can break rendering of the form section.
🔧 Proposed fix
{if $shipping_method == "express"}
<p class="note">Express delivery adds {$express_fee|string_format:"%.2f"}.</p>
{if $promo_code == "WELCOME10"}
<p class="note">Promo applied: 10% off.</p>
{/if}
+{/if}
</fieldset>📝 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 $shipping_method == "express"} | |
| <p class="note">Express delivery adds {$express_fee|string_format:"%.2f"}.</p> | |
| {if $promo_code == "WELCOME10"} | |
| <p class="note">Promo applied: 10% off.</p> | |
| {/if} | |
| </fieldset> | |
| {if $shipping_method == "express"} | |
| <p class="note">Express delivery adds {$express_fee|string_format:"%.2f"}.</p> | |
| {if $promo_code == "WELCOME10"} | |
| <p class="note">Promo applied: 10% off.</p> | |
| {/if} | |
| {/if} | |
| </fieldset> |
🧰 Tools
🪛 smarty-lint (0.3.3)
[warn] 37-37: Use "===" instead of "==".
(eqeqeq)
[warn] 40-40: Use "===" instead of "==".
(eqeqeq)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/checkout.tpl` around lines 37 - 43, The template opens an if block
with `{if $shipping_method == "express"}` but never closes it, causing a parse
error; close that outer conditional by adding a matching `{/if}` after the
express-related content (before the existing `{if $promo_code == "WELCOME10"}`
block or before `</fieldset>` as appropriate) so the `{if $shipping_method ==
"express"}` block is properly terminated and the nested promo `{if $promo_code
== "WELCOME10"}` remains valid.
| {php} | ||
| $tracking = isset($order['tracking_number']) ? $order['tracking_number'] : 'pending'; | ||
| echo "Tracking: " . $tracking . "\n"; | ||
| {/php} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "email_order.tpl" -type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 106
🏁 Script executed:
# Check if the file exists and read it
if [ -f "./smartylint/email_order.tpl" ]; then
cat -n ./smartylint/email_order.tpl
else
echo "File not found at ./smartylint/email_order.tpl"
fd "email_order" --type f
fiRepository: coderabbitai/coderabbit-pr-review
Length of output: 1110
🌐 Web query:
Smarty {php} block deprecated
💡 Result:
In Smarty, the {php} tag (embedded PHP blocks) is deprecated. Authoritative evidence: - Smarty’s own documentation page for {php} states: “IMPORTANT NOTICE: {php} tags are deprecated from Smarty, and should not be used.” It also notes that as of Smarty 3.1 the tags are only available from SmartyBC. - Smarty’s official upgrade guide for Smarty 4 says support for {php} and {include_php} tags and embedded PHP has been completely dropped; the guide instructs rewriting by moving logic to PHP files or creating a plugin. What to do instead: - Move PHP logic out of templates into PHP scripts/controllers/services. - If you need to call functionality from templates, expose it via Smarty plugins (e.g., custom function/modifier or extension) rather than {php} blocks.
Citations:
- 1: https://www.smarty.net/docs/en/language.function.php.tpl
- 2: https://smarty-php.github.io/smarty/4.x/upgrading/
🌐 Web query:
Smarty template {assign} syntax variable escaping
💡 Result:
The {assign} function in Smarty templates does not have built-in syntax or attributes for directly escaping variables. The official Smarty 3 and 4 documentation for {assign} lists attributes like var, value, scope, and the nocache flag, but no escape-related options. Escaping is handled separately when outputting variables using the |escape modifier (e.g., {$name|escape:'html'}) or globally via $smarty->escape_html = true, which applies htmlspecialchars to all variable outputs automatically (can be bypassed with nofilter on specific variables). Variables assigned via {assign} are treated like any others for escaping purposes—no special escaping occurs during assignment itself. For security, always escape user-controlled data on output, as recommended in best practices.
Citations:
- 1: https://www.smarty.net/docs/en/language.function.assign.tpl
- 2: https://www.smarty.net/docs/en/language.modifier.escape.tpl
- 3: https://smarty-php.github.io/smarty/stable/api/variables/assigning/
- 4: https://www.smarty.net/docs/en/api.assign.tpl
- 5: https://smarty-php.github.io/smarty/stable/designers/language-builtin-functions/language-function-assign/
- 6: https://www.smarty.net/docs/en/variable.escape.html.tpl
- 7: https://smarty-php.github.io/smarty/4.x/designers/language-builtin-functions/language-function-assign/
- 8: https://smarty-php.github.io/smarty/4.x/designers/language-modifiers/language-modifier-escape/
Remove deprecated {php} block and move logic to Smarty-safe constructs.
Line 22-25 uses a deprecated {php} block, which is unsupported in Smarty 4 and poses security and maintainability risks. The {php} tag has been completely removed from Smarty 4; move the logic to PHP controllers or expose it via Smarty plugins instead.
Proposed fix
-{php}
- $tracking = isset($order['tracking_number']) ? $order['tracking_number'] : 'pending';
- echo "Tracking: " . $tracking . "\n";
-{/php}
+{assign var="tracking" value=$order.tracking_number|default:"pending"}
+Tracking: {$tracking|escape}📝 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.
| {php} | |
| $tracking = isset($order['tracking_number']) ? $order['tracking_number'] : 'pending'; | |
| echo "Tracking: " . $tracking . "\n"; | |
| {/php} | |
| {assign var="tracking" value=$order.tracking_number|default:"pending"} | |
| Tracking: {$tracking|escape} |
🧰 Tools
🪛 smarty-lint (0.3.3)
[error] 25-25: Left-operand missing in operation.
(invalid-arithmetic-operation)
[warn] 25-25: Don't use unquoted strings. Always use single- or double-quoted strings to prevent misinterpretation.
(unquoted-string)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/email_order.tpl` around lines 22 - 25, Remove the deprecated {php}
block and move the logic to Smarty-safe constructs: either assign the tracking
value from PHP controller (e.g., compute $tracking =
isset($order['tracking_number']) ? $order['tracking_number'] : 'pending' and
$smarty->assign('tracking', $tracking)) or use Smarty template features directly
(use {$order.tracking_number|default:'pending'} to render the value). Replace
the {php} block that references $order['tracking_number'] and $tracking with a
plain template line that outputs the tracking label and the Smarty variable
(e.g., "Tracking: " followed by the Smarty expression) so the template is Smarty
4 compatible and secure.
| {if $debug == "true"} | ||
| <pre class="debug"> | ||
| {$debug_payload} | ||
| </pre> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
git ls-files | grep -i footerRepository: coderabbitai/coderabbit-pr-review
Length of output: 99
🏁 Script executed:
find . -name "footer.tpl" -type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 101
🏁 Script executed:
cat -n smartylint/footer.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 1086
🏁 Script executed:
rg "escape" smartylint/ -A 2 -B 2Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
rg "\|escape" . -t tpl --max-count=20Repository: coderabbitai/coderabbit-pr-review
Length of output: 105
🏁 Script executed:
grep -r "debug_payload" smartylint/ 2>/dev/null || echo "No references found"Repository: coderabbitai/coderabbit-pr-review
Length of output: 132
🏁 Script executed:
rg "debug" smartylint/ --max-count=20Repository: coderabbitai/coderabbit-pr-review
Length of output: 238
🏁 Script executed:
rg "\|" smartylint/ --max-count=30Repository: coderabbitai/coderabbit-pr-review
Length of output: 1042
🏁 Script executed:
fd . smartylint -name "*.tpl" -o -name "*.php" -o -name "*.js" | head -20Repository: coderabbitai/coderabbit-pr-review
Length of output: 308
🏁 Script executed:
rg "debug_payload" . --max-count=20Repository: coderabbitai/coderabbit-pr-review
Length of output: 134
🏁 Script executed:
fd . smartylint -type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 248
🏁 Script executed:
ls -la smartylint/Repository: coderabbitai/coderabbit-pr-review
Length of output: 570
🏁 Script executed:
web_search
Smarty template escape filter syntaxRepository: coderabbitai/coderabbit-pr-review
Length of output: 173
🌐 Web query:
Smarty template escape filter syntax html
💡 Result:
The syntax for the Smarty template escape filter for HTML is {$variable|escape:'html'} or {$variable|escape:"html"}. By default, {$variable|escape} uses HTML escaping. This escapes special characters like & " ' < > using htmlspecialchars with ENT_QUOTES. Examples: - {$articleTitle|escape:'html'} outputs: 'Stiff Opposition Expected to Casketless Funeral Plan' - Other options: 'htmlall' (all entities), 'url', 'quotes', etc. For global HTML escaping, set $smarty->escape_html = true; in PHP (requires template recompilation). To disable for a variable: {$variable nofilter}.
Citations:
- 1: https://smarty-php.github.io/smarty/stable/designers/language-modifiers/language-modifier-escape/
- 2: https://www.smarty.net/docs/en/language.modifier.escape.tpl
- 3: https://smarty-php.github.io/smarty/4.x/designers/language-modifiers/language-modifier-escape/
- 4: https://smarty-php.github.io/smarty/4.x/programmers/api-variables/variable-escape-html/
Harden debug branch condition and escape payload.
Lines 25–28 render {$debug_payload} without escaping, creating a potential XSS vulnerability. The loose comparison on line 25 should also be simplified.
🔧 Proposed fix
-{if $debug == "true"}
+{if $debug}
<pre class="debug">
- {$debug_payload}
+ {$debug_payload|escape}
</pre>
{/if}📝 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 $debug == "true"} | |
| <pre class="debug"> | |
| {$debug_payload} | |
| </pre> | |
| {if $debug} | |
| <pre class="debug"> | |
| {$debug_payload|escape} | |
| </pre> | |
| {/if} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/footer.tpl` around lines 25 - 28, Change the loose string
comparison {if $debug == "true"} to a boolean check {if $debug} and escape the
payload when rendering by replacing {$debug_payload} with an escaped version
like {$debug_payload|escape:'html':'UTF-8'} (or {$debug_payload|escape:'html'}
if UTF-8 is implicit) inside the <pre class="debug">; this hardens the condition
and prevents XSS by ensuring the debug payload is HTML-escaped.
| {include file=meta.tpl} | ||
| {include file="styles.tpl" theme=$current_theme} | ||
|
|
||
| <link rel="canonical" href="https://demoapp.example.com/{$canonical_path}> |
There was a problem hiding this comment.
Fix broken canonical link attribute quoting.
Line 12 is missing the closing quote for href, which breaks HTML structure and can corrupt downstream DOM parsing.
🔧 Proposed fix
-<link rel="canonical" href="https://demoapp.example.com/{$canonical_path}>
+<link rel="canonical" href="https://demoapp.example.com/{$canonical_path|escape:'url'}">📝 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.
| <link rel="canonical" href="https://demoapp.example.com/{$canonical_path}> | |
| <link rel="canonical" href="https://demoapp.example.com/{$canonical_path|escape:'url'}"> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/header.tpl` at line 12, The canonical link tag in header.tpl is
missing the closing quote for the href attribute; update the <link
rel="canonical"...> line so the href value ends with a double quote after
{$canonical_path} (i.e., ensure the attribute reads
href="https://demoapp.example.com/{$canonical_path}"), preserving the existing
template variable and surrounding markup to restore valid HTML and prevent DOM
parsing errors.
| <h1>{$Product.name}</h1> | ||
| <p class="sku">SKU: {$Product.sku|@default:"n/a"}</p> | ||
| <p class="price">{$Product.price|string_format:"%.2f"}</p> | ||
|
|
||
| <div class="description"> | ||
| {$Product.long_description} | ||
| </div> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "product_detail.tpl" -type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 109
🏁 Script executed:
cat -n ./smartylint/product_detail.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 2132
🏁 Script executed:
# Check for Smarty version or composer.json to understand version
find . -name "composer.json" -o -name "package.json" | head -5 | xargs cat 2>/dev/null | head -50Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check if there's a Smarty configuration or middleware that might handle escaping globally or CSRF
rg -l "escape|autoescape" --type-list | head -10
rg "autoescape|auto_literal" -iRepository: coderabbitai/coderabbit-pr-review
Length of output: 467
🏁 Script executed:
# Search for CSRF token handling in the codebase
rg "csrf|token" -i --type-list | head -20Repository: coderabbitai/coderabbit-pr-review
Length of output: 467
🏁 Script executed:
# Search for escaping and autoescape settings
rg "escape|autoescape" -iRepository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Search for CSRF token handling
rg "csrf|csrf_token" -iRepository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Look for Smarty configuration files
find . -name "*.php" -o -name "*.conf" | xargs grep -l "Smarty\|smarty" 2>/dev/null | head -10Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check root config/setup files
ls -la | grep -E "config|setup|smarty"Repository: coderabbitai/coderabbit-pr-review
Length of output: 136
🏁 Script executed:
# List all files in repository
git ls-filesRepository: coderabbitai/coderabbit-pr-review
Length of output: 240
🏁 Script executed:
# Check for any Smarty security or escaping configuration
find . -type f -name "*.php" -o -name "*.tpl" -o -name "*.conf" | head -20Repository: coderabbitai/coderabbit-pr-review
Length of output: 242
🏁 Script executed:
# Look at the header.tpl to see if there's any global escaping setup
cat ./smartylint/header.tpl 2>/dev/nullRepository: coderabbitai/coderabbit-pr-review
Length of output: 1068
🏁 Script executed:
# Check for Smarty configuration or initialization
find . -name "*.php" -type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check README for context
cat README.mdRepository: coderabbitai/coderabbit-pr-review
Length of output: 99
🏁 Script executed:
# Look at other template files to see if they use escaping filters
cat ./smartylint/product_list.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 1415
🏁 Script executed:
# Check for any escaping filters used anywhere in templates
rg "escape|e:|htmlspecialchars"Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Search for any autoescape or security configuration in all files
find . -type f \( -name "*.php" -o -name "*.conf" -o -name "*.yaml" -o -name "*.yml" \)Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
# Check if there are any escaping filters used in other templates
cat ./smartylint/checkout.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 2183
🏁 Script executed:
# Check email template as well
cat ./smartylint/email_order.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 872
Escape all dynamic content before rendering to prevent HTML/script injection.
Lines 11, 12, 16, 36, 37, 39, and 48 render unescaped user/product/review data. User-generated content like $Review.body and product names are particularly at risk. Add |escape or |htmlspecialchars filter to all dynamic outputs. Also replace deprecated @default modifier with @|default (Smarty 3+) or use {if} conditionals.
Additionally, the checkout form (line 20) is missing an explicit CSRF token field—verify framework middleware provides cross-site request forgery protection.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/product_detail.tpl` around lines 11 - 17, Escape all dynamic
template outputs and fix deprecated modifier usage: update occurrences of
{$Product.name}, {$Product.sku|@default:"n/a"},
{$Product.price|string_format:"%.2f"}, {$Product.long_description} and any
{$Review.body} or similar variables to use the Smarty escaping filter (e.g.,
|escape or |htmlspecialchars) and change the deprecated `@default` modifier to the
Smarty 3+ syntax (|default) or wrap with {if} checks; keep numeric formatting
(string_format) but pipe escape after formatting where appropriate. Also ensure
the checkout form includes an explicit CSRF token hidden field (or
verify/instrument framework CSRF middleware) so the form submission includes the
token for server-side validation.
| <form action="/cart/add" method="post"> | ||
| <input type="hidden" name="product_id" value="{$Product.id}"> | ||
| <label> | ||
| Quantity: | ||
| <input type="number" name="qty" min="1" value="1"> | ||
| </label> | ||
| <button type="submit">Add to cart</button> | ||
| </form> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
git ls-files | head -20Repository: coderabbitai/coderabbit-pr-review
Length of output: 240
🏁 Script executed:
fd -t f "product_detail" --type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 107
🏁 Script executed:
fd -t f "cart" --type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
cat -n smartylint/product_detail.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 2132
🏁 Script executed:
cat -n smartylint/header.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 1334
🏁 Script executed:
cat -n smartylint/footer.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 1086
🏁 Script executed:
rg -i "csrf|token|xsrf" --type html --type tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 105
🏁 Script executed:
rg -i "csrf|token|xsrf" --max-count 50Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
fd -t f -e php -e py -e js -e go | head -30Repository: coderabbitai/coderabbit-pr-review
Length of output: 59
🏁 Script executed:
rg "/cart/add" --max-count 20Repository: coderabbitai/coderabbit-pr-review
Length of output: 159
🏁 Script executed:
git ls-filesRepository: coderabbitai/coderabbit-pr-review
Length of output: 240
🏁 Script executed:
find . -type f -name "*.md" -o -name "*.txt" -o -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.xml" | head -20Repository: coderabbitai/coderabbit-pr-review
Length of output: 89
🏁 Script executed:
cat README.mdRepository: coderabbitai/coderabbit-pr-review
Length of output: 99
Add CSRF token to the add-to-cart form.
The form at lines 20-27 performs a state-changing POST request to /cart/add without a CSRF token field. Include a CSRF token input (e.g., <input type="hidden" name="csrf_token" value="{$csrf_token}">) to protect against cross-site request forgery attacks.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/product_detail.tpl` around lines 20 - 27, The add-to-cart form
that posts to "/cart/add" is missing a CSRF token hidden input; update the form
(the <form action="/cart/add" ...> block that contains inputs product_id and qty
and the submit button) to include a hidden field named "csrf_token" with the
template variable value (e.g., {$csrf_token}) so the server can validate the
token on POST; ensure the hidden input appears inside the same form alongside
the existing product_id and qty inputs.
| <h1>{$category_name}</h1> | ||
|
|
||
| <p class="result-count"> | ||
| Showing {$result_count} results for "{$search_query}" | ||
| </p> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "product_list.tpl" -type fRepository: coderabbitai/coderabbit-pr-review
Length of output: 107
🏁 Script executed:
cat -n ./smartylint/product_list.tplRepository: coderabbitai/coderabbit-pr-review
Length of output: 1702
🌐 Web query:
Smarty template engine escape filter security XSS protection
💡 Result:
The Smarty template engine provides the |escape modifier as its primary mechanism for XSS protection. This modifier encodes variables for safe output in various contexts, preventing cross-site scripting (XSS) attacks by escaping special characters like &, ", ', <, and >. Key features: - Default: |escape or |escape:'html' escapes HTML context (& " ' < >). - |escape:'htmlall' escapes all HTML entities. - Other formats: 'url' for URLs, 'quotes' for single quotes, 'javascript' for JS, 'mail' for email obfuscation, 'hex', 'hexentity'. - Charset support (default UTF-8) and double-encode option. Usage example: {$articleTitle|escape:'html'} // Outputs: 'Stiff Opposition...' Global auto-escaping: Set $smarty->escape_html = true to automatically apply htmlspecialchars (equivalent to |escape:'html') to all variables. Disable per-variable with {$var nofilter}. Smarty Security: Enable with $smarty->enableSecurity or $security = true for untrusted templates (e.g., user-edited). Restricts PHP tags, dangerous modifiers/tags, file access to $secure_dir, etc. Whitelists via $allowed_modifiers, $allowed_tags. Primarily prevents code injection/SSTI, complements output escaping for XSS. Past issues: XSS in JS escaping fixed in 3.1.48/4.3.1 (CVE-2023-28447). Use latest versions (copyright to 2026 indicates active maintenance). Best practice: Always apply |escape (context-appropriate) to user-controlled data in HTML/attributes/JS/etc. Combine with Security for high-risk templates. Validate/sanitize inputs upstream.
Citations:
- 1: https://www.smarty.net/docs/en/language.modifier.escape.tpl
- 2: https://www.smarty.net/docs/en/variable.escape.html.tpl
- 3: https://smarty-php.github.io/smarty/stable/api/security/
- 4: https://www.smarty.net/docsv2/en/variable.security.tpl
- 5: https://www.copernica.com/en/documentation/smarty/security
- 6: https://smarty-php.github.io/smarty/stable/designers/language-modifiers/language-modifier-escape/
- 7: https://security.snyk.io/vuln/SNYK-PHP-SMARTYSMARTY-5291896
- 8: GHSA-7j98-h7fp-4vwj
Escape dynamic values in output and fix unquoted attribute value.
Multiple variables are output without escaping, creating XSS vulnerabilities. Most critically, line 25 has an unquoted data-name attribute value that can break markup and enable injection if the variable contains spaces or special characters.
Lines affected:
- Line 4:
{$category_name} - Line 7:
{$search_query}and{$result_count} - Lines 13–18:
{$product.id},{$product.slug},{$product.image_url},{$product.name}(multiple occurrences),{$product.short_description} - Line 22:
{$product.discount_label} - Line 25:
{$product.id}and{$product.name}(latter is unquoted)
Apply Smarty's |escape filter to all user-controlled variables:
🔧 Example fix for the critical unquoted attribute
-<button data-product="{$product.id}" data-name={$product.name}>
+<button data-product="{$product.id|escape}" data-name="{$product.name|escape}">🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/product_list.tpl` around lines 4 - 8, Escape all user-controlled
Smarty template variables and quote attribute values to prevent XSS and broken
markup: wrap occurrences of {$category_name}, {$result_count}, {$search_query},
all {$product.*} fields (e.g., {$product.id}, {$product.slug},
{$product.image_url}, {$product.name}, {$product.short_description},
{$product.discount_label}) with the Smarty |escape modifier (e.g.,
{$variable|escape}) and ensure the data-name attribute uses a quoted, escaped
value (e.g., data-name="{$product.name|escape}"); update every instance in
product_list.tpl where these variables are output (including in URLs,
attributes, and text nodes) so all dynamic output is escaped and attributes are
quoted.
| {foreach $products as $product} | ||
| <li class="product-card" data-id="{$product.id}"> | ||
| <a href="/products/{$product.slug}"> | ||
| <img src="{$product.image_url}" alt="{$product.name}"> | ||
| <h2>{$product.name}</h2> | ||
| <p class="price">{$product.price|string_format:"%.2f"}</p> | ||
| <p class="description">{$product.short_description}</p> | ||
| </a> | ||
|
|
||
| {if $product.on_sale} | ||
| <span class="sale-badge">{$product.discount_label}</span> | ||
| {/if} | ||
|
|
||
| <button data-product="{$product.id}" data-name={$product.name}> | ||
| Add to cart | ||
| </button> | ||
| </li> | ||
| </ul> |
There was a problem hiding this comment.
Close the {foreach} block before </ul>.
Line 12 starts {foreach $products as $product} but the block is never closed, causing template parse failure.
🔧 Proposed fix
{foreach $products as $product}
<li class="product-card" data-id="{$product.id}">
...
</li>
+ {/foreach}
</ul>📝 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.
| {foreach $products as $product} | |
| <li class="product-card" data-id="{$product.id}"> | |
| <a href="/products/{$product.slug}"> | |
| <img src="{$product.image_url}" alt="{$product.name}"> | |
| <h2>{$product.name}</h2> | |
| <p class="price">{$product.price|string_format:"%.2f"}</p> | |
| <p class="description">{$product.short_description}</p> | |
| </a> | |
| {if $product.on_sale} | |
| <span class="sale-badge">{$product.discount_label}</span> | |
| {/if} | |
| <button data-product="{$product.id}" data-name={$product.name}> | |
| Add to cart | |
| </button> | |
| </li> | |
| </ul> | |
| {foreach $products as $product} | |
| <li class="product-card" data-id="{$product.id}"> | |
| <a href="/products/{$product.slug}"> | |
| <img src="{$product.image_url}" alt="{$product.name}"> | |
| <h2>{$product.name}</h2> | |
| <p class="price">{$product.price|string_format:"%.2f"}</p> | |
| <p class="description">{$product.short_description}</p> | |
| </a> | |
| {if $product.on_sale} | |
| <span class="sale-badge">{$product.discount_label}</span> | |
| {/if} | |
| <button data-product="{$product.id}" data-name={$product.name}> | |
| Add to cart | |
| </button> | |
| </li> | |
| {/foreach} | |
| </ul> |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@smartylint/product_list.tpl` around lines 12 - 29, The template opens a
{foreach $products as $product} loop but never closes it, causing a parse error;
close the loop by inserting the matching {/foreach} before the closing </ul> so
the list of <li class="product-card"> elements is properly wrapped and the
conditional {if $product.on_sale} and button remain inside the loop.
Demonstrates the smarty-lint sandboxer tool. Six realistic .tpl files (header, footer, product_list, product_detail, checkout, email_order) for an ecommerce template set, with intentionally embedded violations across smarty-lint's rule categories: unclosed tags, deprecated {php} blocks, deprecated @default modifier, missing escape modifiers on user-controlled output, unquoted include filenames, loose == comparisons, uppercase identifiers, empty blocks, empty comments, and unnecessary {if true} encapsulation. smarty-lint auto-runs on .tpl files with no config required (CodeRabbit creates a temporary smartylint.json scanning **/*.tpl). No .coderabbit.yml needed — no other tool in the sandboxer scans .tpl files.
Summary by CodeRabbit
Release Notes