-
Notifications
You must be signed in to change notification settings - Fork 2
/
GenderFlip.php
184 lines (172 loc) · 4.7 KB
/
GenderFlip.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
<?php
/**
* Flip the genders of some text.
*/
class GenderFlip
{
/**
* Map for simple gender flips.
*
* All words will be converted to lowercase and then duplicated with the
* first character uppercased.
*
* @var array
*/
protected $flips = [
// lower case
'he' => 'she',
'she' => 'he',
'him' => 'her',
'her' => 'his', // conflict with her/him
'his' => 'hers', // conflict with his/her
'her' => 'him', // conflict with her/his
'his' => 'her', // conflict with his/hers
'hers' => 'his',
'man' => 'woman',
'woman' => 'man',
'husband' => 'wife',
'wife' => 'husband',
'mom' => 'dad',
'dad' => 'mom',
'mother' => 'father',
'mothers' => 'fathers',
'father' => 'mother',
'fathers' => 'mothers',
'daughter' => 'son',
'daughters' => 'sons',
'son' => 'daughter',
'sons' => 'daughters',
'girl' => 'boy',
'girls' => 'boys',
'boy' => 'girl',
'boys' => 'girls',
'sister' => 'brother',
'sisters' => 'brothers',
'brother' => 'sister',
'brothers' => 'sisters',
'men' => 'women',
'women' => 'men',
'herself' => 'himself',
'himself' => 'herself',
'mamma' => 'papa',
'papa' => 'mamma',
'niece' => 'nephew',
'nephew' => 'niece',
'nieces' => 'nephews',
'nephews' => 'nieces',
'lady' => 'gentleman',
'ladies' => 'gentlemen',
'gentleman' => 'lady',
'gentlemen' => 'ladies',
];
/**
* Map for pattern-based gender flips.
*
* For special cases that require custom regex patterns.
*
* @var array
*/
protected $patternFlips = [
'/\bMr\b\./' => 'Ms.',
'/\bMrs\b\./' => 'Mr.',
'/\bMiss\b/' => 'Mr.',
'/\bSir\b/' => 'Lady',
'/\bSir\b/' => 'Madam',
'/\bSir\b/' => 'Ma\'am',
'/\bLady\b/' => 'Sir',
'/\bMadam\b/' => 'Sir',
'/\bMa\'am\b/' => 'Sir',
];
/**
* The original, unmodified text passed into the constructor.
*
* @var string
*/
protected $originalText;
/**
* Construct this object, setting the original text.
*
* @param string $text
*/
public function __construct($text)
{
$this->originalText = $text;
}
/**
* Flip the genders of the original text.
*
* @return string
*/
public function flip()
{
$findFormat = '/\b%s\b/';
$replaceFormat = '____%s____';
// First, regularize the simple flips for processing.
$flips = [];
foreach ($this->flips as $find => $replace) {
$find = strtolower($find);
$replace = strtolower($replace);
$flips[$find] = $replace;
$flips[ucfirst($find)] = ucfirst($replace);
}
// Process the pattern flips and simple flips, giving them temporary
// placeholders and corresponding replacements.
$i = 0;
$tempFlips = [];
$replacements = [];
foreach ($this->patternFlips as $find => $replace) {
$tempFlips[$find] = sprintf($replaceFormat, $i);
$replacements[$i] = $replace;
$i++;
}
foreach ($flips as $find => $replace) {
$tempFlips[sprintf($findFormat, $find)] = sprintf($replaceFormat, $i);
$replacements[$i] = $replace;
$i++;
}
// Temporarily replace all gendered words with an indexed placeholder.
$text = preg_replace(
array_keys($tempFlips),
array_values($tempFlips),
$this->originalText
);
// Find all placeholders, replacing them with the corresponding text.
$text = preg_replace_callback(
'/\b_{4}(\d+)_{4}\b/',
function($matches) use ($replacements) {
return $replacements[$matches[1]];
},
$text
);
return $text;
}
/**
* Get the original text.
*
* @return string
*/
public function getOriginalText()
{
return $this->originalText;
}
/**
* Add a flip to the flip map.
*
* @param string $find A word in lowercase
* @param string $replace
*/
public function addFlip($find, $replace)
{
$this->flips[$find] = $replace;
}
/**
* Add a flip to the pattern flip map.
*
* @param string $find A regular expression pattern
* @param string $replace
*/
public function addPatternFlip($find, $replace)
{
$this->patternFlips[$find] = $replace;
}
}