Skip to content

Commit cf70e7d

Browse files
committed
New Plural that is compatible with Natural #10056
1 parent 687fe01 commit cf70e7d

File tree

2 files changed

+209
-0
lines changed

2 files changed

+209
-0
lines changed

src/Api/Plural.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Ecodev\Felix\Api;
6+
7+
final class Plural
8+
{
9+
/**
10+
* Returns the plural form of the given name.
11+
*
12+
* This is **not** necessarily valid english grammar. Its only purpose is for internal usage, not for humans.
13+
*
14+
* This **MUST** be kept in sync with Natural's `makePlural()`.
15+
*
16+
* This is a bit performance-sensitive, so we should keep it fast and only cover cases that we actually need.
17+
*/
18+
public static function make(string $name): string
19+
{
20+
// Words ending in a y preceded by a vowel form their plurals by adding -s:
21+
if (preg_match('/[aeiou]y$/', $name)) {
22+
return $name . 's';
23+
}
24+
25+
$plural = $name . 's';
26+
$plural = preg_replace('/ys$/', 'ies', $plural);
27+
if ($plural === null) {
28+
throw new Exception('Error while making plural');
29+
}
30+
31+
$plural = preg_replace('/ss$/', 'ses', $plural);
32+
if ($plural === null) {
33+
throw new Exception('Error while making plural');
34+
}
35+
36+
return $plural;
37+
}
38+
}

