Skip to content

feat: added User Report Settings Templates support#265

Open
bhdnb wants to merge 1 commit intomasterfrom
user-report-settings-templates
Open

feat: added User Report Settings Templates support#265
bhdnb wants to merge 1 commit intomasterfrom
user-report-settings-templates

Conversation

@bhdnb
Copy link
Collaborator

@bhdnb bhdnb commented Mar 19, 2026

No description provided.

@bhdnb bhdnb self-assigned this Mar 19, 2026
@bhdnb bhdnb linked an issue Mar 19, 2026 that may be closed by this pull request
@bhdnb bhdnb marked this pull request as draft March 19, 2026 15:57
@codecov
Copy link

codecov bot commented Mar 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.01%. Comparing base (8e24d5c) to head (2771256).

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #265      +/-   ##
============================================
+ Coverage     92.75%   93.01%   +0.27%     
- Complexity     1722     1779      +57     
============================================
  Files           163      167       +4     
  Lines          4644     4820     +176     
============================================
+ Hits           4307     4483     +176     
  Misses          337      337              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bhdnb bhdnb force-pushed the user-report-settings-templates branch from cc602d3 to 03cc944 Compare March 19, 2026 16:08
@bhdnb bhdnb force-pushed the user-report-settings-templates branch from 03cc944 to 2771256 Compare March 23, 2026 14:58
@bhdnb bhdnb marked this pull request as ready for review March 23, 2026 15:08
@bhdnb bhdnb requested a review from andrii-bodnar March 23, 2026 15:08
@andrii-bodnar andrii-bodnar requested a review from Copilot March 23, 2026 15:58
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for User Report Settings Templates to the Crowdin API PHP client, including new models for user-scoped templates and hourly-based rate configurations, plus corresponding API methods and tests.

Changes:

  • Introduce UserReportSettingsTemplate model and UserApi methods to list/create/get/update/delete user report settings templates.
  • Add hourly-specific config models (HourlyReportSettingsTemplateConfig, HourlyBaseRates, HourlyIndividualRates) and enable hours as a supported report unit.
  • Extend ReportSettingsTemplateConfig with additional boolean configuration flags and update test coverage accordingly.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/CrowdinApiClient/Model/UserReportSettingsTemplateTest.php New tests covering user template model hydration, setters, validation, and toArray().
tests/CrowdinApiClient/Model/ReportSettingsTemplateTest.php Updates fixture/config expectations and inlines assertions for loading.
tests/CrowdinApiClient/Model/ReportSettingsTemplateConfigTest.php Adds coverage for new boolean config flags and updates setter/load assertions.
tests/CrowdinApiClient/Model/HourlyReportSettingsTemplateConfigTest.php New tests for hourly config model (load/set/exception/toArray).
tests/CrowdinApiClient/Model/HourlyIndividualRatesTest.php New tests for hourly individual rates model behavior and validation.
tests/CrowdinApiClient/Model/HourlyBaseRatesTest.php New tests for hourly base rates model behavior and toArray().
tests/CrowdinApiClient/Api/UserApiTest.php Adds API tests for the new user report settings templates endpoints.
src/CrowdinApiClient/Model/UserReportSettingsTemplate.php New model representing a user report settings template with unit-dependent config.
src/CrowdinApiClient/Model/ReportSettingsTemplateConfig.php Adds new boolean config fields with getters/setters and includes them in toArray().
src/CrowdinApiClient/Model/Report.php Adds UNIT_HOURS and includes it in supported units.
src/CrowdinApiClient/Model/IndividualRates.php Docblock tightening (string[]) for setLanguageIds() parameter.
src/CrowdinApiClient/Model/HourlyReportSettingsTemplateConfig.php New hourly settings template config model (base + individual rates).
src/CrowdinApiClient/Model/HourlyIndividualRates.php New hourly individual rates model with validation and serialization.
src/CrowdinApiClient/Model/HourlyBaseRates.php New hourly base rates model with serialization.
src/CrowdinApiClient/Api/UserApi.php Adds user report settings templates CRUD methods.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

