├── .gitattributes
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── config.yml
└── workflows
│ ├── monorepo-split.yml
│ ├── monorepo-validate.yml
│ ├── php-cs-fixer.yml
│ └── tests.yml
├── .gitignore
├── .php-cs-fixer.dist.php
├── CODE_OF_CONDUCT.md
├── LICENSE.md
├── README.md
├── SECURITY.md
├── composer.json
├── monorepo-builder.php
├── packages
├── airlines-en
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── AirlinesEnServiceProvider.php
├── airlines
│ ├── composer.json
│ ├── resources
│ │ └── lang
│ │ │ └── en
│ │ │ └── validation.php
│ └── src
│ │ ├── AirlinesServiceProvider.php
│ │ ├── Models
│ │ └── Airline.php
│ │ └── Rules
│ │ └── AirlineRule.php
├── airports-en
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── AirportsEnServiceProvider.php
├── airports
│ ├── composer.json
│ ├── resources
│ │ └── lang
│ │ │ └── en
│ │ │ └── validation.php
│ └── src
│ │ ├── AirportsServiceProvider.php
│ │ ├── Models
│ │ └── Airport.php
│ │ └── Rules
│ │ └── AirportRule.php
├── continents-de
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── ContinentsDeServiceProvider.php
├── continents-en
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── ContinentsEnServiceProvider.php
├── continents-pl
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── ContinentsPlServiceProvider.php
├── continents
│ ├── composer.json
│ ├── resources
│ │ └── lang
│ │ │ └── en
│ │ │ └── validation.php
│ └── src
│ │ ├── ContinentsServiceProvider.php
│ │ ├── Models
│ │ └── Continent.php
│ │ └── Rules
│ │ └── ContinentRule.php
├── countries-de
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── CountriesDeServiceProvider.php
├── countries-en
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── CountriesEnServiceProvider.php
├── countries-es
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── CountriesEsServiceProvider.php
├── countries-fr
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── CountriesFrServiceProvider.php
├── countries-pl
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── CountriesPlServiceProvider.php
├── countries
│ ├── composer.json
│ ├── resources
│ │ └── lang
│ │ │ └── en
│ │ │ └── validation.php
│ └── src
│ │ ├── CountriesServiceProvider.php
│ │ ├── Models
│ │ └── Country.php
│ │ └── Rules
│ │ └── CountryRule.php
├── currencies-en
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── CurrenciesEnServiceProvider.php
├── currencies
│ ├── composer.json
│ ├── resources
│ │ └── lang
│ │ │ └── en
│ │ │ └── validation.php
│ └── src
│ │ ├── CurrenciesServiceProvider.php
│ │ ├── Models
│ │ └── Currency.php
│ │ └── Rules
│ │ └── CurrencyRule.php
├── gb-counties-en
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── GbCountiesEnServiceProvider.php
├── gb-counties
│ ├── composer.json
│ ├── resources
│ │ └── lang
│ │ │ └── en
│ │ │ └── validation.php
│ └── src
│ │ ├── GbCountiesServiceProvider.php
│ │ ├── Models
│ │ └── GbCounty.php
│ │ └── Rules
│ │ └── GbCountyRule.php
├── model
│ ├── composer.json
│ ├── config
│ │ └── squire.php
│ └── src
│ │ ├── Model.php
│ │ └── ModelServiceProvider.php
├── regions-en
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── RegionsEnServiceProvider.php
├── regions
│ ├── composer.json
│ ├── resources
│ │ └── lang
│ │ │ └── en
│ │ │ └── validation.php
│ └── src
│ │ ├── Models
│ │ └── Region.php
│ │ ├── RegionsServiceProvider.php
│ │ └── Rules
│ │ └── RegionRule.php
├── repository
│ ├── composer.json
│ └── src
│ │ ├── Exceptions
│ │ ├── SourceNotFoundException.php
│ │ └── TranslationNotFoundException.php
│ │ ├── Repository.php
│ │ ├── RepositoryManager.php
│ │ └── RepositoryServiceProvider.php
├── rule
│ ├── composer.json
│ └── src
│ │ └── Rule.php
├── timezones-en
│ ├── composer.json
│ ├── resources
│ │ └── data.csv
│ └── src
│ │ └── TimezonesEnServiceProvider.php
└── timezones
│ ├── composer.json
│ ├── resources
│ └── lang
│ │ └── en
│ │ └── validation.php
│ └── src
│ ├── Models
│ └── Timezone.php
│ ├── Rules
│ └── TimezoneRule.php
│ └── TimezonesServiceProvider.php
├── phpunit.xml.dist
└── tests
├── ModelTest.php
├── Models
└── Foo.php
├── RuleTest.php
├── Rules
└── FooRule.php
├── TestCase.php
├── TranslationsConsistencyTest.php
└── data
├── foo-en.csv
└── foo-es.csv
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [danharrin]
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | labels: bug
5 | assignees: DanHarrin
6 | ---
7 |
8 | **Describe the bug**
9 | A clear and concise description of what the bug is.
10 |
11 | **To reproduce**
12 | A simplified code example to demonstrate the issue you are facing.
13 |
14 | **Expected behavior**
15 | A clear and concise description of what you expected to happen.
16 |
17 | **Context**
18 | - Squire version: [e.g. 2.0.0]
19 | - Laravel version: [e.g. 8.0.0]
20 | - Server OS: [e.g. Ubuntu 18.04.4]
21 | - PHP version: [e.g. 7.4]
22 |
23 | **Additional details**
24 | Add any other details about the problem here.
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Feature request
4 | url: https://github.com/squirephp/squire/discussions/new
5 | about: For ideas or feature requests
6 | - name: Support questions & other
7 | url: https://github.com/squirephp/squire/discussions/new
8 | about: If you have a question or need help installing using the package
9 |
--------------------------------------------------------------------------------
/.github/workflows/monorepo-split.yml:
--------------------------------------------------------------------------------
1 | name: monorepo-split
2 |
3 | on:
4 | push:
5 | tags: '*'
6 |
7 | jobs:
8 | provide-packages-list:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | - uses: shivammathur/setup-php@v2
13 | with:
14 | php-version: 8.0
15 | coverage: none
16 | - uses: "ramsey/composer-install@v1"
17 | - id: packages-list
18 | run: echo "::set-output name=matrix::$(vendor/bin/monorepo-builder packages-json)"
19 | outputs:
20 | matrix: ${{ steps.packages-list.outputs.matrix }}
21 |
22 | split-monorepo:
23 | needs: provide-packages-list
24 | runs-on: ubuntu-latest
25 | strategy:
26 | fail-fast: false
27 | matrix:
28 | package: ${{fromJson(needs.provide-packages-list.outputs.matrix)}}
29 | steps:
30 | - uses: actions/checkout@v2
31 | - id: previous-tag
32 | uses: "WyriHaximus/github-action-get-previous-tag@master"
33 | - name: Monorepo Split of ${{ matrix.package }}
34 | uses: symplify/github-action-monorepo-split@main
35 | env:
36 | GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
37 | with:
38 | package_directory: 'packages/${{ matrix.package }}'
39 | repository_organization: 'squirephp'
40 | repository_name: '${{ matrix.package }}'
41 | branch: 3.x
42 | tag: ${{ steps.previous-tag.outputs.tag }}
43 | user_name: "Dan Harrin"
44 | user_email: "dan@danharrin.com"
45 |
--------------------------------------------------------------------------------
/.github/workflows/monorepo-validate.yml:
--------------------------------------------------------------------------------
1 | name: monorepo-validate
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | jobs:
8 | run-validation:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 | - name: Cache dependencies
13 | uses: actions/cache@v2
14 | with:
15 | path: vendor
16 | key: composer-${{ hashFiles('composer.lock') }}
17 | - name: Setup PHP
18 | uses: shivammathur/setup-php@v2
19 | with:
20 | php-version: 8.1
21 | extensions: mbstring, pdo, pdo_sqlite
22 | coverage: none
23 | - name: Install dependencies
24 | run: composer install -n --prefer-dist
25 | - name: Validate Dependencies are consistent
26 | run: vendor/bin/monorepo-builder validate
--------------------------------------------------------------------------------
/.github/workflows/php-cs-fixer.yml:
--------------------------------------------------------------------------------
1 | name: php-cs-fixer
2 |
3 | on: push
4 |
5 | jobs:
6 | php-cs-fixer:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - name: Checkout code
10 | uses: actions/checkout@v2
11 | with:
12 | ref: ${{ github.head_ref }}
13 | - name: Run PHP CS Fixer
14 | uses: docker://oskarstark/php-cs-fixer-ga
15 | with:
16 | args: --config=.php-cs-fixer.dist.php --allow-risky=yes
17 | - name: Commit changes
18 | uses: stefanzweifel/git-auto-commit-action@v4
19 | with:
20 | commit_message: >
21 | chore: styling
22 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: tests
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | jobs:
8 | run-tests:
9 | runs-on: ubuntu-latest
10 | strategy:
11 | fail-fast: false
12 | matrix:
13 | php: [8.2, 8.1, 8.0]
14 | laravel: [12.*, 11.*, 10.*, 9.*, 8.*]
15 | dependency-version: [prefer-lowest, prefer-stable]
16 | include:
17 | - laravel: 12.*
18 | testbench: 10.*
19 | - laravel: 11.*
20 | testbench: 9.*
21 | - laravel: 10.*
22 | testbench: 8.*
23 | - laravel: 9.*
24 | testbench: 7.*
25 | - laravel: 8.*
26 | testbench: ^6.23
27 | exclude:
28 | - laravel: 12.*
29 | php: 8.1
30 | - laravel: 12.*
31 | php: 8.0
32 | - laravel: 11.*
33 | php: 8.1
34 | - laravel: 11.*
35 | php: 8.0
36 | - laravel: 10.*
37 | php: 8.0
38 | name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }}
39 | steps:
40 | - uses: actions/checkout@v2
41 | - name: Cache dependencies
42 | uses: actions/cache@v2
43 | with:
44 | path: ~/.composer/cache/files
45 | key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
46 | - name: Setup PHP
47 | uses: shivammathur/setup-php@v2
48 | with:
49 | php-version: ${{ matrix.php }}
50 | extensions: mbstring, pdo, pdo_sqlite
51 | coverage: none
52 | - name: Install dependencies
53 | run: |
54 | composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
55 | composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest
56 | - name: Execute tests
57 | run: vendor/bin/phpunit
58 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | .phpunit.result.cache
3 | .php-cs-fixer.cache
4 | composer.lock
5 |
--------------------------------------------------------------------------------
/.php-cs-fixer.dist.php:
--------------------------------------------------------------------------------
1 | in([
5 | __DIR__ . '/packages',
6 | __DIR__ . '/tests',
7 | ])
8 | ->name('*.php')
9 | ->notName('*.blade.php')
10 | ->ignoreDotFiles(true)
11 | ->ignoreVCS(true);
12 |
13 | return (new PhpCsFixer\Config())
14 | ->setRules([
15 | '@PSR12' => true,
16 | 'array_syntax' => ['syntax' => 'short'],
17 | 'ordered_imports' => ['sort_algorithm' => 'alpha'],
18 | 'no_unused_imports' => true,
19 | 'not_operator_with_successor_space' => true,
20 | 'trailing_comma_in_multiline' => true,
21 | 'phpdoc_scalar' => true,
22 | 'unary_operator_spaces' => true,
23 | 'binary_operator_spaces' => true,
24 | 'blank_line_before_statement' => [
25 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'],
26 | ],
27 | 'phpdoc_single_line_var_spacing' => true,
28 | 'phpdoc_var_without_name' => true,
29 | 'class_attributes_separation' => [
30 | 'elements' => [
31 | 'method' => 'one',
32 | ],
33 | ],
34 | 'method_argument_space' => [
35 | 'on_multiline' => 'ensure_fully_multiline',
36 | 'keep_multiple_spaces_after_comma' => true,
37 | ],
38 | 'single_trait_insert_per_statement' => true,
39 | ])
40 | ->setFinder($finder);
41 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting Dan Harrin at dan@danharrin.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) Squire
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Squire is a library of static Eloquent models for fixture data that is commonly needed in web applications, such as countries, currencies and airports. It's based on the concepts of [Caleb Porzio's Sushi package](https://github.com/calebporzio/sushi).
12 |
13 | Common use cases for Squire include:
14 | - Populating dropdown options, such as a country selector on an address form.
15 | - Attaching extra data to other models in your app, such as airport information to a `Flight` model. See the section on [model relationships](#model-relationships).
16 | - [Validating user input.](#validation)
17 |
18 | ## Contents
19 |
20 | - [Installing a Model](#installing-a-model)
21 | - [Using a Model](#using-a-model)
22 | - [Available Models](#available-models)
23 | - [`Squire\Models\Airline`](#squiremodelsairline)
24 | - [`Squire\Models\Airport`](#squiremodelsairport)
25 | - [`Squire\Models\Continent`](#squiremodelscontinent)
26 | - [`Squire\Models\Country`](#squiremodelscountry)
27 | - [`Squire\Models\Currency`](#squiremodelscurrency)
28 | - [Formatting money](#formatting-money)
29 | - [`Squire\Models\GbCounty`](#squiremodelsgbcounty)
30 | - [`Squire\Models\Region`](#squiremodelsregion)
31 | - [`Squire\Models\Timezone`](#squiremodelstimezone)
32 | - [Model Relationships](#model-relationships)
33 | - [Validation](#validation)
34 | - [Creating your own Models](#creating-your-own-models)
35 | - [Adding a localization](#adding-a-localization)
36 | - [Upgrading from 1.x](#upgrading-from-1x)
37 | - [Need Help?](#need-help)
38 |
39 | ## Installing a Model
40 |
41 | You can use Composer to install Squire models into your application. Each model is available in a variety of languages, and you need only install the ones you will use.
42 |
43 | As an example, you can install the `Squire\Models\Country` model in English:
44 |
45 | ```
46 | composer require squirephp/countries-en
47 | ```
48 |
49 | **A complete list of [available models](#available-models) is below.**
50 |
51 | ## Using a Model
52 |
53 | You can interact with a Squire model just like you would any other Eloquent model, except that it only handles read-only operations.
54 |
55 | ```php
56 | use Squire\Models\Country;
57 |
58 | Country::all(); // Get information about all countries.
59 |
60 | Country::find('us'); // Get information about the United States.
61 |
62 | Country::where('name', 'like', 'a%')->get(); // Get information about all countries beginning with the letter "a".
63 | ```
64 |
65 | ## Available Models
66 |
67 | ### `Squire\Models\Airline`
68 |
69 | #### Installation
70 |
71 | | Locale | Installation Command |
72 | |--|--|
73 | | English | `composer require squirephp/airlines-en` |
74 |
75 | #### Schema
76 |
77 | | Column Name | Description | Example |
78 | |--|--|--|
79 | | `alias` | Alternative name of the airline. | `EasyJet Airline` |
80 | | `call_sign` | Call sign of the airline. | `EASY` |
81 | | `code_iata` | [IATA code](https://en.wikipedia.org/wiki/List_of_airline_codes) of the airline. | `u2` |
82 | | `code_icao` | [ICAO code](https://en.wikipedia.org/wiki/List_of_airline_codes) of the airline. |`ezy` |
83 | | `country_id` | [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) of the airline. | `gb` |
84 | | `name` | Name of the airline. | `easyJet` |
85 |
86 | #### Relationships
87 |
88 | | Relationship name | Model |
89 | |--|--|
90 | | `country` | [`Squire\Models\Country`](#squiremodelscountry) |
91 | | `continent` | [`Squire\Models\Continent`](#squiremodelscontinent) |
92 |
93 |
94 | ### `Squire\Models\Airport`
95 |
96 | #### Installation
97 |
98 | | Locale | Installation Command |
99 | |--|--|
100 | | English | `composer require squirephp/airports-en` |
101 |
102 | #### Schema
103 |
104 | | Column Name | Description | Example |
105 | |--|--|--|
106 | | `code_iata` | [IATA code](https://en.wikipedia.org/wiki/IATA_airport_code) of the airport. | `lhr` |
107 | | `code_icao` | [ICAO code](https://en.wikipedia.org/wiki/ICAO_airport_code) of the airport. |`egll` |
108 | | `country_id` | [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) of the airport. | `gb` |
109 | | `municipality` | Municipality of the airport. | `London` |
110 | | `name` | Name of the airport. | `London Heathrow Airport` |
111 | | `timezone_id` | [PHP timezone identifier](https://www.php.net/manual/en/timezones.php) of the airport. | `Europe/London` |
112 |
113 | #### Relationships
114 |
115 | | Relationship name | Model |
116 | |--|--|
117 | | `country` | [`Squire\Models\Country`](#squiremodelscountry) |
118 | | `timezone` | [`Squire\Models\Timezone`](#squiremodelstimezone) |
119 |
120 | ### `Squire\Models\Continent`
121 |
122 | #### Installation
123 |
124 | | Locale | Installation Command |
125 | | ------- | -------------------------------------------------- |
126 | | German | `composer require squirephp/continents-de` |
127 | | English | `composer require squirephp/continents-en` |
128 | | Polish | `composer require squirephp/continents-pl` |
129 | | Italian | `composer require squirephp-italian/continents-it` |
130 |
131 | #### Schema
132 |
133 | | Column Name | Description | Example |
134 | |--|--|--|
135 | | `code` | Two letter continent code. | `na` |
136 | | `name` | Continent name. | `North America` |
137 |
138 | #### Relationships
139 |
140 | | Relationship name | Model |
141 | |--|--|
142 | | `countries` | [`Squire\Models\Country`](#squiremodelscountry) |
143 | | `regions` | [`Squire\Models\Region`](#squiremodelsregion) |
144 | | `timezones` | [`Squire\Models\Timezone`](#squiremodelstimezone) |
145 |
146 | ### `Squire\Models\Country`
147 |
148 | #### Installation
149 |
150 | | Locale | Installation Command |
151 | | ------- | ------------------------------------------------------- |
152 | | English | `composer require squirephp/countries-en` |
153 | | French | `composer require squirephp/countries-fr` |
154 | | German | `composer require squirephp/countries-de` |
155 | | Polish | `composer require squirephp/countries-pl` |
156 | | Spanish | `composer require squirephp/countries-es` |
157 | | Dutch | `composer require quickstreambe/squirephp-countries-nl` |
158 | | Italian | `composer require squirephp-italian/countries-it` |
159 |
160 | #### Schema
161 |
162 | | Column Name | Description | Example |
163 | |--|--|--|
164 | | `calling_code` | [E.164](https://en.wikipedia.org/wiki/E.164) country calling code. | `1` |
165 | | `capital_city` | Capital city of the country. | `Washington` |
166 | | `code_2` | [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). | `us` |
167 | | `code_3` | [ISO 3166-1 alpha-3 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3). | `usa` |
168 | | `continent_id` | Two letter continent code of the country. | `na` |
169 | | `currency_id` | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) alphabetic currency code of the country. | `usd` |
170 | | `flag` | Unicode flag of the country. | `🇺🇸` |
171 | | `name` | Country name. | `United States` |
172 |
173 | #### Relationships
174 |
175 | | Relationship name | Model |
176 | |--|--|
177 | | `airlines` | [`Squire\Models\Airline`](#squiremodelsairline) |
178 | | `airports` | [`Squire\Models\Airport`](#squiremodelsairport) |
179 | | `continent` | [`Squire\Models\Continent`](#squiremodelscontinent) |
180 | | `currency` | [`Squire\Models\Currency`](#squiremodelscurrency) |
181 | | `regions` | [`Squire\Models\Region`](#squiremodelsregion) |
182 | | `timezones` | [`Squire\Models\Timezone`](#squiremodelstimezone) |
183 |
184 | ### `Squire\Models\Currency`
185 |
186 | #### Installation
187 |
188 | | Locale | Installation Command |
189 | |--|--|
190 | | English | `composer require squirephp/currencies-en` |
191 |
192 | #### Schema
193 |
194 | | Column Name | Description | Example |
195 | |--|--|--|
196 | | `code_alphabetic` | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) alphabetic currency code. | `usd` |
197 | | `code_numeric` | [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) numeric currency code. | `840` |
198 | | `decimal_digits` | Number of decimal digits to use when formatting this currency. | `2` |
199 | | `name` | Currency name. | `US Dollar` |
200 | | `name_plural` | Plural currency name. | `US Dollars` |
201 | | `rounding` | The formatting precison of this currency. | `0` |
202 | | `symbol` | International currency symbol. | `$` |
203 | | `symbol_native` | Native currency symbol. | `$` |
204 |
205 | #### Relationships
206 |
207 | | Relationship name | Model |
208 | |--|--|
209 | | `countries` | [`Squire\Models\Country`](#squiremodelscountry) |
210 |
211 | #### Formatting money
212 |
213 | You may use the `format()` method on any currency model instance to format a given number in that currency:
214 |
215 | ```php
216 | Currency::find('usd')->format(500) // $5.00
217 | Currency::find('usd')->format(500, true) // $500.00, converted
218 | ```
219 |
220 | This functionality uses [`akaunting/laravel-money`](https://github.com/akaunting/laravel-money) internally.
221 |
222 | ### `Squire\Models\GbCounty`
223 |
224 | #### Installation
225 |
226 | | Locale | Installation Command |
227 | |--|--|
228 | | English | `composer require squirephp/gb-counties-en` |
229 |
230 | #### Schema
231 |
232 | | Column Name | Description | Example |
233 | |--|--|--|
234 | | `code` | [ISO 3166-2 county code](https://en.wikipedia.org/wiki/ISO_3166-2). | `gb-ess` |
235 | | `name` | County name. | `Essex` |
236 | | `region_id` | [ISO 3166-2 region code](https://en.wikipedia.org/wiki/ISO_3166-2) of the county. | `gb-eng` |
237 |
238 | #### Relationships
239 |
240 | | Relationship name | Model |
241 | |--|--|
242 | | `region` | [`Squire\Models\Region`](#squiremodelsregion) |
243 |
244 | ### `Squire\Models\Region`
245 |
246 | #### Installation
247 |
248 | | Locale | Installation Command |
249 | |--|--|
250 | | English | `composer require squirephp/regions-en` |
251 |
252 | #### Schema
253 |
254 | | Column Name | Description | Example |
255 | |--|--|--|
256 | | `code` | [ISO 3166-2 region code](https://en.wikipedia.org/wiki/ISO_3166-2). | `us-ny` |
257 | | `country_id` | [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). | `us` |
258 | | `name` | Region name. | `New York` |
259 |
260 | #### Relationships
261 |
262 | | Relationship name | Model |
263 | |--|--|
264 | | `continent` | [`Squire\Models\Continent`](#squiremodelscontinent) |
265 | | `country` | [`Squire\Models\Country`](#squiremodelscountry) |
266 | | `gbCounties` | [`Squire\Models\GbCounty`](#squiremodelsgbcounty) |
267 |
268 | ### `Squire\Models\Timezone`
269 |
270 | #### Installation
271 |
272 | | Locale | Installation Command |
273 | |--|--|
274 | | English | `composer require squirephp/timezones-en` |
275 |
276 | #### Schema
277 |
278 | | Column Name | Description | Example |
279 | |--|--|--|
280 | | `code` | [PHP timezone identifier](https://www.php.net/manual/en/timezones.php). | `America/New_York` |
281 | | `country_id` | [ISO 3166-1 alpha-2 country code](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2). | `us` |
282 | | `long_name` | Full timezone name. | `America/New York` |
283 | | `name` | Short timezone name. | `New York` |
284 |
285 | #### Relationships
286 |
287 | | Relationship name | Model |
288 | |--|--|
289 | | `airports` | [`Squire\Models\Airport`](#squiremodelsairport) |
290 | | `continent` | [`Squire\Models\Continent`](#squiremodelscontinent) |
291 | | `country` | [`Squire\Models\Country`](#squiremodelscountry) |
292 |
293 | #### Methods
294 |
295 | | Method name | Description |
296 | |--|--|
297 | | `getOffset($dateTime)` | Returns the timezone offset from GMT. |
298 |
299 | ## Model Relationships
300 |
301 | Implementing an Eloquent relationship between a model in your app and a Squire model is very simple. There are a couple of approaches you could take.
302 |
303 | ### Using Inheritance
304 |
305 | The simplest option is to create a new model in your app, and let it extend the Squire model. Your new app model will now behave like the original Squire model, except you can register new methods and customise it to your liking:
306 |
307 | ```php
308 | hasMany(User::class);
320 | }
321 | }
322 | ```
323 |
324 | ### Using `resolveRelationUsing()`
325 |
326 | Another option is the `resolveRelationUsing()` method. This allows you to dynamically register a relationship for a Squire model from anywhere in your app, for example, within a service provider:
327 |
328 | ```php
329 | use App\Models\User;
330 | use Illuminate\Database\Eloquent\Relations\HasMany;
331 | use Squire\Models\Country;
332 |
333 | Country::resolveRelationUsing('users', function (Country $country): HasMany {
334 | return $country->hasMany(User::class);
335 | });
336 | ```
337 |
338 | ## Validation
339 |
340 | Squire includes a validation rule for each model installed in your app. These allow you to easily validate user input to ensure that it matches a record in a specific model.
341 |
342 | Rules can be found in the `Squire\Rules` namespace. To use one, simply construct a new rule class and pass in the model column name that you would like to validate against:
343 |
344 | ```php
345 | use Squire\Rules;
346 |
347 | $request->validate([
348 | 'country' => ['required', 'string', new Rules\CountryRule('name')],
349 | ]);
350 | ```
351 |
352 | This code will validate the `country` input against the `name` column on the [`Squire\Models\Country` model](#squiremodelscountry). If the user enters a country that does not exist, a validation error will be thrown.
353 |
354 | ## Creating your own Models
355 |
356 | Squire may not always have a model available for the information you require. In this case, you may want to create your own.
357 |
358 | ### Creating a Model
359 |
360 | Squire models are very simple classes that extend `Squire\Model`. Install it with:
361 |
362 | ```
363 | composer require squirephp/model
364 | ```
365 |
366 | Your model class should contain a single static property, `$schema`. This contains the column structure for your model, and should match the format of the source data.
367 |
368 | ```php
369 | 'string',
379 | 'name' => 'string',
380 | ];
381 | }
382 | ```
383 |
384 | ### Attaching a Model Source
385 |
386 | Your model will require at least one data source to be registered. Each registered data source is associated with a locale. To register a data source, you will need to interact with `Squire\Repository`. Install it with:
387 |
388 | ```
389 | composer require squirephp/repository
390 | ```
391 |
392 | Inside a service provider, register an English source for your model:
393 |
394 | ```php
395 | validate([
490 | 'country' => ['required', 'string', new CountryRule('name')],
491 | ]);
492 | ```
493 |
494 | 3.x:
495 |
496 | ```php
497 | use Squire\Models\Country;
498 | use Squire\Rules\CountryRule;
499 |
500 | Country::find('us');
501 |
502 | $request->validate([
503 | 'country' => ['required', 'string', new CountryRule('name')],
504 | ]);
505 | ```
506 |
507 | All properties and methods in [custom models](#creating-a-model) and [custom validation rules](#creating-a-validation-rule) now need to have the correct types. These can be found in the relevant section of the documentation.
508 |
509 | ### Breaking Changes Introduced in 3.x
510 |
511 | - The minimum PHP version has been bumped to v8.0, and the minimum Laravel version to v8.x.
512 | - Validation rules have been renamed, so they all end with `Rule`. This allows both the model and rule to be imported into the same class without the use of aliasing.
513 | - Types have been introduced to all classes. If you have created [custom models](#creating-a-model) and [custom validation rules](#creating-a-validation-rule), properties and methods now need to use the correct types.
514 | - The primary key of airports is now their ICAO code. The region relationship has been removed and replaced with country. The local code has been removed.
515 | - Empty string values are now null.
516 |
517 | ## Need Help?
518 |
519 | 🐞 If you spot a bug with this package, please [submit a detailed issue](https://github.com/squirephp/squire/issues/new), and wait for assistance.
520 |
521 | 🤔 If you have a question or feature request, please [start a new discussion](https://github.com/squirephp/squire/discussions/new).
522 |
523 | 🔐 If you discover a vulnerability within the package, please review our [security policy](https://github.com/squirephp/squire/blob/main/SECURITY.md).
524 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | | Version | Supported |
6 | | ------- | ------------------ |
7 | | 3.x | :white_check_mark: |
8 | | 2.x | :white_check_mark: |
9 | | 1.x | :white_check_mark: |
10 |
11 | ## Reporting a Vulnerability
12 |
13 | If you discover a security vulnerability within Squire, please email Dan Harrin via [dan@danharrin.com](mailto:dan@danharrin.com). All security vulnerabilities will be promptly addressed.
14 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "squirephp/squire",
3 | "authors": [
4 | {
5 | "name": "Dan Harrin",
6 | "email": "dan@danharrin.com"
7 | },
8 | {
9 | "name": "Krzysztof Rewak",
10 | "email": "krzysztof.rewak@gmail.com"
11 | }
12 | ],
13 | "require": {
14 | "akaunting/laravel-money": "^1.2|^2.1|^3.0|^4.0|^5.1|^6.0",
15 | "ext-pdo_sqlite": "*",
16 | "illuminate/contracts": "^8.0|^9.0|^10.0|^11.0|^12.0",
17 | "illuminate/database": "^8.40|^9.0|^10.0|^11.0|^12.0",
18 | "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0",
19 | "php": "^8.0"
20 | },
21 | "require-dev": {
22 | "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0",
23 | "phpunit/phpunit": "^9.4|^10.0|^11.0",
24 | "symplify/monorepo-builder": "^9.4.21"
25 | },
26 | "autoload": {
27 | "psr-4": {
28 | "Squire\\": [
29 | "packages/airlines-en/src",
30 | "packages/airlines/src",
31 | "packages/airports-en/src",
32 | "packages/airports/src",
33 | "packages/continents-de/src",
34 | "packages/continents-en/src",
35 | "packages/continents-pl/src",
36 | "packages/continents/src",
37 | "packages/countries-de/src",
38 | "packages/countries-en/src",
39 | "packages/countries-es/src",
40 | "packages/countries-fr/src",
41 | "packages/countries-pl/src",
42 | "packages/countries/src",
43 | "packages/currencies-en/src",
44 | "packages/currencies/src",
45 | "packages/gb-counties-en/src",
46 | "packages/gb-counties/src",
47 | "packages/model/src",
48 | "packages/regions-en/src",
49 | "packages/regions/src",
50 | "packages/repository/src",
51 | "packages/rule/src",
52 | "packages/timezones-en/src",
53 | "packages/timezones/src"
54 | ]
55 | }
56 | },
57 | "autoload-dev": {
58 | "psr-4": {
59 | "Squire\\Tests\\": "tests"
60 | }
61 | },
62 | "extra": {
63 | "laravel": {
64 | "providers": [
65 | "Squire\\GbCountiesServiceProvider",
66 | "Squire\\ContinentsEnServiceProvider",
67 | "Squire\\AirportsServiceProvider",
68 | "Squire\\CountriesDeServiceProvider",
69 | "Squire\\AirlinesServiceProvider",
70 | "Squire\\CountriesServiceProvider",
71 | "Squire\\RegionsEnServiceProvider",
72 | "Squire\\ModelServiceProvider",
73 | "Squire\\GbCountiesEnServiceProvider",
74 | "Squire\\AirlinesEnServiceProvider",
75 | "Squire\\CountriesEnServiceProvider",
76 | "Squire\\ContinentsDeServiceProvider",
77 | "Squire\\CountriesFrServiceProvider",
78 | "Squire\\CountriesEsServiceProvider",
79 | "Squire\\TimezonesEnServiceProvider",
80 | "Squire\\CountriesPlServiceProvider",
81 | "Squire\\TimezonesServiceProvider",
82 | "Squire\\ContinentsServiceProvider",
83 | "Squire\\AirportsEnServiceProvider",
84 | "Squire\\CurrenciesEnServiceProvider",
85 | "Squire\\ContinentsPlServiceProvider",
86 | "Squire\\CurrenciesServiceProvider",
87 | "Squire\\RegionsServiceProvider",
88 | "Squire\\RepositoryServiceProvider"
89 | ],
90 | "aliases": {
91 | "RepositoryManager": "Squire\\Repository\\Facades\\Repository"
92 | }
93 | }
94 | },
95 | "replace": {
96 | "squirephp/airlines": "self.version",
97 | "squirephp/airlines-en": "self.version",
98 | "squirephp/airports": "self.version",
99 | "squirephp/airports-en": "self.version",
100 | "squirephp/continents": "self.version",
101 | "squirephp/continents-de": "self.version",
102 | "squirephp/continents-en": "self.version",
103 | "squirephp/continents-pl": "self.version",
104 | "squirephp/countries": "self.version",
105 | "squirephp/countries-de": "self.version",
106 | "squirephp/countries-en": "self.version",
107 | "squirephp/countries-es": "self.version",
108 | "squirephp/countries-fr": "self.version",
109 | "squirephp/countries-pl": "self.version",
110 | "squirephp/currencies": "self.version",
111 | "squirephp/currencies-en": "self.version",
112 | "squirephp/gb-counties": "self.version",
113 | "squirephp/gb-counties-en": "self.version",
114 | "squirephp/model": "self.version",
115 | "squirephp/regions": "self.version",
116 | "squirephp/regions-en": "self.version",
117 | "squirephp/repository": "self.version",
118 | "squirephp/rule": "self.version",
119 | "squirephp/timezones": "self.version",
120 | "squirephp/timezones-en": "self.version"
121 | },
122 | "minimum-stability": "dev",
123 | "prefer-stable": true
124 | }
125 |
--------------------------------------------------------------------------------
/monorepo-builder.php:
--------------------------------------------------------------------------------
1 | parameters();
15 |
16 | $parameters->set(Option::DATA_TO_APPEND, [
17 | 'autoload-dev' => [
18 | 'psr-4' => [
19 | 'Squire\Tests\\' => 'tests',
20 | ],
21 | ],
22 | 'require-dev' => [
23 | 'orchestra/testbench' => '^6.23|^7.0|^8.0|^9.0|^10.0',
24 | 'phpunit/phpunit' => '^9.4|^10.0|^11.0',
25 | 'symplify/monorepo-builder' => '^9.4.21',
26 | ],
27 | 'minimum-stability' => 'dev',
28 | 'prefer-stable' => true
29 | ]);
30 |
31 | $parameters->set(Option::DATA_TO_REMOVE, [
32 | 'minimum-stability' => '*',
33 | ]);
34 |
35 | $services = $containerConfigurator->services();
36 |
37 | # Release workers - in order to execute
38 | $services->set(UpdateReplaceReleaseWorker::class);
39 | $services->set(SetCurrentMutualDependenciesReleaseWorker::class);
40 | $services->set(TagVersionReleaseWorker::class);
41 | $services->set(PushTagReleaseWorker::class);
42 | $services->set(SetNextMutualDependenciesReleaseWorker::class);
43 | $services->set(UpdateBranchAliasReleaseWorker::class);
44 | $services->set(PushNextDevReleaseWorker::class);
45 | };
--------------------------------------------------------------------------------
/packages/airlines-en/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "squirephp/airlines-en",
3 | "description": "A library containing the English translation of Squire's Airline model.",
4 | "keywords": [
5 | "squire"
6 | ],
7 | "license": "MIT",
8 | "homepage": "https://github.com/squirephp",
9 | "support": {
10 | "issues": "https://github.com/squirephp/squire/issues",
11 | "source": "https://github.com/squirephp/squire"
12 | },
13 | "authors": [
14 | {
15 | "name": "Dan Harrin",
16 | "email": "dan@danharrin.com"
17 | }
18 | ],
19 | "require": {
20 | "php": "^8.0",
21 | "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0",
22 | "squirephp/airlines": "self.version",
23 | "squirephp/repository": "self.version"
24 | },
25 | "autoload": {
26 | "psr-4": {
27 | "Squire\\": "src"
28 | }
29 | },
30 | "extra": {
31 | "laravel": {
32 | "providers": [
33 | "Squire\\AirlinesEnServiceProvider"
34 | ]
35 | }
36 | },
37 | "config": {
38 | "sort-packages": true
39 | },
40 | "minimum-stability": "dev"
41 | }
42 |
--------------------------------------------------------------------------------
/packages/airlines-en/src/AirlinesEnServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'The selected :attribute is an invalid airline.',
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/packages/airlines/src/AirlinesServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadTranslationsFrom(__DIR__ . '/../resources/lang', 'squire-airlines');
12 |
13 | $this->publishes([
14 | __DIR__ . '/../resources/lang' => resource_path('lang/vendor/squire-airlines'),
15 | ]);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/airlines/src/Models/Airline.php:
--------------------------------------------------------------------------------
1 | 'string',
13 | 'alias' => 'string',
14 | 'call_sign' => 'string',
15 | 'code_iata' => 'string',
16 | 'code_icao' => 'string',
17 | 'country_id' => 'string',
18 | 'name' => 'string',
19 | ];
20 |
21 | public function country(): BelongsTo
22 | {
23 | return $this->belongsTo(Country::class);
24 | }
25 |
26 | public function continent(): HasOneThrough
27 | {
28 | return $this->hasOneThrough(Continent::class, Country::class);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/airlines/src/Rules/AirlineRule.php:
--------------------------------------------------------------------------------
1 | 'The selected :attribute is an invalid airport.',
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/packages/airports/src/AirportsServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadTranslationsFrom(__DIR__ . '/../resources/lang', 'squire-airports');
12 |
13 | $this->publishes([
14 | __DIR__ . '/../resources/lang' => resource_path('lang/vendor/squire-airports'),
15 | ]);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/airports/src/Models/Airport.php:
--------------------------------------------------------------------------------
1 | 'string',
12 | 'code_iata' => 'string',
13 | 'code_icao' => 'string',
14 | 'country_id' => 'string',
15 | 'municipality' => 'string',
16 | 'name' => 'string',
17 | 'timezone_id' => 'string',
18 | ];
19 |
20 | public function country(): BelongsTo
21 | {
22 | return $this->belongsTo(Country::class);
23 | }
24 |
25 | public function timezone(): BelongsTo
26 | {
27 | return $this->belongsTo(Timezone::class);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/packages/airports/src/Rules/AirportRule.php:
--------------------------------------------------------------------------------
1 | 'The selected :attribute is an invalid continent.',
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/packages/continents/src/ContinentsServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadTranslationsFrom(__DIR__ . '/../resources/lang', 'squire-continents');
12 |
13 | $this->publishes([
14 | __DIR__ . '/../resources/lang' => resource_path('lang/vendor/squire-continents'),
15 | ]);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/continents/src/Models/Continent.php:
--------------------------------------------------------------------------------
1 | 'string',
13 | 'code' => 'string',
14 | 'name' => 'string',
15 | ];
16 |
17 | public function countries(): HasMany
18 | {
19 | return $this->hasMany(Country::class);
20 | }
21 |
22 | public function regions(): HasManyThrough
23 | {
24 | return $this->hasManyThrough(Region::class, Country::class);
25 | }
26 |
27 | public function timezones(): HasManyThrough
28 | {
29 | return $this->hasManyThrough(Timezone::class, Country::class);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/packages/continents/src/Rules/ContinentRule.php:
--------------------------------------------------------------------------------
1 | 'The selected :attribute is an invalid country.',
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/packages/countries/src/CountriesServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadTranslationsFrom(__DIR__ . '/../resources/lang', 'squire-countries');
12 |
13 | $this->publishes([
14 | __DIR__ . '/../resources/lang' => resource_path('lang/vendor/squire-countries'),
15 | ]);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/countries/src/Models/Country.php:
--------------------------------------------------------------------------------
1 | 'string',
13 | 'calling_code' => 'string',
14 | 'capital_city' => 'string',
15 | 'code_2' => 'string',
16 | 'code_3' => 'string',
17 | 'continent_id' => 'string',
18 | 'currency_id' => 'string',
19 | 'flag' => 'string',
20 | 'name' => 'string',
21 | ];
22 |
23 | public function airlines(): HasMany
24 | {
25 | return $this->hasMany(Airline::class);
26 | }
27 |
28 | public function airports(): HasMany
29 | {
30 | return $this->hasMany(Airport::class);
31 | }
32 |
33 | public function continent(): BelongsTo
34 | {
35 | return $this->belongsTo(Continent::class);
36 | }
37 |
38 | public function currency(): BelongsTo
39 | {
40 | return $this->belongsTo(Currency::class);
41 | }
42 |
43 | public function regions(): HasMany
44 | {
45 | return $this->hasMany(Region::class);
46 | }
47 |
48 | public function timezones(): HasMany
49 | {
50 | return $this->hasMany(Timezone::class);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/packages/countries/src/Rules/CountryRule.php:
--------------------------------------------------------------------------------
1 | 'The selected :attribute is an invalid currency.',
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/packages/currencies/src/CurrenciesServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadTranslationsFrom(__DIR__ . '/../resources/lang', 'squire-currencies');
12 |
13 | $this->publishes([
14 | __DIR__ . '/../resources/lang' => resource_path('lang/vendor/squire-currencies'),
15 | ]);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/currencies/src/Models/Currency.php:
--------------------------------------------------------------------------------
1 | 'string',
13 | 'code_alphabetic' => 'string',
14 | 'code_numeric' => 'integer',
15 | 'decimal_digits' => 'integer',
16 | 'name' => 'string',
17 | 'name_plural' => 'string',
18 | 'rounding' => 'integer',
19 | 'symbol' => 'string',
20 | 'symbol_native' => 'string',
21 | ];
22 |
23 | public function countries(): HasMany
24 | {
25 | return $this->hasMany(Country::class);
26 | }
27 |
28 | public function format(float $number, bool $shouldConvert = false): string
29 | {
30 | return (new Money\Money(
31 | $number,
32 | (new Money\Currency(strtoupper($this->id))),
33 | $shouldConvert
34 | ))->format();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/packages/currencies/src/Rules/CurrencyRule.php:
--------------------------------------------------------------------------------
1 | 'The selected :attribute is an invalid county.',
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/packages/gb-counties/src/GbCountiesServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadTranslationsFrom(__DIR__ . '/../resources/lang', 'squire-gb-counties');
12 |
13 | $this->publishes([
14 | __DIR__ . '/../resources/lang' => resource_path('lang/vendor/squire-gb-counties'),
15 | ]);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/gb-counties/src/Models/GbCounty.php:
--------------------------------------------------------------------------------
1 | 'string',
12 | 'code' => 'string',
13 | 'name' => 'string',
14 | 'region_id' => 'string',
15 | ];
16 |
17 | public function region(): BelongsTo
18 | {
19 | return $this->belongsTo(Region::class);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/gb-counties/src/Rules/GbCountyRule.php:
--------------------------------------------------------------------------------
1 | storage_path('framework/cache'),
6 |
7 | 'cache-prefix' => 'squire',
8 |
9 | ];
10 |
--------------------------------------------------------------------------------
/packages/model/src/Model.php:
--------------------------------------------------------------------------------
1 | getFileName());
80 | }
81 |
82 | protected static function getSourceUpdatedAt(?string $locale = null): int
83 | {
84 | return filemtime(Repository::getSource(static::class, $locale));
85 | }
86 |
87 | protected static function setSqliteConnection(string $database): void
88 | {
89 | static::$sqliteConnections[static::class] = app(ConnectionFactory::class)->make([
90 | 'driver' => 'sqlite',
91 | 'database' => $database,
92 | ]);
93 | }
94 |
95 | protected static function isCacheable(): bool
96 | {
97 | $cacheDirectory = static::getCacheDirectory();
98 |
99 | return file_exists($cacheDirectory) && is_writable($cacheDirectory);
100 | }
101 |
102 | public static function cache(array $locales = [])
103 | {
104 | if (! count($locales)) {
105 | $locales = array_keys(Repository::getSources(static::class));
106 | }
107 |
108 | collect($locales)
109 | ->filter(fn (string $locale): bool => Repository::sourceIsRegistered(static::class, $locale))
110 | ->each(function (string $locale): void {
111 | $cachePath = static::getCachePath($locale);
112 |
113 | file_put_contents($cachePath, '');
114 |
115 | static::setSqliteConnection($cachePath);
116 |
117 | static::migrate($locale);
118 |
119 | $modelUpdatedAt = static::getModelUpdatedAt();
120 | $sourceUpdatedAt = static::getSourceUpdatedAt($locale);
121 |
122 | touch($cachePath, $modelUpdatedAt >= $sourceUpdatedAt ? $modelUpdatedAt : $sourceUpdatedAt);
123 | });
124 | }
125 |
126 | public static function migrate(?string $locale = null): void
127 | {
128 | $tableName = (new static())->getTable();
129 |
130 | static::resolveConnection()->getSchemaBuilder()->create($tableName, function (Blueprint $table): void {
131 | foreach (static::$schema as $name => $type) {
132 | $table->{$type}($name)->nullable();
133 | }
134 | });
135 |
136 | $data = collect(Repository::fetchData(static::class));
137 |
138 | $schema = collect(str_getcsv($data->first()));
139 |
140 | $data->transform(function (string $line) use ($schema): Collection {
141 | return $schema->combine(
142 | array_map(fn ($value) => $value !== '' ? $value : null, str_getcsv($line))
143 | );
144 | });
145 |
146 | $data->shift();
147 |
148 | foreach (array_chunk($data->toArray(), 100) ?? [] as $dataToInsert) {
149 | if (empty($dataToInsert)) {
150 | continue;
151 | }
152 |
153 | static::insert($dataToInsert);
154 | }
155 | }
156 |
157 | public static function resolveConnection($connection = null): SQLiteConnection
158 | {
159 | return static::$sqliteConnections[static::class];
160 | }
161 |
162 | public function usesTimestamps(): bool
163 | {
164 | return false;
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/packages/model/src/ModelServiceProvider.php:
--------------------------------------------------------------------------------
1 | publishes([
12 | __DIR__ . '/../config/squire.php' => config_path('squire.php'),
13 | ]);
14 |
15 | $this->mergeConfigFrom(
16 | __DIR__ . '/../config/squire.php',
17 | 'squire'
18 | );
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/regions-en/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "squirephp/regions-en",
3 | "description": "A library containing the English translation of Squire's Region model.",
4 | "keywords": [
5 | "squire"
6 | ],
7 | "license": "MIT",
8 | "homepage": "https://github.com/squirephp",
9 | "support": {
10 | "issues": "https://github.com/squirephp/squire/issues",
11 | "source": "https://github.com/squirephp/squire"
12 | },
13 | "authors": [
14 | {
15 | "name": "Dan Harrin",
16 | "email": "dan@danharrin.com"
17 | }
18 | ],
19 | "require": {
20 | "php": "^8.0",
21 | "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0",
22 | "squirephp/regions": "self.version",
23 | "squirephp/repository": "self.version"
24 | },
25 | "autoload": {
26 | "psr-4": {
27 | "Squire\\": "src"
28 | }
29 | },
30 | "extra": {
31 | "laravel": {
32 | "providers": [
33 | "Squire\\RegionsEnServiceProvider"
34 | ]
35 | }
36 | },
37 | "config": {
38 | "sort-packages": true
39 | },
40 | "minimum-stability": "dev"
41 | }
42 |
--------------------------------------------------------------------------------
/packages/regions-en/src/RegionsEnServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'The selected :attribute is an invalid region.',
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/packages/regions/src/Models/Region.php:
--------------------------------------------------------------------------------
1 | 'string',
14 | 'code' => 'string',
15 | 'country_id' => 'string',
16 | 'name' => 'string',
17 | ];
18 |
19 | public function continent(): HasOneThrough
20 | {
21 | return $this->hasOneThrough(Continent::class, Country::class);
22 | }
23 |
24 | public function country(): BelongsTo
25 | {
26 | return $this->belongsTo(Country::class);
27 | }
28 |
29 | public function gbCounties(): HasMany
30 | {
31 | return $this->hasMany(GbCounty::class);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/packages/regions/src/RegionsServiceProvider.php:
--------------------------------------------------------------------------------
1 | loadTranslationsFrom(__DIR__ . '/../resources/lang', 'squire-regions');
12 |
13 | $this->publishes([
14 | __DIR__ . '/../resources/lang' => resource_path('lang/vendor/squire-regions'),
15 | ]);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/regions/src/Rules/RegionRule.php:
--------------------------------------------------------------------------------
1 | getSource($name, $locale);
16 |
17 | return $this->fetchDataFromSource($source);
18 | }
19 |
20 | public function getSource(string $name, ?string $locale = null): string
21 | {
22 | if ($locale && ! $this->sourceIsRegistered($name, $locale)) {
23 | throw new TranslationNotFoundException($name, $locale);
24 | }
25 |
26 | if (! $locale) {
27 | $locale = $this->getLocale($name);
28 | }
29 |
30 | return $this->getSources($name)[$locale];
31 | }
32 |
33 | public function sourceIsRegistered(string $name, ?string $locale = null): bool
34 | {
35 | if (! $locale) {
36 | return array_key_exists($name, $this->sources);
37 | }
38 |
39 | return array_key_exists($name, $this->sources) && array_key_exists($locale, $this->sources[$name]);
40 | }
41 |
42 | public function getLocale(string $name): string
43 | {
44 | if ($this->sourceIsRegistered($name, $appLocale = App::getLocale())) {
45 | return $appLocale;
46 | }
47 |
48 | if ($this->sourceIsRegistered($name, $appFallbackLocale = config('app.fallback_locale'))) {
49 | return $appFallbackLocale;
50 | }
51 |
52 | return array_key_first($this->getSources($name));
53 | }
54 |
55 | public function getSources(?string $name = null): array | string
56 | {
57 | if (! $name) {
58 | return $this->sources;
59 | }
60 |
61 | if (! $this->sourceIsRegistered($name) || ! count($this->sources[$name])) {
62 | throw new SourceNotFoundException($name);
63 | }
64 |
65 | return $this->sources[$name];
66 | }
67 |
68 | public function fetchDataFromSource($source): array
69 | {
70 | return file($source);
71 | }
72 |
73 | public function registerSource(string $name, string $locale, string $path): void
74 | {
75 | if (! $this->sourceIsRegistered($name)) {
76 | $this->sources[$name] = [];
77 | }
78 |
79 | $this->sources[$name][$locale] = realpath($path);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/packages/repository/src/RepositoryServiceProvider.php:
--------------------------------------------------------------------------------
1 | RepositoryManager::class,
11 | ];
12 | }
13 |
--------------------------------------------------------------------------------
/packages/rule/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "squirephp/rule",
3 | "description": "A library containing the base Squire rule class.",
4 | "keywords": [
5 | "squire"
6 | ],
7 | "license": "MIT",
8 | "homepage": "https://github.com/squirephp",
9 | "support": {
10 | "issues": "https://github.com/squirephp/squire/issues",
11 | "source": "https://github.com/squirephp/squire"
12 | },
13 | "authors": [
14 | {
15 | "name": "Dan Harrin",
16 | "email": "dan@danharrin.com"
17 | }
18 | ],
19 | "require": {
20 | "php": "^8.0",
21 | "illuminate/contracts": "^8.0|^9.0|^10.0|^11.0|^12.0",
22 | "illuminate/database": "^8.40|^9.0|^10.0|^11.0|^12.0",
23 | "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0"
24 | },
25 | "autoload": {
26 | "psr-4": {
27 | "Squire\\": "src"
28 | }
29 | },
30 | "config": {
31 | "sort-packages": true
32 | },
33 | "minimum-stability": "dev"
34 | }
35 |
--------------------------------------------------------------------------------
/packages/rule/src/Rule.php:
--------------------------------------------------------------------------------
1 | column = $column;
18 | }
19 | }
20 |
21 | public function message(): string
22 | {
23 | return __($this->message);
24 | }
25 |
26 | public function passes($attribute, $value): bool
27 | {
28 | return $this->getQueryBuilder()->where($this->column, $value)->exists();
29 | }
30 |
31 | abstract protected function getQueryBuilder(): Builder;
32 | }
33 |
--------------------------------------------------------------------------------
/packages/timezones-en/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "squirephp/timezones-en",
3 | "description": "A library containing the English translation of Squire's Timezone model.",
4 | "keywords": [
5 | "squire"
6 | ],
7 | "license": "MIT",
8 | "homepage": "https://github.com/squirephp",
9 | "support": {
10 | "issues": "https://github.com/squirephp/squire/issues",
11 | "source": "https://github.com/squirephp/squire"
12 | },
13 | "authors": [
14 | {
15 | "name": "Dan Harrin",
16 | "email": "dan@danharrin.com"
17 | }
18 | ],
19 | "require": {
20 | "php": "^8.0",
21 | "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0",
22 | "squirephp/repository": "self.version",
23 | "squirephp/timezones": "self.version"
24 | },
25 | "autoload": {
26 | "psr-4": {
27 | "Squire\\": "src"
28 | }
29 | },
30 | "extra": {
31 | "laravel": {
32 | "providers": [
33 | "Squire\\TimezonesEnServiceProvider"
34 | ]
35 | }
36 | },
37 | "config": {
38 | "sort-packages": true
39 | },
40 | "minimum-stability": "dev"
41 | }
42 |
--------------------------------------------------------------------------------
/packages/timezones-en/resources/data.csv:
--------------------------------------------------------------------------------
1 | id,code,country_id,long_name,name
2 | Africa/Abidjan,Africa/Abidjan,ci,Africa/Abidjan,Abidjan
3 | Africa/Accra,Africa/Accra,gh,Africa/Accra,Accra
4 | Africa/Addis_Ababa,Africa/Addis_Ababa,et,Africa/Addis Ababa,Addis Ababa
5 | Africa/Algiers,Africa/Algiers,dz,Africa/Algiers,Algiers
6 | Africa/Asmara,Africa/Asmara,er,Africa/Asmara,Asmara
7 | Africa/Bamako,Africa/Bamako,ml,Africa/Bamako,Bamako
8 | Africa/Bangui,Africa/Bangui,cf,Africa/Bangui,Bangui
9 | Africa/Banjul,Africa/Banjul,gm,Africa/Banjul,Banjul
10 | Africa/Bissau,Africa/Bissau,gw,Africa/Bissau,Bissau
11 | Africa/Blantyre,Africa/Blantyre,mw,Africa/Blantyre,Blantyre
12 | Africa/Brazzaville,Africa/Brazzaville,cg,Africa/Brazzaville,Brazzaville
13 | Africa/Bujumbura,Africa/Bujumbura,bi,Africa/Bujumbura,Bujumbura
14 | Africa/Cairo,Africa/Cairo,eg,Africa/Cairo,Cairo
15 | Africa/Casablanca,Africa/Casablanca,ma,Africa/Casablanca,Casablanca
16 | Africa/Ceuta,Africa/Ceuta,es,Africa/Ceuta,Ceuta
17 | Africa/Conakry,Africa/Conakry,gn,Africa/Conakry,Conakry
18 | Africa/Dakar,Africa/Dakar,sn,Africa/Dakar,Dakar
19 | Africa/Dar_es_Salaam,Africa/Dar_es_Salaam,tz,Africa/Dar es Salaam,Dar es Salaam
20 | Africa/Djibouti,Africa/Djibouti,dj,Africa/Djibouti,Djibouti
21 | Africa/Douala,Africa/Douala,cm,Africa/Douala,Douala
22 | Africa/El_Aaiun,Africa/El_Aaiun,eh,Africa/El Aaiun,El Aaiun
23 | Africa/Freetown,Africa/Freetown,sl,Africa/Freetown,Freetown
24 | Africa/Gaborone,Africa/Gaborone,bw,Africa/Gaborone,Gaborone
25 | Africa/Harare,Africa/Harare,zw,Africa/Harare,Harare
26 | Africa/Johannesburg,Africa/Johannesburg,za,Africa/Johannesburg,Johannesburg
27 | Africa/Juba,Africa/Juba,ss,Africa/Juba,Juba
28 | Africa/Kampala,Africa/Kampala,ug,Africa/Kampala,Kampala
29 | Africa/Khartoum,Africa/Khartoum,sd,Africa/Khartoum,Khartoum
30 | Africa/Kigali,Africa/Kigali,rw,Africa/Kigali,Kigali
31 | Africa/Kinshasa,Africa/Kinshasa,cd,Africa/Kinshasa,Kinshasa
32 | Africa/Lagos,Africa/Lagos,ng,Africa/Lagos,Lagos
33 | Africa/Libreville,Africa/Libreville,ga,Africa/Libreville,Libreville
34 | Africa/Lome,Africa/Lome,tg,Africa/Lome,Lome
35 | Africa/Luanda,Africa/Luanda,ao,Africa/Luanda,Luanda
36 | Africa/Lubumbashi,Africa/Lubumbashi,cd,Africa/Lubumbashi,Lubumbashi
37 | Africa/Lusaka,Africa/Lusaka,zm,Africa/Lusaka,Lusaka
38 | Africa/Malabo,Africa/Malabo,gq,Africa/Malabo,Malabo
39 | Africa/Maputo,Africa/Maputo,mz,Africa/Maputo,Maputo
40 | Africa/Maseru,Africa/Maseru,ls,Africa/Maseru,Maseru
41 | Africa/Mbabane,Africa/Mbabane,sz,Africa/Mbabane,Mbabane
42 | Africa/Mogadishu,Africa/Mogadishu,so,Africa/Mogadishu,Mogadishu
43 | Africa/Monrovia,Africa/Monrovia,lr,Africa/Monrovia,Monrovia
44 | Africa/Nairobi,Africa/Nairobi,ke,Africa/Nairobi,Nairobi
45 | Africa/Ndjamena,Africa/Ndjamena,td,Africa/Ndjamena,Ndjamena
46 | Africa/Niamey,Africa/Niamey,ne,Africa/Niamey,Niamey
47 | Africa/Nouakchott,Africa/Nouakchott,mr,Africa/Nouakchott,Nouakchott
48 | Africa/Ouagadougou,Africa/Ouagadougou,bf,Africa/Ouagadougou,Ouagadougou
49 | Africa/Porto-Novo,Africa/Porto-Novo,bj,Africa/Porto-Novo,Porto-Novo
50 | Africa/Sao_Tome,Africa/Sao_Tome,st,Africa/Sao Tome,Sao Tome
51 | Africa/Tripoli,Africa/Tripoli,ly,Africa/Tripoli,Tripoli
52 | Africa/Tunis,Africa/Tunis,tn,Africa/Tunis,Tunis
53 | Africa/Windhoek,Africa/Windhoek,na,Africa/Windhoek,Windhoek
54 | America/Adak,America/Adak,us,America/Adak,Adak
55 | America/Anchorage,America/Anchorage,us,America/Anchorage,Anchorage
56 | America/Anguilla,America/Anguilla,ai,America/Anguilla,Anguilla
57 | America/Antigua,America/Antigua,ag,America/Antigua,Antigua
58 | America/Araguaina,America/Araguaina,br,America/Araguaina,Araguaina
59 | America/Argentina/Buenos_Aires,America/Argentina/Buenos_Aires,ar,America/Argentina/Buenos Aires,Argentina/Buenos Aires
60 | America/Argentina/Catamarca,America/Argentina/Catamarca,ar,America/Argentina/Catamarca,Argentina/Catamarca
61 | America/Argentina/Cordoba,America/Argentina/Cordoba,ar,America/Argentina/Cordoba,Argentina/Cordoba
62 | America/Argentina/Jujuy,America/Argentina/Jujuy,ar,America/Argentina/Jujuy,Argentina/Jujuy
63 | America/Argentina/La_Rioja,America/Argentina/La_Rioja,ar,America/Argentina/La Rioja,Argentina/La Rioja
64 | America/Argentina/Mendoza,America/Argentina/Mendoza,ar,America/Argentina/Mendoza,Argentina/Mendoza
65 | America/Argentina/Rio_Gallegos,America/Argentina/Rio_Gallegos,ar,America/Argentina/Rio Gallegos,Argentina/Rio Gallegos
66 | America/Argentina/Salta,America/Argentina/Salta,ar,America/Argentina/Salta,Argentina/Salta
67 | America/Argentina/San_Juan,America/Argentina/San_Juan,ar,America/Argentina/San Juan,Argentina/San Juan
68 | America/Argentina/San_Luis,America/Argentina/San_Luis,ar,America/Argentina/San Luis,Argentina/San Luis
69 | America/Argentina/Tucuman,America/Argentina/Tucuman,ar,America/Argentina/Tucuman,Argentina/Tucuman
70 | America/Argentina/Ushuaia,America/Argentina/Ushuaia,ar,America/Argentina/Ushuaia,Argentina/Ushuaia
71 | America/Aruba,America/Aruba,aw,America/Aruba,Aruba
72 | America/Asuncion,America/Asuncion,py,America/Asuncion,Asuncion
73 | America/Atikokan,America/Atikokan,ca,America/Atikokan,Atikokan
74 | America/Bahia,America/Bahia,br,America/Bahia,Bahia
75 | America/Bahia_Banderas,America/Bahia_Banderas,mx,America/Bahia Banderas,Bahia Banderas
76 | America/Barbados,America/Barbados,bb,America/Barbados,Barbados
77 | America/Belem,America/Belem,br,America/Belem,Belem
78 | America/Belize,America/Belize,bz,America/Belize,Belize
79 | America/Blanc-Sablon,America/Blanc-Sablon,ca,America/Blanc-Sablon,Blanc-Sablon
80 | America/Boa_Vista,America/Boa_Vista,br,America/Boa Vista,Boa Vista
81 | America/Bogota,America/Bogota,co,America/Bogota,Bogota
82 | America/Boise,America/Boise,us,America/Boise,Boise
83 | America/Cambridge_Bay,America/Cambridge_Bay,ca,America/Cambridge Bay,Cambridge Bay
84 | America/Campo_Grande,America/Campo_Grande,br,America/Campo Grande,Campo Grande
85 | America/Cancun,America/Cancun,mx,America/Cancun,Cancun
86 | America/Caracas,America/Caracas,ve,America/Caracas,Caracas
87 | America/Cayenne,America/Cayenne,gf,America/Cayenne,Cayenne
88 | America/Cayman,America/Cayman,ky,America/Cayman,Cayman
89 | America/Chicago,America/Chicago,us,America/Chicago,Chicago
90 | America/Chihuahua,America/Chihuahua,mx,America/Chihuahua,Chihuahua
91 | America/Costa_Rica,America/Costa_Rica,cr,America/Costa Rica,Costa Rica
92 | America/Creston,America/Creston,ca,America/Creston,Creston
93 | America/Cuiaba,America/Cuiaba,br,America/Cuiaba,Cuiaba
94 | America/Curacao,America/Curacao,cw,America/Curacao,Curacao
95 | America/Danmarkshavn,America/Danmarkshavn,gl,America/Danmarkshavn,Danmarkshavn
96 | America/Dawson,America/Dawson,ca,America/Dawson,Dawson
97 | America/Dawson_Creek,America/Dawson_Creek,ca,America/Dawson Creek,Dawson Creek
98 | America/Denver,America/Denver,us,America/Denver,Denver
99 | America/Detroit,America/Detroit,us,America/Detroit,Detroit
100 | America/Dominica,America/Dominica,dm,America/Dominica,Dominica
101 | America/Edmonton,America/Edmonton,ca,America/Edmonton,Edmonton
102 | America/Eirunepe,America/Eirunepe,br,America/Eirunepe,Eirunepe
103 | America/El_Salvador,America/El_Salvador,sv,America/El Salvador,El Salvador
104 | America/Fort_Nelson,America/Fort_Nelson,ca,America/Fort Nelson,Fort Nelson
105 | America/Fortaleza,America/Fortaleza,br,America/Fortaleza,Fortaleza
106 | America/Glace_Bay,America/Glace_Bay,ca,America/Glace Bay,Glace Bay
107 | America/Goose_Bay,America/Goose_Bay,ca,America/Goose Bay,Goose Bay
108 | America/Grand_Turk,America/Grand_Turk,tc,America/Grand Turk,Grand Turk
109 | America/Grenada,America/Grenada,gd,America/Grenada,Grenada
110 | America/Guadeloupe,America/Guadeloupe,gp,America/Guadeloupe,Guadeloupe
111 | America/Guatemala,America/Guatemala,gt,America/Guatemala,Guatemala
112 | America/Guayaquil,America/Guayaquil,ec,America/Guayaquil,Guayaquil
113 | America/Guyana,America/Guyana,gy,America/Guyana,Guyana
114 | America/Halifax,America/Halifax,ca,America/Halifax,Halifax
115 | America/Havana,America/Havana,cu,America/Havana,Havana
116 | America/Hermosillo,America/Hermosillo,mx,America/Hermosillo,Hermosillo
117 | America/Indiana/Indianapolis,America/Indiana/Indianapolis,us,America/Indiana/Indianapolis,Indiana/Indianapolis
118 | America/Indiana/Knox,America/Indiana/Knox,us,America/Indiana/Knox,Indiana/Knox
119 | America/Indiana/Marengo,America/Indiana/Marengo,us,America/Indiana/Marengo,Indiana/Marengo
120 | America/Indiana/Petersburg,America/Indiana/Petersburg,us,America/Indiana/Petersburg,Indiana/Petersburg
121 | America/Indiana/Tell_City,America/Indiana/Tell_City,us,America/Indiana/Tell City,Indiana/Tell City
122 | America/Indiana/Vevay,America/Indiana/Vevay,us,America/Indiana/Vevay,Indiana/Vevay
123 | America/Indiana/Vincennes,America/Indiana/Vincennes,us,America/Indiana/Vincennes,Indiana/Vincennes
124 | America/Indiana/Winamac,America/Indiana/Winamac,us,America/Indiana/Winamac,Indiana/Winamac
125 | America/Inuvik,America/Inuvik,ca,America/Inuvik,Inuvik
126 | America/Iqaluit,America/Iqaluit,ca,America/Iqaluit,Iqaluit
127 | America/Jamaica,America/Jamaica,jm,America/Jamaica,Jamaica
128 | America/Juneau,America/Juneau,us,America/Juneau,Juneau
129 | America/Kentucky/Louisville,America/Kentucky/Louisville,us,America/Kentucky/Louisville,Kentucky/Louisville
130 | America/Kentucky/Monticello,America/Kentucky/Monticello,us,America/Kentucky/Monticello,Kentucky/Monticello
131 | America/Kralendijk,America/Kralendijk,bq,America/Kralendijk,Kralendijk
132 | America/La_Paz,America/La_Paz,bo,America/La Paz,La Paz
133 | America/Lima,America/Lima,pe,America/Lima,Lima
134 | America/Los_Angeles,America/Los_Angeles,us,America/Los Angeles,Los Angeles
135 | America/Lower_Princes,America/Lower_Princes,sx,America/Lower Princes,Lower Princes
136 | America/Maceio,America/Maceio,br,America/Maceio,Maceio
137 | America/Managua,America/Managua,ni,America/Managua,Managua
138 | America/Manaus,America/Manaus,br,America/Manaus,Manaus
139 | America/Marigot,America/Marigot,mf,America/Marigot,Marigot
140 | America/Martinique,America/Martinique,mq,America/Martinique,Martinique
141 | America/Matamoros,America/Matamoros,mx,America/Matamoros,Matamoros
142 | America/Mazatlan,America/Mazatlan,mx,America/Mazatlan,Mazatlan
143 | America/Menominee,America/Menominee,us,America/Menominee,Menominee
144 | America/Merida,America/Merida,mx,America/Merida,Merida
145 | America/Metlakatla,America/Metlakatla,us,America/Metlakatla,Metlakatla
146 | America/Mexico_City,America/Mexico_City,mx,America/Mexico City,Mexico City
147 | America/Miquelon,America/Miquelon,pm,America/Miquelon,Miquelon
148 | America/Moncton,America/Moncton,ca,America/Moncton,Moncton
149 | America/Monterrey,America/Monterrey,mx,America/Monterrey,Monterrey
150 | America/Montevideo,America/Montevideo,uy,America/Montevideo,Montevideo
151 | America/Montserrat,America/Montserrat,ms,America/Montserrat,Montserrat
152 | America/Nassau,America/Nassau,bs,America/Nassau,Nassau
153 | America/New_York,America/New_York,us,America/New York,New York
154 | America/Nipigon,America/Nipigon,ca,America/Nipigon,Nipigon
155 | America/Nome,America/Nome,us,America/Nome,Nome
156 | America/Noronha,America/Noronha,br,America/Noronha,Noronha
157 | America/North_Dakota/Beulah,America/North_Dakota/Beulah,us,America/North Dakota/Beulah,North Dakota/Beulah
158 | America/North_Dakota/Center,America/North_Dakota/Center,us,America/North Dakota/Center,North Dakota/Center
159 | America/North_Dakota/New_Salem,America/North_Dakota/New_Salem,us,America/North Dakota/New Salem,North Dakota/New Salem
160 | America/Nuuk,America/Nuuk,gl,America/Nuuk,Nuuk
161 | America/Ojinaga,America/Ojinaga,mx,America/Ojinaga,Ojinaga
162 | America/Panama,America/Panama,pa,America/Panama,Panama
163 | America/Pangnirtung,America/Pangnirtung,ca,America/Pangnirtung,Pangnirtung
164 | America/Paramaribo,America/Paramaribo,sr,America/Paramaribo,Paramaribo
165 | America/Phoenix,America/Phoenix,us,America/Phoenix,Phoenix
166 | America/Port-au-Prince,America/Port-au-Prince,ht,America/Port-au-Prince,Port-au-Prince
167 | America/Port_of_Spain,America/Port_of_Spain,tt,America/Port of Spain,Port of Spain
168 | America/Porto_Velho,America/Porto_Velho,br,America/Porto Velho,Porto Velho
169 | America/Puerto_Rico,America/Puerto_Rico,pr,America/Puerto Rico,Puerto Rico
170 | America/Punta_Arenas,America/Punta_Arenas,cl,America/Punta Arenas,Punta Arenas
171 | America/Rainy_River,America/Rainy_River,ca,America/Rainy River,Rainy River
172 | America/Rankin_Inlet,America/Rankin_Inlet,ca,America/Rankin Inlet,Rankin Inlet
173 | America/Recife,America/Recife,br,America/Recife,Recife
174 | America/Regina,America/Regina,ca,America/Regina,Regina
175 | America/Resolute,America/Resolute,ca,America/Resolute,Resolute
176 | America/Rio_Branco,America/Rio_Branco,br,America/Rio Branco,Rio Branco
177 | America/Santarem,America/Santarem,br,America/Santarem,Santarem
178 | America/Santiago,America/Santiago,cl,America/Santiago,Santiago
179 | America/Santo_Domingo,America/Santo_Domingo,do,America/Santo Domingo,Santo Domingo
180 | America/Sao_Paulo,America/Sao_Paulo,br,America/Sao Paulo,Sao Paulo
181 | America/Scoresbysund,America/Scoresbysund,gl,America/Scoresbysund,Scoresbysund
182 | America/Sitka,America/Sitka,us,America/Sitka,Sitka
183 | America/St_Barthelemy,America/St_Barthelemy,bl,America/St Barthelemy,St Barthelemy
184 | America/St_Johns,America/St_Johns,ca,America/St Johns,St Johns
185 | America/St_Kitts,America/St_Kitts,kn,America/St Kitts,St Kitts
186 | America/St_Lucia,America/St_Lucia,lc,America/St Lucia,St Lucia
187 | America/St_Thomas,America/St_Thomas,vi,America/St Thomas,St Thomas
188 | America/St_Vincent,America/St_Vincent,vc,America/St Vincent,St Vincent
189 | America/Swift_Current,America/Swift_Current,ca,America/Swift Current,Swift Current
190 | America/Tegucigalpa,America/Tegucigalpa,hn,America/Tegucigalpa,Tegucigalpa
191 | America/Thule,America/Thule,gl,America/Thule,Thule
192 | America/Thunder_Bay,America/Thunder_Bay,ca,America/Thunder Bay,Thunder Bay
193 | America/Tijuana,America/Tijuana,mx,America/Tijuana,Tijuana
194 | America/Toronto,America/Toronto,ca,America/Toronto,Toronto
195 | America/Tortola,America/Tortola,vg,America/Tortola,Tortola
196 | America/Vancouver,America/Vancouver,ca,America/Vancouver,Vancouver
197 | America/Whitehorse,America/Whitehorse,ca,America/Whitehorse,Whitehorse
198 | America/Winnipeg,America/Winnipeg,ca,America/Winnipeg,Winnipeg
199 | America/Yakutat,America/Yakutat,us,America/Yakutat,Yakutat
200 | America/Yellowknife,America/Yellowknife,ca,America/Yellowknife,Yellowknife
201 | Antarctica/Casey,Antarctica/Casey,aq,Antarctica/Casey,Casey
202 | Antarctica/Davis,Antarctica/Davis,aq,Antarctica/Davis,Davis
203 | Antarctica/DumontDUrville,Antarctica/DumontDUrville,aq,Antarctica/DumontDUrville,DumontDUrville
204 | Antarctica/Macquarie,Antarctica/Macquarie,au,Antarctica/Macquarie,Macquarie
205 | Antarctica/Mawson,Antarctica/Mawson,aq,Antarctica/Mawson,Mawson
206 | Antarctica/McMurdo,Antarctica/McMurdo,aq,Antarctica/McMurdo,McMurdo
207 | Antarctica/Palmer,Antarctica/Palmer,aq,Antarctica/Palmer,Palmer
208 | Antarctica/Rothera,Antarctica/Rothera,aq,Antarctica/Rothera,Rothera
209 | Antarctica/Syowa,Antarctica/Syowa,aq,Antarctica/Syowa,Syowa
210 | Antarctica/Troll,Antarctica/Troll,aq,Antarctica/Troll,Troll
211 | Antarctica/Vostok,Antarctica/Vostok,aq,Antarctica/Vostok,Vostok
212 | Arctic/Longyearbyen,Arctic/Longyearbyen,sj,Arctic/Longyearbyen,Longyearbyen
213 | Asia/Aden,Asia/Aden,ye,Asia/Aden,Aden
214 | Asia/Almaty,Asia/Almaty,kz,Asia/Almaty,Almaty
215 | Asia/Amman,Asia/Amman,jo,Asia/Amman,Amman
216 | Asia/Anadyr,Asia/Anadyr,ru,Asia/Anadyr,Anadyr
217 | Asia/Aqtau,Asia/Aqtau,kz,Asia/Aqtau,Aqtau
218 | Asia/Aqtobe,Asia/Aqtobe,kz,Asia/Aqtobe,Aqtobe
219 | Asia/Ashgabat,Asia/Ashgabat,tm,Asia/Ashgabat,Ashgabat
220 | Asia/Atyrau,Asia/Atyrau,kz,Asia/Atyrau,Atyrau
221 | Asia/Baghdad,Asia/Baghdad,iq,Asia/Baghdad,Baghdad
222 | Asia/Bahrain,Asia/Bahrain,bh,Asia/Bahrain,Bahrain
223 | Asia/Baku,Asia/Baku,az,Asia/Baku,Baku
224 | Asia/Bangkok,Asia/Bangkok,th,Asia/Bangkok,Bangkok
225 | Asia/Barnaul,Asia/Barnaul,ru,Asia/Barnaul,Barnaul
226 | Asia/Beirut,Asia/Beirut,lb,Asia/Beirut,Beirut
227 | Asia/Bishkek,Asia/Bishkek,kg,Asia/Bishkek,Bishkek
228 | Asia/Brunei,Asia/Brunei,bn,Asia/Brunei,Brunei
229 | Asia/Chita,Asia/Chita,ru,Asia/Chita,Chita
230 | Asia/Choibalsan,Asia/Choibalsan,mn,Asia/Choibalsan,Choibalsan
231 | Asia/Colombo,Asia/Colombo,lk,Asia/Colombo,Colombo
232 | Asia/Damascus,Asia/Damascus,sy,Asia/Damascus,Damascus
233 | Asia/Dhaka,Asia/Dhaka,bd,Asia/Dhaka,Dhaka
234 | Asia/Dili,Asia/Dili,tl,Asia/Dili,Dili
235 | Asia/Dubai,Asia/Dubai,ae,Asia/Dubai,Dubai
236 | Asia/Dushanbe,Asia/Dushanbe,tj,Asia/Dushanbe,Dushanbe
237 | Asia/Famagusta,Asia/Famagusta,cy,Asia/Famagusta,Famagusta
238 | Asia/Gaza,Asia/Gaza,ps,Asia/Gaza,Gaza
239 | Asia/Hebron,Asia/Hebron,ps,Asia/Hebron,Hebron
240 | Asia/Ho_Chi_Minh,Asia/Ho_Chi_Minh,vn,Asia/Ho Chi Minh,Ho Chi Minh
241 | Asia/Hong_Kong,Asia/Hong_Kong,hk,Asia/Hong Kong,Hong Kong
242 | Asia/Hovd,Asia/Hovd,mn,Asia/Hovd,Hovd
243 | Asia/Irkutsk,Asia/Irkutsk,ru,Asia/Irkutsk,Irkutsk
244 | Asia/Jakarta,Asia/Jakarta,id,Asia/Jakarta,Jakarta
245 | Asia/Jayapura,Asia/Jayapura,id,Asia/Jayapura,Jayapura
246 | Asia/Jerusalem,Asia/Jerusalem,il,Asia/Jerusalem,Jerusalem
247 | Asia/Kabul,Asia/Kabul,af,Asia/Kabul,Kabul
248 | Asia/Kamchatka,Asia/Kamchatka,ru,Asia/Kamchatka,Kamchatka
249 | Asia/Karachi,Asia/Karachi,pk,Asia/Karachi,Karachi
250 | Asia/Kathmandu,Asia/Kathmandu,np,Asia/Kathmandu,Kathmandu
251 | Asia/Khandyga,Asia/Khandyga,ru,Asia/Khandyga,Khandyga
252 | Asia/Kolkata,Asia/Kolkata,in,Asia/Kolkata,Kolkata
253 | Asia/Krasnoyarsk,Asia/Krasnoyarsk,ru,Asia/Krasnoyarsk,Krasnoyarsk
254 | Asia/Kuala_Lumpur,Asia/Kuala_Lumpur,my,Asia/Kuala Lumpur,Kuala Lumpur
255 | Asia/Kuching,Asia/Kuching,my,Asia/Kuching,Kuching
256 | Asia/Kuwait,Asia/Kuwait,kw,Asia/Kuwait,Kuwait
257 | Asia/Macau,Asia/Macau,mo,Asia/Macau,Macau
258 | Asia/Magadan,Asia/Magadan,ru,Asia/Magadan,Magadan
259 | Asia/Makassar,Asia/Makassar,id,Asia/Makassar,Makassar
260 | Asia/Manila,Asia/Manila,ph,Asia/Manila,Manila
261 | Asia/Muscat,Asia/Muscat,om,Asia/Muscat,Muscat
262 | Asia/Nicosia,Asia/Nicosia,cy,Asia/Nicosia,Nicosia
263 | Asia/Novokuznetsk,Asia/Novokuznetsk,ru,Asia/Novokuznetsk,Novokuznetsk
264 | Asia/Novosibirsk,Asia/Novosibirsk,ru,Asia/Novosibirsk,Novosibirsk
265 | Asia/Omsk,Asia/Omsk,ru,Asia/Omsk,Omsk
266 | Asia/Oral,Asia/Oral,kz,Asia/Oral,Oral
267 | Asia/Phnom_Penh,Asia/Phnom_Penh,kh,Asia/Phnom Penh,Phnom Penh
268 | Asia/Pontianak,Asia/Pontianak,id,Asia/Pontianak,Pontianak
269 | Asia/Pyongyang,Asia/Pyongyang,kp,Asia/Pyongyang,Pyongyang
270 | Asia/Qatar,Asia/Qatar,qa,Asia/Qatar,Qatar
271 | Asia/Qostanay,Asia/Qostanay,kz,Asia/Qostanay,Qostanay
272 | Asia/Qyzylorda,Asia/Qyzylorda,kz,Asia/Qyzylorda,Qyzylorda
273 | Asia/Riyadh,Asia/Riyadh,sa,Asia/Riyadh,Riyadh
274 | Asia/Sakhalin,Asia/Sakhalin,ru,Asia/Sakhalin,Sakhalin
275 | Asia/Samarkand,Asia/Samarkand,uz,Asia/Samarkand,Samarkand
276 | Asia/Seoul,Asia/Seoul,kr,Asia/Seoul,Seoul
277 | Asia/Shanghai,Asia/Shanghai,cn,Asia/Shanghai,Shanghai
278 | Asia/Singapore,Asia/Singapore,sg,Asia/Singapore,Singapore
279 | Asia/Srednekolymsk,Asia/Srednekolymsk,ru,Asia/Srednekolymsk,Srednekolymsk
280 | Asia/Taipei,Asia/Taipei,tw,Asia/Taipei,Taipei
281 | Asia/Tashkent,Asia/Tashkent,uz,Asia/Tashkent,Tashkent
282 | Asia/Tbilisi,Asia/Tbilisi,ge,Asia/Tbilisi,Tbilisi
283 | Asia/Tehran,Asia/Tehran,ir,Asia/Tehran,Tehran
284 | Asia/Thimphu,Asia/Thimphu,bt,Asia/Thimphu,Thimphu
285 | Asia/Tokyo,Asia/Tokyo,jp,Asia/Tokyo,Tokyo
286 | Asia/Tomsk,Asia/Tomsk,ru,Asia/Tomsk,Tomsk
287 | Asia/Ulaanbaatar,Asia/Ulaanbaatar,mn,Asia/Ulaanbaatar,Ulaanbaatar
288 | Asia/Urumqi,Asia/Urumqi,cn,Asia/Urumqi,Urumqi
289 | Asia/Ust-Nera,Asia/Ust-Nera,ru,Asia/Ust-Nera,Ust-Nera
290 | Asia/Vientiane,Asia/Vientiane,la,Asia/Vientiane,Vientiane
291 | Asia/Vladivostok,Asia/Vladivostok,ru,Asia/Vladivostok,Vladivostok
292 | Asia/Yakutsk,Asia/Yakutsk,ru,Asia/Yakutsk,Yakutsk
293 | Asia/Yangon,Asia/Yangon,mm,Asia/Yangon,Yangon
294 | Asia/Yekaterinburg,Asia/Yekaterinburg,ru,Asia/Yekaterinburg,Yekaterinburg
295 | Asia/Yerevan,Asia/Yerevan,am,Asia/Yerevan,Yerevan
296 | Atlantic/Azores,Atlantic/Azores,pt,Atlantic/Azores,Azores
297 | Atlantic/Bermuda,Atlantic/Bermuda,bm,Atlantic/Bermuda,Bermuda
298 | Atlantic/Canary,Atlantic/Canary,es,Atlantic/Canary,Canary
299 | Atlantic/Cape_Verde,Atlantic/Cape_Verde,cv,Atlantic/Cape Verde,Cape Verde
300 | Atlantic/Faroe,Atlantic/Faroe,fo,Atlantic/Faroe,Faroe
301 | Atlantic/Madeira,Atlantic/Madeira,pt,Atlantic/Madeira,Madeira
302 | Atlantic/Reykjavik,Atlantic/Reykjavik,is,Atlantic/Reykjavik,Reykjavik
303 | Atlantic/South_Georgia,Atlantic/South_Georgia,gs,Atlantic/South Georgia,South Georgia
304 | Atlantic/St_Helena,Atlantic/St_Helena,sh,Atlantic/St Helena,St Helena
305 | Atlantic/Stanley,Atlantic/Stanley,fk,Atlantic/Stanley,Stanley
306 | Australia/Adelaide,Australia/Adelaide,au,Australia/Adelaide,Adelaide
307 | Australia/Brisbane,Australia/Brisbane,au,Australia/Brisbane,Brisbane
308 | Australia/Broken_Hill,Australia/Broken_Hill,au,Australia/Broken Hill,Broken Hill
309 | Australia/Darwin,Australia/Darwin,au,Australia/Darwin,Darwin
310 | Australia/Eucla,Australia/Eucla,au,Australia/Eucla,Eucla
311 | Australia/Hobart,Australia/Hobart,au,Australia/Hobart,Hobart
312 | Australia/Lindeman,Australia/Lindeman,au,Australia/Lindeman,Lindeman
313 | Australia/Lord_Howe,Australia/Lord_Howe,au,Australia/Lord Howe,Lord Howe
314 | Australia/Melbourne,Australia/Melbourne,au,Australia/Melbourne,Melbourne
315 | Australia/Perth,Australia/Perth,au,Australia/Perth,Perth
316 | Australia/Sydney,Australia/Sydney,au,Australia/Sydney,Sydney
317 | Europe/Amsterdam,Europe/Amsterdam,nl,Europe/Amsterdam,Amsterdam
318 | Europe/Andorra,Europe/Andorra,ad,Europe/Andorra,Andorra
319 | Europe/Astrakhan,Europe/Astrakhan,ru,Europe/Astrakhan,Astrakhan
320 | Europe/Athens,Europe/Athens,gr,Europe/Athens,Athens
321 | Europe/Belgrade,Europe/Belgrade,rs,Europe/Belgrade,Belgrade
322 | Europe/Berlin,Europe/Berlin,de,Europe/Berlin,Berlin
323 | Europe/Bratislava,Europe/Bratislava,sk,Europe/Bratislava,Bratislava
324 | Europe/Brussels,Europe/Brussels,be,Europe/Brussels,Brussels
325 | Europe/Bucharest,Europe/Bucharest,ro,Europe/Bucharest,Bucharest
326 | Europe/Budapest,Europe/Budapest,hu,Europe/Budapest,Budapest
327 | Europe/Busingen,Europe/Busingen,de,Europe/Busingen,Busingen
328 | Europe/Chisinau,Europe/Chisinau,md,Europe/Chisinau,Chisinau
329 | Europe/Copenhagen,Europe/Copenhagen,dk,Europe/Copenhagen,Copenhagen
330 | Europe/Dublin,Europe/Dublin,ie,Europe/Dublin,Dublin
331 | Europe/Gibraltar,Europe/Gibraltar,gi,Europe/Gibraltar,Gibraltar
332 | Europe/Guernsey,Europe/Guernsey,gg,Europe/Guernsey,Guernsey
333 | Europe/Helsinki,Europe/Helsinki,fi,Europe/Helsinki,Helsinki
334 | Europe/Isle_of_Man,Europe/Isle_of_Man,im,Europe/Isle of Man,Isle of Man
335 | Europe/Istanbul,Europe/Istanbul,tr,Europe/Istanbul,Istanbul
336 | Europe/Jersey,Europe/Jersey,je,Europe/Jersey,Jersey
337 | Europe/Kaliningrad,Europe/Kaliningrad,ru,Europe/Kaliningrad,Kaliningrad
338 | Europe/Kiev,Europe/Kiev,ua,Europe/Kiev,Kiev
339 | Europe/Kirov,Europe/Kirov,ru,Europe/Kirov,Kirov
340 | Europe/Lisbon,Europe/Lisbon,pt,Europe/Lisbon,Lisbon
341 | Europe/Ljubljana,Europe/Ljubljana,si,Europe/Ljubljana,Ljubljana
342 | Europe/London,Europe/London,gb,Europe/London,London
343 | Europe/Luxembourg,Europe/Luxembourg,lu,Europe/Luxembourg,Luxembourg
344 | Europe/Madrid,Europe/Madrid,es,Europe/Madrid,Madrid
345 | Europe/Malta,Europe/Malta,mt,Europe/Malta,Malta
346 | Europe/Mariehamn,Europe/Mariehamn,ax,Europe/Mariehamn,Mariehamn
347 | Europe/Minsk,Europe/Minsk,by,Europe/Minsk,Minsk
348 | Europe/Monaco,Europe/Monaco,mc,Europe/Monaco,Monaco
349 | Europe/Moscow,Europe/Moscow,ru,Europe/Moscow,Moscow
350 | Europe/Oslo,Europe/Oslo,no,Europe/Oslo,Oslo
351 | Europe/Paris,Europe/Paris,fr,Europe/Paris,Paris
352 | Europe/Podgorica,Europe/Podgorica,me,Europe/Podgorica,Podgorica
353 | Europe/Prague,Europe/Prague,cz,Europe/Prague,Prague
354 | Europe/Riga,Europe/Riga,lv,Europe/Riga,Riga
355 | Europe/Rome,Europe/Rome,it,Europe/Rome,Rome
356 | Europe/Samara,Europe/Samara,ru,Europe/Samara,Samara
357 | Europe/San_Marino,Europe/San_Marino,sm,Europe/San Marino,San Marino
358 | Europe/Sarajevo,Europe/Sarajevo,ba,Europe/Sarajevo,Sarajevo
359 | Europe/Saratov,Europe/Saratov,ru,Europe/Saratov,Saratov
360 | Europe/Simferopol,Europe/Simferopol,ua,Europe/Simferopol,Simferopol
361 | Europe/Skopje,Europe/Skopje,mk,Europe/Skopje,Skopje
362 | Europe/Sofia,Europe/Sofia,bg,Europe/Sofia,Sofia
363 | Europe/Stockholm,Europe/Stockholm,se,Europe/Stockholm,Stockholm
364 | Europe/Tallinn,Europe/Tallinn,ee,Europe/Tallinn,Tallinn
365 | Europe/Tirane,Europe/Tirane,al,Europe/Tirane,Tirane
366 | Europe/Ulyanovsk,Europe/Ulyanovsk,ru,Europe/Ulyanovsk,Ulyanovsk
367 | Europe/Uzhgorod,Europe/Uzhgorod,ua,Europe/Uzhgorod,Uzhgorod
368 | Europe/Vaduz,Europe/Vaduz,li,Europe/Vaduz,Vaduz
369 | Europe/Vatican,Europe/Vatican,va,Europe/Vatican,Vatican
370 | Europe/Vienna,Europe/Vienna,at,Europe/Vienna,Vienna
371 | Europe/Vilnius,Europe/Vilnius,lt,Europe/Vilnius,Vilnius
372 | Europe/Volgograd,Europe/Volgograd,ru,Europe/Volgograd,Volgograd
373 | Europe/Warsaw,Europe/Warsaw,pl,Europe/Warsaw,Warsaw
374 | Europe/Zagreb,Europe/Zagreb,hr,Europe/Zagreb,Zagreb
375 | Europe/Zaporozhye,Europe/Zaporozhye,ua,Europe/Zaporozhye,Zaporozhye
376 | Europe/Zurich,Europe/Zurich,ch,Europe/Zurich,Zurich
377 | Indian/Antananarivo,Indian/Antananarivo,mg,Indian/Antananarivo,Antananarivo
378 | Indian/Chagos,Indian/Chagos,io,Indian/Chagos,Chagos
379 | Indian/Christmas,Indian/Christmas,cx,Indian/Christmas,Christmas
380 | Indian/Cocos,Indian/Cocos,cc,Indian/Cocos,Cocos
381 | Indian/Comoro,Indian/Comoro,km,Indian/Comoro,Comoro
382 | Indian/Kerguelen,Indian/Kerguelen,tf,Indian/Kerguelen,Kerguelen
383 | Indian/Mahe,Indian/Mahe,sc,Indian/Mahe,Mahe
384 | Indian/Maldives,Indian/Maldives,mv,Indian/Maldives,Maldives
385 | Indian/Mauritius,Indian/Mauritius,mu,Indian/Mauritius,Mauritius
386 | Indian/Mayotte,Indian/Mayotte,yt,Indian/Mayotte,Mayotte
387 | Indian/Reunion,Indian/Reunion,re,Indian/Reunion,Reunion
388 | Pacific/Apia,Pacific/Apia,ws,Pacific/Apia,Apia
389 | Pacific/Auckland,Pacific/Auckland,nz,Pacific/Auckland,Auckland
390 | Pacific/Bougainville,Pacific/Bougainville,pg,Pacific/Bougainville,Bougainville
391 | Pacific/Chatham,Pacific/Chatham,nz,Pacific/Chatham,Chatham
392 | Pacific/Chuuk,Pacific/Chuuk,fm,Pacific/Chuuk,Chuuk
393 | Pacific/Easter,Pacific/Easter,cl,Pacific/Easter,Easter
394 | Pacific/Efate,Pacific/Efate,vu,Pacific/Efate,Efate
395 | Pacific/Enderbury,Pacific/Enderbury,ki,Pacific/Enderbury,Enderbury
396 | Pacific/Fakaofo,Pacific/Fakaofo,tk,Pacific/Fakaofo,Fakaofo
397 | Pacific/Fiji,Pacific/Fiji,fj,Pacific/Fiji,Fiji
398 | Pacific/Funafuti,Pacific/Funafuti,tv,Pacific/Funafuti,Funafuti
399 | Pacific/Galapagos,Pacific/Galapagos,ec,Pacific/Galapagos,Galapagos
400 | Pacific/Gambier,Pacific/Gambier,pf,Pacific/Gambier,Gambier
401 | Pacific/Guadalcanal,Pacific/Guadalcanal,sb,Pacific/Guadalcanal,Guadalcanal
402 | Pacific/Guam,Pacific/Guam,gu,Pacific/Guam,Guam
403 | Pacific/Honolulu,Pacific/Honolulu,us,Pacific/Honolulu,Honolulu
404 | Pacific/Kiritimati,Pacific/Kiritimati,ki,Pacific/Kiritimati,Kiritimati
405 | Pacific/Kosrae,Pacific/Kosrae,fm,Pacific/Kosrae,Kosrae
406 | Pacific/Kwajalein,Pacific/Kwajalein,mh,Pacific/Kwajalein,Kwajalein
407 | Pacific/Majuro,Pacific/Majuro,mh,Pacific/Majuro,Majuro
408 | Pacific/Marquesas,Pacific/Marquesas,pf,Pacific/Marquesas,Marquesas
409 | Pacific/Midway,Pacific/Midway,um,Pacific/Midway,Midway
410 | Pacific/Nauru,Pacific/Nauru,nr,Pacific/Nauru,Nauru
411 | Pacific/Niue,Pacific/Niue,nu,Pacific/Niue,Niue
412 | Pacific/Norfolk,Pacific/Norfolk,nf,Pacific/Norfolk,Norfolk
413 | Pacific/Noumea,Pacific/Noumea,nc,Pacific/Noumea,Noumea
414 | Pacific/Pago_Pago,Pacific/Pago_Pago,as,Pacific/Pago Pago,Pago Pago
415 | Pacific/Palau,Pacific/Palau,pw,Pacific/Palau,Palau
416 | Pacific/Pitcairn,Pacific/Pitcairn,pn,Pacific/Pitcairn,Pitcairn
417 | Pacific/Pohnpei,Pacific/Pohnpei,fm,Pacific/Pohnpei,Pohnpei
418 | Pacific/Port_Moresby,Pacific/Port_Moresby,pg,Pacific/Port Moresby,Port Moresby
419 | Pacific/Rarotonga,Pacific/Rarotonga,ck,Pacific/Rarotonga,Rarotonga
420 | Pacific/Saipan,Pacific/Saipan,mp,Pacific/Saipan,Saipan
421 | Pacific/Tahiti,Pacific/Tahiti,pf,Pacific/Tahiti,Tahiti
422 | Pacific/Tarawa,Pacific/Tarawa,ki,Pacific/Tarawa,Tarawa
423 | Pacific/Tongatapu,Pacific/Tongatapu,to,Pacific/Tongatapu,Tongatapu
424 | Pacific/Wake,Pacific/Wake,um,Pacific/Wake,Wake
425 | Pacific/Wallis,Pacific/Wallis,wf,Pacific/Wallis,Wallis
426 | UTC,UTC,,Coordinated Universal Time,UTC
--------------------------------------------------------------------------------
/packages/timezones-en/src/TimezonesEnServiceProvider.php:
--------------------------------------------------------------------------------
1 | 'The selected :attribute is an invalid timezone.',
6 |
7 | ];
8 |
--------------------------------------------------------------------------------
/packages/timezones/src/Models/Timezone.php:
--------------------------------------------------------------------------------
1 | 'string',
16 | 'code' => 'string',
17 | 'country_id' => 'string',
18 | 'long_name' => 'string',
19 | 'name' => 'string',
20 | ];
21 |
22 | public static function getDefault(): ?static
23 | {
24 | return static::find(config('app.timezone'));
25 | }
26 |
27 | public function airports(): HasMany
28 | {
29 | return $this->hasMany(Airport::class);
30 | }
31 |
32 | public function continent(): HasOneThrough
33 | {
34 | return $this->hasOneThrough(Continent::class, Country::class);
35 | }
36 |
37 | public function country(): BelongsTo
38 | {
39 | return $this->belongsTo(Country::class);
40 | }
41 |
42 | public function getOffset(DateTimeInterface $dateTime): int|false|null
43 | {
44 | if (! $this->id) {
45 | return null;
46 | }
47 |
48 | return (new DateTimeZone($this->id))->getOffset($dateTime);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/packages/timezones/src/Rules/TimezoneRule.php:
--------------------------------------------------------------------------------
1 | loadTranslationsFrom(__DIR__ . '/../resources/lang', 'squire-timezones');
12 |
13 | $this->publishes([
14 | __DIR__ . '/../resources/lang' => resource_path('lang/vendor/squire-timezones'),
15 | ]);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | tests
6 |
7 |
8 |
9 |
10 | packages
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/tests/ModelTest.php:
--------------------------------------------------------------------------------
1 | assertEquals(2, Models\Foo::count());
24 | $this->assertEquals('bar', Models\Foo::first()->foo);
25 |
26 | $this->testModel(Airline::class);
27 | $this->testModel(Airport::class);
28 | $this->testModel(Continent::class);
29 | $this->testModel(Country::class);
30 | $this->testModel(Currency::class);
31 | $this->testModel(GbCounty::class);
32 | $this->testModel(Region::class);
33 | $this->testModel(Timezone::class);
34 | }
35 |
36 | protected function testModel(string $model): void
37 | {
38 | $locales = array_keys(Repository::getSources($model));
39 |
40 | foreach ($locales as $locale) {
41 | App::setLocale($locale);
42 |
43 | $model::clearBootedModels();
44 |
45 | $this->assertIsObject($model::all());
46 | }
47 | }
48 |
49 | /** @test */
50 | public function can_translate_models(): void
51 | {
52 | Repository::registerSource(Models\Foo::class, 'en', __DIR__ . '/data/foo-en.csv');
53 | Repository::registerSource(Models\Foo::class, 'es', __DIR__ . '/data/foo-es.csv');
54 |
55 | App::setLocale('en');
56 | $this->assertEquals('en', Models\Foo::first()->lang);
57 |
58 | Models\Foo::clearBootedModels();
59 |
60 | App::setLocale('es');
61 | $this->assertEquals('es', Models\Foo::first()->lang);
62 | }
63 |
64 | /** @test */
65 | public function can_format_usd(): void
66 | {
67 | $this->assertSame('$5.00', Currency::find('usd')->format(500));
68 | $this->assertSame('$500.00', Currency::find('usd')->format(500, true));
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/tests/Models/Foo.php:
--------------------------------------------------------------------------------
1 | 'string',
11 | 'lang' => 'string',
12 | ];
13 | }
14 |
--------------------------------------------------------------------------------
/tests/RuleTest.php:
--------------------------------------------------------------------------------
1 | testRule(Rules\FooRule::class, Models\Foo::class);
33 |
34 | $this->testRule(AirlineRule::class, Airline::class);
35 | $this->testRule(AirportRule::class, Airport::class);
36 | $this->testRule(ContinentRule::class, Continent::class);
37 | $this->testRule(CountryRule::class, Country::class);
38 | $this->testRule(CurrencyRule::class, Currency::class);
39 | $this->testRule(GbCountyRule::class, GbCounty::class);
40 | $this->testRule(RegionRule::class, Region::class);
41 | $this->testRule(TimezoneRule::class, Timezone::class);
42 | }
43 |
44 | protected function testRule(string $rule, string $model): void
45 | {
46 | $primaryKey = array_keys($model::$schema)[0];
47 | $secondaryKey = array_keys($model::$schema)[1];
48 |
49 | $this->assertTrue(Validator::make([
50 | $primaryKey => $model::first()->{$primaryKey},
51 | $secondaryKey => $model::first()->{$secondaryKey},
52 | ], [
53 | $primaryKey => [new $rule()],
54 | $secondaryKey => [new $rule($secondaryKey)],
55 | ])->passes());
56 |
57 | $this->assertTrue(Validator::make([
58 | $primaryKey => null,
59 | $secondaryKey => null,
60 | ], [
61 | $primaryKey => [new $rule()],
62 | $secondaryKey => [new $rule($secondaryKey)],
63 | ])->fails());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tests/Rules/FooRule.php:
--------------------------------------------------------------------------------
1 | filter(fn (string $name): bool => $this->isTranslatedPackageDirectory($name))
16 | ->map(fn (string $name): string => str_replace(static::PACKAGES_DIRECTORY, '', $name))
17 | ->groupBy(function (string $name): string {
18 | $parts = explode('-', $name);
19 | unset($parts[count($parts) - 1]);
20 |
21 | return implode('-', $parts);
22 | })
23 | ->filter(fn (Collection $translations): bool => $translations->count() > 1)
24 | ->each(function (Collection $translations, string $package): void {
25 | $previous = null;
26 |
27 | $translations->each(function (string $translation) use ($package, &$previous) {
28 | $lines = count(explode('\n', file_get_contents(static::PACKAGES_DIRECTORY . $translation . '/resources/data.csv')));
29 |
30 | if ($previous !== null) {
31 | $this->assertSame($lines, $previous, "Number of data entires in {$package} is not the same for translations ($translation).");
32 | }
33 |
34 | $previous = $lines;
35 | });
36 | });
37 | }
38 |
39 | protected function isTranslatedPackageDirectory(string $name): bool
40 | {
41 | $parts = explode('-', $name);
42 |
43 | if (count($parts) <= 1) {
44 | return false;
45 | }
46 |
47 | return strlen($parts[count($parts) - 1]) === 2;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/data/foo-en.csv:
--------------------------------------------------------------------------------
1 | foo,lang
2 | bar,en
3 | baz,en
--------------------------------------------------------------------------------
/tests/data/foo-es.csv:
--------------------------------------------------------------------------------
1 | foo,lang
2 | bar,es
3 | baz,es
--------------------------------------------------------------------------------