tests/Api/PluralTest.php

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EcodevTests\Felix\Api;
6+
7+
use Ecodev\Felix\Api\Plural;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class PluralTest extends TestCase
11+
{
12+
/**
13+
* @dataProvider providerMake
14+
*/
15+
public function testMake(string $input, string $expected): void
16+
{
17+
self::assertSame($expected, Plural::make($input));
18+
}
19+
20+
public function providerMake(): iterable
21+
{
22+
yield ['Account', 'Accounts'];
23+
yield ['AccountingDocument', 'AccountingDocuments'];
24+
yield ['Action', 'Actions'];
25+
yield ['Aggregation', 'Aggregations'];
26+
yield ['AggregationSet', 'AggregationSets'];
27+
yield ['Answer', 'Answers'];
28+
yield ['AntiqueName', 'AntiqueNames'];
29+
yield ['Artist', 'Artists'];
30+
yield ['AttributeDefinition', 'AttributeDefinitions'];
31+
yield ['AttributeValue', 'AttributeValues'];
32+
yield ['AuditNote', 'AuditNotes'];
33+
yield ['AuditNoteContainerInterface', 'AuditNoteContainerInterfaces'];
34+
yield ['AutomaticStateStampInterface', 'AutomaticStateStampInterfaces'];
35+
yield ['BelongChecklistInterface', 'BelongChecklistInterfaces'];
36+
yield ['BelongGroupInterface', 'BelongGroupInterfaces'];
37+
yield ['BelongOrganizationInterface', 'BelongOrganizationInterfaces'];
38+
yield ['BelongShopInterface', 'BelongShopInterfaces'];
39+
yield ['Bookable', 'Bookables'];
40+
yield ['BookableMetadata', 'BookableMetadatas'];
41+
yield ['BookableTag', 'BookableTags'];
42+
yield ['Booking', 'Bookings'];
43+
yield ['Calendar', 'Calendars'];
44+
yield ['Card', 'Cards'];
45+
yield ['Cart', 'Carts'];
46+
yield ['CartLine', 'CartLines'];
47+
yield ['Change', 'Changes'];
48+
yield ['Chapter', 'Chapters'];
49+
yield ['Checklist', 'Checklists'];
50+
yield ['ChecklistDocument', 'ChecklistDocuments'];
51+
yield ['ChecklistGroup', 'ChecklistGroups'];
52+
yield ['City', 'Cities'];
53+
yield ['Cluster', 'Clusters'];
54+
yield ['Collection', 'Collections'];
55+
yield ['Comment', 'Comments'];
56+
yield ['Communication', 'Communications'];
57+
yield ['ComputableInterface', 'ComputableInterfaces'];
58+
yield ['Configuration', 'Configurations'];
59+
yield ['Constraint', 'Constraints'];
60+
yield ['Control', 'Controls'];
61+
yield ['Country', 'Countries'];
62+
yield ['Course', 'Courses'];
63+
yield ['Dating', 'Datings'];
64+
yield ['Document', 'Documents'];
65+
yield ['DocumentInterface', 'DocumentInterfaces'];
66+
yield ['DocumentNote', 'DocumentNotes'];
67+
yield ['DocumentType', 'DocumentTypes'];
68+
yield ['Domain', 'Domains'];
69+
yield ['Door', 'Doors'];
70+
yield ['DynamicScale', 'DynamicScales'];
71+
yield ['EconomicActivity', 'EconomicActivities'];
72+
yield ['EmailRecipient', 'EmailRecipients'];
73+
yield ['EmailRecipientInterface', 'EmailRecipientInterfaces'];
74+
yield ['Equipment', 'Equipments'];
75+
yield ['Event', 'Events'];
76+
yield ['ExpenseClaim', 'ExpenseClaims'];
77+
yield ['Export', 'Exports'];
78+
yield ['FacilitatorDocument', 'FacilitatorDocuments'];
79+
yield ['Faq', 'Faqs'];
80+
yield ['FaqCategory', 'FaqCategories'];
81+
yield ['File', 'Files'];
82+
yield ['Folder', 'Folders'];
83+
yield ['Group', 'Groups'];
84+
yield ['GroupDocument', 'GroupDocuments'];
85+
yield ['HasParentInterface', 'HasParentInterfaces'];
86+
yield ['HasScaleAndThresholdsInterface', 'HasScaleAndThresholdsInterfaces'];
87+
yield ['Holiday', 'Holidays'];
88+
yield ['IdentityProvider', 'IdentityProviders'];
89+
yield ['Image', 'Images'];
90+
yield ['Indicator', 'Indicators'];
91+
yield ['IndicatorDocument', 'IndicatorDocuments'];
92+
yield ['Institution', 'Institutions'];
93+
yield ['Invoicable', 'Invoicables'];
94+
yield ['InvoicableLine', 'InvoicableLines'];
95+
yield ['Legal', 'Legals'];
96+
yield ['LegalReference', 'LegalReferences'];
97+
yield ['Lesson', 'Lessons'];
98+
yield ['LessonData', 'LessonDatas'];
99+
yield ['License', 'Licenses'];
100+
yield ['Log', 'Logs'];
101+
yield ['Map', 'Maps'];
102+
yield ['MapCalendar', 'MapCalendars'];
103+
yield ['MapPlace', 'MapPlaces'];
104+
yield ['Material', 'Materials'];
105+
yield ['Message', 'Messages'];
106+
yield ['News', 'Newses'];
107+
yield ['NotifiableInterface', 'NotifiableInterfaces'];
108+
yield ['Objective', 'Objectives'];
109+
yield ['Order', 'Orders'];
110+
yield ['OrderLine', 'OrderLines'];
111+
yield ['Organization', 'Organizations'];
112+
yield ['OrganizationChecklist', 'OrganizationChecklists'];
113+
yield ['PaymentMethod', 'PaymentMethods'];
114+
yield ['Period', 'Periods'];
115+
yield ['Place', 'Places'];
116+
yield ['PlaceType', 'PlaceTypes'];
117+
yield ['Position', 'Positions'];
118+
yield ['Preset', 'Presets'];
119+
yield ['Process', 'Processes'];
120+
yield ['Product', 'Products'];
121+
yield ['ProductTag', 'ProductTags'];
122+
yield ['Question', 'Questions'];
123+
yield ['QuestionSuggestion', 'QuestionSuggestions'];
124+
yield ['Region', 'Regions'];
125+
yield ['Report', 'Reports'];
126+
yield ['Risk', 'Risks'];
127+
yield ['RiskClassification', 'RiskClassifications'];
128+
yield ['RiskFrequency', 'RiskFrequencies'];
129+
yield ['RiskLevel', 'RiskLevels'];
130+
yield ['RiskMatrix', 'RiskMatrixs'];
131+
yield ['RiskSeverity', 'RiskSeverities'];
132+
yield ['Rite', 'Rites'];
133+
yield ['RoleContextInterface', 'RoleContextInterfaces'];
134+
yield ['Scale', 'Scales'];
135+
yield ['ScaleLike', 'ScaleLikes'];
136+
yield ['Section', 'Sections'];
137+
yield ['Session', 'Sessions'];
138+
yield ['Setting', 'Settings'];
139+
yield ['Sheet', 'Sheets'];
140+
yield ['SheetCalendar', 'SheetCalendars'];
141+
yield ['SheetOutput', 'SheetOutputs'];
142+
yield ['Shift', 'Shifts'];
143+
yield ['ShiftTag', 'ShiftTags'];
144+
yield ['Shop', 'Shops'];
145+
yield ['Site', 'Sites'];
146+
yield ['SiteChecklist', 'SiteChecklists'];
147+
yield ['State', 'States'];
148+
yield ['Statistic', 'Statistics'];
149+
yield ['StockMovement', 'StockMovements'];
150+
yield ['Subscription', 'Subscriptions'];
151+
yield ['SubscriptionForm', 'SubscriptionForms'];
152+
yield ['Suggestion', 'Suggestions'];
153+
yield ['Tag', 'Tags'];
154+
yield ['Task', 'Tasks'];
155+
yield ['Taxonomy', 'Taxonomies'];
156+
yield ['Theme', 'Themes'];
157+
yield ['Thesaurus', 'Thesauruses'];
158+
yield ['Threshold', 'Thresholds'];
159+
yield ['Timelog', 'Timelogs'];
160+
yield ['Transaction', 'Transactions'];
161+
yield ['TransactionLine', 'TransactionLines'];
162+
yield ['TransactionTag', 'TransactionTags'];
163+
yield ['User', 'Users'];
164+
yield ['UserCalendar', 'UserCalendars'];
165+
yield ['UserGroup', 'UserGroups'];
166+
yield ['UserOrganization', 'UserOrganizations'];
167+
yield ['UserPlace', 'UserPlaces'];
168+
yield ['UserSite', 'UserSites'];
169+
yield ['UserTag', 'UserTags'];
170+
}
171+
}

0 commit comments

Comments
 (0)