foreach ($individualRates as $individualRate) {
if (!$individualRate instanceof HourlyIndividualRates) {
throw new InvalidArgumentException(
'Argument "individualRates" must contain only IndividualRates objects'
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In setIndividualRates(), the exception message says it must contain only IndividualRates objects, but this method actually requires HourlyIndividualRates instances. This is misleading for callers debugging type errors; update the message (and corresponding test expectation) to mention HourlyIndividualRates.

Suggested change
'Argument "individualRates" must contain only IndividualRates objects'
'Argument "individualRates" must contain only HourlyIndividualRates objects'

Copilot uses AI. Check for mistakes.
* @param HourlyReportSettingsTemplateConfig|ReportSettingsTemplateConfig $config
*/
public function setConfig($config): void
{
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setConfig() accepts any value and assigns it to $this->config, but toArray() assumes the config has toArray(); passing the wrong type will cause a runtime error. Consider validating that $config is an instance of ReportSettingsTemplateConfig or HourlyReportSettingsTemplateConfig and throwing InvalidArgumentException otherwise.

Suggested change
{
{
if (
!$config instanceof HourlyReportSettingsTemplateConfig
&& !$config instanceof ReportSettingsTemplateConfig
) {
throw new InvalidArgumentException(
sprintf(
'Argument "config" must be instance of %s or %s',
HourlyReportSettingsTemplateConfig::class,
ReportSettingsTemplateConfig::class
)
);
}

Copilot uses AI. Check for mistakes.
)
);
}

Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the unit via setUnit() can put the model into an inconsistent state (e.g., switching to hours while $config is still a ReportSettingsTemplateConfig). Since the constructor chooses config type based on unit, setUnit() should either update/recreate $config accordingly or enforce that the existing config type matches the chosen unit (throwing an exception on mismatch).

Suggested change
if (isset($this->config)) {
$expectedConfigClass = $unit === Report::UNIT_HOURS
? HourlyReportSettingsTemplateConfig::class
: ReportSettingsTemplateConfig::class;
if (!($this->config instanceof $expectedConfigClass)) {
throw new InvalidArgumentException(
sprintf(
'Config type "%s" does not match unit "%s". Expected instance of %s.',
is_object($this->config) ? get_class($this->config) : gettype($this->config),
$unit,
$expectedConfigClass
)
);
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +49 to +53
[
'languageIds' => ['uk', 'en', 'jp'],
'userIds' => [8],
'hourly' => 0.3,
],
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In testSetData(), HourlyIndividualRates is instantiated with an extra array nesting (new HourlyIndividualRates([ [ ... ] ])). That structure doesn’t match the model’s expected input shape (associative array with languageIds, userIds, hourly) and makes the test pass without actually verifying the intended values. Pass the associative array directly so the test validates real behavior.

Suggested change
[
'languageIds' => ['uk', 'en', 'jp'],
'userIds' => [8],
'hourly' => 0.3,
],
'languageIds' => ['uk', 'en', 'jp'],
'userIds' => [8],
'hourly' => 0.3,

Copilot uses AI. Check for mistakes.
/**
* @dataProvider languageIdsExceptionDataProvider
*/
public function testSetLanguageIdsEmptyThrowsException(array $languageIds, string $exceptionMessage): void
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test method name mentions only the “empty” case, but the data provider also covers an invalid-type case. Renaming the test to something like testSetLanguageIdsException (or splitting into two tests) would better reflect what’s being asserted.

Suggested change
public function testSetLanguageIdsEmptyThrowsException(array $languageIds, string $exceptionMessage): void
public function testSetLanguageIdsException(array $languageIds, string $exceptionMessage): void

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add 'User Report Settings Templates' endpoints support

2 participants