mirror of
https://github.com/FOSSBilling/FOSSBilling.git
synced 2026-10-23 03:37:01 +09:00
* Guard Activity index template against missing client/staff nested data
The activity log API at Activity/Api/Admin.php:38-49 only injects a
nested 'client' or 'staff' key when the corresponding *_id is set
(via isset() which returns false for null). System events and
client-only events therefore have no 'client' key, while staff-only
events have no 'client' key.
Under strict_variables, '{% if event.client %}' (line 191) throws
"Key 'client' ... does not exist" for any event without a client.
Switch the conditional to event.client_id / event.staff_id (always
present as SQL columns) and add '|default("")' to the nested
event.client.email / event.client.name / event.staff.email / event.staff.name
accesses so deleted-but-referenced records render gracefully.
* Guard Security iplookup template against empty country/asn data
When the GeoIP or ASN lookup fails (IncompleteRecord from MaxMind), the
Service catches and substitutes [] for the missing data. Under
strict_variables, the empty mapping at record.asn / record.country
causes line 48 to throw "sequence/mapping is empty".
Twig's |default filter on a GetAttrExpression compiles to a safe
is-defined check, so it correctly falls through to the placeholder
when the underlying array is empty or the key is missing.
Verified:
- /admin/security/iplookup?ip=192.168.1.1 (private IP, empty asn)
renders the row with 'Unknown' ASN cells.
- /admin/security/iplookup?ip=8.8.8.8 still renders
'15169' / 'GOOGLE' / 'United States'.
* Initialize notes/rel arrays in Support toApiArray so templates render without errors
Two related issues surfaced under strict_variables on the admin support
ticket page:
1. toApiArray only set $data['notes'] inside the foreach loop over
ticket notes. Tickets without any notes therefore had no 'notes' key
and 'ticket.notes|length' in mod_support_ticket.html.twig:42 threw
'Key "notes" does not exist'.
2. _getRelDetails returned [] (empty array) when a ticket has no
related entity. mod_support_ticket.html.twig sets {% set task =
ticket.rel %} and then accesses task.task, task.type, task.status
etc. on the next lines. Any access into an empty mapping throws
under strict_variables.
Fixes:
- Service::toApiArray: always initialize $data['notes'] = [] for admin
identity so the key is present even when empty.
- Service::_getRelDetails: always return the base structure with all
fields (id, type, task, new_value, status) set to null when there
is no related entity. Skip the DB lookups for the non-rel case.
Template hardening (defense-in-depth, in case other code paths return
a different shape):
- mod_support_ticket.html.twig:42: 'ticket.notes|length' -> 'is defined and
ticket.notes|length'.
- mod_support_ticket.html.twig:222: 'ticket.notes' -> 'ticket.notes|default([])'.
- mod_support_tickets.html.twig:238: same is defined guard.
Verified on dev:
- /admin/support/ticket/1 renders without errors.
- API now returns rel as {id: null, type: null, ...} and notes: [] for
tickets without related data.
- 1777 local tests pass, PHPStan clean.
* Harden tests and add Twig/ToApi linters
* Remove redundant setAccessible calls in tests
* Update cspell.json word list
* Add UrlAwarePermissiveContainer & trim errors
* Add geoip stub and fix ParserFactory usage
* Enforce and apply parentheses for new expressions
55 lines
2.6 KiB
PHP
55 lines
2.6 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Copyright 2022-2025 FOSSBilling
|
|
* Copyright 2011-2021 BoxBilling, Inc.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* @copyright FOSSBilling (https://www.fossbilling.org)
|
|
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache-2.0
|
|
*/
|
|
|
|
if (!file_exists(__DIR__ . '/src')) {
|
|
exit(0);
|
|
}
|
|
|
|
return (new PhpCsFixer\Config())
|
|
->setRules([
|
|
'@auto' => true, // Applies newest PER-CS and optimizations for PHP, based on project's composer.json file.
|
|
'@PHP8x5Migration' => true, // Rules to improve code for PHP 8.5 compatibility.
|
|
'@Symfony' => true, // Rules that follow the official Symfony Coding Standards.
|
|
'concat_space' => ['spacing' => 'one'],
|
|
'protected_to_private' => false,
|
|
'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false], // Enforce non-Yoda style.
|
|
'blank_line_before_statement' => ['statements' => ['break', 'continue', 'return', 'throw', 'try']], // Removed 'declare' from the default list.
|
|
'get_class_to_class_keyword' => true, // Risky if the get_class function is overridden. In our case, it's not.
|
|
'dir_constant' => true, // Risky when the function dirname is overridden. In our case, it's not.
|
|
'array_push' => true, // Risky when the function array_push is overridden. In our case, it's not.
|
|
'no_useless_sprintf' => true, // Risky when the function sprintf is overridden. In our case, it's not.
|
|
'no_homoglyph_names' => true, // Risky - https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/rules/naming/no_homoglyph_names.rst.
|
|
// Keep parentheses around `new ClassName()->method()` chains so the
|
|
// code parses on PHP 8.3 — the project's minimum supported version.
|
|
// PHP 8.4 added the ability to omit the parens
|
|
// (https://wiki.php.net/rfc/new_without_parentheses) and the
|
|
// `@auto` rule set's default of `use_parentheses: false` enforces
|
|
// that, but the CI matrix still runs on PHP 8.3 where the bare
|
|
// `new X()->y()` form is a syntax error.
|
|
'new_expression_parentheses' => ['use_parentheses' => true],
|
|
])
|
|
->setRiskyAllowed(true)
|
|
->setFinder(
|
|
(new PhpCsFixer\Finder())
|
|
->in([__DIR__ . '/src', __DIR__ . '/tests'])
|
|
->exclude([
|
|
'data',
|
|
'locale',
|
|
'themes',
|
|
'vendor',
|
|
])
|
|
->notPath(
|
|
'config-sample.php'
|
|
)
|
|
)
|
|
->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect())
|
|
->setCacheFile(__DIR__.'/cache/.php-cs-fixer.cache');
|