new deployer command

This commit is contained in:
Mark Gregory
2026-09-16 13:22:16 +01:00
parent fac5df8cc3
commit 3410ab85fe
15 changed files with 26429 additions and 441 deletions
File diff suppressed because it is too large Load Diff
@@ -11,257 +11,12 @@ class IsoCountriesSeeder extends Seeder
public function run(): void
{
$now = Carbon::now();
$countries = [
['alpha2' => 'AD', 'alpha3' => 'AND', 'numeric' => '020', 'name' => 'Andorra', 'official_name' => 'Principality of Andorra', 'common_name' => null, 'flag_emoji' => '🇦🇩'],
['alpha2' => 'AE', 'alpha3' => 'ARE', 'numeric' => '784', 'name' => 'United Arab Emirates', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇪'],
['alpha2' => 'AF', 'alpha3' => 'AFG', 'numeric' => '004', 'name' => 'Afghanistan', 'official_name' => 'Islamic Republic of Afghanistan', 'common_name' => null, 'flag_emoji' => '🇦🇫'],
['alpha2' => 'AG', 'alpha3' => 'ATG', 'numeric' => '028', 'name' => 'Antigua and Barbuda', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇬'],
['alpha2' => 'AI', 'alpha3' => 'AIA', 'numeric' => '660', 'name' => 'Anguilla', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇮'],
['alpha2' => 'AL', 'alpha3' => 'ALB', 'numeric' => '008', 'name' => 'Albania', 'official_name' => 'Republic of Albania', 'common_name' => null, 'flag_emoji' => '🇦🇱'],
['alpha2' => 'AM', 'alpha3' => 'ARM', 'numeric' => '051', 'name' => 'Armenia', 'official_name' => 'Republic of Armenia', 'common_name' => null, 'flag_emoji' => '🇦🇲'],
['alpha2' => 'AO', 'alpha3' => 'AGO', 'numeric' => '024', 'name' => 'Angola', 'official_name' => 'Republic of Angola', 'common_name' => null, 'flag_emoji' => '🇦🇴'],
['alpha2' => 'AQ', 'alpha3' => 'ATA', 'numeric' => '010', 'name' => 'Antarctica', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇶'],
['alpha2' => 'AR', 'alpha3' => 'ARG', 'numeric' => '032', 'name' => 'Argentina', 'official_name' => 'Argentine Republic', 'common_name' => null, 'flag_emoji' => '🇦🇷'],
['alpha2' => 'AS', 'alpha3' => 'ASM', 'numeric' => '016', 'name' => 'American Samoa', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇸'],
['alpha2' => 'AT', 'alpha3' => 'AUT', 'numeric' => '040', 'name' => 'Austria', 'official_name' => 'Republic of Austria', 'common_name' => null, 'flag_emoji' => '🇦🇹'],
['alpha2' => 'AU', 'alpha3' => 'AUS', 'numeric' => '036', 'name' => 'Australia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇺'],
['alpha2' => 'AW', 'alpha3' => 'ABW', 'numeric' => '533', 'name' => 'Aruba', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇼'],
['alpha2' => 'AX', 'alpha3' => 'ALA', 'numeric' => '248', 'name' => 'Åland Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇦🇽'],
['alpha2' => 'AZ', 'alpha3' => 'AZE', 'numeric' => '031', 'name' => 'Azerbaijan', 'official_name' => 'Republic of Azerbaijan', 'common_name' => null, 'flag_emoji' => '🇦🇿'],
['alpha2' => 'BA', 'alpha3' => 'BIH', 'numeric' => '070', 'name' => 'Bosnia and Herzegovina', 'official_name' => 'Republic of Bosnia and Herzegovina', 'common_name' => null, 'flag_emoji' => '🇧🇦'],
['alpha2' => 'BB', 'alpha3' => 'BRB', 'numeric' => '052', 'name' => 'Barbados', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇧'],
['alpha2' => 'BD', 'alpha3' => 'BGD', 'numeric' => '050', 'name' => 'Bangladesh', 'official_name' => 'People\'s Republic of Bangladesh', 'common_name' => null, 'flag_emoji' => '🇧🇩'],
['alpha2' => 'BE', 'alpha3' => 'BEL', 'numeric' => '056', 'name' => 'Belgium', 'official_name' => 'Kingdom of Belgium', 'common_name' => null, 'flag_emoji' => '🇧🇪'],
['alpha2' => 'BF', 'alpha3' => 'BFA', 'numeric' => '854', 'name' => 'Burkina Faso', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇫'],
['alpha2' => 'BG', 'alpha3' => 'BGR', 'numeric' => '100', 'name' => 'Bulgaria', 'official_name' => 'Republic of Bulgaria', 'common_name' => null, 'flag_emoji' => '🇧🇬'],
['alpha2' => 'BH', 'alpha3' => 'BHR', 'numeric' => '048', 'name' => 'Bahrain', 'official_name' => 'Kingdom of Bahrain', 'common_name' => null, 'flag_emoji' => '🇧🇭'],
['alpha2' => 'BI', 'alpha3' => 'BDI', 'numeric' => '108', 'name' => 'Burundi', 'official_name' => 'Republic of Burundi', 'common_name' => null, 'flag_emoji' => '🇧🇮'],
['alpha2' => 'BJ', 'alpha3' => 'BEN', 'numeric' => '204', 'name' => 'Benin', 'official_name' => 'Republic of Benin', 'common_name' => null, 'flag_emoji' => '🇧🇯'],
['alpha2' => 'BL', 'alpha3' => 'BLM', 'numeric' => '652', 'name' => 'Saint Barthélemy', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇱'],
['alpha2' => 'BM', 'alpha3' => 'BMU', 'numeric' => '060', 'name' => 'Bermuda', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇲'],
['alpha2' => 'BN', 'alpha3' => 'BRN', 'numeric' => '096', 'name' => 'Brunei Darussalam', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇳'],
['alpha2' => 'BO', 'alpha3' => 'BOL', 'numeric' => '068', 'name' => 'Bolivia, Plurinational State of', 'official_name' => 'Plurinational State of Bolivia', 'common_name' => 'Bolivia', 'flag_emoji' => '🇧🇴'],
['alpha2' => 'BQ', 'alpha3' => 'BES', 'numeric' => '535', 'name' => 'Bonaire, Sint Eustatius and Saba', 'official_name' => 'Bonaire, Sint Eustatius and Saba', 'common_name' => null, 'flag_emoji' => '🇧🇶'],
['alpha2' => 'BR', 'alpha3' => 'BRA', 'numeric' => '076', 'name' => 'Brazil', 'official_name' => 'Federative Republic of Brazil', 'common_name' => null, 'flag_emoji' => '🇧🇷'],
['alpha2' => 'BS', 'alpha3' => 'BHS', 'numeric' => '044', 'name' => 'Bahamas', 'official_name' => 'Commonwealth of the Bahamas', 'common_name' => null, 'flag_emoji' => '🇧🇸'],
['alpha2' => 'BT', 'alpha3' => 'BTN', 'numeric' => '064', 'name' => 'Bhutan', 'official_name' => 'Kingdom of Bhutan', 'common_name' => null, 'flag_emoji' => '🇧🇹'],
['alpha2' => 'BV', 'alpha3' => 'BVT', 'numeric' => '074', 'name' => 'Bouvet Island', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇻'],
['alpha2' => 'BW', 'alpha3' => 'BWA', 'numeric' => '072', 'name' => 'Botswana', 'official_name' => 'Republic of Botswana', 'common_name' => null, 'flag_emoji' => '🇧🇼'],
['alpha2' => 'BY', 'alpha3' => 'BLR', 'numeric' => '112', 'name' => 'Belarus', 'official_name' => 'Republic of Belarus', 'common_name' => null, 'flag_emoji' => '🇧🇾'],
['alpha2' => 'BZ', 'alpha3' => 'BLZ', 'numeric' => '084', 'name' => 'Belize', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇧🇿'],
['alpha2' => 'CA', 'alpha3' => 'CAN', 'numeric' => '124', 'name' => 'Canada', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇦'],
['alpha2' => 'CC', 'alpha3' => 'CCK', 'numeric' => '166', 'name' => 'Cocos (Keeling) Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇨'],
['alpha2' => 'CD', 'alpha3' => 'COD', 'numeric' => '180', 'name' => 'Congo, The Democratic Republic of the', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇩'],
['alpha2' => 'CF', 'alpha3' => 'CAF', 'numeric' => '140', 'name' => 'Central African Republic', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇫'],
['alpha2' => 'CG', 'alpha3' => 'COG', 'numeric' => '178', 'name' => 'Congo', 'official_name' => 'Republic of the Congo', 'common_name' => null, 'flag_emoji' => '🇨🇬'],
['alpha2' => 'CH', 'alpha3' => 'CHE', 'numeric' => '756', 'name' => 'Switzerland', 'official_name' => 'Swiss Confederation', 'common_name' => null, 'flag_emoji' => '🇨🇭'],
['alpha2' => 'CI', 'alpha3' => 'CIV', 'numeric' => '384', 'name' => 'Côte d\'Ivoire', 'official_name' => 'Republic of Côte d\'Ivoire', 'common_name' => null, 'flag_emoji' => '🇨🇮'],
['alpha2' => 'CK', 'alpha3' => 'COK', 'numeric' => '184', 'name' => 'Cook Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇰'],
['alpha2' => 'CL', 'alpha3' => 'CHL', 'numeric' => '152', 'name' => 'Chile', 'official_name' => 'Republic of Chile', 'common_name' => null, 'flag_emoji' => '🇨🇱'],
['alpha2' => 'CM', 'alpha3' => 'CMR', 'numeric' => '120', 'name' => 'Cameroon', 'official_name' => 'Republic of Cameroon', 'common_name' => null, 'flag_emoji' => '🇨🇲'],
['alpha2' => 'CN', 'alpha3' => 'CHN', 'numeric' => '156', 'name' => 'China', 'official_name' => 'People\'s Republic of China', 'common_name' => null, 'flag_emoji' => '🇨🇳'],
['alpha2' => 'CO', 'alpha3' => 'COL', 'numeric' => '170', 'name' => 'Colombia', 'official_name' => 'Republic of Colombia', 'common_name' => null, 'flag_emoji' => '🇨🇴'],
['alpha2' => 'CR', 'alpha3' => 'CRI', 'numeric' => '188', 'name' => 'Costa Rica', 'official_name' => 'Republic of Costa Rica', 'common_name' => null, 'flag_emoji' => '🇨🇷'],
['alpha2' => 'CU', 'alpha3' => 'CUB', 'numeric' => '192', 'name' => 'Cuba', 'official_name' => 'Republic of Cuba', 'common_name' => null, 'flag_emoji' => '🇨🇺'],
['alpha2' => 'CV', 'alpha3' => 'CPV', 'numeric' => '132', 'name' => 'Cabo Verde', 'official_name' => 'Republic of Cabo Verde', 'common_name' => null, 'flag_emoji' => '🇨🇻'],
['alpha2' => 'CW', 'alpha3' => 'CUW', 'numeric' => '531', 'name' => 'Curaçao', 'official_name' => 'Curaçao', 'common_name' => null, 'flag_emoji' => '🇨🇼'],
['alpha2' => 'CX', 'alpha3' => 'CXR', 'numeric' => '162', 'name' => 'Christmas Island', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇨🇽'],
['alpha2' => 'CY', 'alpha3' => 'CYP', 'numeric' => '196', 'name' => 'Cyprus', 'official_name' => 'Republic of Cyprus', 'common_name' => null, 'flag_emoji' => '🇨🇾'],
['alpha2' => 'CZ', 'alpha3' => 'CZE', 'numeric' => '203', 'name' => 'Czechia', 'official_name' => 'Czech Republic', 'common_name' => null, 'flag_emoji' => '🇨🇿'],
['alpha2' => 'DE', 'alpha3' => 'DEU', 'numeric' => '276', 'name' => 'Germany', 'official_name' => 'Federal Republic of Germany', 'common_name' => null, 'flag_emoji' => '🇩🇪'],
['alpha2' => 'DJ', 'alpha3' => 'DJI', 'numeric' => '262', 'name' => 'Djibouti', 'official_name' => 'Republic of Djibouti', 'common_name' => null, 'flag_emoji' => '🇩🇯'],
['alpha2' => 'DK', 'alpha3' => 'DNK', 'numeric' => '208', 'name' => 'Denmark', 'official_name' => 'Kingdom of Denmark', 'common_name' => null, 'flag_emoji' => '🇩🇰'],
['alpha2' => 'DM', 'alpha3' => 'DMA', 'numeric' => '212', 'name' => 'Dominica', 'official_name' => 'Commonwealth of Dominica', 'common_name' => null, 'flag_emoji' => '🇩🇲'],
['alpha2' => 'DO', 'alpha3' => 'DOM', 'numeric' => '214', 'name' => 'Dominican Republic', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇩🇴'],
['alpha2' => 'DZ', 'alpha3' => 'DZA', 'numeric' => '012', 'name' => 'Algeria', 'official_name' => 'People\'s Democratic Republic of Algeria', 'common_name' => null, 'flag_emoji' => '🇩🇿'],
['alpha2' => 'EC', 'alpha3' => 'ECU', 'numeric' => '218', 'name' => 'Ecuador', 'official_name' => 'Republic of Ecuador', 'common_name' => null, 'flag_emoji' => '🇪🇨'],
['alpha2' => 'EE', 'alpha3' => 'EST', 'numeric' => '233', 'name' => 'Estonia', 'official_name' => 'Republic of Estonia', 'common_name' => null, 'flag_emoji' => '🇪🇪'],
['alpha2' => 'EG', 'alpha3' => 'EGY', 'numeric' => '818', 'name' => 'Egypt', 'official_name' => 'Arab Republic of Egypt', 'common_name' => null, 'flag_emoji' => '🇪🇬'],
['alpha2' => 'EH', 'alpha3' => 'ESH', 'numeric' => '732', 'name' => 'Western Sahara', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇪🇭'],
['alpha2' => 'ER', 'alpha3' => 'ERI', 'numeric' => '232', 'name' => 'Eritrea', 'official_name' => 'the State of Eritrea', 'common_name' => null, 'flag_emoji' => '🇪🇷'],
['alpha2' => 'ES', 'alpha3' => 'ESP', 'numeric' => '724', 'name' => 'Spain', 'official_name' => 'Kingdom of Spain', 'common_name' => null, 'flag_emoji' => '🇪🇸'],
['alpha2' => 'ET', 'alpha3' => 'ETH', 'numeric' => '231', 'name' => 'Ethiopia', 'official_name' => 'Federal Democratic Republic of Ethiopia', 'common_name' => null, 'flag_emoji' => '🇪🇹'],
['alpha2' => 'FI', 'alpha3' => 'FIN', 'numeric' => '246', 'name' => 'Finland', 'official_name' => 'Republic of Finland', 'common_name' => null, 'flag_emoji' => '🇫🇮'],
['alpha2' => 'FJ', 'alpha3' => 'FJI', 'numeric' => '242', 'name' => 'Fiji', 'official_name' => 'Republic of Fiji', 'common_name' => null, 'flag_emoji' => '🇫🇯'],
['alpha2' => 'FK', 'alpha3' => 'FLK', 'numeric' => '238', 'name' => 'Falkland Islands (Malvinas)', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇫🇰'],
['alpha2' => 'FM', 'alpha3' => 'FSM', 'numeric' => '583', 'name' => 'Micronesia, Federated States of', 'official_name' => 'Federated States of Micronesia', 'common_name' => null, 'flag_emoji' => '🇫🇲'],
['alpha2' => 'FO', 'alpha3' => 'FRO', 'numeric' => '234', 'name' => 'Faroe Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇫🇴'],
['alpha2' => 'FR', 'alpha3' => 'FRA', 'numeric' => '250', 'name' => 'France', 'official_name' => 'French Republic', 'common_name' => null, 'flag_emoji' => '🇫🇷'],
['alpha2' => 'GA', 'alpha3' => 'GAB', 'numeric' => '266', 'name' => 'Gabon', 'official_name' => 'Gabonese Republic', 'common_name' => null, 'flag_emoji' => '🇬🇦'],
['alpha2' => 'GB', 'alpha3' => 'GBR', 'numeric' => '826', 'name' => 'United Kingdom', 'official_name' => 'United Kingdom of Great Britain and Northern Ireland', 'common_name' => null, 'flag_emoji' => '🇬🇧'],
['alpha2' => 'GD', 'alpha3' => 'GRD', 'numeric' => '308', 'name' => 'Grenada', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇩'],
['alpha2' => 'GE', 'alpha3' => 'GEO', 'numeric' => '268', 'name' => 'Georgia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇪'],
['alpha2' => 'GF', 'alpha3' => 'GUF', 'numeric' => '254', 'name' => 'French Guiana', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇫'],
['alpha2' => 'GG', 'alpha3' => 'GGY', 'numeric' => '831', 'name' => 'Guernsey', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇬'],
['alpha2' => 'GH', 'alpha3' => 'GHA', 'numeric' => '288', 'name' => 'Ghana', 'official_name' => 'Republic of Ghana', 'common_name' => null, 'flag_emoji' => '🇬🇭'],
['alpha2' => 'GI', 'alpha3' => 'GIB', 'numeric' => '292', 'name' => 'Gibraltar', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇮'],
['alpha2' => 'GL', 'alpha3' => 'GRL', 'numeric' => '304', 'name' => 'Greenland', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇱'],
['alpha2' => 'GM', 'alpha3' => 'GMB', 'numeric' => '270', 'name' => 'Gambia', 'official_name' => 'Republic of the Gambia', 'common_name' => null, 'flag_emoji' => '🇬🇲'],
['alpha2' => 'GN', 'alpha3' => 'GIN', 'numeric' => '324', 'name' => 'Guinea', 'official_name' => 'Republic of Guinea', 'common_name' => null, 'flag_emoji' => '🇬🇳'],
['alpha2' => 'GP', 'alpha3' => 'GLP', 'numeric' => '312', 'name' => 'Guadeloupe', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇵'],
['alpha2' => 'GQ', 'alpha3' => 'GNQ', 'numeric' => '226', 'name' => 'Equatorial Guinea', 'official_name' => 'Republic of Equatorial Guinea', 'common_name' => null, 'flag_emoji' => '🇬🇶'],
['alpha2' => 'GR', 'alpha3' => 'GRC', 'numeric' => '300', 'name' => 'Greece', 'official_name' => 'Hellenic Republic', 'common_name' => null, 'flag_emoji' => '🇬🇷'],
['alpha2' => 'GS', 'alpha3' => 'SGS', 'numeric' => '239', 'name' => 'South Georgia and the South Sandwich Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇸'],
['alpha2' => 'GT', 'alpha3' => 'GTM', 'numeric' => '320', 'name' => 'Guatemala', 'official_name' => 'Republic of Guatemala', 'common_name' => null, 'flag_emoji' => '🇬🇹'],
['alpha2' => 'GU', 'alpha3' => 'GUM', 'numeric' => '316', 'name' => 'Guam', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇬🇺'],
['alpha2' => 'GW', 'alpha3' => 'GNB', 'numeric' => '624', 'name' => 'Guinea-Bissau', 'official_name' => 'Republic of Guinea-Bissau', 'common_name' => null, 'flag_emoji' => '🇬🇼'],
['alpha2' => 'GY', 'alpha3' => 'GUY', 'numeric' => '328', 'name' => 'Guyana', 'official_name' => 'Republic of Guyana', 'common_name' => null, 'flag_emoji' => '🇬🇾'],
['alpha2' => 'HK', 'alpha3' => 'HKG', 'numeric' => '344', 'name' => 'Hong Kong', 'official_name' => 'Hong Kong Special Administrative Region of China', 'common_name' => null, 'flag_emoji' => '🇭🇰'],
['alpha2' => 'HM', 'alpha3' => 'HMD', 'numeric' => '334', 'name' => 'Heard Island and McDonald Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇭🇲'],
['alpha2' => 'HN', 'alpha3' => 'HND', 'numeric' => '340', 'name' => 'Honduras', 'official_name' => 'Republic of Honduras', 'common_name' => null, 'flag_emoji' => '🇭🇳'],
['alpha2' => 'HR', 'alpha3' => 'HRV', 'numeric' => '191', 'name' => 'Croatia', 'official_name' => 'Republic of Croatia', 'common_name' => null, 'flag_emoji' => '🇭🇷'],
['alpha2' => 'HT', 'alpha3' => 'HTI', 'numeric' => '332', 'name' => 'Haiti', 'official_name' => 'Republic of Haiti', 'common_name' => null, 'flag_emoji' => '🇭🇹'],
['alpha2' => 'HU', 'alpha3' => 'HUN', 'numeric' => '348', 'name' => 'Hungary', 'official_name' => 'Hungary', 'common_name' => null, 'flag_emoji' => '🇭🇺'],
['alpha2' => 'ID', 'alpha3' => 'IDN', 'numeric' => '360', 'name' => 'Indonesia', 'official_name' => 'Republic of Indonesia', 'common_name' => null, 'flag_emoji' => '🇮🇩'],
['alpha2' => 'IE', 'alpha3' => 'IRL', 'numeric' => '372', 'name' => 'Ireland', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇮🇪'],
['alpha2' => 'IL', 'alpha3' => 'ISR', 'numeric' => '376', 'name' => 'Israel', 'official_name' => 'State of Israel', 'common_name' => null, 'flag_emoji' => '🇮🇱'],
['alpha2' => 'IM', 'alpha3' => 'IMN', 'numeric' => '833', 'name' => 'Isle of Man', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇮🇲'],
['alpha2' => 'IN', 'alpha3' => 'IND', 'numeric' => '356', 'name' => 'India', 'official_name' => 'Republic of India', 'common_name' => null, 'flag_emoji' => '🇮🇳'],
['alpha2' => 'IO', 'alpha3' => 'IOT', 'numeric' => '086', 'name' => 'British Indian Ocean Territory', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇮🇴'],
['alpha2' => 'IQ', 'alpha3' => 'IRQ', 'numeric' => '368', 'name' => 'Iraq', 'official_name' => 'Republic of Iraq', 'common_name' => null, 'flag_emoji' => '🇮🇶'],
['alpha2' => 'IR', 'alpha3' => 'IRN', 'numeric' => '364', 'name' => 'Iran, Islamic Republic of', 'official_name' => 'Islamic Republic of Iran', 'common_name' => 'Iran', 'flag_emoji' => '🇮🇷'],
['alpha2' => 'IS', 'alpha3' => 'ISL', 'numeric' => '352', 'name' => 'Iceland', 'official_name' => 'Republic of Iceland', 'common_name' => null, 'flag_emoji' => '🇮🇸'],
['alpha2' => 'IT', 'alpha3' => 'ITA', 'numeric' => '380', 'name' => 'Italy', 'official_name' => 'Italian Republic', 'common_name' => null, 'flag_emoji' => '🇮🇹'],
['alpha2' => 'JE', 'alpha3' => 'JEY', 'numeric' => '832', 'name' => 'Jersey', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇯🇪'],
['alpha2' => 'JM', 'alpha3' => 'JAM', 'numeric' => '388', 'name' => 'Jamaica', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇯🇲'],
['alpha2' => 'JO', 'alpha3' => 'JOR', 'numeric' => '400', 'name' => 'Jordan', 'official_name' => 'Hashemite Kingdom of Jordan', 'common_name' => null, 'flag_emoji' => '🇯🇴'],
['alpha2' => 'JP', 'alpha3' => 'JPN', 'numeric' => '392', 'name' => 'Japan', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇯🇵'],
['alpha2' => 'KE', 'alpha3' => 'KEN', 'numeric' => '404', 'name' => 'Kenya', 'official_name' => 'Republic of Kenya', 'common_name' => null, 'flag_emoji' => '🇰🇪'],
['alpha2' => 'KG', 'alpha3' => 'KGZ', 'numeric' => '417', 'name' => 'Kyrgyzstan', 'official_name' => 'Kyrgyz Republic', 'common_name' => null, 'flag_emoji' => '🇰🇬'],
['alpha2' => 'KH', 'alpha3' => 'KHM', 'numeric' => '116', 'name' => 'Cambodia', 'official_name' => 'Kingdom of Cambodia', 'common_name' => null, 'flag_emoji' => '🇰🇭'],
['alpha2' => 'KI', 'alpha3' => 'KIR', 'numeric' => '296', 'name' => 'Kiribati', 'official_name' => 'Republic of Kiribati', 'common_name' => null, 'flag_emoji' => '🇰🇮'],
['alpha2' => 'KM', 'alpha3' => 'COM', 'numeric' => '174', 'name' => 'Comoros', 'official_name' => 'Union of the Comoros', 'common_name' => null, 'flag_emoji' => '🇰🇲'],
['alpha2' => 'KN', 'alpha3' => 'KNA', 'numeric' => '659', 'name' => 'Saint Kitts and Nevis', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇰🇳'],
['alpha2' => 'KP', 'alpha3' => 'PRK', 'numeric' => '408', 'name' => 'Korea, Democratic People\'s Republic of', 'official_name' => 'Democratic People\'s Republic of Korea', 'common_name' => 'North Korea', 'flag_emoji' => '🇰🇵'],
['alpha2' => 'KR', 'alpha3' => 'KOR', 'numeric' => '410', 'name' => 'Korea, Republic of', 'official_name' => null, 'common_name' => 'South Korea', 'flag_emoji' => '🇰🇷'],
['alpha2' => 'KW', 'alpha3' => 'KWT', 'numeric' => '414', 'name' => 'Kuwait', 'official_name' => 'State of Kuwait', 'common_name' => null, 'flag_emoji' => '🇰🇼'],
['alpha2' => 'KY', 'alpha3' => 'CYM', 'numeric' => '136', 'name' => 'Cayman Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇰🇾'],
['alpha2' => 'KZ', 'alpha3' => 'KAZ', 'numeric' => '398', 'name' => 'Kazakhstan', 'official_name' => 'Republic of Kazakhstan', 'common_name' => null, 'flag_emoji' => '🇰🇿'],
['alpha2' => 'LA', 'alpha3' => 'LAO', 'numeric' => '418', 'name' => 'Lao People\'s Democratic Republic', 'official_name' => null, 'common_name' => 'Laos', 'flag_emoji' => '🇱🇦'],
['alpha2' => 'LB', 'alpha3' => 'LBN', 'numeric' => '422', 'name' => 'Lebanon', 'official_name' => 'Lebanese Republic', 'common_name' => null, 'flag_emoji' => '🇱🇧'],
['alpha2' => 'LC', 'alpha3' => 'LCA', 'numeric' => '662', 'name' => 'Saint Lucia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇱🇨'],
['alpha2' => 'LI', 'alpha3' => 'LIE', 'numeric' => '438', 'name' => 'Liechtenstein', 'official_name' => 'Principality of Liechtenstein', 'common_name' => null, 'flag_emoji' => '🇱🇮'],
['alpha2' => 'LK', 'alpha3' => 'LKA', 'numeric' => '144', 'name' => 'Sri Lanka', 'official_name' => 'Democratic Socialist Republic of Sri Lanka', 'common_name' => null, 'flag_emoji' => '🇱🇰'],
['alpha2' => 'LR', 'alpha3' => 'LBR', 'numeric' => '430', 'name' => 'Liberia', 'official_name' => 'Republic of Liberia', 'common_name' => null, 'flag_emoji' => '🇱🇷'],
['alpha2' => 'LS', 'alpha3' => 'LSO', 'numeric' => '426', 'name' => 'Lesotho', 'official_name' => 'Kingdom of Lesotho', 'common_name' => null, 'flag_emoji' => '🇱🇸'],
['alpha2' => 'LT', 'alpha3' => 'LTU', 'numeric' => '440', 'name' => 'Lithuania', 'official_name' => 'Republic of Lithuania', 'common_name' => null, 'flag_emoji' => '🇱🇹'],
['alpha2' => 'LU', 'alpha3' => 'LUX', 'numeric' => '442', 'name' => 'Luxembourg', 'official_name' => 'Grand Duchy of Luxembourg', 'common_name' => null, 'flag_emoji' => '🇱🇺'],
['alpha2' => 'LV', 'alpha3' => 'LVA', 'numeric' => '428', 'name' => 'Latvia', 'official_name' => 'Republic of Latvia', 'common_name' => null, 'flag_emoji' => '🇱🇻'],
['alpha2' => 'LY', 'alpha3' => 'LBY', 'numeric' => '434', 'name' => 'Libya', 'official_name' => 'Libya', 'common_name' => null, 'flag_emoji' => '🇱🇾'],
['alpha2' => 'MA', 'alpha3' => 'MAR', 'numeric' => '504', 'name' => 'Morocco', 'official_name' => 'Kingdom of Morocco', 'common_name' => null, 'flag_emoji' => '🇲🇦'],
['alpha2' => 'MC', 'alpha3' => 'MCO', 'numeric' => '492', 'name' => 'Monaco', 'official_name' => 'Principality of Monaco', 'common_name' => null, 'flag_emoji' => '🇲🇨'],
['alpha2' => 'MD', 'alpha3' => 'MDA', 'numeric' => '498', 'name' => 'Moldova, Republic of', 'official_name' => 'Republic of Moldova', 'common_name' => 'Moldova', 'flag_emoji' => '🇲🇩'],
['alpha2' => 'ME', 'alpha3' => 'MNE', 'numeric' => '499', 'name' => 'Montenegro', 'official_name' => 'Montenegro', 'common_name' => null, 'flag_emoji' => '🇲🇪'],
['alpha2' => 'MF', 'alpha3' => 'MAF', 'numeric' => '663', 'name' => 'Saint Martin (French part)', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇫'],
['alpha2' => 'MG', 'alpha3' => 'MDG', 'numeric' => '450', 'name' => 'Madagascar', 'official_name' => 'Republic of Madagascar', 'common_name' => null, 'flag_emoji' => '🇲🇬'],
['alpha2' => 'MH', 'alpha3' => 'MHL', 'numeric' => '584', 'name' => 'Marshall Islands', 'official_name' => 'Republic of the Marshall Islands', 'common_name' => null, 'flag_emoji' => '🇲🇭'],
['alpha2' => 'MK', 'alpha3' => 'MKD', 'numeric' => '807', 'name' => 'North Macedonia', 'official_name' => 'Republic of North Macedonia', 'common_name' => null, 'flag_emoji' => '🇲🇰'],
['alpha2' => 'ML', 'alpha3' => 'MLI', 'numeric' => '466', 'name' => 'Mali', 'official_name' => 'Republic of Mali', 'common_name' => null, 'flag_emoji' => '🇲🇱'],
['alpha2' => 'MM', 'alpha3' => 'MMR', 'numeric' => '104', 'name' => 'Myanmar', 'official_name' => 'Republic of Myanmar', 'common_name' => null, 'flag_emoji' => '🇲🇲'],
['alpha2' => 'MN', 'alpha3' => 'MNG', 'numeric' => '496', 'name' => 'Mongolia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇳'],
['alpha2' => 'MO', 'alpha3' => 'MAC', 'numeric' => '446', 'name' => 'Macao', 'official_name' => 'Macao Special Administrative Region of China', 'common_name' => null, 'flag_emoji' => '🇲🇴'],
['alpha2' => 'MP', 'alpha3' => 'MNP', 'numeric' => '580', 'name' => 'Northern Mariana Islands', 'official_name' => 'Commonwealth of the Northern Mariana Islands', 'common_name' => null, 'flag_emoji' => '🇲🇵'],
['alpha2' => 'MQ', 'alpha3' => 'MTQ', 'numeric' => '474', 'name' => 'Martinique', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇶'],
['alpha2' => 'MR', 'alpha3' => 'MRT', 'numeric' => '478', 'name' => 'Mauritania', 'official_name' => 'Islamic Republic of Mauritania', 'common_name' => null, 'flag_emoji' => '🇲🇷'],
['alpha2' => 'MS', 'alpha3' => 'MSR', 'numeric' => '500', 'name' => 'Montserrat', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇸'],
['alpha2' => 'MT', 'alpha3' => 'MLT', 'numeric' => '470', 'name' => 'Malta', 'official_name' => 'Republic of Malta', 'common_name' => null, 'flag_emoji' => '🇲🇹'],
['alpha2' => 'MU', 'alpha3' => 'MUS', 'numeric' => '480', 'name' => 'Mauritius', 'official_name' => 'Republic of Mauritius', 'common_name' => null, 'flag_emoji' => '🇲🇺'],
['alpha2' => 'MV', 'alpha3' => 'MDV', 'numeric' => '462', 'name' => 'Maldives', 'official_name' => 'Republic of Maldives', 'common_name' => null, 'flag_emoji' => '🇲🇻'],
['alpha2' => 'MW', 'alpha3' => 'MWI', 'numeric' => '454', 'name' => 'Malawi', 'official_name' => 'Republic of Malawi', 'common_name' => null, 'flag_emoji' => '🇲🇼'],
['alpha2' => 'MX', 'alpha3' => 'MEX', 'numeric' => '484', 'name' => 'Mexico', 'official_name' => 'United Mexican States', 'common_name' => null, 'flag_emoji' => '🇲🇽'],
['alpha2' => 'MY', 'alpha3' => 'MYS', 'numeric' => '458', 'name' => 'Malaysia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇲🇾'],
['alpha2' => 'MZ', 'alpha3' => 'MOZ', 'numeric' => '508', 'name' => 'Mozambique', 'official_name' => 'Republic of Mozambique', 'common_name' => null, 'flag_emoji' => '🇲🇿'],
['alpha2' => 'NA', 'alpha3' => 'NAM', 'numeric' => '516', 'name' => 'Namibia', 'official_name' => 'Republic of Namibia', 'common_name' => null, 'flag_emoji' => '🇳🇦'],
['alpha2' => 'NC', 'alpha3' => 'NCL', 'numeric' => '540', 'name' => 'New Caledonia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇳🇨'],
['alpha2' => 'NE', 'alpha3' => 'NER', 'numeric' => '562', 'name' => 'Niger', 'official_name' => 'Republic of the Niger', 'common_name' => null, 'flag_emoji' => '🇳🇪'],
['alpha2' => 'NF', 'alpha3' => 'NFK', 'numeric' => '574', 'name' => 'Norfolk Island', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇳🇫'],
['alpha2' => 'NG', 'alpha3' => 'NGA', 'numeric' => '566', 'name' => 'Nigeria', 'official_name' => 'Federal Republic of Nigeria', 'common_name' => null, 'flag_emoji' => '🇳🇬'],
['alpha2' => 'NI', 'alpha3' => 'NIC', 'numeric' => '558', 'name' => 'Nicaragua', 'official_name' => 'Republic of Nicaragua', 'common_name' => null, 'flag_emoji' => '🇳🇮'],
['alpha2' => 'NL', 'alpha3' => 'NLD', 'numeric' => '528', 'name' => 'Netherlands', 'official_name' => 'Kingdom of the Netherlands', 'common_name' => null, 'flag_emoji' => '🇳🇱'],
['alpha2' => 'NO', 'alpha3' => 'NOR', 'numeric' => '578', 'name' => 'Norway', 'official_name' => 'Kingdom of Norway', 'common_name' => null, 'flag_emoji' => '🇳🇴'],
['alpha2' => 'NP', 'alpha3' => 'NPL', 'numeric' => '524', 'name' => 'Nepal', 'official_name' => 'Federal Democratic Republic of Nepal', 'common_name' => null, 'flag_emoji' => '🇳🇵'],
['alpha2' => 'NR', 'alpha3' => 'NRU', 'numeric' => '520', 'name' => 'Nauru', 'official_name' => 'Republic of Nauru', 'common_name' => null, 'flag_emoji' => '🇳🇷'],
['alpha2' => 'NU', 'alpha3' => 'NIU', 'numeric' => '570', 'name' => 'Niue', 'official_name' => 'Niue', 'common_name' => null, 'flag_emoji' => '🇳🇺'],
['alpha2' => 'NZ', 'alpha3' => 'NZL', 'numeric' => '554', 'name' => 'New Zealand', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇳🇿'],
['alpha2' => 'OM', 'alpha3' => 'OMN', 'numeric' => '512', 'name' => 'Oman', 'official_name' => 'Sultanate of Oman', 'common_name' => null, 'flag_emoji' => '🇴🇲'],
['alpha2' => 'PA', 'alpha3' => 'PAN', 'numeric' => '591', 'name' => 'Panama', 'official_name' => 'Republic of Panama', 'common_name' => null, 'flag_emoji' => '🇵🇦'],
['alpha2' => 'PE', 'alpha3' => 'PER', 'numeric' => '604', 'name' => 'Peru', 'official_name' => 'Republic of Peru', 'common_name' => null, 'flag_emoji' => '🇵🇪'],
['alpha2' => 'PF', 'alpha3' => 'PYF', 'numeric' => '258', 'name' => 'French Polynesia', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇵🇫'],
['alpha2' => 'PG', 'alpha3' => 'PNG', 'numeric' => '598', 'name' => 'Papua New Guinea', 'official_name' => 'Independent State of Papua New Guinea', 'common_name' => null, 'flag_emoji' => '🇵🇬'],
['alpha2' => 'PH', 'alpha3' => 'PHL', 'numeric' => '608', 'name' => 'Philippines', 'official_name' => 'Republic of the Philippines', 'common_name' => null, 'flag_emoji' => '🇵🇭'],
['alpha2' => 'PK', 'alpha3' => 'PAK', 'numeric' => '586', 'name' => 'Pakistan', 'official_name' => 'Islamic Republic of Pakistan', 'common_name' => null, 'flag_emoji' => '🇵🇰'],
['alpha2' => 'PL', 'alpha3' => 'POL', 'numeric' => '616', 'name' => 'Poland', 'official_name' => 'Republic of Poland', 'common_name' => null, 'flag_emoji' => '🇵🇱'],
['alpha2' => 'PM', 'alpha3' => 'SPM', 'numeric' => '666', 'name' => 'Saint Pierre and Miquelon', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇵🇲'],
['alpha2' => 'PN', 'alpha3' => 'PCN', 'numeric' => '612', 'name' => 'Pitcairn', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇵🇳'],
['alpha2' => 'PR', 'alpha3' => 'PRI', 'numeric' => '630', 'name' => 'Puerto Rico', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇵🇷'],
['alpha2' => 'PS', 'alpha3' => 'PSE', 'numeric' => '275', 'name' => 'Palestine, State of', 'official_name' => 'the State of Palestine', 'common_name' => null, 'flag_emoji' => '🇵🇸'],
['alpha2' => 'PT', 'alpha3' => 'PRT', 'numeric' => '620', 'name' => 'Portugal', 'official_name' => 'Portuguese Republic', 'common_name' => null, 'flag_emoji' => '🇵🇹'],
['alpha2' => 'PW', 'alpha3' => 'PLW', 'numeric' => '585', 'name' => 'Palau', 'official_name' => 'Republic of Palau', 'common_name' => null, 'flag_emoji' => '🇵🇼'],
['alpha2' => 'PY', 'alpha3' => 'PRY', 'numeric' => '600', 'name' => 'Paraguay', 'official_name' => 'Republic of Paraguay', 'common_name' => null, 'flag_emoji' => '🇵🇾'],
['alpha2' => 'QA', 'alpha3' => 'QAT', 'numeric' => '634', 'name' => 'Qatar', 'official_name' => 'State of Qatar', 'common_name' => null, 'flag_emoji' => '🇶🇦'],
['alpha2' => 'RE', 'alpha3' => 'REU', 'numeric' => '638', 'name' => 'Réunion', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇷🇪'],
['alpha2' => 'RO', 'alpha3' => 'ROU', 'numeric' => '642', 'name' => 'Romania', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇷🇴'],
['alpha2' => 'RS', 'alpha3' => 'SRB', 'numeric' => '688', 'name' => 'Serbia', 'official_name' => 'Republic of Serbia', 'common_name' => null, 'flag_emoji' => '🇷🇸'],
['alpha2' => 'RU', 'alpha3' => 'RUS', 'numeric' => '643', 'name' => 'Russian Federation', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇷🇺'],
['alpha2' => 'RW', 'alpha3' => 'RWA', 'numeric' => '646', 'name' => 'Rwanda', 'official_name' => 'Rwandese Republic', 'common_name' => null, 'flag_emoji' => '🇷🇼'],
['alpha2' => 'SA', 'alpha3' => 'SAU', 'numeric' => '682', 'name' => 'Saudi Arabia', 'official_name' => 'Kingdom of Saudi Arabia', 'common_name' => null, 'flag_emoji' => '🇸🇦'],
['alpha2' => 'SB', 'alpha3' => 'SLB', 'numeric' => '090', 'name' => 'Solomon Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇸🇧'],
['alpha2' => 'SC', 'alpha3' => 'SYC', 'numeric' => '690', 'name' => 'Seychelles', 'official_name' => 'Republic of Seychelles', 'common_name' => null, 'flag_emoji' => '🇸🇨'],
['alpha2' => 'SD', 'alpha3' => 'SDN', 'numeric' => '729', 'name' => 'Sudan', 'official_name' => 'Republic of the Sudan', 'common_name' => null, 'flag_emoji' => '🇸🇩'],
['alpha2' => 'SE', 'alpha3' => 'SWE', 'numeric' => '752', 'name' => 'Sweden', 'official_name' => 'Kingdom of Sweden', 'common_name' => null, 'flag_emoji' => '🇸🇪'],
['alpha2' => 'SG', 'alpha3' => 'SGP', 'numeric' => '702', 'name' => 'Singapore', 'official_name' => 'Republic of Singapore', 'common_name' => null, 'flag_emoji' => '🇸🇬'],
['alpha2' => 'SH', 'alpha3' => 'SHN', 'numeric' => '654', 'name' => 'Saint Helena, Ascension and Tristan da Cunha', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇸🇭'],
['alpha2' => 'SI', 'alpha3' => 'SVN', 'numeric' => '705', 'name' => 'Slovenia', 'official_name' => 'Republic of Slovenia', 'common_name' => null, 'flag_emoji' => '🇸🇮'],
['alpha2' => 'SJ', 'alpha3' => 'SJM', 'numeric' => '744', 'name' => 'Svalbard and Jan Mayen', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇸🇯'],
['alpha2' => 'SK', 'alpha3' => 'SVK', 'numeric' => '703', 'name' => 'Slovakia', 'official_name' => 'Slovak Republic', 'common_name' => null, 'flag_emoji' => '🇸🇰'],
['alpha2' => 'SL', 'alpha3' => 'SLE', 'numeric' => '694', 'name' => 'Sierra Leone', 'official_name' => 'Republic of Sierra Leone', 'common_name' => null, 'flag_emoji' => '🇸🇱'],
['alpha2' => 'SM', 'alpha3' => 'SMR', 'numeric' => '674', 'name' => 'San Marino', 'official_name' => 'Republic of San Marino', 'common_name' => null, 'flag_emoji' => '🇸🇲'],
['alpha2' => 'SN', 'alpha3' => 'SEN', 'numeric' => '686', 'name' => 'Senegal', 'official_name' => 'Republic of Senegal', 'common_name' => null, 'flag_emoji' => '🇸🇳'],
['alpha2' => 'SO', 'alpha3' => 'SOM', 'numeric' => '706', 'name' => 'Somalia', 'official_name' => 'Federal Republic of Somalia', 'common_name' => null, 'flag_emoji' => '🇸🇴'],
['alpha2' => 'SR', 'alpha3' => 'SUR', 'numeric' => '740', 'name' => 'Suriname', 'official_name' => 'Republic of Suriname', 'common_name' => null, 'flag_emoji' => '🇸🇷'],
['alpha2' => 'SS', 'alpha3' => 'SSD', 'numeric' => '728', 'name' => 'South Sudan', 'official_name' => 'Republic of South Sudan', 'common_name' => null, 'flag_emoji' => '🇸🇸'],
['alpha2' => 'ST', 'alpha3' => 'STP', 'numeric' => '678', 'name' => 'Sao Tome and Principe', 'official_name' => 'Democratic Republic of Sao Tome and Principe', 'common_name' => null, 'flag_emoji' => '🇸🇹'],
['alpha2' => 'SV', 'alpha3' => 'SLV', 'numeric' => '222', 'name' => 'El Salvador', 'official_name' => 'Republic of El Salvador', 'common_name' => null, 'flag_emoji' => '🇸🇻'],
['alpha2' => 'SX', 'alpha3' => 'SXM', 'numeric' => '534', 'name' => 'Sint Maarten (Dutch part)', 'official_name' => 'Sint Maarten (Dutch part)', 'common_name' => null, 'flag_emoji' => '🇸🇽'],
['alpha2' => 'SY', 'alpha3' => 'SYR', 'numeric' => '760', 'name' => 'Syrian Arab Republic', 'official_name' => null, 'common_name' => 'Syria', 'flag_emoji' => '🇸🇾'],
['alpha2' => 'SZ', 'alpha3' => 'SWZ', 'numeric' => '748', 'name' => 'Eswatini', 'official_name' => 'Kingdom of Eswatini', 'common_name' => null, 'flag_emoji' => '🇸🇿'],
['alpha2' => 'TC', 'alpha3' => 'TCA', 'numeric' => '796', 'name' => 'Turks and Caicos Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇨'],
['alpha2' => 'TD', 'alpha3' => 'TCD', 'numeric' => '148', 'name' => 'Chad', 'official_name' => 'Republic of Chad', 'common_name' => null, 'flag_emoji' => '🇹🇩'],
['alpha2' => 'TF', 'alpha3' => 'ATF', 'numeric' => '260', 'name' => 'French Southern Territories', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇫'],
['alpha2' => 'TG', 'alpha3' => 'TGO', 'numeric' => '768', 'name' => 'Togo', 'official_name' => 'Togolese Republic', 'common_name' => null, 'flag_emoji' => '🇹🇬'],
['alpha2' => 'TH', 'alpha3' => 'THA', 'numeric' => '764', 'name' => 'Thailand', 'official_name' => 'Kingdom of Thailand', 'common_name' => null, 'flag_emoji' => '🇹🇭'],
['alpha2' => 'TJ', 'alpha3' => 'TJK', 'numeric' => '762', 'name' => 'Tajikistan', 'official_name' => 'Republic of Tajikistan', 'common_name' => null, 'flag_emoji' => '🇹🇯'],
['alpha2' => 'TK', 'alpha3' => 'TKL', 'numeric' => '772', 'name' => 'Tokelau', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇰'],
['alpha2' => 'TL', 'alpha3' => 'TLS', 'numeric' => '626', 'name' => 'Timor-Leste', 'official_name' => 'Democratic Republic of Timor-Leste', 'common_name' => null, 'flag_emoji' => '🇹🇱'],
['alpha2' => 'TM', 'alpha3' => 'TKM', 'numeric' => '795', 'name' => 'Turkmenistan', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇲'],
['alpha2' => 'TN', 'alpha3' => 'TUN', 'numeric' => '788', 'name' => 'Tunisia', 'official_name' => 'Republic of Tunisia', 'common_name' => null, 'flag_emoji' => '🇹🇳'],
['alpha2' => 'TO', 'alpha3' => 'TON', 'numeric' => '776', 'name' => 'Tonga', 'official_name' => 'Kingdom of Tonga', 'common_name' => null, 'flag_emoji' => '🇹🇴'],
['alpha2' => 'TR', 'alpha3' => 'TUR', 'numeric' => '792', 'name' => 'Türkiye', 'official_name' => 'Republic of Türkiye', 'common_name' => null, 'flag_emoji' => '🇹🇷'],
['alpha2' => 'TT', 'alpha3' => 'TTO', 'numeric' => '780', 'name' => 'Trinidad and Tobago', 'official_name' => 'Republic of Trinidad and Tobago', 'common_name' => null, 'flag_emoji' => '🇹🇹'],
['alpha2' => 'TV', 'alpha3' => 'TUV', 'numeric' => '798', 'name' => 'Tuvalu', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇹🇻'],
['alpha2' => 'TW', 'alpha3' => 'TWN', 'numeric' => '158', 'name' => 'Taiwan, Province of China', 'official_name' => 'Taiwan, Province of China', 'common_name' => 'Taiwan', 'flag_emoji' => '🇹🇼'],
['alpha2' => 'TZ', 'alpha3' => 'TZA', 'numeric' => '834', 'name' => 'Tanzania, United Republic of', 'official_name' => 'United Republic of Tanzania', 'common_name' => 'Tanzania', 'flag_emoji' => '🇹🇿'],
['alpha2' => 'UA', 'alpha3' => 'UKR', 'numeric' => '804', 'name' => 'Ukraine', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇺🇦'],
['alpha2' => 'UG', 'alpha3' => 'UGA', 'numeric' => '800', 'name' => 'Uganda', 'official_name' => 'Republic of Uganda', 'common_name' => null, 'flag_emoji' => '🇺🇬'],
['alpha2' => 'UM', 'alpha3' => 'UMI', 'numeric' => '581', 'name' => 'United States Minor Outlying Islands', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇺🇲'],
['alpha2' => 'US', 'alpha3' => 'USA', 'numeric' => '840', 'name' => 'United States', 'official_name' => 'United States of America', 'common_name' => null, 'flag_emoji' => '🇺🇸'],
['alpha2' => 'UY', 'alpha3' => 'URY', 'numeric' => '858', 'name' => 'Uruguay', 'official_name' => 'Eastern Republic of Uruguay', 'common_name' => null, 'flag_emoji' => '🇺🇾'],
['alpha2' => 'UZ', 'alpha3' => 'UZB', 'numeric' => '860', 'name' => 'Uzbekistan', 'official_name' => 'Republic of Uzbekistan', 'common_name' => null, 'flag_emoji' => '🇺🇿'],
['alpha2' => 'VA', 'alpha3' => 'VAT', 'numeric' => '336', 'name' => 'Holy See (Vatican City State)', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇻🇦'],
['alpha2' => 'VC', 'alpha3' => 'VCT', 'numeric' => '670', 'name' => 'Saint Vincent and the Grenadines', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇻🇨'],
['alpha2' => 'VE', 'alpha3' => 'VEN', 'numeric' => '862', 'name' => 'Venezuela, Bolivarian Republic of', 'official_name' => 'Bolivarian Republic of Venezuela', 'common_name' => 'Venezuela', 'flag_emoji' => '🇻🇪'],
['alpha2' => 'VG', 'alpha3' => 'VGB', 'numeric' => '092', 'name' => 'Virgin Islands, British', 'official_name' => 'British Virgin Islands', 'common_name' => null, 'flag_emoji' => '🇻🇬'],
['alpha2' => 'VI', 'alpha3' => 'VIR', 'numeric' => '850', 'name' => 'Virgin Islands, U.S.', 'official_name' => 'Virgin Islands of the United States', 'common_name' => null, 'flag_emoji' => '🇻🇮'],
['alpha2' => 'VN', 'alpha3' => 'VNM', 'numeric' => '704', 'name' => 'Viet Nam', 'official_name' => 'Socialist Republic of Viet Nam', 'common_name' => 'Vietnam', 'flag_emoji' => '🇻🇳'],
['alpha2' => 'VU', 'alpha3' => 'VUT', 'numeric' => '548', 'name' => 'Vanuatu', 'official_name' => 'Republic of Vanuatu', 'common_name' => null, 'flag_emoji' => '🇻🇺'],
['alpha2' => 'WF', 'alpha3' => 'WLF', 'numeric' => '876', 'name' => 'Wallis and Futuna', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇼🇫'],
['alpha2' => 'WS', 'alpha3' => 'WSM', 'numeric' => '882', 'name' => 'Samoa', 'official_name' => 'Independent State of Samoa', 'common_name' => null, 'flag_emoji' => '🇼🇸'],
['alpha2' => 'YE', 'alpha3' => 'YEM', 'numeric' => '887', 'name' => 'Yemen', 'official_name' => 'Republic of Yemen', 'common_name' => null, 'flag_emoji' => '🇾🇪'],
['alpha2' => 'YT', 'alpha3' => 'MYT', 'numeric' => '175', 'name' => 'Mayotte', 'official_name' => null, 'common_name' => null, 'flag_emoji' => '🇾🇹'],
['alpha2' => 'ZA', 'alpha3' => 'ZAF', 'numeric' => '710', 'name' => 'South Africa', 'official_name' => 'Republic of South Africa', 'common_name' => null, 'flag_emoji' => '🇿🇦'],
['alpha2' => 'ZM', 'alpha3' => 'ZMB', 'numeric' => '894', 'name' => 'Zambia', 'official_name' => 'Republic of Zambia', 'common_name' => null, 'flag_emoji' => '🇿🇲'],
['alpha2' => 'ZW', 'alpha3' => 'ZWE', 'numeric' => '716', 'name' => 'Zimbabwe', 'official_name' => 'Republic of Zimbabwe', 'common_name' => null, 'flag_emoji' => '🇿🇼'],
];
/** @var list<array<string, mixed>> $countries */
$countries = json_decode(
file_get_contents(dirname(__DIR__) . '/Data/iso_countries.json'),
true,
flags: JSON_THROW_ON_ERROR,
);
foreach ($countries as $index => $country) {
Country::query()->updateOrCreate(
@@ -52,18 +52,16 @@ class DocumentationAttachment extends Model
{
$bytes = (int) $this->size;
$label = number_format($bytes / 1048576, 1) . ' MB';
if ($bytes <= 0) {
return 'Unknown size';
$label = 'Unknown size';
} elseif ($bytes < 1024) {
$label = $bytes . ' B';
} elseif ($bytes < 1048576) {
$label = number_format($bytes / 1024, 1) . ' KB';
}
if ($bytes < 1024) {
return $bytes . ' B';
}
if ($bytes < 1048576) {
return number_format($bytes / 1024, 1) . ' KB';
}
return number_format($bytes / 1048576, 1) . ' MB';
return $label;
}
}
@@ -38,34 +38,31 @@ final class GitWebhookController
$event = $this->eventName($request, $provider);
$deliveryId = $this->deliveryId($request, $provider);
$rawPayload = $request->getContent();
$status = 202;
$payload = [];
if (! $repository->is_active) {
$result = $this->rejectedResult('Repository is inactive.');
$service->logWebhook($repository, $provider, $deliveryId, $event, $result);
return response()->json($result, 403);
}
if (! $this->hasValidSignature($request, $repository, $provider, $rawPayload)) {
$status = 403;
} elseif (! $this->hasValidSignature($request, $repository, $provider, $rawPayload)) {
$result = $this->rejectedResult(self::SIGNATURE_FAILED);
$service->logWebhook($repository, $provider, $deliveryId, $event, $result);
return response()->json($result, 403);
$status = 403;
} else {
try {
/** @var array<string, mixed> $payload */
$payload = json_decode($rawPayload, true, 512, JSON_THROW_ON_ERROR);
$result = $service->ingest($repository, $payload, $provider, $deliveryId, $event);
} catch (JsonException) {
$result = $this->rejectedResult('Invalid JSON webhook payload.');
$status = 400;
}
}
try {
/** @var array<string, mixed> $payload */
$payload = json_decode($rawPayload, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException) {
$result = $this->rejectedResult('Invalid JSON webhook payload.');
$service->logWebhook($repository, $provider, $deliveryId, $event, $result);
return response()->json($result, 400);
if ($status !== 202) {
$service->logWebhook($repository, $provider, $deliveryId, $event, $result, $payload);
}
$result = $service->ingest($repository, $payload, $provider, $deliveryId, $event);
return response()->json($result, 202);
return response()->json($result, $status);
}
/**
@@ -77,33 +74,34 @@ final class GitWebhookController
$event = $this->eventName($request, $provider);
$deliveryId = $this->deliveryId($request, $provider);
$rawPayload = $request->getContent();
$status = 202;
$repository = null;
try {
/** @var array<string, mixed> $payload */
$payload = json_decode($rawPayload, true, 512, JSON_THROW_ON_ERROR);
$repository = $this->repositoryForGiteaPayload($payload);
if (! $repository instanceof GitRepository) {
$result = $this->rejectedResult('No active Helpdesk Git repository matched the Gitea webhook payload.');
$status = 404;
} elseif (! $this->hasValidGiteaSecurity($request, $repository, $provider, $rawPayload)) {
$result = $this->rejectedResult(self::SIGNATURE_FAILED);
$status = 403;
} else {
$result = $service->ingest($repository, $payload, $provider, $deliveryId, $event);
}
} catch (JsonException) {
return response()->json($this->rejectedResult('Invalid JSON webhook payload.'), 400);
$payload = [];
$result = $this->rejectedResult('Invalid JSON webhook payload.');
$status = 400;
}
$repository = $this->repositoryForGiteaPayload($payload);
if (! $repository instanceof GitRepository) {
return response()->json(
$this->rejectedResult('No active Helpdesk Git repository matched the Gitea webhook payload.'),
404,
);
}
if (! $this->hasValidGiteaSecurity($request, $repository, $provider, $rawPayload)) {
$result = $this->rejectedResult(self::SIGNATURE_FAILED);
if ($repository instanceof GitRepository && $status !== 202) {
$service->logWebhook($repository, $provider, $deliveryId, $event, $result, $payload);
return response()->json($result, 403);
}
$result = $service->ingest($repository, $payload, $provider, $deliveryId, $event);
return response()->json($result, 202);
return response()->json($result, $status);
}
/**
@@ -235,31 +233,27 @@ final class GitWebhookController
->where('is_active', true)
->whereRaw('LOWER(provider) IN (?, ?)', ['gitea', 'git'])
->get();
$matchedRepository = null;
if ($repositories->isEmpty()) {
Log::warning('Helpdesk Gitea webhook received but no active Gitea/git repository is configured.');
} else {
$normalisedPayloadValues = $this->normalisedPayloadRepositoryValues($payload);
$matchedRepository = $repositories->first(
fn (GitRepository $repository): bool => $this->repositoryMatchesPayload($repository, $normalisedPayloadValues),
);
return null;
}
$normalisedPayloadValues = $this->normalisedPayloadRepositoryValues($payload);
foreach ($repositories as $repository) {
if ($this->repositoryMatchesPayload($repository, $normalisedPayloadValues)) {
return $repository;
if (! $matchedRepository instanceof GitRepository && $repositories->count() === 1) {
$matchedRepository = $repositories->first();
} elseif (! $matchedRepository instanceof GitRepository) {
Log::warning('Helpdesk Gitea webhook did not match any configured repository.', [
'payload_repository' => Arr::get($payload, 'repository.full_name') ?: Arr::get($payload, 'repository.clone_url') ?: Arr::get($payload, 'repository.html_url'),
'configured_repository_count' => $repositories->count(),
]);
}
}
if ($repositories->count() === 1) {
return $repositories->first();
}
Log::warning('Helpdesk Gitea webhook did not match any configured repository.', [
'payload_repository' => Arr::get($payload, 'repository.full_name') ?: Arr::get($payload, 'repository.clone_url') ?: Arr::get($payload, 'repository.html_url'),
'configured_repository_count' => $repositories->count(),
]);
return null;
return $matchedRepository instanceof GitRepository ? $matchedRepository : null;
}
/** @param array<string, mixed> $payload
@@ -879,10 +879,8 @@ final class SettingsManager extends Component
return $model;
}
/** @var TModel $model */
$model = $modelClass::query()->create($data);
return $model;
/** @var TModel */
return $modelClass::query()->create($data);
} catch (QueryException $exception) {
throw ValidationException::withMessages([
'settings' => 'The record could not be saved. Check the slug is unique for this section/company and try again.',
+5 -3
View File
@@ -22,6 +22,8 @@ use Modules\Helpdesk\Services\TicketService;
final class TicketCreate extends Component
{
private const COMPANY_NULL_ORDER = 'company_id is null';
use WithFileUploads;
public ?int $company_id = null;
@@ -188,7 +190,7 @@ final class TicketCreate extends Component
$query->where('company_id', $this->company_id)
->orWhereNull('company_id');
}))
->orderByRaw('company_id is null')
->orderByRaw(self::COMPANY_NULL_ORDER)
->orderBy('name')
->value('id');
}
@@ -201,7 +203,7 @@ final class TicketCreate extends Component
$query->where('company_id', $this->company_id)
->orWhereNull('company_id');
}))
->orderByRaw('company_id is null')
->orderByRaw(self::COMPANY_NULL_ORDER)
->orderBy('name')
->value('id');
}
@@ -218,7 +220,7 @@ final class TicketCreate extends Component
$query->where('team_id', $this->team_id)
->orWhereNull('team_id');
}))
->orderByRaw('company_id is null')
->orderByRaw(self::COMPANY_NULL_ORDER)
->orderByRaw('team_id is null')
->orderBy('title')
->value('id');
+16 -20
View File
@@ -515,19 +515,17 @@ final class TicketShow extends Component
*/
public function firstResponseSlaClasses(): string
{
$classes = 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100';
if ($this->firstResponseWasBreached()) {
return 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100';
$classes = 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100';
} elseif ($this->ticket->first_response_at !== null) {
$classes = 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100';
} elseif ($this->firstResponseIsDueSoon()) {
$classes = 'border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100';
}
if ($this->ticket->first_response_at !== null) {
return 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100';
}
if ($this->firstResponseIsDueSoon()) {
return 'border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100';
}
return 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100';
return $classes;
}
/**
@@ -567,19 +565,17 @@ final class TicketShow extends Component
*/
public function resolutionSlaClasses(): string
{
$classes = 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100';
if ($this->resolutionWasBreached()) {
return 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100';
$classes = 'border-red-300 bg-red-50 text-red-900 dark:border-red-900 dark:bg-red-950 dark:text-red-100';
} elseif ($this->ticket->completed_at !== null) {
$classes = 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100';
} elseif ($this->resolutionIsDueSoon()) {
$classes = 'border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100';
}
if ($this->ticket->completed_at !== null) {
return 'border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-900 dark:bg-emerald-950 dark:text-emerald-100';
}
if ($this->resolutionIsDueSoon()) {
return 'border-amber-300 bg-amber-50 text-amber-950 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100';
}
return 'border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-900 dark:bg-blue-950 dark:text-blue-100';
return $classes;
}
/**
+17 -20
View File
@@ -45,16 +45,13 @@ final class AttachmentService
$size = (int) Storage::disk($disk)->size($path);
}
Attachment::query()->create($this->attachmentAttributes(
ticket: $ticket,
comment: $comment,
userId: $userId,
disk: $disk,
path: $path,
originalName: $originalName,
mimeType: $mimeType,
size: $size,
));
Attachment::query()->create($this->attachmentAttributes($ticket, $comment, $userId, [
'disk' => $disk,
'path' => $path,
'original_name' => $originalName,
'mime_type' => $mimeType,
'size' => $size,
]));
}
}
@@ -72,29 +69,29 @@ final class AttachmentService
*
* @return array<string, mixed>
*/
private function attachmentAttributes(Ticket $ticket, ?Comment $comment, int $userId, string $disk, string $path, string $originalName, string $mimeType, int $size): array
private function attachmentAttributes(Ticket $ticket, ?Comment $comment, int $userId, array $file): array
{
$attributes = [
'ticket_id' => $ticket->id,
'comment_id' => $comment?->id,
'user_id' => $userId,
'disk' => $disk,
'path' => $path,
'original_name' => $originalName,
'mime_type' => $mimeType,
'size' => $size,
'disk' => $file['disk'],
'path' => $file['path'],
'original_name' => $file['original_name'],
'mime_type' => $file['mime_type'],
'size' => $file['size'],
];
if (Schema::hasColumn('helpdesk_attachments', 'extension')) {
$attributes['extension'] = strtolower((string) pathinfo($originalName, PATHINFO_EXTENSION));
$attributes['extension'] = strtolower((string) pathinfo($file['original_name'], PATHINFO_EXTENSION));
}
if (Schema::hasColumn('helpdesk_attachments', 'category')) {
$attributes['category'] = $this->categoryFor($originalName, $mimeType);
$attributes['category'] = $this->categoryFor($file['original_name'], $file['mime_type']);
}
if (Schema::hasColumn('helpdesk_attachments', 'checksum_sha256') && Storage::disk($disk)->exists($path)) {
$stream = Storage::disk($disk)->readStream($path);
if (Schema::hasColumn('helpdesk_attachments', 'checksum_sha256') && Storage::disk($file['disk'])->exists($file['path'])) {
$stream = Storage::disk($file['disk'])->readStream($file['path']);
if (is_resource($stream)) {
$context = hash_init('sha256');
@@ -23,6 +23,8 @@ use Throwable;
final class GitWebhookIngestionService
{
private const PUSH_HOOK = 'push hook';
/**
* Matches the generated Helpdesk reference format, for example HD-2026-00042.
*/
@@ -173,10 +175,10 @@ final class GitWebhookIngestionService
return match ($normalisedProvider) {
'github' => in_array($normalisedEvent, ['push', ''], true),
'gitlab' => in_array($normalisedEvent, ['push hook', 'push', ''], true),
'gitea' => in_array($normalisedEvent, ['push', 'push hook', ''], true),
'gitlab' => in_array($normalisedEvent, [self::PUSH_HOOK, 'push', ''], true),
'gitea' => in_array($normalisedEvent, ['push', self::PUSH_HOOK, ''], true),
'bitbucket' => in_array($normalisedEvent, ['repo push', 'push', ''], true),
default => in_array($normalisedEvent, ['push', 'repo push', 'push hook', ''], true),
default => in_array($normalisedEvent, ['push', 'repo push', self::PUSH_HOOK, ''], true),
};
}
@@ -214,23 +216,14 @@ final class GitWebhookIngestionService
{
$commits = $payload['commits'] ?? null;
if (is_array($commits) && $commits !== []) {
return array_values(array_filter($commits, static fn (mixed $commit): bool => is_array($commit)));
if (! is_array($commits) || $commits === []) {
$headCommit = $payload['head_commit'] ?? null;
$commits = is_array($headCommit) ? [$headCommit] : Arr::get($payload, 'push.changes.0.commits', []);
}
$headCommit = $payload['head_commit'] ?? null;
if (is_array($headCommit)) {
return [$headCommit];
}
$bitbucketCommits = Arr::get($payload, 'push.changes.0.commits', []);
if (is_array($bitbucketCommits)) {
return array_values(array_filter($bitbucketCommits, static fn (mixed $commit): bool => is_array($commit)));
}
return [];
return is_array($commits)
? array_values(array_filter($commits, static fn (mixed $commit): bool => is_array($commit)))
: [];
}
/**
+2 -1
View File
@@ -190,7 +190,8 @@ final class TicketService
];
if (Schema::hasColumn('helpdesk_comments', 'subject')) {
$payload['subject'] = trim((string) ($subject ?: ($parentId === null ? 'Response' : 'RE: Response')));
$defaultSubject = $parentId === null ? 'Response' : 'RE: Response';
$payload['subject'] = trim((string) ($subject ?: $defaultSubject));
}
return $payload;
@@ -34,7 +34,7 @@ final class WorkflowNotificationService
$recipient = $this->recipient($template->to_role, $ticket, $actor);
if ($recipient === null || blank($recipient->email ?? null)) {
$this->log($template, $ticket, $event, null, 'skipped', 'No recipient email was available.');
$this->log($template, $ticket, $event, ['recipient' => null, 'status' => 'skipped', 'error' => 'No recipient email was available.']);
return;
}
@@ -56,10 +56,10 @@ final class WorkflowNotificationService
}
});
$this->log($template, $ticket, $event, (string) $recipient->email, 'sent', null, $subject, $trackingToken);
$this->log($template, $ticket, $event, ['recipient' => (string) $recipient->email, 'status' => 'sent', 'subject' => $subject, 'tracking_token' => $trackingToken]);
} catch (Throwable $exception) {
Log::warning('Helpdesk workflow email failed.', ['event' => $event, 'ticket_id' => $ticket->id, 'error' => $exception->getMessage()]);
$this->log($template, $ticket, $event, (string) $recipient->email, 'failed', $exception->getMessage(), $subject);
$this->log($template, $ticket, $event, ['recipient' => (string) $recipient->email, 'status' => 'failed', 'error' => $exception->getMessage(), 'subject' => $subject]);
}
});
}
@@ -157,17 +157,18 @@ final class WorkflowNotificationService
return '<img src="' . e($url) . '" width="1" height="1" alt="" style="display:none" />';
}
private function log(WorkflowTemplate $template, Ticket $ticket, string $event, ?string $recipient, string $status, ?string $error = null, ?string $subject = null, ?string $trackingToken = null): void
/** @param array{recipient:?string,status:string,error?:?string,subject?:?string,tracking_token?:?string} $details */
private function log(WorkflowTemplate $template, Ticket $ticket, string $event, array $details): void
{
WorkflowLog::query()->create([
'template_id' => $template->id,
'ticket_id' => $ticket->id,
'event' => $event,
'recipient' => $recipient,
'subject' => $subject,
'status' => $status,
'tracking_token' => $trackingToken,
'error' => $error,
'recipient' => $details['recipient'],
'subject' => $details['subject'] ?? null,
'status' => $details['status'],
'tracking_token' => $details['tracking_token'] ?? null,
'error' => $details['error'] ?? null,
]);
}
}
+21 -44
View File
@@ -18,31 +18,28 @@ class DatabaseStage extends Command
{
$local = $this->localConfiguration();
$stage = $this->stageConfiguration();
$exitCode = self::SUCCESS;
if (! $this->validateStageConfiguration($stage)) {
return self::FAILURE;
$exitCode = self::FAILURE;
} else {
[$localDump, $remoteDump] = $this->dumpPaths();
$this->displayCloneSummary($local, $stage);
if (! $this->confirmed($stage)) {
$this->warn('Cancelled.');
} else {
try {
$this->runClone($local, $stage, $localDump, $remoteDump);
$this->reportSuccess($local, $stage);
} catch (\Throwable $exception) {
$this->reportFailure($exception, $localDump, $remoteDump);
$exitCode = self::FAILURE;
}
}
}
[$localDump, $remoteDump] = $this->dumpPaths();
$this->displayCloneSummary($local, $stage);
if (! $this->confirmed($stage)) {
$this->warn('Cancelled.');
return self::SUCCESS;
}
try {
$this->runClone($local, $stage, $localDump, $remoteDump);
} catch (\Throwable $exception) {
$this->reportFailure($exception, $localDump, $remoteDump);
return self::FAILURE;
}
$this->reportSuccess($local, $stage);
return self::SUCCESS;
return $exitCode;
}
/** @return array<string, mixed> */
@@ -130,7 +127,7 @@ class DatabaseStage extends Command
{
$this->ensureDumpDirectory($localDump);
$this->createDump($local, $localDump);
$this->line(' Dump size: ' . $this->formatBytes((int) filesize($localDump)));
$this->line(' Dump size: ' . number_format((int) filesize($localDump) / 1048576, 2) . ' MB');
$this->verifyDump($localDump);
$this->uploadDump($stage, $localDump, $remoteDump);
$this->recreateStageDatabase($stage);
@@ -195,8 +192,8 @@ class DatabaseStage extends Command
private function recreateStageDatabase(array $stage): void
{
$this->components->task('Recreating stage database', function () use ($stage): bool {
$database = $this->quoteSqlIdentifier((string) $stage['database']);
$owner = $this->quoteSqlIdentifier((string) $stage['username']);
$database = '"' . str_replace('"', '""', (string) $stage['database']) . '"';
$owner = '"' . str_replace('"', '""', (string) $stage['username']) . '"';
$terminateDatabase = str_replace("'", "''", (string) $stage['database']);
$sql = "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{$terminateDatabase}' AND pid <> pg_backend_pid();\n"
. "DROP DATABASE IF EXISTS {$database};\nCREATE DATABASE {$database} WITH OWNER {$owner} ENCODING 'UTF8' TEMPLATE template0;";
@@ -291,24 +288,4 @@ class DatabaseStage extends Command
$this->components->info('Stage PostgreSQL database cloned successfully.');
$this->line("Local {$local['database']} → Stage {$stage['database']}");
}
private function quoteSqlIdentifier(string $identifier): string
{
return '"' . str_replace('"', '""', $identifier) . '"';
}
private function formatBytes(int $bytes): string
{
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max($bytes, 0);
$power = $bytes > 0
? min((int) floor(log($bytes, 1024)), count($units) - 1)
: 0;
return number_format(
$bytes / (1024 ** $power),
$power === 0 ? 0 : 2,
) . ' ' . $units[$power];
}
}
+24034
View File
File diff suppressed because it is too large Load Diff
+5 -3
View File
@@ -14,6 +14,8 @@ use Laravel\Jetstream\Http\Controllers\Inertia\UserProfileController;
use Laravel\Jetstream\Http\Controllers\TeamInvitationController;
use Laravel\Jetstream\Jetstream;
const TEAM_ROUTE = '/teams/{team}';
Route::group(['middleware' => config('jetstream.middleware', ['web'])], function () {
if (Jetstream::hasTermsAndPrivacyPolicyFeature()) {
Route::get('/terms-of-service', [TermsOfServiceController::class, 'show'])->name('terms.show');
@@ -57,9 +59,9 @@ Route::group(['middleware' => config('jetstream.middleware', ['web'])], function
if (Jetstream::hasTeamFeatures()) {
Route::get('/teams/create', [TeamController::class, 'create'])->name('teams.create');
Route::post('/teams', [TeamController::class, 'store'])->name('teams.store');
Route::get('/teams/{team}', [TeamController::class, 'show'])->name('teams.show');
Route::put('/teams/{team}', [TeamController::class, 'update'])->name('teams.update');
Route::delete('/teams/{team}', [TeamController::class, 'destroy'])->name('teams.destroy');
Route::get(TEAM_ROUTE, [TeamController::class, 'show'])->name('teams.show');
Route::put(TEAM_ROUTE, [TeamController::class, 'update'])->name('teams.update');
Route::delete(TEAM_ROUTE, [TeamController::class, 'destroy'])->name('teams.destroy');
Route::put('/current-team', [CurrentTeamController::class, 'update'])->name('current-team.update');
Route::post('/teams/{team}/members', [TeamMemberController::class, 'store'])->name('team-members.store');
Route::put('/teams/{team}/members/{user}', [TeamMemberController::class, 'update'])->name('team-members.update');
@@ -17,9 +17,6 @@ class PlatformAdministrationBrowserTest extends DuskTestCase
$admin = $this->platformAdminUser();
$this->seedPlatformDashboardData();
$companyName = 'Abbott Logistics ' . uniqid();
$billingEmail = 'billing+' . uniqid() . '@abbott.example';
$this->browse(function (Browser $browser) use ($admin): void {
$browser->loginAs($admin)
->visit('/admin');